Skip to content

Commit d17555a

Browse files
crisbetoatscott
authored andcommitted
fix(compiler): incorrect spans for AST inside input value with leading space (#63082)
When parsing expressions inside a bound attribute, we offset all of its spans by an `absoluteOffset` in order to get the right spans in the source file. The offset was incorrect when parsing an attribute with leading spaces during the construction of the Ivy AST, because of the combination of: 1. We were setting the offset by looking at `valueSpan.start`. 2. The Ivy parser sets `leadingTriviaChars: [' ', '\n']` which means that spaces and new lines will be ignored in the `sourceSpan.start`. These changes resolve the issue by using `valueSpan.fullStart` which includes the leading spaces. Fixes #63069. PR Close #63082
1 parent 06f5879 commit d17555a

File tree

2 files changed

+21
-2
lines changed

2 files changed

+21
-2
lines changed

packages/compiler/src/render3/r3_template_transform.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -697,8 +697,8 @@ class HtmlAstToIvyAst implements html.Visitor {
697697
const value = attribute.value;
698698
const srcSpan = attribute.sourceSpan;
699699
const absoluteOffset = attribute.valueSpan
700-
? attribute.valueSpan.start.offset
701-
: srcSpan.start.offset;
700+
? attribute.valueSpan.fullStart.offset
701+
: srcSpan.fullStart.offset;
702702

703703
function createKeySpan(srcSpan: ParseSourceSpan, prefix: string, identifier: string) {
704704
// We need to adjust the start location for the keySpan to account for the removed 'data-'

packages/compiler/test/render3/r3_ast_spans_spec.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
* found in the LICENSE file at https://angular.dev/license
77
*/
88

9+
import {ASTWithSource} from '../../src/expression_parser/ast';
910
import {ParseSourceSpan} from '../../src/parse_util';
1011
import * as t from '../../src/render3/r3_ast';
1112

@@ -409,6 +410,24 @@ describe('R3 AST source spans', () => {
409410
['BoundAttribute', '@animation', 'animation', '<empty>'],
410411
]);
411412
});
413+
414+
it('should not throw off span of value in bound attribute when leading spaces are present', () => {
415+
const assertValueSpan = (template: string, start: number, end: number) => {
416+
const result = parse(template);
417+
const boundAttribute = (result.nodes[0] as t.Element).inputs[0];
418+
const span = (boundAttribute.value as ASTWithSource).ast.sourceSpan;
419+
420+
expect(span.start).toBe(start);
421+
expect(span.end).toBe(end);
422+
};
423+
424+
assertValueSpan('<a [b]="helloWorld"></a>', 8, 18);
425+
assertValueSpan('<a [b]=" helloWorld"></a>', 9, 19);
426+
assertValueSpan('<a [b]=" helloWorld"></a>', 10, 20);
427+
assertValueSpan('<a [b]=" helloWorld"></a>', 11, 21);
428+
assertValueSpan('<a [b]=" helloWorld"></a>', 12, 22);
429+
assertValueSpan('<a [b]=" helloWorld"></a>', 50, 60);
430+
});
412431
});
413432

414433
describe('templates', () => {

0 commit comments

Comments
 (0)