diff --git a/packages/babel-parser/src/parser/statement.js b/packages/babel-parser/src/parser/statement.js index 9e890d2ef6..61551ead75 100644 --- a/packages/babel-parser/src/parser/statement.js +++ b/packages/babel-parser/src/parser/statement.js @@ -305,15 +305,7 @@ export default class StatementParser extends ExpressionParser { } } - if (this.eat(tt.parenL)) { - const node = this.startNodeAt(startPos, startLoc); - node.callee = expr; - node.arguments = this.parseCallExpressionArguments(tt.parenR, false); - this.toReferencedList(node.arguments); - expr = this.finishNode(node, "CallExpression"); - } - - node.expression = expr; + node.expression = this.parseMaybeDecoratorArguments(expr); this.state.decoratorStack.pop(); } else { node.expression = this.parseMaybeAssign(); @@ -321,6 +313,18 @@ export default class StatementParser extends ExpressionParser { return this.finishNode(node, "Decorator"); } + parseMaybeDecoratorArguments(expr: N.Expression): N.Expression { + if (this.eat(tt.parenL)) { + const node = this.startNodeAtNode(expr); + node.callee = expr; + node.arguments = this.parseCallExpressionArguments(tt.parenR, false); + this.toReferencedList(node.arguments); + return this.finishNode(node, "CallExpression"); + } + + return expr; + } + parseBreakContinueStatement( node: N.BreakStatement | N.ContinueStatement, keyword: string, diff --git a/packages/babel-parser/src/plugins/typescript.js b/packages/babel-parser/src/plugins/typescript.js index 10561da600..f298521b63 100644 --- a/packages/babel-parser/src/plugins/typescript.js +++ b/packages/babel-parser/src/plugins/typescript.js @@ -2047,6 +2047,22 @@ export default (superClass: Class): Class => } } + parseMaybeDecoratorArguments(expr: N.Expression): N.Expression { + if (this.isRelational("<")) { + const typeArguments = this.tsParseTypeArguments(); + + if (this.match(tt.parenL)) { + const call = super.parseMaybeDecoratorArguments(expr); + call.typeParameters = typeArguments; + return call; + } + + this.unexpected(this.state.start, tt.parenL); + } + + return super.parseMaybeDecoratorArguments(expr); + } + // === === === === === === === === === === === === === === === === // Note: All below methods are duplicates of something in flow.js. // Not sure what the best way to combine these is. diff --git a/packages/babel-parser/test/fixtures/typescript/decorators/type-arguments-invalid/input.js b/packages/babel-parser/test/fixtures/typescript/decorators/type-arguments-invalid/input.js new file mode 100644 index 0000000000..5a4b902e4d --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/decorators/type-arguments-invalid/input.js @@ -0,0 +1,2 @@ +@decorator +class Test {} diff --git a/packages/babel-parser/test/fixtures/typescript/decorators/type-arguments-invalid/options.json b/packages/babel-parser/test/fixtures/typescript/decorators/type-arguments-invalid/options.json new file mode 100644 index 0000000000..02d8a1c26f --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/decorators/type-arguments-invalid/options.json @@ -0,0 +1,7 @@ +{ + "plugins": [ + "typescript", + ["decorators", { "decoratorsBeforeExport": true }] + ], + "throws": "Unexpected token, expected \"(\" (2:0)" +} diff --git a/packages/babel-parser/test/fixtures/typescript/decorators/type-arguments/input.js b/packages/babel-parser/test/fixtures/typescript/decorators/type-arguments/input.js new file mode 100644 index 0000000000..cb1c5dd447 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/decorators/type-arguments/input.js @@ -0,0 +1,2 @@ +@decorator() +class Test {} diff --git a/packages/babel-parser/test/fixtures/typescript/decorators/type-arguments/options.json b/packages/babel-parser/test/fixtures/typescript/decorators/type-arguments/options.json new file mode 100644 index 0000000000..714918723f --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/decorators/type-arguments/options.json @@ -0,0 +1,6 @@ +{ + "plugins": [ + "typescript", + ["decorators", { "decoratorsBeforeExport": true }] + ] +} diff --git a/packages/babel-parser/test/fixtures/typescript/decorators/type-arguments/output.json b/packages/babel-parser/test/fixtures/typescript/decorators/type-arguments/output.json new file mode 100644 index 0000000000..91add31ed1 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/decorators/type-arguments/output.json @@ -0,0 +1,166 @@ +{ + "type": "File", + "start": 0, + "end": 34, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 2, + "column": 13 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 34, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 2, + "column": 13 + } + }, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ClassDeclaration", + "start": 0, + "end": 34, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 2, + "column": 13 + } + }, + "decorators": [ + { + "type": "Decorator", + "start": 0, + "end": 20, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 20 + } + }, + "expression": { + "type": "CallExpression", + "start": 1, + "end": 20, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 20 + } + }, + "callee": { + "type": "Identifier", + "start": 1, + "end": 10, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 10 + }, + "identifierName": "decorator" + }, + "name": "decorator" + }, + "arguments": [], + "typeParameters": { + "type": "TSTypeParameterInstantiation", + "start": 10, + "end": 18, + "loc": { + "start": { + "line": 1, + "column": 10 + }, + "end": { + "line": 1, + "column": 18 + } + }, + "params": [ + { + "type": "TSStringKeyword", + "start": 11, + "end": 17, + "loc": { + "start": { + "line": 1, + "column": 11 + }, + "end": { + "line": 1, + "column": 17 + } + } + } + ] + } + } + } + ], + "id": { + "type": "Identifier", + "start": 27, + "end": 31, + "loc": { + "start": { + "line": 2, + "column": 6 + }, + "end": { + "line": 2, + "column": 10 + }, + "identifierName": "Test" + }, + "name": "Test" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start": 32, + "end": 34, + "loc": { + "start": { + "line": 2, + "column": 11 + }, + "end": { + "line": 2, + "column": 13 + } + }, + "body": [] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/typescript/decorators/abstract-class/input.js b/packages/babel-parser/test/fixtures/typescript/legacy-decorators/abstract-class/input.js similarity index 100% rename from packages/babel-parser/test/fixtures/typescript/decorators/abstract-class/input.js rename to packages/babel-parser/test/fixtures/typescript/legacy-decorators/abstract-class/input.js diff --git a/packages/babel-parser/test/fixtures/typescript/decorators/abstract-class/options.json b/packages/babel-parser/test/fixtures/typescript/legacy-decorators/abstract-class/options.json similarity index 100% rename from packages/babel-parser/test/fixtures/typescript/decorators/abstract-class/options.json rename to packages/babel-parser/test/fixtures/typescript/legacy-decorators/abstract-class/options.json diff --git a/packages/babel-parser/test/fixtures/typescript/decorators/abstract-class/output.json b/packages/babel-parser/test/fixtures/typescript/legacy-decorators/abstract-class/output.json similarity index 100% rename from packages/babel-parser/test/fixtures/typescript/decorators/abstract-class/output.json rename to packages/babel-parser/test/fixtures/typescript/legacy-decorators/abstract-class/output.json diff --git a/packages/babel-parser/test/fixtures/typescript/legacy-decorators/type-arguments/input.js b/packages/babel-parser/test/fixtures/typescript/legacy-decorators/type-arguments/input.js new file mode 100644 index 0000000000..cb1c5dd447 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/legacy-decorators/type-arguments/input.js @@ -0,0 +1,2 @@ +@decorator() +class Test {} diff --git a/packages/babel-parser/test/fixtures/typescript/legacy-decorators/type-arguments/options.json b/packages/babel-parser/test/fixtures/typescript/legacy-decorators/type-arguments/options.json new file mode 100644 index 0000000000..b95c143bc2 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/legacy-decorators/type-arguments/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["typescript", "decorators-legacy"] +} diff --git a/packages/babel-parser/test/fixtures/typescript/legacy-decorators/type-arguments/output.json b/packages/babel-parser/test/fixtures/typescript/legacy-decorators/type-arguments/output.json new file mode 100644 index 0000000000..91add31ed1 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/legacy-decorators/type-arguments/output.json @@ -0,0 +1,166 @@ +{ + "type": "File", + "start": 0, + "end": 34, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 2, + "column": 13 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 34, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 2, + "column": 13 + } + }, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ClassDeclaration", + "start": 0, + "end": 34, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 2, + "column": 13 + } + }, + "decorators": [ + { + "type": "Decorator", + "start": 0, + "end": 20, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 20 + } + }, + "expression": { + "type": "CallExpression", + "start": 1, + "end": 20, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 20 + } + }, + "callee": { + "type": "Identifier", + "start": 1, + "end": 10, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 10 + }, + "identifierName": "decorator" + }, + "name": "decorator" + }, + "arguments": [], + "typeParameters": { + "type": "TSTypeParameterInstantiation", + "start": 10, + "end": 18, + "loc": { + "start": { + "line": 1, + "column": 10 + }, + "end": { + "line": 1, + "column": 18 + } + }, + "params": [ + { + "type": "TSStringKeyword", + "start": 11, + "end": 17, + "loc": { + "start": { + "line": 1, + "column": 11 + }, + "end": { + "line": 1, + "column": 17 + } + } + } + ] + } + } + } + ], + "id": { + "type": "Identifier", + "start": 27, + "end": 31, + "loc": { + "start": { + "line": 2, + "column": 6 + }, + "end": { + "line": 2, + "column": 10 + }, + "identifierName": "Test" + }, + "name": "Test" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start": 32, + "end": 34, + "loc": { + "start": { + "line": 2, + "column": 11 + }, + "end": { + "line": 2, + "column": 13 + } + }, + "body": [] + } + } + ], + "directives": [] + } +} \ No newline at end of file