fix(compiler): include parenthesis in expression source spans (#40740)

The parser does not include parenthesis in the AST, so if a LHS
expression would be parenthesized then its start span would start
after the opening parenthesis. Previously, some parent AST nodes would
be created with the start span of its LHS as its own start, so this
resulted in the parent AST node not encompassing the opening parenthesis
in its source span. This commit fixes the issue by capturing the start
index prior to parsing a child AST tree, which is then used as the
start of the source span of the the parent AST node that is parsed.

Fixes #40721

PR Close #40740
This commit is contained in:
JoostK
2021-02-06 20:25:12 +01:00
committed by Alex Rickabaugh
parent 94f4d5cba6
commit bbf61fc2be
2 changed files with 49 additions and 20 deletions
@@ -371,6 +371,39 @@ describe('parser', () => {
expect(unparseWithSpan(ast)).toContain(['a.b = c', 'a.b = c']);
expect(unparseWithSpan(ast)).toContain(['a.b = c', '[nameSpan] b']);
});
it('should include parenthesis in spans', () => {
// When a LHS expression is parenthesized, the parenthesis on the left used to be
// excluded from the span. This test verifies that the parenthesis are properly included
// in the span for both LHS and RHS expressions.
// https://github.com/angular/angular/issues/40721
expectSpan('(foo) && (bar)');
expectSpan('(foo) || (bar)');
expectSpan('(foo) == (bar)');
expectSpan('(foo) === (bar)');
expectSpan('(foo) != (bar)');
expectSpan('(foo) !== (bar)');
expectSpan('(foo) > (bar)');
expectSpan('(foo) >= (bar)');
expectSpan('(foo) < (bar)');
expectSpan('(foo) <= (bar)');
expectSpan('(foo) + (bar)');
expectSpan('(foo) - (bar)');
expectSpan('(foo) * (bar)');
expectSpan('(foo) / (bar)');
expectSpan('(foo) % (bar)');
expectSpan('(foo) | pipe');
expectSpan('(foo)()');
expectSpan('(foo).bar');
expectSpan('(foo)?.bar');
expectSpan('(foo).bar = (baz)');
expectSpan('(foo | pipe) == false');
expectSpan('(((foo) && bar) || baz) === true');
function expectSpan(input: string) {
expect(unparseWithSpan(parseBinding(input))).toContain([jasmine.any(String), input]);
}
});
});
describe('general error handling', () => {