Skip to content

Commit 59eef29

Browse files
alxhubatscott
authored andcommitted
fix(compiler): correct spans when parsing bindings with comments (#44678)
When parsing a binding with a comment at the end of the expression, the parser previously had logic to offset the parsed spans by the length of the comment. This logic seemed not to serve any useful purpose, and instead resulted in the corruption of the spans. For example, in the expression `{{foo // comment}}`, the parser would map the parsed `foo` `PropertyRead` node at the location of the characters 'ent' from the comment suffix. This commit removes that logic, correcting the parsed spans of such nodes in the presence of comments. Removing this logic does not seem to have caused any tests to fail. PR Close #44678
1 parent 1e918b6 commit 59eef29

File tree

3 files changed

+33
-8
lines changed

3 files changed

+33
-8
lines changed

packages/compiler-cli/src/ngtsc/indexer/test/template_spec.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,19 @@ function bind(template: string) {
2121

2222
runInEachFileSystem(() => {
2323
describe('getTemplateIdentifiers', () => {
24+
it('should handle comments in interpolations', () => {
25+
const template = '{{foo // comment}}';
26+
const refs = getTemplateIdentifiers(bind(template));
27+
28+
const [ref] = Array.from(refs);
29+
expect(ref).toEqual({
30+
name: 'foo',
31+
kind: IdentifierKind.Property,
32+
span: new AbsoluteSourceSpan(2, 5),
33+
target: null,
34+
});
35+
});
36+
2437
it('should generate nothing in empty template', () => {
2538
const template = '';
2639
const refs = getTemplateIdentifiers(bind(template));

packages/compiler/src/expression_parser/parser.ts

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,11 @@ export class Parser {
3939
interpolationConfig: InterpolationConfig = DEFAULT_INTERPOLATION_CONFIG): ASTWithSource {
4040
this._checkNoInterpolation(input, location, interpolationConfig);
4141
const sourceToLex = this._stripComments(input);
42-
const tokens = this._lexer.tokenize(this._stripComments(input));
43-
const ast = new _ParseAST(
44-
input, location, absoluteOffset, tokens, sourceToLex.length, true, this.errors,
45-
input.length - sourceToLex.length)
46-
.parseChain();
42+
const tokens = this._lexer.tokenize(sourceToLex);
43+
const ast =
44+
new _ParseAST(
45+
input, location, absoluteOffset, tokens, sourceToLex.length, true, this.errors, 0)
46+
.parseChain();
4747
return new ASTWithSource(ast, input, location, absoluteOffset, this.errors);
4848
}
4949

@@ -91,8 +91,7 @@ export class Parser {
9191
const sourceToLex = this._stripComments(input);
9292
const tokens = this._lexer.tokenize(sourceToLex);
9393
return new _ParseAST(
94-
input, location, absoluteOffset, tokens, sourceToLex.length, false, this.errors,
95-
input.length - sourceToLex.length)
94+
input, location, absoluteOffset, tokens, sourceToLex.length, false, this.errors, 0)
9695
.parseChain();
9796
}
9897

@@ -162,7 +161,7 @@ export class Parser {
162161
const tokens = this._lexer.tokenize(sourceToLex);
163162
const ast = new _ParseAST(
164163
input, location, absoluteOffset, tokens, sourceToLex.length, false,
165-
this.errors, offsets[i] + (expressionText.length - sourceToLex.length))
164+
this.errors, offsets[i])
166165
.parseChain();
167166
expressionNodes.push(ast);
168167
}

packages/compiler/test/render3/r3_ast_absolute_span_spec.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,23 @@
77
*/
88

99
import {AbsoluteSourceSpan} from '@angular/compiler';
10+
1011
import {humanizeExpressionSource} from './util/expression';
1112
import {parseR3 as parse} from './view/util';
1213

1314
describe('expression AST absolute source spans', () => {
15+
it('should handle comment in interpolation', () => {
16+
expect(humanizeExpressionSource(parse('{{foo // comment}}', {preserveWhitespaces: true}).nodes))
17+
.toContain(['foo', new AbsoluteSourceSpan(2, 5)]);
18+
});
19+
20+
it('should handle comment in an action binding', () => {
21+
expect(humanizeExpressionSource(parse('<button (click)="foo = true // comment">Save</button>', {
22+
preserveWhitespaces: true
23+
}).nodes))
24+
.toContain(['foo = true', new AbsoluteSourceSpan(17, 27)]);
25+
});
26+
1427
// TODO(ayazhafiz): duplicate this test without `preserveWhitespaces` once whitespace rewriting is
1528
// moved to post-R3AST generation.
1629
it('should provide absolute offsets with arbitrary whitespace', () => {

0 commit comments

Comments
 (0)