fix(compiler): absolute source span for template attribute expressions (#33189)
Prior to this commit, the absolute spans (relative to template source file rather than the start of an expression) of expressions in a template attribute like `*ngIf` were generated incorrectly, equating to the relative spans. This fixes the bug by passing an `absoluteOffset` parameter when parsing template bindings. Through some levels of indirection, this is required for the Language Service to support text replacement in https://github.com/angular/angular/pull/33091. PR Close #33189
This commit is contained in:
parent
422eb14dc0
commit
fd4fed14d8
|
@ -118,7 +118,7 @@ export class BindingParser {
|
|||
tplKey: string, tplValue: string, sourceSpan: ParseSourceSpan, absoluteOffset: number,
|
||||
targetMatchableAttrs: string[][], targetProps: ParsedProperty[],
|
||||
targetVars: ParsedVariable[]) {
|
||||
const bindings = this._parseTemplateBindings(tplKey, tplValue, sourceSpan);
|
||||
const bindings = this._parseTemplateBindings(tplKey, tplValue, sourceSpan, absoluteOffset);
|
||||
|
||||
for (let i = 0; i < bindings.length; i++) {
|
||||
const binding = bindings[i];
|
||||
|
@ -137,13 +137,14 @@ export class BindingParser {
|
|||
}
|
||||
}
|
||||
|
||||
private _parseTemplateBindings(tplKey: string, tplValue: string, sourceSpan: ParseSourceSpan):
|
||||
TemplateBinding[] {
|
||||
private _parseTemplateBindings(
|
||||
tplKey: string, tplValue: string, sourceSpan: ParseSourceSpan,
|
||||
absoluteOffset: number): TemplateBinding[] {
|
||||
const sourceInfo = sourceSpan.start.toString();
|
||||
|
||||
try {
|
||||
const bindingsResult = this._exprParser.parseTemplateBindings(
|
||||
tplKey, tplValue, sourceInfo, sourceSpan.start.offset);
|
||||
const bindingsResult =
|
||||
this._exprParser.parseTemplateBindings(tplKey, tplValue, sourceInfo, absoluteOffset);
|
||||
this._reportExpressionParserErrors(bindingsResult.errors, sourceSpan);
|
||||
bindingsResult.templateBindings.forEach((binding) => {
|
||||
if (binding.expression) {
|
||||
|
|
|
@ -44,6 +44,12 @@ describe('expression AST absolute source spans', () => {
|
|||
.toContain(['condition ? true : false', new AbsoluteSourceSpan(22, 46)]);
|
||||
});
|
||||
|
||||
it('should provide absolute offsets of an expression in a template attribute', () => {
|
||||
expect(humanizeExpressionSource(parse('<div *ngIf="value | async"></div>').nodes)).toContain([
|
||||
'(value | async)', new AbsoluteSourceSpan(12, 25)
|
||||
]);
|
||||
});
|
||||
|
||||
describe('binary expression', () => {
|
||||
it('should provide absolute offsets of a binary expression', () => {
|
||||
expect(humanizeExpressionSource(parse('<div>{{1 + 2}}<div>').nodes)).toContain([
|
||||
|
|
|
@ -102,7 +102,10 @@ class ExpressionSourceHumanizer extends e.RecursiveAstVisitor implements t.Visit
|
|||
super.visitQuote(ast, null);
|
||||
}
|
||||
|
||||
visitTemplate(ast: t.Template) { t.visitAll(this, ast.children); }
|
||||
visitTemplate(ast: t.Template) {
|
||||
t.visitAll(this, ast.children);
|
||||
t.visitAll(this, ast.templateAttrs);
|
||||
}
|
||||
visitElement(ast: t.Element) {
|
||||
t.visitAll(this, ast.children);
|
||||
t.visitAll(this, ast.inputs);
|
||||
|
|
Loading…
Reference in New Issue