Skip to content

Commit

Permalink
refactor(compiler): track the closing source-span of TagPlaceholders (#…
Browse files Browse the repository at this point in the history
…38747)

The `TagPlaceholder` can contain children, in which case there are two source
spans of interest: the opening tag and the closing tag. This commit now allows
the closing tag source-span to be tracked, so that it can be used later in
source-mapping.

PR Close #38747
  • Loading branch information
petebacondarwin authored and atscott committed Sep 8, 2020
1 parent 3876202 commit cfd4c0b
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 8 deletions.
5 changes: 3 additions & 2 deletions packages/compiler/src/i18n/i18n_ast.ts
Expand Up @@ -87,7 +87,7 @@ export class TagPlaceholder implements Node {
constructor(
public tag: string, public attrs: {[k: string]: string}, public startName: string,
public closeName: string, public children: Node[], public isVoid: boolean,
public sourceSpan: ParseSourceSpan) {}
public sourceSpan: ParseSourceSpan, public closeSourceSpan: ParseSourceSpan|null) {}

visit(visitor: Visitor, context?: any): any {
return visitor.visitTagPlaceholder(this, context);
Expand Down Expand Up @@ -151,7 +151,8 @@ export class CloneVisitor implements Visitor {
visitTagPlaceholder(ph: TagPlaceholder, context?: any): TagPlaceholder {
const children = ph.children.map(n => n.visit(this, context));
return new TagPlaceholder(
ph.tag, ph.attrs, ph.startName, ph.closeName, children, ph.isVoid, ph.sourceSpan);
ph.tag, ph.attrs, ph.startName, ph.closeName, children, ph.isVoid, ph.sourceSpan,
ph.closeSourceSpan);
}

visitPlaceholder(ph: Placeholder, context?: any): Placeholder {
Expand Down
19 changes: 15 additions & 4 deletions packages/compiler/src/i18n/i18n_parser.ts
Expand Up @@ -93,7 +93,8 @@ class _I18nVisitor implements html.Visitor {
}

const node = new i18n.TagPlaceholder(
el.name, attrs, startPhName, closePhName, children, isVoid, el.sourceSpan!);
el.name, attrs, startPhName, closePhName, children, isVoid, el.startSourceSpan!,
el.endSourceSpan);
return context.visitNodeFn(el, node);
}

Expand Down Expand Up @@ -167,22 +168,32 @@ class _I18nVisitor implements html.Visitor {

if (splitInterpolation.strings[i].length) {
// No need to add empty strings
nodes.push(new i18n.Text(splitInterpolation.strings[i], sourceSpan));
const stringSpan = getOffsetSourceSpan(sourceSpan, splitInterpolation.stringSpans[i]);
nodes.push(new i18n.Text(splitInterpolation.strings[i], stringSpan));
}

nodes.push(new i18n.Placeholder(expression, phName, sourceSpan));
const expressionSpan =
getOffsetSourceSpan(sourceSpan, splitInterpolation.expressionsSpans[i]);
nodes.push(new i18n.Placeholder(expression, phName, expressionSpan));
context.placeholderToContent[phName] = sDelimiter + expression + eDelimiter;
}

// The last index contains no expression
const lastStringIdx = splitInterpolation.strings.length - 1;
if (splitInterpolation.strings[lastStringIdx].length) {
nodes.push(new i18n.Text(splitInterpolation.strings[lastStringIdx], sourceSpan));
const stringSpan =
getOffsetSourceSpan(sourceSpan, splitInterpolation.stringSpans[lastStringIdx]);
nodes.push(new i18n.Text(splitInterpolation.strings[lastStringIdx], stringSpan));
}
return container;
}
}

function getOffsetSourceSpan(
sourceSpan: ParseSourceSpan, {start, end}: {start: number, end: number}): ParseSourceSpan {
return new ParseSourceSpan(sourceSpan.start.moveBy(start), sourceSpan.start.moveBy(end));
}

const _CUSTOM_PH_EXP =
/\/\/[\s\S]*i18n[\s\S]*\([\s\S]*ph[\s\S]*=[\s\S]*("|')([\s\S]*?)\1[\s\S]*\)/g;

Expand Down
3 changes: 2 additions & 1 deletion packages/compiler/src/i18n/message_bundle.ts
Expand Up @@ -94,7 +94,8 @@ class MapPlaceholderNames extends i18n.CloneVisitor {
const closeName = ph.closeName ? mapper.toPublicName(ph.closeName)! : ph.closeName;
const children = ph.children.map(n => n.visit(this, mapper));
return new i18n.TagPlaceholder(
ph.tag, ph.attrs, startName, closeName, children, ph.isVoid, ph.sourceSpan);
ph.tag, ph.attrs, startName, closeName, children, ph.isVoid, ph.sourceSpan,
ph.closeSourceSpan);
}

visitPlaceholder(ph: i18n.Placeholder, mapper: PlaceholderMapper): i18n.Placeholder {
Expand Down
2 changes: 1 addition & 1 deletion packages/compiler/test/i18n/serializers/i18n_ast_spec.ts
Expand Up @@ -41,7 +41,7 @@ import {_extractMessages} from '../i18n_parser_spec';
new i18n.IcuPlaceholder(null!, '', null!),
],
null!);
const tag = new i18n.TagPlaceholder('', {}, '', '', [container], false, null!);
const tag = new i18n.TagPlaceholder('', {}, '', '', [container], false, null!, null);
const icu = new i18n.Icu('', '', {tag}, null!);

icu.visit(visitor);
Expand Down

0 comments on commit cfd4c0b

Please sign in to comment.