From d27469954ca1cfbbed6b9f73a4d36c80918c7700 Mon Sep 17 00:00:00 2001 From: ayazhafiz Date: Tue, 15 Oct 2019 17:02:56 -0500 Subject: [PATCH] fix(compiler): absolute source span for template attribute expressions 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. (cherry picked from commit 9e2b784b28d9958548abc7863b8a7d8f4352c380) --- .../compiler/src/template_parser/binding_parser.ts | 11 ++++++----- .../test/render3/r3_ast_absolute_span_spec.ts | 7 +++++++ packages/compiler/test/render3/util/expression.ts | 5 ++++- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/packages/compiler/src/template_parser/binding_parser.ts b/packages/compiler/src/template_parser/binding_parser.ts index b2e52327ab849..64c6438a59b80 100644 --- a/packages/compiler/src/template_parser/binding_parser.ts +++ b/packages/compiler/src/template_parser/binding_parser.ts @@ -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) { diff --git a/packages/compiler/test/render3/r3_ast_absolute_span_spec.ts b/packages/compiler/test/render3/r3_ast_absolute_span_spec.ts index 151e2906e0e9d..fe53406a32991 100644 --- a/packages/compiler/test/render3/r3_ast_absolute_span_spec.ts +++ b/packages/compiler/test/render3/r3_ast_absolute_span_spec.ts @@ -44,6 +44,13 @@ 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', () => { + debugger; + expect(humanizeExpressionSource(parse('
').nodes)).toContain([ + '(value | async)', new AbsoluteSourceSpan(12, 25) + ]); + }); + describe('binary expression', () => { it('should provide absolute offsets of a binary expression', () => { expect(humanizeExpressionSource(parse('
{{1 + 2}}
').nodes)).toContain([ diff --git a/packages/compiler/test/render3/util/expression.ts b/packages/compiler/test/render3/util/expression.ts index 5ed2c4b7d7c18..12331d8636597 100644 --- a/packages/compiler/test/render3/util/expression.ts +++ b/packages/compiler/test/render3/util/expression.ts @@ -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);