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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user