Skip to content

Commit

Permalink
feat(compiler): support recovery of malformed property writes (#39103)
Browse files Browse the repository at this point in the history
This feature is trivial to support since
89c5255 has landed.

PR Close #39103
  • Loading branch information
ayazhafiz authored and alxhub committed Oct 22, 2020
1 parent d331e09 commit e44e10b
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 1 deletion.
8 changes: 7 additions & 1 deletion packages/compiler/src/expression_parser/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -848,7 +848,13 @@ export class _ParseAST {
parseAccessMemberOrMethodCall(receiver: AST, isSafe: boolean = false): AST {
const start = receiver.span.start;
const nameStart = this.inputIndex;
const id = this.expectIdentifierOrKeyword();
const id = this.withContext(ParseContextFlags.Writable, () => {
const id = this.expectIdentifierOrKeyword();
if (id.length === 0) {
this.error(`Expected identifier for property access`, receiver.span.end);
}
return id;
});
const nameSpan = this.sourceSpan(nameStart);

if (this.consumeOptionalCharacter(chars.$LPAREN)) {
Expand Down
32 changes: 32 additions & 0 deletions packages/compiler/test/expression_parser/parser_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,38 @@ describe('parser', () => {
});
});

describe('property write', () => {
it('should parse property writes', () => {
checkAction('a.a = 1 + 2');
checkAction('this.a.a = 1 + 2', 'a.a = 1 + 2');
checkAction('a.a.a = 1 + 2');
});

describe('malformed property writes', () => {
it('should recover on empty rvalues', () => {
checkActionWithError('a.a = ', 'a.a = ', 'Unexpected end of expression');
});

it('should recover on incomplete rvalues', () => {
checkActionWithError('a.a = 1 + ', 'a.a = 1 + ', 'Unexpected end of expression');
});

it('should recover on missing properties', () => {
checkActionWithError(
'a. = 1', 'a. = 1', 'Expected identifier for property access at column 2');
});

it('should error on writes after a property write', () => {
const ast = parseAction('a.a = 1 = 2');
expect(unparse(ast)).toEqual('a.a = 1');
validate(ast);

expect(ast.errors.length).toBe(1);
expect(ast.errors[0].message).toContain('Unexpected token \'=\'');
});
});
});

describe('method calls', () => {
it('should parse method calls', () => {
checkAction('fn()');
Expand Down

0 comments on commit e44e10b

Please sign in to comment.