From dbaf37806b9bfe8ec85c9ba3f4d140a0f73087dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Mon, 22 Aug 2022 17:15:40 +0200 Subject: [PATCH] Make the parser error recoverable --- .../src/parse-error/standard-errors.ts | 2 + packages/babel-parser/src/parser/statement.ts | 12 ++- .../options.json | 3 +- .../output.json | 89 +++++++++++++++++++ 4 files changed, 100 insertions(+), 6 deletions(-) create mode 100644 packages/babel-parser/test/fixtures/experimental/decorators/parenthesized-allowCallParenthesized-false-invalid/output.json diff --git a/packages/babel-parser/src/parse-error/standard-errors.ts b/packages/babel-parser/src/parse-error/standard-errors.ts index a4087dfcc718..e50a5a33e007 100644 --- a/packages/babel-parser/src/parse-error/standard-errors.ts +++ b/packages/babel-parser/src/parse-error/standard-errors.ts @@ -50,6 +50,8 @@ export default { }: { kind: "const" | "destructuring"; }) => `Missing initializer in ${kind} declaration.`, + DecoratorArgumentsOutsideParentheses: + "Decorator arguments must be moved inside parentheses: use '@(decorator(args))' instead of '@(decorator)(args)'.", DecoratorBeforeExport: "Decorators must be placed *before* the 'export' keyword. You can set the 'decoratorsBeforeExport' option to false to use the 'export @decorator class {}' syntax.", DecoratorConstructor: diff --git a/packages/babel-parser/src/parser/statement.ts b/packages/babel-parser/src/parser/statement.ts index 625e8c94f64f..4c2fc5237a9b 100644 --- a/packages/babel-parser/src/parser/statement.ts +++ b/packages/babel-parser/src/parser/statement.ts @@ -581,12 +581,16 @@ export default abstract class StatementParser extends ExpressionParser { this.expect(tt.parenR); expr = this.wrapParenthesis(startPos, startLoc, expr); + const paramsStartLoc = this.state.startLoc; + node.expression = this.parseMaybeDecoratorArguments(expr); if ( - this.getPluginOption("decorators", "allowCallParenthesized") !== false + this.getPluginOption("decorators", "allowCallParenthesized") === + false && + node.expression !== expr ) { - node.expression = this.parseMaybeDecoratorArguments(expr); - } else { - node.expression = expr; + this.raise(Errors.DecoratorArgumentsOutsideParentheses, { + at: paramsStartLoc, + }); } } else { expr = this.parseIdentifier(false); diff --git a/packages/babel-parser/test/fixtures/experimental/decorators/parenthesized-allowCallParenthesized-false-invalid/options.json b/packages/babel-parser/test/fixtures/experimental/decorators/parenthesized-allowCallParenthesized-false-invalid/options.json index 5aa243f88223..9a7fd5e2efb9 100644 --- a/packages/babel-parser/test/fixtures/experimental/decorators/parenthesized-allowCallParenthesized-false-invalid/options.json +++ b/packages/babel-parser/test/fixtures/experimental/decorators/parenthesized-allowCallParenthesized-false-invalid/options.json @@ -7,6 +7,5 @@ "decoratorsBeforeExport": false } ] - ], - "throws": "Unexpected token (2:13)" + ] } diff --git a/packages/babel-parser/test/fixtures/experimental/decorators/parenthesized-allowCallParenthesized-false-invalid/output.json b/packages/babel-parser/test/fixtures/experimental/decorators/parenthesized-allowCallParenthesized-false-invalid/output.json new file mode 100644 index 000000000000..436ea880e3cf --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/decorators/parenthesized-allowCallParenthesized-false-invalid/output.json @@ -0,0 +1,89 @@ +{ + "type": "File", + "start":0,"end":45,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":3,"column":1,"index":45}}, + "errors": [ + "SyntaxError: Decorator arguments must be moved inside parentheses: use '@(decorator(args))' instead of '@(decorator)(args)'. (2:13)" + ], + "program": { + "type": "Program", + "start":0,"end":45,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":3,"column":1,"index":45}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ClassDeclaration", + "start":0,"end":45,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":3,"column":1,"index":45}}, + "id": { + "type": "Identifier", + "start":6,"end":9,"loc":{"start":{"line":1,"column":6,"index":6},"end":{"line":1,"column":9,"index":9},"identifierName":"Foo"}, + "name": "Foo" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start":10,"end":45,"loc":{"start":{"line":1,"column":10,"index":10},"end":{"line":3,"column":1,"index":45}}, + "body": [ + { + "type": "ClassMethod", + "start":14,"end":43,"loc":{"start":{"line":2,"column":2,"index":14},"end":{"line":2,"column":31,"index":43}}, + "decorators": [ + { + "type": "Decorator", + "start":14,"end":30,"loc":{"start":{"line":2,"column":2,"index":14},"end":{"line":2,"column":18,"index":30}}, + "expression": { + "type": "CallExpression", + "start":16,"end":30,"loc":{"start":{"line":2,"column":4,"index":16},"end":{"line":2,"column":18,"index":30}}, + "callee": { + "type": "MemberExpression", + "start":16,"end":24,"loc":{"start":{"line":2,"column":4,"index":16},"end":{"line":2,"column":12,"index":24}}, + "object": { + "type": "ThisExpression", + "start":16,"end":20,"loc":{"start":{"line":2,"column":4,"index":16},"end":{"line":2,"column":8,"index":20}} + }, + "computed": false, + "property": { + "type": "Identifier", + "start":21,"end":24,"loc":{"start":{"line":2,"column":9,"index":21},"end":{"line":2,"column":12,"index":24},"identifierName":"foo"}, + "name": "foo" + }, + "extra": { + "parenthesized": true, + "parenStart": 15 + } + }, + "arguments": [ + { + "type": "Identifier", + "start":26,"end":29,"loc":{"start":{"line":2,"column":14,"index":26},"end":{"line":2,"column":17,"index":29},"identifierName":"bar"}, + "name": "bar" + } + ] + } + } + ], + "static": false, + "key": { + "type": "Identifier", + "start":31,"end":38,"loc":{"start":{"line":2,"column":19,"index":31},"end":{"line":2,"column":26,"index":38},"identifierName":"method3"}, + "name": "method3" + }, + "computed": false, + "kind": "method", + "id": null, + "generator": false, + "async": false, + "params": [], + "body": { + "type": "BlockStatement", + "start":41,"end":43,"loc":{"start":{"line":2,"column":29,"index":41},"end":{"line":2,"column":31,"index":43}}, + "body": [], + "directives": [] + } + } + ] + } + } + ], + "directives": [] + } +}