diff --git a/packages/babel-generator/src/generators/expressions.ts b/packages/babel-generator/src/generators/expressions.ts index a5bdc1e6b2a3..146c21113a36 100644 --- a/packages/babel-generator/src/generators/expressions.ts +++ b/packages/babel-generator/src/generators/expressions.ts @@ -113,9 +113,45 @@ export function Super(this: Printer) { this.word("super"); } +function isDecoratorMemberExpression( + node: t.Expression | t.V8IntrinsicIdentifier, +) { + switch (node.type) { + case "Identifier": + return true; + case "MemberExpression": + return ( + !node.computed && + node.property.type === "Identifier" && + isDecoratorMemberExpression(node.object) + ); + default: + return false; + } +} +function shouldParenthesizeDecoratorExpression( + node: t.Expression | t.V8IntrinsicIdentifier, +) { + if (node.type === "CallExpression") { + node = node.callee; + } + if (node.type === "ParenthesizedExpression") { + // We didn't check extra?.parenthesized here because we don't track decorators in needsParen + return false; + } + return !isDecoratorMemberExpression(node); +} + export function Decorator(this: Printer, node: t.Decorator) { this.token("@"); - this.print(node.expression, node); + const { expression } = node; + if (shouldParenthesizeDecoratorExpression(expression)) { + this.token("("); + this.print(expression, node); + this.token(")"); + } else { + this.print(expression, node); + } this.newline(); } diff --git a/packages/babel-generator/test/fixtures/decorators-legacy/ts-class-modifier-with-retainlines/options.json b/packages/babel-generator/test/fixtures/decorators-legacy/ts-class-modifier-with-retainlines/options.json index ab2bf8d8c808..e084a5f55dbf 100644 --- a/packages/babel-generator/test/fixtures/decorators-legacy/ts-class-modifier-with-retainlines/options.json +++ b/packages/babel-generator/test/fixtures/decorators-legacy/ts-class-modifier-with-retainlines/options.json @@ -1 +1,5 @@ -{ "plugins": ["classProperties", "decorators-legacy", "typescript"], "decoratorsBeforeExport": true, "retainLines": true } +{ + "plugins": ["decorators-legacy", "typescript"], + "decoratorsBeforeExport": true, + "retainLines": true +} diff --git a/packages/babel-generator/test/fixtures/decorators/decorator-call-expression/input.js b/packages/babel-generator/test/fixtures/decorators/decorator-call-expression/input.js new file mode 100644 index 000000000000..9a4b711e3f86 --- /dev/null +++ b/packages/babel-generator/test/fixtures/decorators/decorator-call-expression/input.js @@ -0,0 +1,6 @@ +class C { + @dec(0) + @globalThis.dec(0) + @(globalThis["dec"])(0) + p +} diff --git a/packages/babel-generator/test/fixtures/decorators/decorator-call-expression/output.js b/packages/babel-generator/test/fixtures/decorators/decorator-call-expression/output.js new file mode 100644 index 000000000000..29da7bae2050 --- /dev/null +++ b/packages/babel-generator/test/fixtures/decorators/decorator-call-expression/output.js @@ -0,0 +1,6 @@ +class C { + @dec(0) + @globalThis.dec(0) + @(globalThis["dec"](0)) + p; +} \ No newline at end of file diff --git a/packages/babel-generator/test/fixtures/decorators/decorator-member-expression/input.js b/packages/babel-generator/test/fixtures/decorators/decorator-member-expression/input.js new file mode 100644 index 000000000000..b2200c0546aa --- /dev/null +++ b/packages/babel-generator/test/fixtures/decorators/decorator-member-expression/input.js @@ -0,0 +1,6 @@ +class C { + @dec + @globalThis.dec + @globalThis.self.dec + p +} diff --git a/packages/babel-generator/test/fixtures/decorators/decorator-member-expression/output.js b/packages/babel-generator/test/fixtures/decorators/decorator-member-expression/output.js new file mode 100644 index 000000000000..b975b0de24a7 --- /dev/null +++ b/packages/babel-generator/test/fixtures/decorators/decorator-member-expression/output.js @@ -0,0 +1,6 @@ +class C { + @dec + @globalThis.dec + @globalThis.self.dec + p; +} \ No newline at end of file diff --git a/packages/babel-generator/test/fixtures/decorators/decorator-parenthesized-expression-createParenthesizedExpression/input.js b/packages/babel-generator/test/fixtures/decorators/decorator-parenthesized-expression-createParenthesizedExpression/input.js new file mode 100644 index 000000000000..8cec169bc925 --- /dev/null +++ b/packages/babel-generator/test/fixtures/decorators/decorator-parenthesized-expression-createParenthesizedExpression/input.js @@ -0,0 +1,30 @@ +class C extends class {} { + #x; + constructor() { + class ShouldPreserveParens { + @(decs[0]) + @(decs`1`) + @(this?.two) + @(self.#x) + @(this.dec) + @(super.dec) + @(new DecFactory) + @(decs[three])() + p; + } + + class ShouldNotAddParens { + @decs + @decs.one + @decs.two() + p; + } + + class WillPreserveParens { + @(decs) + @(decs.one) + @(decs.two()) + p; + } + } +} diff --git a/packages/babel-generator/test/fixtures/decorators/decorator-parenthesized-expression-createParenthesizedExpression/options.json b/packages/babel-generator/test/fixtures/decorators/decorator-parenthesized-expression-createParenthesizedExpression/options.json new file mode 100644 index 000000000000..2c4e18802e58 --- /dev/null +++ b/packages/babel-generator/test/fixtures/decorators/decorator-parenthesized-expression-createParenthesizedExpression/options.json @@ -0,0 +1,5 @@ +{ + "plugins": [["decorators", { "decoratorsBeforeExport": false }]], + "decoratorsBeforeExport": true, + "parserOpts": { "createParenthesizedExpressions": true } +} diff --git a/packages/babel-generator/test/fixtures/decorators/decorator-parenthesized-expression-createParenthesizedExpression/output.js b/packages/babel-generator/test/fixtures/decorators/decorator-parenthesized-expression-createParenthesizedExpression/output.js new file mode 100644 index 000000000000..a3e2fb794feb --- /dev/null +++ b/packages/babel-generator/test/fixtures/decorators/decorator-parenthesized-expression-createParenthesizedExpression/output.js @@ -0,0 +1,32 @@ +class C extends class {} { + #x; + + constructor() { + class ShouldPreserveParens { + @(decs[0]) + @(decs`1`) + @(this?.two) + @(self.#x) + @(this.dec) + @(super.dec) + @(new DecFactory()) + @(decs[three])() + p; + } + + class ShouldNotAddParens { + @decs + @decs.one + @decs.two() + p; + } + + class WillPreserveParens { + @(decs) + @(decs.one) + @(decs.two()) + p; + } + } + +} \ No newline at end of file diff --git a/packages/babel-generator/test/fixtures/decorators/decorator-parenthesized-expression/input.js b/packages/babel-generator/test/fixtures/decorators/decorator-parenthesized-expression/input.js new file mode 100644 index 000000000000..2681044f93ad --- /dev/null +++ b/packages/babel-generator/test/fixtures/decorators/decorator-parenthesized-expression/input.js @@ -0,0 +1,34 @@ +class C extends class {} { + #x; + constructor() { + class ShouldPreserveParens { + @(decs[0]) + @(decs`1`) + @(this?.two) + @(self.#x) + @(this.dec) + @(super.dec) + @(new DecFactory) + p; + } + + class ShouldNotAddParens { + @decs + @decs.one + @decs.two() + p; + } + + class ShouldAddParens { + @(decs[three])() + p; + } + + class ShouldRemoveParens { + @(decs) + @(decs.one) + @(decs.two()) + p; + } + } +} diff --git a/packages/babel-generator/test/fixtures/decorators/decorator-parenthesized-expression/output.js b/packages/babel-generator/test/fixtures/decorators/decorator-parenthesized-expression/output.js new file mode 100644 index 000000000000..2c2780aee874 --- /dev/null +++ b/packages/babel-generator/test/fixtures/decorators/decorator-parenthesized-expression/output.js @@ -0,0 +1,36 @@ +class C extends class {} { + #x; + + constructor() { + class ShouldPreserveParens { + @(decs[0]) + @(decs`1`) + @(this?.two) + @(self.#x) + @(this.dec) + @(super.dec) + @(new DecFactory()) + p; + } + + class ShouldNotAddParens { + @decs + @decs.one + @decs.two() + p; + } + + class ShouldAddParens { + @(decs[three]()) + p; + } + + class ShouldRemoveParens { + @decs + @decs.one + @decs.two() + p; + } + } + +} \ No newline at end of file diff --git a/packages/babel-generator/test/fixtures/decorators/options.json b/packages/babel-generator/test/fixtures/decorators/options.json index a91f97747064..234fb2bac889 100644 --- a/packages/babel-generator/test/fixtures/decorators/options.json +++ b/packages/babel-generator/test/fixtures/decorators/options.json @@ -1,9 +1,4 @@ { - "plugins": [ - ["decorators", { "decoratorsBeforeExport": false }], - "classProperties", - "classPrivateProperties", - "classPrivateMethods" - ], + "plugins": [["decorators", { "decoratorsBeforeExport": false }]], "decoratorsBeforeExport": true } diff --git a/packages/babel-parser/src/parser/expression.js b/packages/babel-parser/src/parser/expression.js index a6318ef65905..1b58a874696e 100644 --- a/packages/babel-parser/src/parser/expression.js +++ b/packages/babel-parser/src/parser/expression.js @@ -1770,21 +1770,29 @@ export default class ExpressionParser extends LValParser { val = exprList[0]; } + return this.wrapParenthesis(startPos, startLoc, val); + } + + wrapParenthesis( + startPos: number, + startLoc: Position, + expression: N.Expression, + ): N.Expression { if (!this.options.createParenthesizedExpressions) { - this.addExtra(val, "parenthesized", true); - this.addExtra(val, "parenStart", startPos); + this.addExtra(expression, "parenthesized", true); + this.addExtra(expression, "parenStart", startPos); this.takeSurroundingComments( - val, + expression, startPos, this.state.lastTokEndLoc.index, ); - return val; + return expression; } const parenExpression = this.startNodeAt(startPos, startLoc); - parenExpression.expression = val; + parenExpression.expression = expression; this.finishNode(parenExpression, "ParenthesizedExpression"); return parenExpression; } diff --git a/packages/babel-parser/src/parser/statement.js b/packages/babel-parser/src/parser/statement.js index 1ca7c1a5ef04..968c48261f76 100644 --- a/packages/babel-parser/src/parser/statement.js +++ b/packages/babel-parser/src/parser/statement.js @@ -539,9 +539,13 @@ export default class StatementParser extends ExpressionParser { const startLoc = this.state.startLoc; let expr: N.Expression; - if (this.eat(tt.parenL)) { + if (this.match(tt.parenL)) { + const startPos = this.state.start; + const startLoc = this.state.startLoc; + this.next(); // eat '(' expr = this.parseExpression(); this.expect(tt.parenR); + expr = this.wrapParenthesis(startPos, startLoc, expr); } else { expr = this.parseIdentifier(false); diff --git a/packages/babel-parser/test/fixtures/experimental/decorators-2/invalid-unparenthesized-arrow/input.js b/packages/babel-parser/test/fixtures/experimental/decorators-2/invalid-unparenthesized-arrow/input.js new file mode 100644 index 000000000000..47c595e2795f --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/decorators-2/invalid-unparenthesized-arrow/input.js @@ -0,0 +1,3 @@ +class Foo { + @() => () => "bar" p; +} diff --git a/packages/babel-parser/test/fixtures/experimental/decorators-2/invalid-unparenthesized-arrow/options.json b/packages/babel-parser/test/fixtures/experimental/decorators-2/invalid-unparenthesized-arrow/options.json new file mode 100644 index 000000000000..b2f4797ad803 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/decorators-2/invalid-unparenthesized-arrow/options.json @@ -0,0 +1,3 @@ +{ + "throws": "Unexpected token (2:4)" +} diff --git a/packages/babel-parser/test/fixtures/experimental/decorators-2/nested-class-decorator/output.json b/packages/babel-parser/test/fixtures/experimental/decorators-2/nested-class-decorator/output.json index d95e3a91918c..756131a8000a 100644 --- a/packages/babel-parser/test/fixtures/experimental/decorators-2/nested-class-decorator/output.json +++ b/packages/babel-parser/test/fixtures/experimental/decorators-2/nested-class-decorator/output.json @@ -56,7 +56,11 @@ } } } - ] + ], + "extra": { + "parenthesized": true, + "parenStart": 1 + } } } ], diff --git a/packages/babel-parser/test/fixtures/experimental/decorators-2/nested-method-decorator/output.json b/packages/babel-parser/test/fixtures/experimental/decorators-2/nested-method-decorator/output.json index b3050a539249..dc418f4e3a94 100644 --- a/packages/babel-parser/test/fixtures/experimental/decorators-2/nested-method-decorator/output.json +++ b/packages/babel-parser/test/fixtures/experimental/decorators-2/nested-method-decorator/output.json @@ -81,6 +81,10 @@ } } ] + }, + "extra": { + "parenthesized": true, + "parenStart": 14 } } } diff --git a/packages/babel-parser/test/fixtures/experimental/decorators-2/parenthesized-createParenthesizedExpressions/input.js b/packages/babel-parser/test/fixtures/experimental/decorators-2/parenthesized-createParenthesizedExpressions/input.js new file mode 100644 index 000000000000..28509117bf29 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/decorators-2/parenthesized-createParenthesizedExpressions/input.js @@ -0,0 +1,8 @@ +@(foo().bar) +class Foo { + @(member[expression]) method() {} + + @(foo + bar) method2() {} + + @(this.foo)(bar) method3() {} +} diff --git a/packages/babel-parser/test/fixtures/experimental/decorators-2/parenthesized-createParenthesizedExpressions/options.json b/packages/babel-parser/test/fixtures/experimental/decorators-2/parenthesized-createParenthesizedExpressions/options.json new file mode 100644 index 000000000000..50270cedd0d4 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/decorators-2/parenthesized-createParenthesizedExpressions/options.json @@ -0,0 +1,4 @@ +{ + "plugins": [["decorators", { "decoratorsBeforeExport": false }]], + "createParenthesizedExpressions": true +} diff --git a/packages/babel-parser/test/fixtures/experimental/decorators-2/parenthesized-createParenthesizedExpressions/output.json b/packages/babel-parser/test/fixtures/experimental/decorators-2/parenthesized-createParenthesizedExpressions/output.json new file mode 100644 index 000000000000..ba5245995c60 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/decorators-2/parenthesized-createParenthesizedExpressions/output.json @@ -0,0 +1,210 @@ +{ + "type": "File", + "start":0,"end":124,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":8,"column":1,"index":124}}, + "program": { + "type": "Program", + "start":0,"end":124,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":8,"column":1,"index":124}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ClassDeclaration", + "start":0,"end":124,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":8,"column":1,"index":124}}, + "decorators": [ + { + "type": "Decorator", + "start":0,"end":12,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":12,"index":12}}, + "expression": { + "type": "ParenthesizedExpression", + "start":1,"end":12,"loc":{"start":{"line":1,"column":1,"index":1},"end":{"line":1,"column":12,"index":12}}, + "expression": { + "type": "MemberExpression", + "start":2,"end":11,"loc":{"start":{"line":1,"column":2,"index":2},"end":{"line":1,"column":11,"index":11}}, + "object": { + "type": "CallExpression", + "start":2,"end":7,"loc":{"start":{"line":1,"column":2,"index":2},"end":{"line":1,"column":7,"index":7}}, + "callee": { + "type": "Identifier", + "start":2,"end":5,"loc":{"start":{"line":1,"column":2,"index":2},"end":{"line":1,"column":5,"index":5},"identifierName":"foo"}, + "name": "foo" + }, + "arguments": [] + }, + "computed": false, + "property": { + "type": "Identifier", + "start":8,"end":11,"loc":{"start":{"line":1,"column":8,"index":8},"end":{"line":1,"column":11,"index":11},"identifierName":"bar"}, + "name": "bar" + } + } + } + } + ], + "id": { + "type": "Identifier", + "start":19,"end":22,"loc":{"start":{"line":2,"column":6,"index":19},"end":{"line":2,"column":9,"index":22},"identifierName":"Foo"}, + "name": "Foo" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start":23,"end":124,"loc":{"start":{"line":2,"column":10,"index":23},"end":{"line":8,"column":1,"index":124}}, + "body": [ + { + "type": "ClassMethod", + "start":27,"end":60,"loc":{"start":{"line":3,"column":2,"index":27},"end":{"line":3,"column":35,"index":60}}, + "decorators": [ + { + "type": "Decorator", + "start":27,"end":48,"loc":{"start":{"line":3,"column":2,"index":27},"end":{"line":3,"column":23,"index":48}}, + "expression": { + "type": "ParenthesizedExpression", + "start":28,"end":48,"loc":{"start":{"line":3,"column":3,"index":28},"end":{"line":3,"column":23,"index":48}}, + "expression": { + "type": "MemberExpression", + "start":29,"end":47,"loc":{"start":{"line":3,"column":4,"index":29},"end":{"line":3,"column":22,"index":47}}, + "object": { + "type": "Identifier", + "start":29,"end":35,"loc":{"start":{"line":3,"column":4,"index":29},"end":{"line":3,"column":10,"index":35},"identifierName":"member"}, + "name": "member" + }, + "computed": true, + "property": { + "type": "Identifier", + "start":36,"end":46,"loc":{"start":{"line":3,"column":11,"index":36},"end":{"line":3,"column":21,"index":46},"identifierName":"expression"}, + "name": "expression" + } + } + } + } + ], + "static": false, + "key": { + "type": "Identifier", + "start":49,"end":55,"loc":{"start":{"line":3,"column":24,"index":49},"end":{"line":3,"column":30,"index":55},"identifierName":"method"}, + "name": "method" + }, + "computed": false, + "kind": "method", + "id": null, + "generator": false, + "async": false, + "params": [], + "body": { + "type": "BlockStatement", + "start":58,"end":60,"loc":{"start":{"line":3,"column":33,"index":58},"end":{"line":3,"column":35,"index":60}}, + "body": [], + "directives": [] + } + }, + { + "type": "ClassMethod", + "start":64,"end":89,"loc":{"start":{"line":5,"column":2,"index":64},"end":{"line":5,"column":27,"index":89}}, + "decorators": [ + { + "type": "Decorator", + "start":64,"end":76,"loc":{"start":{"line":5,"column":2,"index":64},"end":{"line":5,"column":14,"index":76}}, + "expression": { + "type": "ParenthesizedExpression", + "start":65,"end":76,"loc":{"start":{"line":5,"column":3,"index":65},"end":{"line":5,"column":14,"index":76}}, + "expression": { + "type": "BinaryExpression", + "start":66,"end":75,"loc":{"start":{"line":5,"column":4,"index":66},"end":{"line":5,"column":13,"index":75}}, + "left": { + "type": "Identifier", + "start":66,"end":69,"loc":{"start":{"line":5,"column":4,"index":66},"end":{"line":5,"column":7,"index":69},"identifierName":"foo"}, + "name": "foo" + }, + "operator": "+", + "right": { + "type": "Identifier", + "start":72,"end":75,"loc":{"start":{"line":5,"column":10,"index":72},"end":{"line":5,"column":13,"index":75},"identifierName":"bar"}, + "name": "bar" + } + } + } + } + ], + "static": false, + "key": { + "type": "Identifier", + "start":77,"end":84,"loc":{"start":{"line":5,"column":15,"index":77},"end":{"line":5,"column":22,"index":84},"identifierName":"method2"}, + "name": "method2" + }, + "computed": false, + "kind": "method", + "id": null, + "generator": false, + "async": false, + "params": [], + "body": { + "type": "BlockStatement", + "start":87,"end":89,"loc":{"start":{"line":5,"column":25,"index":87},"end":{"line":5,"column":27,"index":89}}, + "body": [], + "directives": [] + } + }, + { + "type": "ClassMethod", + "start":93,"end":122,"loc":{"start":{"line":7,"column":2,"index":93},"end":{"line":7,"column":31,"index":122}}, + "decorators": [ + { + "type": "Decorator", + "start":93,"end":109,"loc":{"start":{"line":7,"column":2,"index":93},"end":{"line":7,"column":18,"index":109}}, + "expression": { + "type": "CallExpression", + "start":94,"end":109,"loc":{"start":{"line":7,"column":3,"index":94},"end":{"line":7,"column":18,"index":109}}, + "callee": { + "type": "ParenthesizedExpression", + "start":94,"end":104,"loc":{"start":{"line":7,"column":3,"index":94},"end":{"line":7,"column":13,"index":104}}, + "expression": { + "type": "MemberExpression", + "start":95,"end":103,"loc":{"start":{"line":7,"column":4,"index":95},"end":{"line":7,"column":12,"index":103}}, + "object": { + "type": "ThisExpression", + "start":95,"end":99,"loc":{"start":{"line":7,"column":4,"index":95},"end":{"line":7,"column":8,"index":99}} + }, + "computed": false, + "property": { + "type": "Identifier", + "start":100,"end":103,"loc":{"start":{"line":7,"column":9,"index":100},"end":{"line":7,"column":12,"index":103},"identifierName":"foo"}, + "name": "foo" + } + } + }, + "arguments": [ + { + "type": "Identifier", + "start":105,"end":108,"loc":{"start":{"line":7,"column":14,"index":105},"end":{"line":7,"column":17,"index":108},"identifierName":"bar"}, + "name": "bar" + } + ] + } + } + ], + "static": false, + "key": { + "type": "Identifier", + "start":110,"end":117,"loc":{"start":{"line":7,"column":19,"index":110},"end":{"line":7,"column":26,"index":117},"identifierName":"method3"}, + "name": "method3" + }, + "computed": false, + "kind": "method", + "id": null, + "generator": false, + "async": false, + "params": [], + "body": { + "type": "BlockStatement", + "start":120,"end":122,"loc":{"start":{"line":7,"column":29,"index":120},"end":{"line":7,"column":31,"index":122}}, + "body": [], + "directives": [] + } + } + ] + } + } + ], + "directives": [] + } +} diff --git a/packages/babel-parser/test/fixtures/experimental/decorators-2/parenthesized/input.js b/packages/babel-parser/test/fixtures/experimental/decorators-2/parenthesized/input.js index 79f9aa697108..28509117bf29 100644 --- a/packages/babel-parser/test/fixtures/experimental/decorators-2/parenthesized/input.js +++ b/packages/babel-parser/test/fixtures/experimental/decorators-2/parenthesized/input.js @@ -3,4 +3,6 @@ class Foo { @(member[expression]) method() {} @(foo + bar) method2() {} -} \ No newline at end of file + + @(this.foo)(bar) method3() {} +} diff --git a/packages/babel-parser/test/fixtures/experimental/decorators-2/parenthesized/output.json b/packages/babel-parser/test/fixtures/experimental/decorators-2/parenthesized/output.json index c2b57d346967..0d826cdd1f1d 100644 --- a/packages/babel-parser/test/fixtures/experimental/decorators-2/parenthesized/output.json +++ b/packages/babel-parser/test/fixtures/experimental/decorators-2/parenthesized/output.json @@ -1,15 +1,15 @@ { "type": "File", - "start":0,"end":91,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":6,"column":1,"index":91}}, + "start":0,"end":124,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":8,"column":1,"index":124}}, "program": { "type": "Program", - "start":0,"end":91,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":6,"column":1,"index":91}}, + "start":0,"end":124,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":8,"column":1,"index":124}}, "sourceType": "script", "interpreter": null, "body": [ { "type": "ClassDeclaration", - "start":0,"end":91,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":6,"column":1,"index":91}}, + "start":0,"end":124,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":8,"column":1,"index":124}}, "decorators": [ { "type": "Decorator", @@ -32,6 +32,10 @@ "type": "Identifier", "start":8,"end":11,"loc":{"start":{"line":1,"column":8,"index":8},"end":{"line":1,"column":11,"index":11},"identifierName":"bar"}, "name": "bar" + }, + "extra": { + "parenthesized": true, + "parenStart": 1 } } } @@ -44,7 +48,7 @@ "superClass": null, "body": { "type": "ClassBody", - "start":23,"end":91,"loc":{"start":{"line":2,"column":10,"index":23},"end":{"line":6,"column":1,"index":91}}, + "start":23,"end":124,"loc":{"start":{"line":2,"column":10,"index":23},"end":{"line":8,"column":1,"index":124}}, "body": [ { "type": "ClassMethod", @@ -66,6 +70,10 @@ "type": "Identifier", "start":36,"end":46,"loc":{"start":{"line":3,"column":11,"index":36},"end":{"line":3,"column":21,"index":46},"identifierName":"expression"}, "name": "expression" + }, + "extra": { + "parenthesized": true, + "parenStart": 28 } } } @@ -109,6 +117,10 @@ "type": "Identifier", "start":72,"end":75,"loc":{"start":{"line":5,"column":10,"index":72},"end":{"line":5,"column":13,"index":75},"identifierName":"bar"}, "name": "bar" + }, + "extra": { + "parenthesized": true, + "parenStart": 65 } } } @@ -131,6 +143,63 @@ "body": [], "directives": [] } + }, + { + "type": "ClassMethod", + "start":93,"end":122,"loc":{"start":{"line":7,"column":2,"index":93},"end":{"line":7,"column":31,"index":122}}, + "decorators": [ + { + "type": "Decorator", + "start":93,"end":109,"loc":{"start":{"line":7,"column":2,"index":93},"end":{"line":7,"column":18,"index":109}}, + "expression": { + "type": "CallExpression", + "start":95,"end":109,"loc":{"start":{"line":7,"column":4,"index":95},"end":{"line":7,"column":18,"index":109}}, + "callee": { + "type": "MemberExpression", + "start":95,"end":103,"loc":{"start":{"line":7,"column":4,"index":95},"end":{"line":7,"column":12,"index":103}}, + "object": { + "type": "ThisExpression", + "start":95,"end":99,"loc":{"start":{"line":7,"column":4,"index":95},"end":{"line":7,"column":8,"index":99}} + }, + "computed": false, + "property": { + "type": "Identifier", + "start":100,"end":103,"loc":{"start":{"line":7,"column":9,"index":100},"end":{"line":7,"column":12,"index":103},"identifierName":"foo"}, + "name": "foo" + }, + "extra": { + "parenthesized": true, + "parenStart": 94 + } + }, + "arguments": [ + { + "type": "Identifier", + "start":105,"end":108,"loc":{"start":{"line":7,"column":14,"index":105},"end":{"line":7,"column":17,"index":108},"identifierName":"bar"}, + "name": "bar" + } + ] + } + } + ], + "static": false, + "key": { + "type": "Identifier", + "start":110,"end":117,"loc":{"start":{"line":7,"column":19,"index":110},"end":{"line":7,"column":26,"index":117},"identifierName":"method3"}, + "name": "method3" + }, + "computed": false, + "kind": "method", + "id": null, + "generator": false, + "async": false, + "params": [], + "body": { + "type": "BlockStatement", + "start":120,"end":122,"loc":{"start":{"line":7,"column":29,"index":120},"end":{"line":7,"column":31,"index":122}}, + "body": [], + "directives": [] + } } ] } diff --git a/packages/babel-parser/test/fixtures/experimental/pipeline-operator/hack-double-at-proposal-class-decorator-with-parenthesized-identifier/output.json b/packages/babel-parser/test/fixtures/experimental/pipeline-operator/hack-double-at-proposal-class-decorator-with-parenthesized-identifier/output.json index 9cd91e15c027..54408c3fe6d0 100644 --- a/packages/babel-parser/test/fixtures/experimental/pipeline-operator/hack-double-at-proposal-class-decorator-with-parenthesized-identifier/output.json +++ b/packages/babel-parser/test/fixtures/experimental/pipeline-operator/hack-double-at-proposal-class-decorator-with-parenthesized-identifier/output.json @@ -29,7 +29,11 @@ "expression": { "type": "Identifier", "start":11,"end":14,"loc":{"start":{"line":1,"column":11,"index":11},"end":{"line":1,"column":14,"index":14},"identifierName":"foo"}, - "name": "foo" + "name": "foo", + "extra": { + "parenthesized": true, + "parenStart": 10 + } } } ], diff --git a/packages/babel-parser/test/fixtures/experimental/pipeline-operator/hack-double-at-proposal-class-decorator-with-parenthesized-topic/output.json b/packages/babel-parser/test/fixtures/experimental/pipeline-operator/hack-double-at-proposal-class-decorator-with-parenthesized-topic/output.json index 1f8c51fdcca0..cf4c957c0729 100644 --- a/packages/babel-parser/test/fixtures/experimental/pipeline-operator/hack-double-at-proposal-class-decorator-with-parenthesized-topic/output.json +++ b/packages/babel-parser/test/fixtures/experimental/pipeline-operator/hack-double-at-proposal-class-decorator-with-parenthesized-topic/output.json @@ -28,7 +28,11 @@ "start":9,"end":14,"loc":{"start":{"line":1,"column":9,"index":9},"end":{"line":1,"column":14,"index":14}}, "expression": { "type": "TopicReference", - "start":11,"end":13,"loc":{"start":{"line":1,"column":11,"index":11},"end":{"line":1,"column":13,"index":13}} + "start":11,"end":13,"loc":{"start":{"line":1,"column":11,"index":11},"end":{"line":1,"column":13,"index":13}}, + "extra": { + "parenthesized": true, + "parenStart": 10 + } } } ], diff --git a/packages/babel-parser/test/fixtures/experimental/pipeline-operator/hack-double-caret-proposal-class-decorator-with-parenthesized-identifier/output.json b/packages/babel-parser/test/fixtures/experimental/pipeline-operator/hack-double-caret-proposal-class-decorator-with-parenthesized-identifier/output.json index 9cd91e15c027..54408c3fe6d0 100644 --- a/packages/babel-parser/test/fixtures/experimental/pipeline-operator/hack-double-caret-proposal-class-decorator-with-parenthesized-identifier/output.json +++ b/packages/babel-parser/test/fixtures/experimental/pipeline-operator/hack-double-caret-proposal-class-decorator-with-parenthesized-identifier/output.json @@ -29,7 +29,11 @@ "expression": { "type": "Identifier", "start":11,"end":14,"loc":{"start":{"line":1,"column":11,"index":11},"end":{"line":1,"column":14,"index":14},"identifierName":"foo"}, - "name": "foo" + "name": "foo", + "extra": { + "parenthesized": true, + "parenStart": 10 + } } } ], diff --git a/packages/babel-parser/test/fixtures/experimental/pipeline-operator/hack-double-caret-proposal-class-decorator-with-parenthesized-topic/output.json b/packages/babel-parser/test/fixtures/experimental/pipeline-operator/hack-double-caret-proposal-class-decorator-with-parenthesized-topic/output.json index 1f8c51fdcca0..cf4c957c0729 100644 --- a/packages/babel-parser/test/fixtures/experimental/pipeline-operator/hack-double-caret-proposal-class-decorator-with-parenthesized-topic/output.json +++ b/packages/babel-parser/test/fixtures/experimental/pipeline-operator/hack-double-caret-proposal-class-decorator-with-parenthesized-topic/output.json @@ -28,7 +28,11 @@ "start":9,"end":14,"loc":{"start":{"line":1,"column":9,"index":9},"end":{"line":1,"column":14,"index":14}}, "expression": { "type": "TopicReference", - "start":11,"end":13,"loc":{"start":{"line":1,"column":11,"index":11},"end":{"line":1,"column":13,"index":13}} + "start":11,"end":13,"loc":{"start":{"line":1,"column":11,"index":11},"end":{"line":1,"column":13,"index":13}}, + "extra": { + "parenthesized": true, + "parenStart": 10 + } } } ], diff --git a/packages/babel-parser/test/fixtures/placeholders/class/decorators/output.json b/packages/babel-parser/test/fixtures/placeholders/class/decorators/output.json index 0e81241ff555..ef4404a37fd4 100644 --- a/packages/babel-parser/test/fixtures/placeholders/class/decorators/output.json +++ b/packages/babel-parser/test/fixtures/placeholders/class/decorators/output.json @@ -22,7 +22,11 @@ "start":4,"end":7,"loc":{"start":{"line":1,"column":4,"index":4},"end":{"line":1,"column":7,"index":7},"identifierName":"FOO"}, "name": "FOO" }, - "expectedNode": "Expression" + "expectedNode": "Expression", + "extra": { + "parenthesized": true, + "parenStart": 1 + } } } ],