From 232f242b00e9c69798bcd39e64bc9cbd623f1808 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Mon, 10 Oct 2022 17:45:51 +0200 Subject: [PATCH 01/10] Fix handling of comments with decorators before `export` --- .../comments/decorators-after-export/input.js | 2 + .../decorators-after-export/options.json | 4 + .../decorators-after-export/output.js | 3 + .../decorators-before-export/input.js | 2 + .../decorators-before-export/options.json | 4 + .../decorators-before-export/output.js | 3 + .../decorators-legacy-before-export/input.js | 2 + .../options.json | 4 + .../decorators-legacy-before-export/output.js | 3 + packages/babel-parser/src/parser/statement.ts | 67 ++++++- .../decorators-after-export/input.js | 2 + .../decorators-after-export/options.json | 3 + .../decorators-after-export/output.json | 169 ++++++++++++++++++ .../decorators-before-export/input.js | 2 + .../decorators-before-export/options.json | 3 + .../decorators-before-export/output.json | 169 ++++++++++++++++++ .../decorators-legacy-before-export/input.js | 2 + .../options.json | 3 + .../output.json | 169 ++++++++++++++++++ 19 files changed, 609 insertions(+), 7 deletions(-) create mode 100644 packages/babel-generator/test/fixtures/comments/decorators-after-export/input.js create mode 100644 packages/babel-generator/test/fixtures/comments/decorators-after-export/options.json create mode 100644 packages/babel-generator/test/fixtures/comments/decorators-after-export/output.js create mode 100644 packages/babel-generator/test/fixtures/comments/decorators-before-export/input.js create mode 100644 packages/babel-generator/test/fixtures/comments/decorators-before-export/options.json create mode 100644 packages/babel-generator/test/fixtures/comments/decorators-before-export/output.js create mode 100644 packages/babel-generator/test/fixtures/comments/decorators-legacy-before-export/input.js create mode 100644 packages/babel-generator/test/fixtures/comments/decorators-legacy-before-export/options.json create mode 100644 packages/babel-generator/test/fixtures/comments/decorators-legacy-before-export/output.js create mode 100644 packages/babel-parser/test/fixtures/comments/decorators/decorators-after-export/input.js create mode 100644 packages/babel-parser/test/fixtures/comments/decorators/decorators-after-export/options.json create mode 100644 packages/babel-parser/test/fixtures/comments/decorators/decorators-after-export/output.json create mode 100644 packages/babel-parser/test/fixtures/comments/decorators/decorators-before-export/input.js create mode 100644 packages/babel-parser/test/fixtures/comments/decorators/decorators-before-export/options.json create mode 100644 packages/babel-parser/test/fixtures/comments/decorators/decorators-before-export/output.json create mode 100644 packages/babel-parser/test/fixtures/comments/decorators/decorators-legacy-before-export/input.js create mode 100644 packages/babel-parser/test/fixtures/comments/decorators/decorators-legacy-before-export/options.json create mode 100644 packages/babel-parser/test/fixtures/comments/decorators/decorators-legacy-before-export/output.json diff --git a/packages/babel-generator/test/fixtures/comments/decorators-after-export/input.js b/packages/babel-generator/test/fixtures/comments/decorators-after-export/input.js new file mode 100644 index 000000000000..9da3127c870d --- /dev/null +++ b/packages/babel-generator/test/fixtures/comments/decorators-after-export/input.js @@ -0,0 +1,2 @@ +/* 1 */ export /* 2 */ @dec1 /* 3 */ @dec2 +/* 4 */ class /* 5 */ C /* 6 */ { /* 7 */ } /* 8 */ diff --git a/packages/babel-generator/test/fixtures/comments/decorators-after-export/options.json b/packages/babel-generator/test/fixtures/comments/decorators-after-export/options.json new file mode 100644 index 000000000000..7ebfdd91777b --- /dev/null +++ b/packages/babel-generator/test/fixtures/comments/decorators-after-export/options.json @@ -0,0 +1,4 @@ +{ + "plugins": [["decorators", { "decoratorsBeforeExport": false }]], + "decoratorsBeforeExport": false +} diff --git a/packages/babel-generator/test/fixtures/comments/decorators-after-export/output.js b/packages/babel-generator/test/fixtures/comments/decorators-after-export/output.js new file mode 100644 index 000000000000..07c8cfe55a40 --- /dev/null +++ b/packages/babel-generator/test/fixtures/comments/decorators-after-export/output.js @@ -0,0 +1,3 @@ +/* 1 */export /* 2 */@dec1 +/* 3 */@dec2 +/* 4 */class /* 5 */C /* 6 */ {/* 7 */} /* 8 */ \ No newline at end of file diff --git a/packages/babel-generator/test/fixtures/comments/decorators-before-export/input.js b/packages/babel-generator/test/fixtures/comments/decorators-before-export/input.js new file mode 100644 index 000000000000..1f74bcfc3941 --- /dev/null +++ b/packages/babel-generator/test/fixtures/comments/decorators-before-export/input.js @@ -0,0 +1,2 @@ +/* 1 */ @dec1 /* 2 */ @dec2 /* 3 */ +export /* 4 */ class /* 5 */ C /* 6 */ { /* 7 */ } /* 8 */ diff --git a/packages/babel-generator/test/fixtures/comments/decorators-before-export/options.json b/packages/babel-generator/test/fixtures/comments/decorators-before-export/options.json new file mode 100644 index 000000000000..788cc225058a --- /dev/null +++ b/packages/babel-generator/test/fixtures/comments/decorators-before-export/options.json @@ -0,0 +1,4 @@ +{ + "plugins": [["decorators", { "decoratorsBeforeExport": true }]], + "decoratorsBeforeExport": true +} diff --git a/packages/babel-generator/test/fixtures/comments/decorators-before-export/output.js b/packages/babel-generator/test/fixtures/comments/decorators-before-export/output.js new file mode 100644 index 000000000000..9443cc496b8d --- /dev/null +++ b/packages/babel-generator/test/fixtures/comments/decorators-before-export/output.js @@ -0,0 +1,3 @@ +/* 1 */@dec1 +/* 2 */@dec2 +/* 3 */export /* 4 */class /* 5 */C /* 6 */ {/* 7 */} /* 8 */ \ No newline at end of file diff --git a/packages/babel-generator/test/fixtures/comments/decorators-legacy-before-export/input.js b/packages/babel-generator/test/fixtures/comments/decorators-legacy-before-export/input.js new file mode 100644 index 000000000000..1f74bcfc3941 --- /dev/null +++ b/packages/babel-generator/test/fixtures/comments/decorators-legacy-before-export/input.js @@ -0,0 +1,2 @@ +/* 1 */ @dec1 /* 2 */ @dec2 /* 3 */ +export /* 4 */ class /* 5 */ C /* 6 */ { /* 7 */ } /* 8 */ diff --git a/packages/babel-generator/test/fixtures/comments/decorators-legacy-before-export/options.json b/packages/babel-generator/test/fixtures/comments/decorators-legacy-before-export/options.json new file mode 100644 index 000000000000..01109f3ab2f7 --- /dev/null +++ b/packages/babel-generator/test/fixtures/comments/decorators-legacy-before-export/options.json @@ -0,0 +1,4 @@ +{ + "plugins": ["decorators-legacy"], + "decoratorsBeforeExport": true +} diff --git a/packages/babel-generator/test/fixtures/comments/decorators-legacy-before-export/output.js b/packages/babel-generator/test/fixtures/comments/decorators-legacy-before-export/output.js new file mode 100644 index 000000000000..9443cc496b8d --- /dev/null +++ b/packages/babel-generator/test/fixtures/comments/decorators-legacy-before-export/output.js @@ -0,0 +1,3 @@ +/* 1 */@dec1 +/* 2 */@dec2 +/* 3 */export /* 4 */class /* 5 */C /* 6 */ {/* 7 */} /* 8 */ \ No newline at end of file diff --git a/packages/babel-parser/src/parser/statement.ts b/packages/babel-parser/src/parser/statement.ts index 56481df9aae0..991532e7316b 100644 --- a/packages/babel-parser/src/parser/statement.ts +++ b/packages/babel-parser/src/parser/statement.ts @@ -531,6 +531,14 @@ export default abstract class StatementParser extends ExpressionParser { } } + decoratorsEnabledBeforeExport(): boolean { + if (this.hasPlugin("decorators-legacy")) return true; + return ( + this.hasPlugin("decorators") && + !!this.getPluginOption("decorators", "decoratorsBeforeExport") + ); + } + takeDecorators(node: N.HasDecorators): void { const decorators = this.state.decoratorStack[this.state.decoratorStack.length - 1]; @@ -538,6 +546,34 @@ export default abstract class StatementParser extends ExpressionParser { node.decorators = decorators; this.resetStartLocationFromNode(node, decorators[0]); this.state.decoratorStack[this.state.decoratorStack.length - 1] = []; + + // In case of decorators followed by `export`, we manually mark the + // comments between `export` and `class` as leading comments of the + // class declaration node. + // This is needed because the class location range overlaps with + // `export`, and thus they would me marked as inner comments of + // the class declaration. + // @dec export /* comment */ class Foo {} + // See [parseDecorators] for the hanling of comments before decorators + if (this.decoratorsEnabledBeforeExport()) { + const { + start, + lastTokStart, + lastTokEndLoc: { index: lastTokEnd }, + } = this.state; + + if (this.input.slice(lastTokStart, lastTokEnd) === "export") { + const { commentStack } = this.state; + for (let i = commentStack.length - 1; i >= 0; i--) { + const commentWS = commentStack[i]; + if (commentWS.start >= lastTokEnd && commentWS.end <= start) { + commentWS.trailingNode = node as N.Node; + } else if (commentWS.end < lastTokEnd) { + break; + } + } + } + } } } @@ -546,8 +582,9 @@ export default abstract class StatementParser extends ExpressionParser { } parseDecorators(this: Parser, allowExport?: boolean): void { - const currentContextDecorators = - this.state.decoratorStack[this.state.decoratorStack.length - 1]; + const { decoratorStack } = this.state; + const currentContextDecorators = decoratorStack[decoratorStack.length - 1]; + while (this.match(tt.at)) { const decorator = this.parseDecorator(); currentContextDecorators.push(decorator); @@ -558,12 +595,27 @@ export default abstract class StatementParser extends ExpressionParser { this.unexpected(); } - if ( - this.hasPlugin("decorators") && - !this.getPluginOption("decorators", "decoratorsBeforeExport") - ) { + if (!this.decoratorsEnabledBeforeExport()) { this.raise(Errors.DecoratorExportClass, { at: this.state.startLoc }); } + + // In case of comments followed by a decorator followed by `export`, + // we manually attach them to the decorator node rather than to the + // class declaration node. This is because the class location range + // overlaps with `export`, and this causes confusing comments behavior: + // /* comment */ @dec export class Foo {} + // See [takeDecorators] for the hanling of comments after `export` + const firstDecorator = decoratorStack[decoratorStack.length - 1][0]; + const { commentStack } = this.state; + for (let i = commentStack.length - 1; i >= 0; i--) { + const commentWS = commentStack[i]; + if (commentWS.trailingNode === firstDecorator) { + this.finalizeComment(commentWS); + commentStack.splice(i, 1); + } else if (commentWS.end < firstDecorator.start) { + break; + } + } } else if (!this.canHaveLeadingDecorator()) { throw this.raise(Errors.UnexpectedLeadingDecorator, { at: this.state.startLoc, @@ -1480,9 +1532,10 @@ export default abstract class StatementParser extends ExpressionParser { isStatement: /* T === ClassDeclaration */ boolean, optionalId?: boolean, ): T { - this.next(); this.takeDecorators(node); + this.next(); // 'class' + // A class definition is always strict mode code. const oldStrict = this.state.strict; this.state.strict = true; diff --git a/packages/babel-parser/test/fixtures/comments/decorators/decorators-after-export/input.js b/packages/babel-parser/test/fixtures/comments/decorators/decorators-after-export/input.js new file mode 100644 index 000000000000..9da3127c870d --- /dev/null +++ b/packages/babel-parser/test/fixtures/comments/decorators/decorators-after-export/input.js @@ -0,0 +1,2 @@ +/* 1 */ export /* 2 */ @dec1 /* 3 */ @dec2 +/* 4 */ class /* 5 */ C /* 6 */ { /* 7 */ } /* 8 */ diff --git a/packages/babel-parser/test/fixtures/comments/decorators/decorators-after-export/options.json b/packages/babel-parser/test/fixtures/comments/decorators/decorators-after-export/options.json new file mode 100644 index 000000000000..6c9cc72327dc --- /dev/null +++ b/packages/babel-parser/test/fixtures/comments/decorators/decorators-after-export/options.json @@ -0,0 +1,3 @@ +{ + "plugins": [["decorators", { "decoratorsBeforeExport": false }]] +} diff --git a/packages/babel-parser/test/fixtures/comments/decorators/decorators-after-export/output.json b/packages/babel-parser/test/fixtures/comments/decorators/decorators-after-export/output.json new file mode 100644 index 000000000000..ed59d3127ecb --- /dev/null +++ b/packages/babel-parser/test/fixtures/comments/decorators/decorators-after-export/output.json @@ -0,0 +1,169 @@ +{ + "type": "File", + "start":0,"end":94,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":2,"column":51,"index":94}}, + "errors": [ + "SyntaxError: 'import' and 'export' may appear only with 'sourceType: \"module\"' (1:8)" + ], + "program": { + "type": "Program", + "start":0,"end":94,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":2,"column":51,"index":94}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ExportNamedDeclaration", + "start":8,"end":86,"loc":{"start":{"line":1,"column":8,"index":8},"end":{"line":2,"column":43,"index":86}}, + "specifiers": [], + "source": null, + "declaration": { + "type": "ClassDeclaration", + "start":23,"end":86,"loc":{"start":{"line":1,"column":23,"index":23},"end":{"line":2,"column":43,"index":86}}, + "decorators": [ + { + "type": "Decorator", + "start":23,"end":28,"loc":{"start":{"line":1,"column":23,"index":23},"end":{"line":1,"column":28,"index":28}}, + "expression": { + "type": "Identifier", + "start":24,"end":28,"loc":{"start":{"line":1,"column":24,"index":24},"end":{"line":1,"column":28,"index":28},"identifierName":"dec1"}, + "name": "dec1" + }, + "trailingComments": [ + { + "type": "CommentBlock", + "value": " 3 ", + "start":29,"end":36,"loc":{"start":{"line":1,"column":29,"index":29},"end":{"line":1,"column":36,"index":36}} + } + ] + }, + { + "type": "Decorator", + "start":37,"end":42,"loc":{"start":{"line":1,"column":37,"index":37},"end":{"line":1,"column":42,"index":42}}, + "expression": { + "type": "Identifier", + "start":38,"end":42,"loc":{"start":{"line":1,"column":38,"index":38},"end":{"line":1,"column":42,"index":42},"identifierName":"dec2"}, + "name": "dec2" + }, + "trailingComments": [ + { + "type": "CommentBlock", + "value": " 4 ", + "start":43,"end":50,"loc":{"start":{"line":2,"column":0,"index":43},"end":{"line":2,"column":7,"index":50}} + } + ], + "leadingComments": [ + { + "type": "CommentBlock", + "value": " 3 ", + "start":29,"end":36,"loc":{"start":{"line":1,"column":29,"index":29},"end":{"line":1,"column":36,"index":36}} + } + ] + } + ], + "id": { + "type": "Identifier", + "start":65,"end":66,"loc":{"start":{"line":2,"column":22,"index":65},"end":{"line":2,"column":23,"index":66},"identifierName":"C"}, + "name": "C", + "trailingComments": [ + { + "type": "CommentBlock", + "value": " 6 ", + "start":67,"end":74,"loc":{"start":{"line":2,"column":24,"index":67},"end":{"line":2,"column":31,"index":74}} + } + ], + "leadingComments": [ + { + "type": "CommentBlock", + "value": " 5 ", + "start":57,"end":64,"loc":{"start":{"line":2,"column":14,"index":57},"end":{"line":2,"column":21,"index":64}} + } + ] + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start":75,"end":86,"loc":{"start":{"line":2,"column":32,"index":75},"end":{"line":2,"column":43,"index":86}}, + "body": [], + "innerComments": [ + { + "type": "CommentBlock", + "value": " 7 ", + "start":77,"end":84,"loc":{"start":{"line":2,"column":34,"index":77},"end":{"line":2,"column":41,"index":84}} + } + ], + "leadingComments": [ + { + "type": "CommentBlock", + "value": " 6 ", + "start":67,"end":74,"loc":{"start":{"line":2,"column":24,"index":67},"end":{"line":2,"column":31,"index":74}} + } + ] + }, + "leadingComments": [ + { + "type": "CommentBlock", + "value": " 2 ", + "start":15,"end":22,"loc":{"start":{"line":1,"column":15,"index":15},"end":{"line":1,"column":22,"index":22}} + } + ] + }, + "trailingComments": [ + { + "type": "CommentBlock", + "value": " 8 ", + "start":87,"end":94,"loc":{"start":{"line":2,"column":44,"index":87},"end":{"line":2,"column":51,"index":94}} + } + ], + "leadingComments": [ + { + "type": "CommentBlock", + "value": " 1 ", + "start":0,"end":7,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":7,"index":7}} + } + ] + } + ], + "directives": [] + }, + "comments": [ + { + "type": "CommentBlock", + "value": " 1 ", + "start":0,"end":7,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":7,"index":7}} + }, + { + "type": "CommentBlock", + "value": " 2 ", + "start":15,"end":22,"loc":{"start":{"line":1,"column":15,"index":15},"end":{"line":1,"column":22,"index":22}} + }, + { + "type": "CommentBlock", + "value": " 3 ", + "start":29,"end":36,"loc":{"start":{"line":1,"column":29,"index":29},"end":{"line":1,"column":36,"index":36}} + }, + { + "type": "CommentBlock", + "value": " 4 ", + "start":43,"end":50,"loc":{"start":{"line":2,"column":0,"index":43},"end":{"line":2,"column":7,"index":50}} + }, + { + "type": "CommentBlock", + "value": " 5 ", + "start":57,"end":64,"loc":{"start":{"line":2,"column":14,"index":57},"end":{"line":2,"column":21,"index":64}} + }, + { + "type": "CommentBlock", + "value": " 6 ", + "start":67,"end":74,"loc":{"start":{"line":2,"column":24,"index":67},"end":{"line":2,"column":31,"index":74}} + }, + { + "type": "CommentBlock", + "value": " 7 ", + "start":77,"end":84,"loc":{"start":{"line":2,"column":34,"index":77},"end":{"line":2,"column":41,"index":84}} + }, + { + "type": "CommentBlock", + "value": " 8 ", + "start":87,"end":94,"loc":{"start":{"line":2,"column":44,"index":87},"end":{"line":2,"column":51,"index":94}} + } + ] +} diff --git a/packages/babel-parser/test/fixtures/comments/decorators/decorators-before-export/input.js b/packages/babel-parser/test/fixtures/comments/decorators/decorators-before-export/input.js new file mode 100644 index 000000000000..1f74bcfc3941 --- /dev/null +++ b/packages/babel-parser/test/fixtures/comments/decorators/decorators-before-export/input.js @@ -0,0 +1,2 @@ +/* 1 */ @dec1 /* 2 */ @dec2 /* 3 */ +export /* 4 */ class /* 5 */ C /* 6 */ { /* 7 */ } /* 8 */ diff --git a/packages/babel-parser/test/fixtures/comments/decorators/decorators-before-export/options.json b/packages/babel-parser/test/fixtures/comments/decorators/decorators-before-export/options.json new file mode 100644 index 000000000000..fe752ff5f509 --- /dev/null +++ b/packages/babel-parser/test/fixtures/comments/decorators/decorators-before-export/options.json @@ -0,0 +1,3 @@ +{ + "plugins": [["decorators", { "decoratorsBeforeExport": true }]] +} diff --git a/packages/babel-parser/test/fixtures/comments/decorators/decorators-before-export/output.json b/packages/babel-parser/test/fixtures/comments/decorators/decorators-before-export/output.json new file mode 100644 index 000000000000..ac4698f5c4d8 --- /dev/null +++ b/packages/babel-parser/test/fixtures/comments/decorators/decorators-before-export/output.json @@ -0,0 +1,169 @@ +{ + "type": "File", + "start":0,"end":94,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":2,"column":58,"index":94}}, + "errors": [ + "SyntaxError: 'import' and 'export' may appear only with 'sourceType: \"module\"' (2:0)" + ], + "program": { + "type": "Program", + "start":0,"end":94,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":2,"column":58,"index":94}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ExportNamedDeclaration", + "start":36,"end":86,"loc":{"start":{"line":2,"column":0,"index":36},"end":{"line":2,"column":50,"index":86}}, + "specifiers": [], + "source": null, + "declaration": { + "type": "ClassDeclaration", + "start":8,"end":86,"loc":{"start":{"line":1,"column":8,"index":8},"end":{"line":2,"column":50,"index":86}}, + "decorators": [ + { + "type": "Decorator", + "start":8,"end":13,"loc":{"start":{"line":1,"column":8,"index":8},"end":{"line":1,"column":13,"index":13}}, + "expression": { + "type": "Identifier", + "start":9,"end":13,"loc":{"start":{"line":1,"column":9,"index":9},"end":{"line":1,"column":13,"index":13},"identifierName":"dec1"}, + "name": "dec1" + }, + "leadingComments": [ + { + "type": "CommentBlock", + "value": " 1 ", + "start":0,"end":7,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":7,"index":7}} + } + ], + "trailingComments": [ + { + "type": "CommentBlock", + "value": " 2 ", + "start":14,"end":21,"loc":{"start":{"line":1,"column":14,"index":14},"end":{"line":1,"column":21,"index":21}} + } + ] + }, + { + "type": "Decorator", + "start":22,"end":27,"loc":{"start":{"line":1,"column":22,"index":22},"end":{"line":1,"column":27,"index":27}}, + "expression": { + "type": "Identifier", + "start":23,"end":27,"loc":{"start":{"line":1,"column":23,"index":23},"end":{"line":1,"column":27,"index":27},"identifierName":"dec2"}, + "name": "dec2" + }, + "trailingComments": [ + { + "type": "CommentBlock", + "value": " 3 ", + "start":28,"end":35,"loc":{"start":{"line":1,"column":28,"index":28},"end":{"line":1,"column":35,"index":35}} + } + ], + "leadingComments": [ + { + "type": "CommentBlock", + "value": " 2 ", + "start":14,"end":21,"loc":{"start":{"line":1,"column":14,"index":14},"end":{"line":1,"column":21,"index":21}} + } + ] + } + ], + "id": { + "type": "Identifier", + "start":65,"end":66,"loc":{"start":{"line":2,"column":29,"index":65},"end":{"line":2,"column":30,"index":66},"identifierName":"C"}, + "name": "C", + "trailingComments": [ + { + "type": "CommentBlock", + "value": " 6 ", + "start":67,"end":74,"loc":{"start":{"line":2,"column":31,"index":67},"end":{"line":2,"column":38,"index":74}} + } + ], + "leadingComments": [ + { + "type": "CommentBlock", + "value": " 5 ", + "start":57,"end":64,"loc":{"start":{"line":2,"column":21,"index":57},"end":{"line":2,"column":28,"index":64}} + } + ] + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start":75,"end":86,"loc":{"start":{"line":2,"column":39,"index":75},"end":{"line":2,"column":50,"index":86}}, + "body": [], + "innerComments": [ + { + "type": "CommentBlock", + "value": " 7 ", + "start":77,"end":84,"loc":{"start":{"line":2,"column":41,"index":77},"end":{"line":2,"column":48,"index":84}} + } + ], + "leadingComments": [ + { + "type": "CommentBlock", + "value": " 6 ", + "start":67,"end":74,"loc":{"start":{"line":2,"column":31,"index":67},"end":{"line":2,"column":38,"index":74}} + } + ] + }, + "leadingComments": [ + { + "type": "CommentBlock", + "value": " 4 ", + "start":43,"end":50,"loc":{"start":{"line":2,"column":7,"index":43},"end":{"line":2,"column":14,"index":50}} + } + ] + }, + "trailingComments": [ + { + "type": "CommentBlock", + "value": " 8 ", + "start":87,"end":94,"loc":{"start":{"line":2,"column":51,"index":87},"end":{"line":2,"column":58,"index":94}} + } + ] + } + ], + "directives": [] + }, + "comments": [ + { + "type": "CommentBlock", + "value": " 1 ", + "start":0,"end":7,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":7,"index":7}} + }, + { + "type": "CommentBlock", + "value": " 2 ", + "start":14,"end":21,"loc":{"start":{"line":1,"column":14,"index":14},"end":{"line":1,"column":21,"index":21}} + }, + { + "type": "CommentBlock", + "value": " 3 ", + "start":28,"end":35,"loc":{"start":{"line":1,"column":28,"index":28},"end":{"line":1,"column":35,"index":35}} + }, + { + "type": "CommentBlock", + "value": " 4 ", + "start":43,"end":50,"loc":{"start":{"line":2,"column":7,"index":43},"end":{"line":2,"column":14,"index":50}} + }, + { + "type": "CommentBlock", + "value": " 5 ", + "start":57,"end":64,"loc":{"start":{"line":2,"column":21,"index":57},"end":{"line":2,"column":28,"index":64}} + }, + { + "type": "CommentBlock", + "value": " 6 ", + "start":67,"end":74,"loc":{"start":{"line":2,"column":31,"index":67},"end":{"line":2,"column":38,"index":74}} + }, + { + "type": "CommentBlock", + "value": " 7 ", + "start":77,"end":84,"loc":{"start":{"line":2,"column":41,"index":77},"end":{"line":2,"column":48,"index":84}} + }, + { + "type": "CommentBlock", + "value": " 8 ", + "start":87,"end":94,"loc":{"start":{"line":2,"column":51,"index":87},"end":{"line":2,"column":58,"index":94}} + } + ] +} diff --git a/packages/babel-parser/test/fixtures/comments/decorators/decorators-legacy-before-export/input.js b/packages/babel-parser/test/fixtures/comments/decorators/decorators-legacy-before-export/input.js new file mode 100644 index 000000000000..1f74bcfc3941 --- /dev/null +++ b/packages/babel-parser/test/fixtures/comments/decorators/decorators-legacy-before-export/input.js @@ -0,0 +1,2 @@ +/* 1 */ @dec1 /* 2 */ @dec2 /* 3 */ +export /* 4 */ class /* 5 */ C /* 6 */ { /* 7 */ } /* 8 */ diff --git a/packages/babel-parser/test/fixtures/comments/decorators/decorators-legacy-before-export/options.json b/packages/babel-parser/test/fixtures/comments/decorators/decorators-legacy-before-export/options.json new file mode 100644 index 000000000000..a6855c41cfad --- /dev/null +++ b/packages/babel-parser/test/fixtures/comments/decorators/decorators-legacy-before-export/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["decorators-legacy"] +} diff --git a/packages/babel-parser/test/fixtures/comments/decorators/decorators-legacy-before-export/output.json b/packages/babel-parser/test/fixtures/comments/decorators/decorators-legacy-before-export/output.json new file mode 100644 index 000000000000..ac4698f5c4d8 --- /dev/null +++ b/packages/babel-parser/test/fixtures/comments/decorators/decorators-legacy-before-export/output.json @@ -0,0 +1,169 @@ +{ + "type": "File", + "start":0,"end":94,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":2,"column":58,"index":94}}, + "errors": [ + "SyntaxError: 'import' and 'export' may appear only with 'sourceType: \"module\"' (2:0)" + ], + "program": { + "type": "Program", + "start":0,"end":94,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":2,"column":58,"index":94}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ExportNamedDeclaration", + "start":36,"end":86,"loc":{"start":{"line":2,"column":0,"index":36},"end":{"line":2,"column":50,"index":86}}, + "specifiers": [], + "source": null, + "declaration": { + "type": "ClassDeclaration", + "start":8,"end":86,"loc":{"start":{"line":1,"column":8,"index":8},"end":{"line":2,"column":50,"index":86}}, + "decorators": [ + { + "type": "Decorator", + "start":8,"end":13,"loc":{"start":{"line":1,"column":8,"index":8},"end":{"line":1,"column":13,"index":13}}, + "expression": { + "type": "Identifier", + "start":9,"end":13,"loc":{"start":{"line":1,"column":9,"index":9},"end":{"line":1,"column":13,"index":13},"identifierName":"dec1"}, + "name": "dec1" + }, + "leadingComments": [ + { + "type": "CommentBlock", + "value": " 1 ", + "start":0,"end":7,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":7,"index":7}} + } + ], + "trailingComments": [ + { + "type": "CommentBlock", + "value": " 2 ", + "start":14,"end":21,"loc":{"start":{"line":1,"column":14,"index":14},"end":{"line":1,"column":21,"index":21}} + } + ] + }, + { + "type": "Decorator", + "start":22,"end":27,"loc":{"start":{"line":1,"column":22,"index":22},"end":{"line":1,"column":27,"index":27}}, + "expression": { + "type": "Identifier", + "start":23,"end":27,"loc":{"start":{"line":1,"column":23,"index":23},"end":{"line":1,"column":27,"index":27},"identifierName":"dec2"}, + "name": "dec2" + }, + "trailingComments": [ + { + "type": "CommentBlock", + "value": " 3 ", + "start":28,"end":35,"loc":{"start":{"line":1,"column":28,"index":28},"end":{"line":1,"column":35,"index":35}} + } + ], + "leadingComments": [ + { + "type": "CommentBlock", + "value": " 2 ", + "start":14,"end":21,"loc":{"start":{"line":1,"column":14,"index":14},"end":{"line":1,"column":21,"index":21}} + } + ] + } + ], + "id": { + "type": "Identifier", + "start":65,"end":66,"loc":{"start":{"line":2,"column":29,"index":65},"end":{"line":2,"column":30,"index":66},"identifierName":"C"}, + "name": "C", + "trailingComments": [ + { + "type": "CommentBlock", + "value": " 6 ", + "start":67,"end":74,"loc":{"start":{"line":2,"column":31,"index":67},"end":{"line":2,"column":38,"index":74}} + } + ], + "leadingComments": [ + { + "type": "CommentBlock", + "value": " 5 ", + "start":57,"end":64,"loc":{"start":{"line":2,"column":21,"index":57},"end":{"line":2,"column":28,"index":64}} + } + ] + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start":75,"end":86,"loc":{"start":{"line":2,"column":39,"index":75},"end":{"line":2,"column":50,"index":86}}, + "body": [], + "innerComments": [ + { + "type": "CommentBlock", + "value": " 7 ", + "start":77,"end":84,"loc":{"start":{"line":2,"column":41,"index":77},"end":{"line":2,"column":48,"index":84}} + } + ], + "leadingComments": [ + { + "type": "CommentBlock", + "value": " 6 ", + "start":67,"end":74,"loc":{"start":{"line":2,"column":31,"index":67},"end":{"line":2,"column":38,"index":74}} + } + ] + }, + "leadingComments": [ + { + "type": "CommentBlock", + "value": " 4 ", + "start":43,"end":50,"loc":{"start":{"line":2,"column":7,"index":43},"end":{"line":2,"column":14,"index":50}} + } + ] + }, + "trailingComments": [ + { + "type": "CommentBlock", + "value": " 8 ", + "start":87,"end":94,"loc":{"start":{"line":2,"column":51,"index":87},"end":{"line":2,"column":58,"index":94}} + } + ] + } + ], + "directives": [] + }, + "comments": [ + { + "type": "CommentBlock", + "value": " 1 ", + "start":0,"end":7,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":7,"index":7}} + }, + { + "type": "CommentBlock", + "value": " 2 ", + "start":14,"end":21,"loc":{"start":{"line":1,"column":14,"index":14},"end":{"line":1,"column":21,"index":21}} + }, + { + "type": "CommentBlock", + "value": " 3 ", + "start":28,"end":35,"loc":{"start":{"line":1,"column":28,"index":28},"end":{"line":1,"column":35,"index":35}} + }, + { + "type": "CommentBlock", + "value": " 4 ", + "start":43,"end":50,"loc":{"start":{"line":2,"column":7,"index":43},"end":{"line":2,"column":14,"index":50}} + }, + { + "type": "CommentBlock", + "value": " 5 ", + "start":57,"end":64,"loc":{"start":{"line":2,"column":21,"index":57},"end":{"line":2,"column":28,"index":64}} + }, + { + "type": "CommentBlock", + "value": " 6 ", + "start":67,"end":74,"loc":{"start":{"line":2,"column":31,"index":67},"end":{"line":2,"column":38,"index":74}} + }, + { + "type": "CommentBlock", + "value": " 7 ", + "start":77,"end":84,"loc":{"start":{"line":2,"column":41,"index":77},"end":{"line":2,"column":48,"index":84}} + }, + { + "type": "CommentBlock", + "value": " 8 ", + "start":87,"end":94,"loc":{"start":{"line":2,"column":51,"index":87},"end":{"line":2,"column":58,"index":94}} + } + ] +} From aece54839975b39c757e06be5aeb23c032ff1a89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Wed, 12 Oct 2022 22:07:13 +0200 Subject: [PATCH 02/10] decoratorsBeforeExport removed in babel 8 --- .../test/fixtures/comments/decorators-before-export/options.json | 1 + .../comments/decorators-legacy-before-export/options.json | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/babel-generator/test/fixtures/comments/decorators-before-export/options.json b/packages/babel-generator/test/fixtures/comments/decorators-before-export/options.json index 788cc225058a..f82968d9ccb5 100644 --- a/packages/babel-generator/test/fixtures/comments/decorators-before-export/options.json +++ b/packages/babel-generator/test/fixtures/comments/decorators-before-export/options.json @@ -1,4 +1,5 @@ { + "BABEL_8_BREAKING": false, "plugins": [["decorators", { "decoratorsBeforeExport": true }]], "decoratorsBeforeExport": true } diff --git a/packages/babel-generator/test/fixtures/comments/decorators-legacy-before-export/options.json b/packages/babel-generator/test/fixtures/comments/decorators-legacy-before-export/options.json index 01109f3ab2f7..eb02a2a23e19 100644 --- a/packages/babel-generator/test/fixtures/comments/decorators-legacy-before-export/options.json +++ b/packages/babel-generator/test/fixtures/comments/decorators-legacy-before-export/options.json @@ -1,4 +1,5 @@ { + "BABEL_8_BREAKING": false, "plugins": ["decorators-legacy"], "decoratorsBeforeExport": true } From 7094d0d12f08897228d49bb32d5923a30f10b16e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Tue, 25 Oct 2022 00:16:40 +0200 Subject: [PATCH 03/10] Move to comments.ts --- packages/babel-parser/src/parser/comments.ts | 61 +++++++++++++++++++ packages/babel-parser/src/parser/statement.ts | 51 +++------------- 2 files changed, 70 insertions(+), 42 deletions(-) diff --git a/packages/babel-parser/src/parser/comments.ts b/packages/babel-parser/src/parser/comments.ts index 04e7261c8961..be8a2e248db8 100644 --- a/packages/babel-parser/src/parser/comments.ts +++ b/packages/babel-parser/src/parser/comments.ts @@ -289,4 +289,65 @@ export default class CommentsParser extends BaseParser { } } } + + /* + * Used to finalize the leading comments of a node, even if they could + * be attached as leading comments to a parent node. + * + * In case of comments followed by a decorator followed by `export`, + * we manually attach them to the decorator node rather than to the + * class declaration node. This is because the class location range + * overlaps with `export`, and this causes confusing comments behavior: + * + */ // /* comment */ @dec export class Foo {} + /* + * See [takeLeadingCommentsAfterLastToken] for the hanling of comments + * after `export`. + */ + forceFinalizeLeadingComments(node: Node): void { + const { commentStack } = this.state; + for (let i = commentStack.length - 1; i >= 0; i--) { + const commentWS = commentStack[i]; + if (commentWS.trailingNode === node) { + this.finalizeComment(commentWS); + commentStack.splice(i, 1); + } else if (commentWS.end < node.start) { + break; + } + } + } + + /* + * Used to take the comments after the last token as leading + * comments of the given node, even if their start position + * is after the start position of the node. + * + * In case of decorators followed by `export`, we manually mark the + * comments between `export` and `class` as leading comments of the + * class declaration node. + * This is needed because the class location range overlaps with + * `export`, and thus they would be marked as inner comments of + * the class declaration: + * + */ // @dec export /* comment */ class Foo {} + /* + * See [forceFinalizeLeadingComments] for the handling of comments + * before decorators. + */ + takeLeadingCommentsAfterLastToken(node: Undone): void { + const { + start, + lastTokEndLoc: { index: lastTokEnd }, + } = this.state; + + const { commentStack } = this.state; + for (let i = commentStack.length - 1; i >= 0; i--) { + const commentWS = commentStack[i]; + if (commentWS.start >= lastTokEnd && commentWS.end <= start) { + commentWS.trailingNode = node as Node; + } else if (commentWS.end < lastTokEnd) { + break; + } + } + } } diff --git a/packages/babel-parser/src/parser/statement.ts b/packages/babel-parser/src/parser/statement.ts index 991532e7316b..1fbdfbdb8447 100644 --- a/packages/babel-parser/src/parser/statement.ts +++ b/packages/babel-parser/src/parser/statement.ts @@ -547,32 +547,14 @@ export default abstract class StatementParser extends ExpressionParser { this.resetStartLocationFromNode(node, decorators[0]); this.state.decoratorStack[this.state.decoratorStack.length - 1] = []; - // In case of decorators followed by `export`, we manually mark the - // comments between `export` and `class` as leading comments of the - // class declaration node. - // This is needed because the class location range overlaps with - // `export`, and thus they would me marked as inner comments of - // the class declaration. - // @dec export /* comment */ class Foo {} - // See [parseDecorators] for the hanling of comments before decorators - if (this.decoratorsEnabledBeforeExport()) { - const { - start, - lastTokStart, - lastTokEndLoc: { index: lastTokEnd }, - } = this.state; - - if (this.input.slice(lastTokStart, lastTokEnd) === "export") { - const { commentStack } = this.state; - for (let i = commentStack.length - 1; i >= 0; i--) { - const commentWS = commentStack[i]; - if (commentWS.start >= lastTokEnd && commentWS.end <= start) { - commentWS.trailingNode = node as N.Node; - } else if (commentWS.end < lastTokEnd) { - break; - } - } - } + if ( + this.decoratorsEnabledBeforeExport() && + this.input.slice( + this.state.lastTokStart, + this.state.lastTokEndLoc.index, + ) === "export" + ) { + this.takeLeadingCommentsAfterLastToken(node); } } } @@ -599,23 +581,8 @@ export default abstract class StatementParser extends ExpressionParser { this.raise(Errors.DecoratorExportClass, { at: this.state.startLoc }); } - // In case of comments followed by a decorator followed by `export`, - // we manually attach them to the decorator node rather than to the - // class declaration node. This is because the class location range - // overlaps with `export`, and this causes confusing comments behavior: - // /* comment */ @dec export class Foo {} - // See [takeDecorators] for the hanling of comments after `export` const firstDecorator = decoratorStack[decoratorStack.length - 1][0]; - const { commentStack } = this.state; - for (let i = commentStack.length - 1; i >= 0; i--) { - const commentWS = commentStack[i]; - if (commentWS.trailingNode === firstDecorator) { - this.finalizeComment(commentWS); - commentStack.splice(i, 1); - } else if (commentWS.end < firstDecorator.start) { - break; - } - } + this.forceFinalizeLeadingComments(firstDecorator); } else if (!this.canHaveLeadingDecorator()) { throw this.raise(Errors.UnexpectedLeadingDecorator, { at: this.state.startLoc, From 599fa754fcc8f5de379b22ea3c007c105fdf77d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Tue, 25 Oct 2022 15:01:33 +0200 Subject: [PATCH 04/10] Refactor decorators parsing, attach decorators after comments --- packages/babel-parser/src/parser/comments.ts | 61 ----- .../babel-parser/src/parser/expression.ts | 11 +- packages/babel-parser/src/parser/statement.ts | 130 ++++++---- packages/babel-parser/src/plugins/estree.ts | 7 +- .../babel-parser/src/plugins/flow/index.ts | 7 +- .../babel-parser/src/plugins/placeholders.ts | 7 +- .../src/plugins/typescript/index.ts | 39 ++- packages/babel-parser/src/tokenizer/state.ts | 5 - .../decorators-after-export/input.js | 3 + .../decorators-after-export/options.json | 1 + .../decorators-after-export/output.json | 229 ++++++++++++++--- .../decorators-before-export/input.js | 3 + .../decorators-before-export/options.json | 1 + .../decorators-before-export/output.json | 239 +++++++++++++++--- .../decorators-legacy-before-export/input.js | 3 + .../options.json | 1 + .../output.json | 239 +++++++++++++++--- 17 files changed, 727 insertions(+), 259 deletions(-) diff --git a/packages/babel-parser/src/parser/comments.ts b/packages/babel-parser/src/parser/comments.ts index be8a2e248db8..04e7261c8961 100644 --- a/packages/babel-parser/src/parser/comments.ts +++ b/packages/babel-parser/src/parser/comments.ts @@ -289,65 +289,4 @@ export default class CommentsParser extends BaseParser { } } } - - /* - * Used to finalize the leading comments of a node, even if they could - * be attached as leading comments to a parent node. - * - * In case of comments followed by a decorator followed by `export`, - * we manually attach them to the decorator node rather than to the - * class declaration node. This is because the class location range - * overlaps with `export`, and this causes confusing comments behavior: - * - */ // /* comment */ @dec export class Foo {} - /* - * See [takeLeadingCommentsAfterLastToken] for the hanling of comments - * after `export`. - */ - forceFinalizeLeadingComments(node: Node): void { - const { commentStack } = this.state; - for (let i = commentStack.length - 1; i >= 0; i--) { - const commentWS = commentStack[i]; - if (commentWS.trailingNode === node) { - this.finalizeComment(commentWS); - commentStack.splice(i, 1); - } else if (commentWS.end < node.start) { - break; - } - } - } - - /* - * Used to take the comments after the last token as leading - * comments of the given node, even if their start position - * is after the start position of the node. - * - * In case of decorators followed by `export`, we manually mark the - * comments between `export` and `class` as leading comments of the - * class declaration node. - * This is needed because the class location range overlaps with - * `export`, and thus they would be marked as inner comments of - * the class declaration: - * - */ // @dec export /* comment */ class Foo {} - /* - * See [forceFinalizeLeadingComments] for the handling of comments - * before decorators. - */ - takeLeadingCommentsAfterLastToken(node: Undone): void { - const { - start, - lastTokEndLoc: { index: lastTokEnd }, - } = this.state; - - const { commentStack } = this.state; - for (let i = commentStack.length - 1; i >= 0; i--) { - const commentWS = commentStack[i]; - if (commentWS.start >= lastTokEnd && commentWS.end <= start) { - commentWS.trailingNode = node as Node; - } else if (commentWS.end < lastTokEnd) { - break; - } - } - } } diff --git a/packages/babel-parser/src/parser/expression.ts b/packages/babel-parser/src/parser/expression.ts index 3f6ea34b224a..2318aad454fa 100644 --- a/packages/babel-parser/src/parser/expression.ts +++ b/packages/babel-parser/src/parser/expression.ts @@ -100,7 +100,6 @@ export default abstract class ExpressionParser extends LValParser { node: N.Function, allowModifiers?: boolean, ): void; - abstract takeDecorators(node: N.HasDecorators): void; abstract parseBlockOrModuleBlockBody( body: N.Statement[], directives: N.Directive[] | null | undefined, @@ -1102,6 +1101,7 @@ export default abstract class ExpressionParser extends LValParser { refExpressionErrors?: ExpressionErrors | null, ): N.Expression { let node; + let decorators: N.Decorator[] | null = null; const { type } = this.state; switch (type) { @@ -1198,12 +1198,13 @@ export default abstract class ExpressionParser extends LValParser { return this.parseFunctionOrFunctionSent(); case tt.at: - this.parseDecorators(); + decorators = this.parseDecorators(); // fall through case tt._class: - node = this.startNode(); - this.takeDecorators(node); - return this.parseClass(node, false); + return this.maybeTakeDecorators( + decorators, + this.parseClass(this.startNode(), false), + ); case tt._new: return this.parseNewOrNewTarget(); diff --git a/packages/babel-parser/src/parser/statement.ts b/packages/babel-parser/src/parser/statement.ts index 1fbdfbdb8447..9d9f43f621ad 100644 --- a/packages/babel-parser/src/parser/statement.ts +++ b/packages/babel-parser/src/parser/statement.ts @@ -340,16 +340,19 @@ export default abstract class StatementParser extends ExpressionParser { context?: string | null, topLevel?: boolean, ): N.Statement { + let decorators: N.Decorator[] | null = null; + if (this.match(tt.at)) { - this.parseDecorators(true); + decorators = this.parseDecorators(true); } - return this.parseStatementContent(context, topLevel); + return this.parseStatementContent(context, topLevel, decorators); } parseStatementContent( this: Parser, context?: string | null, topLevel?: boolean | null, + decorators?: N.Decorator[] | null, ): N.Statement { let starttype = this.state.type; const node = this.startNode(); @@ -390,9 +393,13 @@ export default abstract class StatementParser extends ExpressionParser { !context, ); - case tt._class: + case tt._class: { if (context) this.unexpected(); - return this.parseClass(node as Undone, true); + return this.maybeTakeDecorators( + decorators, + this.parseClass(node as Undone, true), + ); + } case tt._if: return this.parseIfStatement(node as Undone); @@ -462,6 +469,7 @@ export default abstract class StatementParser extends ExpressionParser { | N.ExportDefaultDeclaration | N.ExportDefaultDeclaration >, + decorators, ); if ( @@ -521,6 +529,7 @@ export default abstract class StatementParser extends ExpressionParser { return this.parseExpressionStatement( node as Undone, expr, + decorators, ); } } @@ -539,38 +548,26 @@ export default abstract class StatementParser extends ExpressionParser { ); } - takeDecorators(node: N.HasDecorators): void { - const decorators = - this.state.decoratorStack[this.state.decoratorStack.length - 1]; - if (decorators.length) { - node.decorators = decorators; - this.resetStartLocationFromNode(node, decorators[0]); - this.state.decoratorStack[this.state.decoratorStack.length - 1] = []; - - if ( - this.decoratorsEnabledBeforeExport() && - this.input.slice( - this.state.lastTokStart, - this.state.lastTokEndLoc.index, - ) === "export" - ) { - this.takeLeadingCommentsAfterLastToken(node); - } + maybeTakeDecorators( + maybeDecorators: N.Decorator[] | null, + node: T, + ): T { + if (maybeDecorators) { + node.decorators = maybeDecorators; + this.resetStartLocationFromNode(node, maybeDecorators[0]); } + return node; } canHaveLeadingDecorator(): boolean { return this.match(tt._class); } - parseDecorators(this: Parser, allowExport?: boolean): void { - const { decoratorStack } = this.state; - const currentContextDecorators = decoratorStack[decoratorStack.length - 1]; - - while (this.match(tt.at)) { - const decorator = this.parseDecorator(); - currentContextDecorators.push(decorator); - } + parseDecorators(this: Parser, allowExport?: boolean): N.Decorator[] { + const decorators = []; + do { + decorators.push(this.parseDecorator()); + } while (this.match(tt.at)); if (this.match(tt._export)) { if (!allowExport) { @@ -580,14 +577,13 @@ export default abstract class StatementParser extends ExpressionParser { if (!this.decoratorsEnabledBeforeExport()) { this.raise(Errors.DecoratorExportClass, { at: this.state.startLoc }); } - - const firstDecorator = decoratorStack[decoratorStack.length - 1][0]; - this.forceFinalizeLeadingComments(firstDecorator); } else if (!this.canHaveLeadingDecorator()) { throw this.raise(Errors.UnexpectedLeadingDecorator, { at: this.state.startLoc, }); } + + return decorators; } parseDecorator(this: Parser): N.Decorator { @@ -597,10 +593,6 @@ export default abstract class StatementParser extends ExpressionParser { this.next(); if (this.hasPlugin("decorators")) { - // Every time a decorator class expression is evaluated, a new empty array is pushed onto the stack - // So that the decorators of any nested class expressions will be dealt with separately - this.state.decoratorStack.push([]); - const startLoc = this.state.startLoc; let expr: N.Expression; @@ -643,8 +635,6 @@ export default abstract class StatementParser extends ExpressionParser { node.expression = this.parseMaybeDecoratorArguments(expr); } - - this.state.decoratorStack.pop(); } else { node.expression = this.parseExprSubscripts(); } @@ -1121,6 +1111,8 @@ export default abstract class StatementParser extends ExpressionParser { parseExpressionStatement( node: Undone, expr: N.Expression, + /* eslint-disable @typescript-eslint/no-unused-vars -- used in TypeScript parser */ + decorators: N.Decorator[] | null, ) { node.expression = expr; this.semicolon(); @@ -1499,8 +1491,6 @@ export default abstract class StatementParser extends ExpressionParser { isStatement: /* T === ClassDeclaration */ boolean, optionalId?: boolean, ): T { - this.takeDecorators(node); - this.next(); // 'class' // A class definition is always strict mode code. @@ -2130,6 +2120,7 @@ export default abstract class StatementParser extends ExpressionParser { | N.ExportAllDeclaration | N.ExportNamedDeclaration >, + decorators: N.Decorator[] | null, ): N.AnyExport { const hasDefault = this.maybeParseExportDefaultSpecifier( // @ts-expect-error todo(flow->ts) @@ -2154,6 +2145,9 @@ export default abstract class StatementParser extends ExpressionParser { if (hasStar && !hasNamespace) { if (hasDefault) this.unexpected(); + if (decorators) { + throw this.raise(Errors.UnsupportedDecoratorExport, { at: node }); + } this.parseExportFrom(node as Undone, true); return this.finishNode(node, "ExportAllDeclaration"); @@ -2174,6 +2168,9 @@ export default abstract class StatementParser extends ExpressionParser { let hasDeclaration; if (isFromRequired || hasSpecifiers) { hasDeclaration = false; + if (decorators) { + throw this.raise(Errors.UnsupportedDecoratorExport, { at: node }); + } this.parseExportFrom( node as Undone, isFromRequired, @@ -2191,16 +2188,37 @@ export default abstract class StatementParser extends ExpressionParser { false, !!(node as Undone).source, ); - return this.finishNode(node, "ExportNamedDeclaration"); + const finished = this.finishNode( + node as Undone, + "ExportNamedDeclaration", + ); + if (finished.declaration?.type === "ClassDeclaration") { + this.maybeTakeDecorators(decorators, finished.declaration); + } else if (decorators) { + throw this.raise(Errors.UnsupportedDecoratorExport, { at: node }); + } + return finished; } if (this.eat(tt._default)) { // export default ... - (node as Undone).declaration = - this.parseExportDefaultExpression(); - this.checkExport(node as Undone, true, true); + const decl = this.parseExportDefaultExpression(); + (node as Undone).declaration = decl; + + const finished = this.finishNode( + node as Undone, + "ExportDefaultDeclaration", + ); + + if (decl.type === "ClassDeclaration") { + this.maybeTakeDecorators(decorators, decl as N.ClassDeclaration); + } else if (decorators) { + throw this.raise(Errors.UnsupportedDecoratorExport, { at: node }); + } + + this.checkExport(finished, true, true); - return this.finishNode(node, "ExportDefaultDeclaration"); + return finished; } throw this.unexpected(null, tt.braceL); @@ -2311,8 +2329,10 @@ export default abstract class StatementParser extends ExpressionParser { ) { this.raise(Errors.DecoratorBeforeExport, { at: this.state.startLoc }); } - this.parseDecorators(false); - return this.parseClass(expr as Undone, true, true); + return this.maybeTakeDecorators( + this.parseDecorators(false), + this.parseClass(this.startNode(), true, true), + ); } if (this.match(tt._const) || this.match(tt._var) || this.isLet()) { @@ -2331,6 +2351,14 @@ export default abstract class StatementParser extends ExpressionParser { // eslint-disable-next-line @typescript-eslint/no-unused-vars node: Undone, ): N.Declaration | undefined | null { + if (this.match(tt._class)) { + const node = this.parseClass( + this.startNode(), + true, + false, + ); + return node; + } return this.parseStatement(null) as N.Declaration; } @@ -2494,14 +2522,6 @@ export default abstract class StatementParser extends ExpressionParser { } } } - - const currentContextDecorators = - this.state.decoratorStack[this.state.decoratorStack.length - 1]; - // If node.declaration is a class, it will take all decorators in the current context. - // Thus we should throw if we see non-empty decorators here. - if (currentContextDecorators.length) { - throw this.raise(Errors.UnsupportedDecoratorExport, { at: node }); - } } checkDeclaration(node: N.Pattern | N.ObjectProperty): void { diff --git a/packages/babel-parser/src/plugins/estree.ts b/packages/babel-parser/src/plugins/estree.ts index 0e0c2fb1f8bb..6a1797fc29f5 100644 --- a/packages/babel-parser/src/plugins/estree.ts +++ b/packages/babel-parser/src/plugins/estree.ts @@ -451,8 +451,11 @@ export default (superClass: typeof Parser) => super.toReferencedArguments(node); } - parseExport(unfinished: Undone) { - const node = super.parseExport(unfinished); + parseExport( + unfinished: Undone, + decorators: N.Decorator[] | null, + ) { + const node = super.parseExport(unfinished, decorators); switch (node.type) { case "ExportAllDeclaration": diff --git a/packages/babel-parser/src/plugins/flow/index.ts b/packages/babel-parser/src/plugins/flow/index.ts index 62fd136c83ef..7cc0a5afb648 100644 --- a/packages/babel-parser/src/plugins/flow/index.ts +++ b/packages/babel-parser/src/plugins/flow/index.ts @@ -637,6 +637,7 @@ export default (superClass: typeof Parser) => ) { node = this.parseExport( node as Undone, + /* decorators */ null, ); if (node.type === "ExportNamedDeclaration") { node.type = "ExportDeclaration"; @@ -1955,6 +1956,7 @@ export default (superClass: typeof Parser) => parseExpressionStatement( node: N.ExpressionStatement, expr: N.Expression, + decorators: N.Decorator[] | null, ): N.ExpressionStatement { if (expr.type === "Identifier") { if (expr.name === "declare") { @@ -1982,7 +1984,7 @@ export default (superClass: typeof Parser) => } } - return super.parseExpressionStatement(node, expr); + return super.parseExpressionStatement(node, expr, decorators); } // export type @@ -2228,8 +2230,9 @@ export default (superClass: typeof Parser) => parseExport( node: Undone, + decorators: N.Decorator[] | null, ): N.AnyExport { - const decl = super.parseExport(node); + const decl = super.parseExport(node, decorators); if ( decl.type === "ExportNamedDeclaration" || decl.type === "ExportAllDeclaration" diff --git a/packages/babel-parser/src/plugins/placeholders.ts b/packages/babel-parser/src/plugins/placeholders.ts index a89b150f8c9b..d7a93656d2c3 100644 --- a/packages/babel-parser/src/plugins/placeholders.ts +++ b/packages/babel-parser/src/plugins/placeholders.ts @@ -241,7 +241,6 @@ export default (superClass: typeof Parser) => const type = isStatement ? "ClassDeclaration" : "ClassExpression"; this.next(); - this.takeDecorators(node); const oldStrict = this.state.strict; const placeholder = this.parsePlaceholder("Identifier"); @@ -272,9 +271,9 @@ export default (superClass: typeof Parser) => return this.finishNode(node, type); } - parseExport(node: N.Node): N.AnyExport { + parseExport(node: N.Node, decorators: N.Decorator[] | null): N.AnyExport { const placeholder = this.parsePlaceholder("Identifier"); - if (!placeholder) return super.parseExport(node); + if (!placeholder) return super.parseExport(node, decorators); if (!this.isContextual(tt._from) && !this.match(tt.comma)) { // export %%DECL%%; @@ -290,7 +289,7 @@ export default (superClass: typeof Parser) => specifier.exported = placeholder; node.specifiers = [this.finishNode(specifier, "ExportDefaultSpecifier")]; - return super.parseExport(node); + return super.parseExport(node, decorators); } isExportDefaultSpecifier(): boolean { diff --git a/packages/babel-parser/src/plugins/typescript/index.ts b/packages/babel-parser/src/plugins/typescript/index.ts index af522420fb6e..46c214214ff5 100644 --- a/packages/babel-parser/src/plugins/typescript/index.ts +++ b/packages/babel-parser/src/plugins/typescript/index.ts @@ -2073,6 +2073,7 @@ export default (superClass: ClassWithMixin) => nany, this.state.value, /* next */ true, + /* decorators */ null, ); } }); @@ -2084,12 +2085,14 @@ export default (superClass: ClassWithMixin) => this.startNode(), this.state.value, /* next */ true, + /* decorators */ null, ); } tsParseExpressionStatement( node: Undone, expr: N.Identifier, + decorators: N.Decorator[] | null, ): N.Declaration | undefined | null { switch (expr.name) { case "declare": { @@ -2117,7 +2120,12 @@ export default (superClass: ClassWithMixin) => break; default: - return this.tsParseDeclaration(node, expr.name, /* next */ false); + return this.tsParseDeclaration( + node, + expr.name, + /* next */ false, + decorators, + ); } } @@ -2126,6 +2134,7 @@ export default (superClass: ClassWithMixin) => node: any, value: string, next: boolean, + decorators: N.Decorator[] | null, ): N.Declaration | undefined | null { // no declaration apart from enum can be followed by a line break. switch (value) { @@ -2134,7 +2143,7 @@ export default (superClass: ClassWithMixin) => this.tsCheckLineTerminator(next) && (this.match(tt._class) || tokenIsIdentifier(this.state.type)) ) { - return this.tsParseAbstractDeclaration(node); + return this.tsParseAbstractDeclaration(node, decorators); } break; @@ -2659,7 +2668,10 @@ export default (superClass: ClassWithMixin) => return importNode; } - parseExport(node: Undone): N.AnyExport { + parseExport( + node: Undone, + decorators: N.Decorator[] | null, + ): N.AnyExport { if (this.match(tt._import)) { // `export import A = B;` this.next(); // eat `tt._import` @@ -2703,6 +2715,7 @@ export default (superClass: ClassWithMixin) => return super.parseExport( node as Undone, + decorators, ); } } @@ -2784,6 +2797,7 @@ export default (superClass: ClassWithMixin) => parseStatementContent( context?: string | null, topLevel?: boolean | null, + decorators?: N.Decorator[] | null, ): N.Statement { if (this.match(tt._const) && this.isLookaheadContextual("enum")) { const node = this.startNode(); @@ -2802,7 +2816,7 @@ export default (superClass: ClassWithMixin) => if (result) return result; } - return super.parseStatementContent(context, topLevel); + return super.parseStatementContent(context, topLevel, decorators); } parseAccessModifier(): N.Accessibility | undefined | null { @@ -2953,13 +2967,14 @@ export default (superClass: ClassWithMixin) => parseExpressionStatement( node: Undone, expr: N.Expression, + decorators: N.Decorator[] | null, ): N.Statement { const decl = expr.type === "Identifier" ? // @ts-expect-error refine typings - this.tsParseExpressionStatement(node, expr) + this.tsParseExpressionStatement(node, expr, decorators) : undefined; - return decl || super.parseExpressionStatement(node, expr); + return decl || super.parseExpressionStatement(node, expr, decorators); } // export type @@ -3808,13 +3823,17 @@ export default (superClass: ClassWithMixin) => tsParseAbstractDeclaration( node: any, + decorators: N.Decorator[] | null, ): N.ClassDeclaration | N.TsInterfaceDeclaration | undefined | null { if (this.match(tt._class)) { node.abstract = true; - return this.parseClass( - node as N.ClassDeclaration, - /* isStatement */ true, - /* optionalId */ false, + return this.maybeTakeDecorators( + decorators, + this.parseClass( + node as N.ClassDeclaration, + /* isStatement */ true, + /* optionalId */ false, + ), ); } else if (this.isContextual(tt._interface)) { // for invalid abstract interface diff --git a/packages/babel-parser/src/tokenizer/state.ts b/packages/babel-parser/src/tokenizer/state.ts index e5667faf2dfd..15dc028efe15 100644 --- a/packages/babel-parser/src/tokenizer/state.ts +++ b/packages/babel-parser/src/tokenizer/state.ts @@ -92,11 +92,6 @@ export default class State { statementStart?: number; }> = []; - // Leading decorators. Last element of the stack represents the decorators in current context. - // Supports nesting of decorators, e.g. @foo(@bar class inner {}) class outer {} - // where @foo belongs to the outer class and @bar to the inner - decoratorStack: Array> = [[]]; - // Comment store for Program.comments comments: Array = []; diff --git a/packages/babel-parser/test/fixtures/comments/decorators/decorators-after-export/input.js b/packages/babel-parser/test/fixtures/comments/decorators/decorators-after-export/input.js index 9da3127c870d..1f389f07c313 100644 --- a/packages/babel-parser/test/fixtures/comments/decorators/decorators-after-export/input.js +++ b/packages/babel-parser/test/fixtures/comments/decorators/decorators-after-export/input.js @@ -1,2 +1,5 @@ /* 1 */ export /* 2 */ @dec1 /* 3 */ @dec2 /* 4 */ class /* 5 */ C /* 6 */ { /* 7 */ } /* 8 */ + +/* A */ export /* B */ default /* C */ @dec1 /* D */ @dec2 +/* E */ class /* F */ { /* G */ } /* H */ diff --git a/packages/babel-parser/test/fixtures/comments/decorators/decorators-after-export/options.json b/packages/babel-parser/test/fixtures/comments/decorators/decorators-after-export/options.json index 6c9cc72327dc..ca59dc053473 100644 --- a/packages/babel-parser/test/fixtures/comments/decorators/decorators-after-export/options.json +++ b/packages/babel-parser/test/fixtures/comments/decorators/decorators-after-export/options.json @@ -1,3 +1,4 @@ { + "sourceType": "module", "plugins": [["decorators", { "decoratorsBeforeExport": false }]] } diff --git a/packages/babel-parser/test/fixtures/comments/decorators/decorators-after-export/output.json b/packages/babel-parser/test/fixtures/comments/decorators/decorators-after-export/output.json index ed59d3127ecb..a97646fedb65 100644 --- a/packages/babel-parser/test/fixtures/comments/decorators/decorators-after-export/output.json +++ b/packages/babel-parser/test/fixtures/comments/decorators/decorators-after-export/output.json @@ -1,13 +1,10 @@ { "type": "File", - "start":0,"end":94,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":2,"column":51,"index":94}}, - "errors": [ - "SyntaxError: 'import' and 'export' may appear only with 'sourceType: \"module\"' (1:8)" - ], + "start":0,"end":196,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":5,"column":41,"index":196}}, "program": { "type": "Program", - "start":0,"end":94,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":2,"column":51,"index":94}}, - "sourceType": "script", + "start":0,"end":196,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":5,"column":41,"index":196}}, + "sourceType": "module", "interpreter": null, "body": [ { @@ -18,6 +15,45 @@ "declaration": { "type": "ClassDeclaration", "start":23,"end":86,"loc":{"start":{"line":1,"column":23,"index":23},"end":{"line":2,"column":43,"index":86}}, + "id": { + "type": "Identifier", + "start":65,"end":66,"loc":{"start":{"line":2,"column":22,"index":65},"end":{"line":2,"column":23,"index":66},"identifierName":"C"}, + "name": "C", + "trailingComments": [ + { + "type": "CommentBlock", + "value": " 6 ", + "start":67,"end":74,"loc":{"start":{"line":2,"column":24,"index":67},"end":{"line":2,"column":31,"index":74}} + } + ], + "leadingComments": [ + { + "type": "CommentBlock", + "value": " 5 ", + "start":57,"end":64,"loc":{"start":{"line":2,"column":14,"index":57},"end":{"line":2,"column":21,"index":64}} + } + ] + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start":75,"end":86,"loc":{"start":{"line":2,"column":32,"index":75},"end":{"line":2,"column":43,"index":86}}, + "body": [], + "innerComments": [ + { + "type": "CommentBlock", + "value": " 7 ", + "start":77,"end":84,"loc":{"start":{"line":2,"column":34,"index":77},"end":{"line":2,"column":41,"index":84}} + } + ], + "leadingComments": [ + { + "type": "CommentBlock", + "value": " 6 ", + "start":67,"end":74,"loc":{"start":{"line":2,"column":24,"index":67},"end":{"line":2,"column":31,"index":74}} + } + ] + }, "decorators": [ { "type": "Decorator", @@ -33,6 +69,13 @@ "value": " 3 ", "start":29,"end":36,"loc":{"start":{"line":1,"column":29,"index":29},"end":{"line":1,"column":36,"index":36}} } + ], + "leadingComments": [ + { + "type": "CommentBlock", + "value": " 2 ", + "start":15,"end":22,"loc":{"start":{"line":1,"column":15,"index":15},"end":{"line":1,"column":22,"index":22}} + } ] }, { @@ -59,65 +102,141 @@ ] } ], - "id": { - "type": "Identifier", - "start":65,"end":66,"loc":{"start":{"line":2,"column":22,"index":65},"end":{"line":2,"column":23,"index":66},"identifierName":"C"}, - "name": "C", - "trailingComments": [ - { - "type": "CommentBlock", - "value": " 6 ", - "start":67,"end":74,"loc":{"start":{"line":2,"column":24,"index":67},"end":{"line":2,"column":31,"index":74}} - } - ], - "leadingComments": [ - { - "type": "CommentBlock", - "value": " 5 ", - "start":57,"end":64,"loc":{"start":{"line":2,"column":14,"index":57},"end":{"line":2,"column":21,"index":64}} - } - ] + "leadingComments": [ + { + "type": "CommentBlock", + "value": " 4 ", + "start":43,"end":50,"loc":{"start":{"line":2,"column":0,"index":43},"end":{"line":2,"column":7,"index":50}} + } + ] + }, + "trailingComments": [ + { + "type": "CommentBlock", + "value": " 8 ", + "start":87,"end":94,"loc":{"start":{"line":2,"column":44,"index":87},"end":{"line":2,"column":51,"index":94}} }, + { + "type": "CommentBlock", + "value": " A ", + "start":96,"end":103,"loc":{"start":{"line":4,"column":0,"index":96},"end":{"line":4,"column":7,"index":103}} + } + ], + "leadingComments": [ + { + "type": "CommentBlock", + "value": " 1 ", + "start":0,"end":7,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":7,"index":7}} + } + ] + }, + { + "type": "ExportDefaultDeclaration", + "start":104,"end":188,"loc":{"start":{"line":4,"column":8,"index":104},"end":{"line":5,"column":33,"index":188}}, + "declaration": { + "type": "ClassDeclaration", + "start":135,"end":188,"loc":{"start":{"line":4,"column":39,"index":135},"end":{"line":5,"column":33,"index":188}}, + "id": null, "superClass": null, "body": { "type": "ClassBody", - "start":75,"end":86,"loc":{"start":{"line":2,"column":32,"index":75},"end":{"line":2,"column":43,"index":86}}, + "start":177,"end":188,"loc":{"start":{"line":5,"column":22,"index":177},"end":{"line":5,"column":33,"index":188}}, "body": [], "innerComments": [ { "type": "CommentBlock", - "value": " 7 ", - "start":77,"end":84,"loc":{"start":{"line":2,"column":34,"index":77},"end":{"line":2,"column":41,"index":84}} + "value": " G ", + "start":179,"end":186,"loc":{"start":{"line":5,"column":24,"index":179},"end":{"line":5,"column":31,"index":186}} } ], "leadingComments": [ { "type": "CommentBlock", - "value": " 6 ", - "start":67,"end":74,"loc":{"start":{"line":2,"column":24,"index":67},"end":{"line":2,"column":31,"index":74}} + "value": " F ", + "start":169,"end":176,"loc":{"start":{"line":5,"column":14,"index":169},"end":{"line":5,"column":21,"index":176}} } ] }, + "decorators": [ + { + "type": "Decorator", + "start":135,"end":140,"loc":{"start":{"line":4,"column":39,"index":135},"end":{"line":4,"column":44,"index":140}}, + "expression": { + "type": "Identifier", + "start":136,"end":140,"loc":{"start":{"line":4,"column":40,"index":136},"end":{"line":4,"column":44,"index":140},"identifierName":"dec1"}, + "name": "dec1" + }, + "trailingComments": [ + { + "type": "CommentBlock", + "value": " D ", + "start":141,"end":148,"loc":{"start":{"line":4,"column":45,"index":141},"end":{"line":4,"column":52,"index":148}} + } + ], + "leadingComments": [ + { + "type": "CommentBlock", + "value": " C ", + "start":127,"end":134,"loc":{"start":{"line":4,"column":31,"index":127},"end":{"line":4,"column":38,"index":134}} + } + ] + }, + { + "type": "Decorator", + "start":149,"end":154,"loc":{"start":{"line":4,"column":53,"index":149},"end":{"line":4,"column":58,"index":154}}, + "expression": { + "type": "Identifier", + "start":150,"end":154,"loc":{"start":{"line":4,"column":54,"index":150},"end":{"line":4,"column":58,"index":154},"identifierName":"dec2"}, + "name": "dec2" + }, + "trailingComments": [ + { + "type": "CommentBlock", + "value": " E ", + "start":155,"end":162,"loc":{"start":{"line":5,"column":0,"index":155},"end":{"line":5,"column":7,"index":162}} + } + ], + "leadingComments": [ + { + "type": "CommentBlock", + "value": " D ", + "start":141,"end":148,"loc":{"start":{"line":4,"column":45,"index":141},"end":{"line":4,"column":52,"index":148}} + } + ] + } + ], "leadingComments": [ { "type": "CommentBlock", - "value": " 2 ", - "start":15,"end":22,"loc":{"start":{"line":1,"column":15,"index":15},"end":{"line":1,"column":22,"index":22}} + "value": " E ", + "start":155,"end":162,"loc":{"start":{"line":5,"column":0,"index":155},"end":{"line":5,"column":7,"index":162}} } ] }, + "innerComments": [ + { + "type": "CommentBlock", + "value": " B ", + "start":111,"end":118,"loc":{"start":{"line":4,"column":15,"index":111},"end":{"line":4,"column":22,"index":118}} + } + ], "trailingComments": [ { "type": "CommentBlock", - "value": " 8 ", - "start":87,"end":94,"loc":{"start":{"line":2,"column":44,"index":87},"end":{"line":2,"column":51,"index":94}} + "value": " H ", + "start":189,"end":196,"loc":{"start":{"line":5,"column":34,"index":189},"end":{"line":5,"column":41,"index":196}} } ], "leadingComments": [ { "type": "CommentBlock", - "value": " 1 ", - "start":0,"end":7,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":7,"index":7}} + "value": " 8 ", + "start":87,"end":94,"loc":{"start":{"line":2,"column":44,"index":87},"end":{"line":2,"column":51,"index":94}} + }, + { + "type": "CommentBlock", + "value": " A ", + "start":96,"end":103,"loc":{"start":{"line":4,"column":0,"index":96},"end":{"line":4,"column":7,"index":103}} } ] } @@ -164,6 +283,46 @@ "type": "CommentBlock", "value": " 8 ", "start":87,"end":94,"loc":{"start":{"line":2,"column":44,"index":87},"end":{"line":2,"column":51,"index":94}} + }, + { + "type": "CommentBlock", + "value": " A ", + "start":96,"end":103,"loc":{"start":{"line":4,"column":0,"index":96},"end":{"line":4,"column":7,"index":103}} + }, + { + "type": "CommentBlock", + "value": " B ", + "start":111,"end":118,"loc":{"start":{"line":4,"column":15,"index":111},"end":{"line":4,"column":22,"index":118}} + }, + { + "type": "CommentBlock", + "value": " C ", + "start":127,"end":134,"loc":{"start":{"line":4,"column":31,"index":127},"end":{"line":4,"column":38,"index":134}} + }, + { + "type": "CommentBlock", + "value": " D ", + "start":141,"end":148,"loc":{"start":{"line":4,"column":45,"index":141},"end":{"line":4,"column":52,"index":148}} + }, + { + "type": "CommentBlock", + "value": " E ", + "start":155,"end":162,"loc":{"start":{"line":5,"column":0,"index":155},"end":{"line":5,"column":7,"index":162}} + }, + { + "type": "CommentBlock", + "value": " F ", + "start":169,"end":176,"loc":{"start":{"line":5,"column":14,"index":169},"end":{"line":5,"column":21,"index":176}} + }, + { + "type": "CommentBlock", + "value": " G ", + "start":179,"end":186,"loc":{"start":{"line":5,"column":24,"index":179},"end":{"line":5,"column":31,"index":186}} + }, + { + "type": "CommentBlock", + "value": " H ", + "start":189,"end":196,"loc":{"start":{"line":5,"column":34,"index":189},"end":{"line":5,"column":41,"index":196}} } ] } diff --git a/packages/babel-parser/test/fixtures/comments/decorators/decorators-before-export/input.js b/packages/babel-parser/test/fixtures/comments/decorators/decorators-before-export/input.js index 1f74bcfc3941..83739b654ed7 100644 --- a/packages/babel-parser/test/fixtures/comments/decorators/decorators-before-export/input.js +++ b/packages/babel-parser/test/fixtures/comments/decorators/decorators-before-export/input.js @@ -1,2 +1,5 @@ /* 1 */ @dec1 /* 2 */ @dec2 /* 3 */ export /* 4 */ class /* 5 */ C /* 6 */ { /* 7 */ } /* 8 */ + +/* A */ @dec1 /* B */ @dec2 /* C */ +export /* D */ default /* E */ class /* F */ { /* G */ } /* H */ diff --git a/packages/babel-parser/test/fixtures/comments/decorators/decorators-before-export/options.json b/packages/babel-parser/test/fixtures/comments/decorators/decorators-before-export/options.json index fe752ff5f509..3d20bee94540 100644 --- a/packages/babel-parser/test/fixtures/comments/decorators/decorators-before-export/options.json +++ b/packages/babel-parser/test/fixtures/comments/decorators/decorators-before-export/options.json @@ -1,3 +1,4 @@ { + "sourceType": "module", "plugins": [["decorators", { "decoratorsBeforeExport": true }]] } diff --git a/packages/babel-parser/test/fixtures/comments/decorators/decorators-before-export/output.json b/packages/babel-parser/test/fixtures/comments/decorators/decorators-before-export/output.json index ac4698f5c4d8..ef21aaef6329 100644 --- a/packages/babel-parser/test/fixtures/comments/decorators/decorators-before-export/output.json +++ b/packages/babel-parser/test/fixtures/comments/decorators/decorators-before-export/output.json @@ -1,13 +1,10 @@ { "type": "File", - "start":0,"end":94,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":2,"column":58,"index":94}}, - "errors": [ - "SyntaxError: 'import' and 'export' may appear only with 'sourceType: \"module\"' (2:0)" - ], + "start":0,"end":196,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":5,"column":64,"index":196}}, "program": { "type": "Program", - "start":0,"end":94,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":2,"column":58,"index":94}}, - "sourceType": "script", + "start":0,"end":196,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":5,"column":64,"index":196}}, + "sourceType": "module", "interpreter": null, "body": [ { @@ -18,6 +15,52 @@ "declaration": { "type": "ClassDeclaration", "start":8,"end":86,"loc":{"start":{"line":1,"column":8,"index":8},"end":{"line":2,"column":50,"index":86}}, + "id": { + "type": "Identifier", + "start":65,"end":66,"loc":{"start":{"line":2,"column":29,"index":65},"end":{"line":2,"column":30,"index":66},"identifierName":"C"}, + "name": "C", + "trailingComments": [ + { + "type": "CommentBlock", + "value": " 6 ", + "start":67,"end":74,"loc":{"start":{"line":2,"column":31,"index":67},"end":{"line":2,"column":38,"index":74}} + } + ], + "leadingComments": [ + { + "type": "CommentBlock", + "value": " 5 ", + "start":57,"end":64,"loc":{"start":{"line":2,"column":21,"index":57},"end":{"line":2,"column":28,"index":64}} + } + ] + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start":75,"end":86,"loc":{"start":{"line":2,"column":39,"index":75},"end":{"line":2,"column":50,"index":86}}, + "body": [], + "innerComments": [ + { + "type": "CommentBlock", + "value": " 7 ", + "start":77,"end":84,"loc":{"start":{"line":2,"column":41,"index":77},"end":{"line":2,"column":48,"index":84}} + } + ], + "leadingComments": [ + { + "type": "CommentBlock", + "value": " 6 ", + "start":67,"end":74,"loc":{"start":{"line":2,"column":31,"index":67},"end":{"line":2,"column":38,"index":74}} + } + ] + }, + "leadingComments": [ + { + "type": "CommentBlock", + "value": " 4 ", + "start":43,"end":50,"loc":{"start":{"line":2,"column":7,"index":43},"end":{"line":2,"column":14,"index":50}} + } + ], "decorators": [ { "type": "Decorator", @@ -27,18 +70,18 @@ "start":9,"end":13,"loc":{"start":{"line":1,"column":9,"index":9},"end":{"line":1,"column":13,"index":13},"identifierName":"dec1"}, "name": "dec1" }, - "leadingComments": [ + "trailingComments": [ { "type": "CommentBlock", - "value": " 1 ", - "start":0,"end":7,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":7,"index":7}} + "value": " 2 ", + "start":14,"end":21,"loc":{"start":{"line":1,"column":14,"index":14},"end":{"line":1,"column":21,"index":21}} } ], - "trailingComments": [ + "leadingComments": [ { "type": "CommentBlock", - "value": " 2 ", - "start":14,"end":21,"loc":{"start":{"line":1,"column":14,"index":14},"end":{"line":1,"column":21,"index":21}} + "value": " 1 ", + "start":0,"end":7,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":7,"index":7}} } ] }, @@ -65,59 +108,135 @@ } ] } - ], - "id": { - "type": "Identifier", - "start":65,"end":66,"loc":{"start":{"line":2,"column":29,"index":65},"end":{"line":2,"column":30,"index":66},"identifierName":"C"}, - "name": "C", - "trailingComments": [ - { - "type": "CommentBlock", - "value": " 6 ", - "start":67,"end":74,"loc":{"start":{"line":2,"column":31,"index":67},"end":{"line":2,"column":38,"index":74}} - } - ], - "leadingComments": [ - { - "type": "CommentBlock", - "value": " 5 ", - "start":57,"end":64,"loc":{"start":{"line":2,"column":21,"index":57},"end":{"line":2,"column":28,"index":64}} - } - ] + ] + }, + "trailingComments": [ + { + "type": "CommentBlock", + "value": " 8 ", + "start":87,"end":94,"loc":{"start":{"line":2,"column":51,"index":87},"end":{"line":2,"column":58,"index":94}} }, + { + "type": "CommentBlock", + "value": " A ", + "start":96,"end":103,"loc":{"start":{"line":4,"column":0,"index":96},"end":{"line":4,"column":7,"index":103}} + } + ], + "leadingComments": [ + { + "type": "CommentBlock", + "value": " 3 ", + "start":28,"end":35,"loc":{"start":{"line":1,"column":28,"index":28},"end":{"line":1,"column":35,"index":35}} + } + ] + }, + { + "type": "ExportDefaultDeclaration", + "start":132,"end":188,"loc":{"start":{"line":5,"column":0,"index":132},"end":{"line":5,"column":56,"index":188}}, + "declaration": { + "type": "ClassDeclaration", + "start":104,"end":188,"loc":{"start":{"line":4,"column":8,"index":104},"end":{"line":5,"column":56,"index":188}}, + "id": null, "superClass": null, "body": { "type": "ClassBody", - "start":75,"end":86,"loc":{"start":{"line":2,"column":39,"index":75},"end":{"line":2,"column":50,"index":86}}, + "start":177,"end":188,"loc":{"start":{"line":5,"column":45,"index":177},"end":{"line":5,"column":56,"index":188}}, "body": [], "innerComments": [ { "type": "CommentBlock", - "value": " 7 ", - "start":77,"end":84,"loc":{"start":{"line":2,"column":41,"index":77},"end":{"line":2,"column":48,"index":84}} + "value": " G ", + "start":179,"end":186,"loc":{"start":{"line":5,"column":47,"index":179},"end":{"line":5,"column":54,"index":186}} } ], "leadingComments": [ { "type": "CommentBlock", - "value": " 6 ", - "start":67,"end":74,"loc":{"start":{"line":2,"column":31,"index":67},"end":{"line":2,"column":38,"index":74}} + "value": " F ", + "start":169,"end":176,"loc":{"start":{"line":5,"column":37,"index":169},"end":{"line":5,"column":44,"index":176}} } ] }, "leadingComments": [ { "type": "CommentBlock", - "value": " 4 ", - "start":43,"end":50,"loc":{"start":{"line":2,"column":7,"index":43},"end":{"line":2,"column":14,"index":50}} + "value": " E ", + "start":155,"end":162,"loc":{"start":{"line":5,"column":23,"index":155},"end":{"line":5,"column":30,"index":162}} + } + ], + "decorators": [ + { + "type": "Decorator", + "start":104,"end":109,"loc":{"start":{"line":4,"column":8,"index":104},"end":{"line":4,"column":13,"index":109}}, + "expression": { + "type": "Identifier", + "start":105,"end":109,"loc":{"start":{"line":4,"column":9,"index":105},"end":{"line":4,"column":13,"index":109},"identifierName":"dec1"}, + "name": "dec1" + }, + "trailingComments": [ + { + "type": "CommentBlock", + "value": " B ", + "start":110,"end":117,"loc":{"start":{"line":4,"column":14,"index":110},"end":{"line":4,"column":21,"index":117}} + } + ], + "leadingComments": [ + { + "type": "CommentBlock", + "value": " 8 ", + "start":87,"end":94,"loc":{"start":{"line":2,"column":51,"index":87},"end":{"line":2,"column":58,"index":94}} + }, + { + "type": "CommentBlock", + "value": " A ", + "start":96,"end":103,"loc":{"start":{"line":4,"column":0,"index":96},"end":{"line":4,"column":7,"index":103}} + } + ] + }, + { + "type": "Decorator", + "start":118,"end":123,"loc":{"start":{"line":4,"column":22,"index":118},"end":{"line":4,"column":27,"index":123}}, + "expression": { + "type": "Identifier", + "start":119,"end":123,"loc":{"start":{"line":4,"column":23,"index":119},"end":{"line":4,"column":27,"index":123},"identifierName":"dec2"}, + "name": "dec2" + }, + "trailingComments": [ + { + "type": "CommentBlock", + "value": " C ", + "start":124,"end":131,"loc":{"start":{"line":4,"column":28,"index":124},"end":{"line":4,"column":35,"index":131}} + } + ], + "leadingComments": [ + { + "type": "CommentBlock", + "value": " B ", + "start":110,"end":117,"loc":{"start":{"line":4,"column":14,"index":110},"end":{"line":4,"column":21,"index":117}} + } + ] } ] }, + "innerComments": [ + { + "type": "CommentBlock", + "value": " D ", + "start":139,"end":146,"loc":{"start":{"line":5,"column":7,"index":139},"end":{"line":5,"column":14,"index":146}} + } + ], "trailingComments": [ { "type": "CommentBlock", - "value": " 8 ", - "start":87,"end":94,"loc":{"start":{"line":2,"column":51,"index":87},"end":{"line":2,"column":58,"index":94}} + "value": " H ", + "start":189,"end":196,"loc":{"start":{"line":5,"column":57,"index":189},"end":{"line":5,"column":64,"index":196}} + } + ], + "leadingComments": [ + { + "type": "CommentBlock", + "value": " C ", + "start":124,"end":131,"loc":{"start":{"line":4,"column":28,"index":124},"end":{"line":4,"column":35,"index":131}} } ] } @@ -164,6 +283,46 @@ "type": "CommentBlock", "value": " 8 ", "start":87,"end":94,"loc":{"start":{"line":2,"column":51,"index":87},"end":{"line":2,"column":58,"index":94}} + }, + { + "type": "CommentBlock", + "value": " A ", + "start":96,"end":103,"loc":{"start":{"line":4,"column":0,"index":96},"end":{"line":4,"column":7,"index":103}} + }, + { + "type": "CommentBlock", + "value": " B ", + "start":110,"end":117,"loc":{"start":{"line":4,"column":14,"index":110},"end":{"line":4,"column":21,"index":117}} + }, + { + "type": "CommentBlock", + "value": " C ", + "start":124,"end":131,"loc":{"start":{"line":4,"column":28,"index":124},"end":{"line":4,"column":35,"index":131}} + }, + { + "type": "CommentBlock", + "value": " D ", + "start":139,"end":146,"loc":{"start":{"line":5,"column":7,"index":139},"end":{"line":5,"column":14,"index":146}} + }, + { + "type": "CommentBlock", + "value": " E ", + "start":155,"end":162,"loc":{"start":{"line":5,"column":23,"index":155},"end":{"line":5,"column":30,"index":162}} + }, + { + "type": "CommentBlock", + "value": " F ", + "start":169,"end":176,"loc":{"start":{"line":5,"column":37,"index":169},"end":{"line":5,"column":44,"index":176}} + }, + { + "type": "CommentBlock", + "value": " G ", + "start":179,"end":186,"loc":{"start":{"line":5,"column":47,"index":179},"end":{"line":5,"column":54,"index":186}} + }, + { + "type": "CommentBlock", + "value": " H ", + "start":189,"end":196,"loc":{"start":{"line":5,"column":57,"index":189},"end":{"line":5,"column":64,"index":196}} } ] } diff --git a/packages/babel-parser/test/fixtures/comments/decorators/decorators-legacy-before-export/input.js b/packages/babel-parser/test/fixtures/comments/decorators/decorators-legacy-before-export/input.js index 1f74bcfc3941..83739b654ed7 100644 --- a/packages/babel-parser/test/fixtures/comments/decorators/decorators-legacy-before-export/input.js +++ b/packages/babel-parser/test/fixtures/comments/decorators/decorators-legacy-before-export/input.js @@ -1,2 +1,5 @@ /* 1 */ @dec1 /* 2 */ @dec2 /* 3 */ export /* 4 */ class /* 5 */ C /* 6 */ { /* 7 */ } /* 8 */ + +/* A */ @dec1 /* B */ @dec2 /* C */ +export /* D */ default /* E */ class /* F */ { /* G */ } /* H */ diff --git a/packages/babel-parser/test/fixtures/comments/decorators/decorators-legacy-before-export/options.json b/packages/babel-parser/test/fixtures/comments/decorators/decorators-legacy-before-export/options.json index a6855c41cfad..5e6a01579b8a 100644 --- a/packages/babel-parser/test/fixtures/comments/decorators/decorators-legacy-before-export/options.json +++ b/packages/babel-parser/test/fixtures/comments/decorators/decorators-legacy-before-export/options.json @@ -1,3 +1,4 @@ { + "sourceType": "module", "plugins": ["decorators-legacy"] } diff --git a/packages/babel-parser/test/fixtures/comments/decorators/decorators-legacy-before-export/output.json b/packages/babel-parser/test/fixtures/comments/decorators/decorators-legacy-before-export/output.json index ac4698f5c4d8..ef21aaef6329 100644 --- a/packages/babel-parser/test/fixtures/comments/decorators/decorators-legacy-before-export/output.json +++ b/packages/babel-parser/test/fixtures/comments/decorators/decorators-legacy-before-export/output.json @@ -1,13 +1,10 @@ { "type": "File", - "start":0,"end":94,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":2,"column":58,"index":94}}, - "errors": [ - "SyntaxError: 'import' and 'export' may appear only with 'sourceType: \"module\"' (2:0)" - ], + "start":0,"end":196,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":5,"column":64,"index":196}}, "program": { "type": "Program", - "start":0,"end":94,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":2,"column":58,"index":94}}, - "sourceType": "script", + "start":0,"end":196,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":5,"column":64,"index":196}}, + "sourceType": "module", "interpreter": null, "body": [ { @@ -18,6 +15,52 @@ "declaration": { "type": "ClassDeclaration", "start":8,"end":86,"loc":{"start":{"line":1,"column":8,"index":8},"end":{"line":2,"column":50,"index":86}}, + "id": { + "type": "Identifier", + "start":65,"end":66,"loc":{"start":{"line":2,"column":29,"index":65},"end":{"line":2,"column":30,"index":66},"identifierName":"C"}, + "name": "C", + "trailingComments": [ + { + "type": "CommentBlock", + "value": " 6 ", + "start":67,"end":74,"loc":{"start":{"line":2,"column":31,"index":67},"end":{"line":2,"column":38,"index":74}} + } + ], + "leadingComments": [ + { + "type": "CommentBlock", + "value": " 5 ", + "start":57,"end":64,"loc":{"start":{"line":2,"column":21,"index":57},"end":{"line":2,"column":28,"index":64}} + } + ] + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start":75,"end":86,"loc":{"start":{"line":2,"column":39,"index":75},"end":{"line":2,"column":50,"index":86}}, + "body": [], + "innerComments": [ + { + "type": "CommentBlock", + "value": " 7 ", + "start":77,"end":84,"loc":{"start":{"line":2,"column":41,"index":77},"end":{"line":2,"column":48,"index":84}} + } + ], + "leadingComments": [ + { + "type": "CommentBlock", + "value": " 6 ", + "start":67,"end":74,"loc":{"start":{"line":2,"column":31,"index":67},"end":{"line":2,"column":38,"index":74}} + } + ] + }, + "leadingComments": [ + { + "type": "CommentBlock", + "value": " 4 ", + "start":43,"end":50,"loc":{"start":{"line":2,"column":7,"index":43},"end":{"line":2,"column":14,"index":50}} + } + ], "decorators": [ { "type": "Decorator", @@ -27,18 +70,18 @@ "start":9,"end":13,"loc":{"start":{"line":1,"column":9,"index":9},"end":{"line":1,"column":13,"index":13},"identifierName":"dec1"}, "name": "dec1" }, - "leadingComments": [ + "trailingComments": [ { "type": "CommentBlock", - "value": " 1 ", - "start":0,"end":7,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":7,"index":7}} + "value": " 2 ", + "start":14,"end":21,"loc":{"start":{"line":1,"column":14,"index":14},"end":{"line":1,"column":21,"index":21}} } ], - "trailingComments": [ + "leadingComments": [ { "type": "CommentBlock", - "value": " 2 ", - "start":14,"end":21,"loc":{"start":{"line":1,"column":14,"index":14},"end":{"line":1,"column":21,"index":21}} + "value": " 1 ", + "start":0,"end":7,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":7,"index":7}} } ] }, @@ -65,59 +108,135 @@ } ] } - ], - "id": { - "type": "Identifier", - "start":65,"end":66,"loc":{"start":{"line":2,"column":29,"index":65},"end":{"line":2,"column":30,"index":66},"identifierName":"C"}, - "name": "C", - "trailingComments": [ - { - "type": "CommentBlock", - "value": " 6 ", - "start":67,"end":74,"loc":{"start":{"line":2,"column":31,"index":67},"end":{"line":2,"column":38,"index":74}} - } - ], - "leadingComments": [ - { - "type": "CommentBlock", - "value": " 5 ", - "start":57,"end":64,"loc":{"start":{"line":2,"column":21,"index":57},"end":{"line":2,"column":28,"index":64}} - } - ] + ] + }, + "trailingComments": [ + { + "type": "CommentBlock", + "value": " 8 ", + "start":87,"end":94,"loc":{"start":{"line":2,"column":51,"index":87},"end":{"line":2,"column":58,"index":94}} }, + { + "type": "CommentBlock", + "value": " A ", + "start":96,"end":103,"loc":{"start":{"line":4,"column":0,"index":96},"end":{"line":4,"column":7,"index":103}} + } + ], + "leadingComments": [ + { + "type": "CommentBlock", + "value": " 3 ", + "start":28,"end":35,"loc":{"start":{"line":1,"column":28,"index":28},"end":{"line":1,"column":35,"index":35}} + } + ] + }, + { + "type": "ExportDefaultDeclaration", + "start":132,"end":188,"loc":{"start":{"line":5,"column":0,"index":132},"end":{"line":5,"column":56,"index":188}}, + "declaration": { + "type": "ClassDeclaration", + "start":104,"end":188,"loc":{"start":{"line":4,"column":8,"index":104},"end":{"line":5,"column":56,"index":188}}, + "id": null, "superClass": null, "body": { "type": "ClassBody", - "start":75,"end":86,"loc":{"start":{"line":2,"column":39,"index":75},"end":{"line":2,"column":50,"index":86}}, + "start":177,"end":188,"loc":{"start":{"line":5,"column":45,"index":177},"end":{"line":5,"column":56,"index":188}}, "body": [], "innerComments": [ { "type": "CommentBlock", - "value": " 7 ", - "start":77,"end":84,"loc":{"start":{"line":2,"column":41,"index":77},"end":{"line":2,"column":48,"index":84}} + "value": " G ", + "start":179,"end":186,"loc":{"start":{"line":5,"column":47,"index":179},"end":{"line":5,"column":54,"index":186}} } ], "leadingComments": [ { "type": "CommentBlock", - "value": " 6 ", - "start":67,"end":74,"loc":{"start":{"line":2,"column":31,"index":67},"end":{"line":2,"column":38,"index":74}} + "value": " F ", + "start":169,"end":176,"loc":{"start":{"line":5,"column":37,"index":169},"end":{"line":5,"column":44,"index":176}} } ] }, "leadingComments": [ { "type": "CommentBlock", - "value": " 4 ", - "start":43,"end":50,"loc":{"start":{"line":2,"column":7,"index":43},"end":{"line":2,"column":14,"index":50}} + "value": " E ", + "start":155,"end":162,"loc":{"start":{"line":5,"column":23,"index":155},"end":{"line":5,"column":30,"index":162}} + } + ], + "decorators": [ + { + "type": "Decorator", + "start":104,"end":109,"loc":{"start":{"line":4,"column":8,"index":104},"end":{"line":4,"column":13,"index":109}}, + "expression": { + "type": "Identifier", + "start":105,"end":109,"loc":{"start":{"line":4,"column":9,"index":105},"end":{"line":4,"column":13,"index":109},"identifierName":"dec1"}, + "name": "dec1" + }, + "trailingComments": [ + { + "type": "CommentBlock", + "value": " B ", + "start":110,"end":117,"loc":{"start":{"line":4,"column":14,"index":110},"end":{"line":4,"column":21,"index":117}} + } + ], + "leadingComments": [ + { + "type": "CommentBlock", + "value": " 8 ", + "start":87,"end":94,"loc":{"start":{"line":2,"column":51,"index":87},"end":{"line":2,"column":58,"index":94}} + }, + { + "type": "CommentBlock", + "value": " A ", + "start":96,"end":103,"loc":{"start":{"line":4,"column":0,"index":96},"end":{"line":4,"column":7,"index":103}} + } + ] + }, + { + "type": "Decorator", + "start":118,"end":123,"loc":{"start":{"line":4,"column":22,"index":118},"end":{"line":4,"column":27,"index":123}}, + "expression": { + "type": "Identifier", + "start":119,"end":123,"loc":{"start":{"line":4,"column":23,"index":119},"end":{"line":4,"column":27,"index":123},"identifierName":"dec2"}, + "name": "dec2" + }, + "trailingComments": [ + { + "type": "CommentBlock", + "value": " C ", + "start":124,"end":131,"loc":{"start":{"line":4,"column":28,"index":124},"end":{"line":4,"column":35,"index":131}} + } + ], + "leadingComments": [ + { + "type": "CommentBlock", + "value": " B ", + "start":110,"end":117,"loc":{"start":{"line":4,"column":14,"index":110},"end":{"line":4,"column":21,"index":117}} + } + ] } ] }, + "innerComments": [ + { + "type": "CommentBlock", + "value": " D ", + "start":139,"end":146,"loc":{"start":{"line":5,"column":7,"index":139},"end":{"line":5,"column":14,"index":146}} + } + ], "trailingComments": [ { "type": "CommentBlock", - "value": " 8 ", - "start":87,"end":94,"loc":{"start":{"line":2,"column":51,"index":87},"end":{"line":2,"column":58,"index":94}} + "value": " H ", + "start":189,"end":196,"loc":{"start":{"line":5,"column":57,"index":189},"end":{"line":5,"column":64,"index":196}} + } + ], + "leadingComments": [ + { + "type": "CommentBlock", + "value": " C ", + "start":124,"end":131,"loc":{"start":{"line":4,"column":28,"index":124},"end":{"line":4,"column":35,"index":131}} } ] } @@ -164,6 +283,46 @@ "type": "CommentBlock", "value": " 8 ", "start":87,"end":94,"loc":{"start":{"line":2,"column":51,"index":87},"end":{"line":2,"column":58,"index":94}} + }, + { + "type": "CommentBlock", + "value": " A ", + "start":96,"end":103,"loc":{"start":{"line":4,"column":0,"index":96},"end":{"line":4,"column":7,"index":103}} + }, + { + "type": "CommentBlock", + "value": " B ", + "start":110,"end":117,"loc":{"start":{"line":4,"column":14,"index":110},"end":{"line":4,"column":21,"index":117}} + }, + { + "type": "CommentBlock", + "value": " C ", + "start":124,"end":131,"loc":{"start":{"line":4,"column":28,"index":124},"end":{"line":4,"column":35,"index":131}} + }, + { + "type": "CommentBlock", + "value": " D ", + "start":139,"end":146,"loc":{"start":{"line":5,"column":7,"index":139},"end":{"line":5,"column":14,"index":146}} + }, + { + "type": "CommentBlock", + "value": " E ", + "start":155,"end":162,"loc":{"start":{"line":5,"column":23,"index":155},"end":{"line":5,"column":30,"index":162}} + }, + { + "type": "CommentBlock", + "value": " F ", + "start":169,"end":176,"loc":{"start":{"line":5,"column":37,"index":169},"end":{"line":5,"column":44,"index":176}} + }, + { + "type": "CommentBlock", + "value": " G ", + "start":179,"end":186,"loc":{"start":{"line":5,"column":47,"index":179},"end":{"line":5,"column":54,"index":186}} + }, + { + "type": "CommentBlock", + "value": " H ", + "start":189,"end":196,"loc":{"start":{"line":5,"column":57,"index":189},"end":{"line":5,"column":64,"index":196}} } ] } From 1c1fa44c413db786999fb6ae5db2aada2b21a23e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Tue, 25 Oct 2022 15:18:14 +0200 Subject: [PATCH 05/10] Add generator tests --- .../fixtures/comments/decorators-after-export/input.js | 3 +++ .../fixtures/comments/decorators-after-export/output.js | 9 +++++++-- .../fixtures/comments/decorators-before-export/input.js | 3 +++ .../fixtures/comments/decorators-before-export/output.js | 9 ++++++++- .../comments/decorators-legacy-before-export/input.js | 3 +++ .../comments/decorators-legacy-before-export/output.js | 9 ++++++++- 6 files changed, 32 insertions(+), 4 deletions(-) diff --git a/packages/babel-generator/test/fixtures/comments/decorators-after-export/input.js b/packages/babel-generator/test/fixtures/comments/decorators-after-export/input.js index 9da3127c870d..1f389f07c313 100644 --- a/packages/babel-generator/test/fixtures/comments/decorators-after-export/input.js +++ b/packages/babel-generator/test/fixtures/comments/decorators-after-export/input.js @@ -1,2 +1,5 @@ /* 1 */ export /* 2 */ @dec1 /* 3 */ @dec2 /* 4 */ class /* 5 */ C /* 6 */ { /* 7 */ } /* 8 */ + +/* A */ export /* B */ default /* C */ @dec1 /* D */ @dec2 +/* E */ class /* F */ { /* G */ } /* H */ diff --git a/packages/babel-generator/test/fixtures/comments/decorators-after-export/output.js b/packages/babel-generator/test/fixtures/comments/decorators-after-export/output.js index 07c8cfe55a40..ec4d468c88bc 100644 --- a/packages/babel-generator/test/fixtures/comments/decorators-after-export/output.js +++ b/packages/babel-generator/test/fixtures/comments/decorators-after-export/output.js @@ -1,3 +1,8 @@ -/* 1 */export /* 2 */@dec1 +/* 1 */export /* 4 */ /* 2 */@dec1 /* 3 */@dec2 -/* 4 */class /* 5 */C /* 6 */ {/* 7 */} /* 8 */ \ No newline at end of file +class /* 5 */C /* 6 */ {/* 7 */} /* 8 */ + +/* A */ +export default /* E */ /* C */@dec1 +/* D */@dec2 +class /* F */{/* G */} /* H */ \ No newline at end of file diff --git a/packages/babel-generator/test/fixtures/comments/decorators-before-export/input.js b/packages/babel-generator/test/fixtures/comments/decorators-before-export/input.js index 1f74bcfc3941..83739b654ed7 100644 --- a/packages/babel-generator/test/fixtures/comments/decorators-before-export/input.js +++ b/packages/babel-generator/test/fixtures/comments/decorators-before-export/input.js @@ -1,2 +1,5 @@ /* 1 */ @dec1 /* 2 */ @dec2 /* 3 */ export /* 4 */ class /* 5 */ C /* 6 */ { /* 7 */ } /* 8 */ + +/* A */ @dec1 /* B */ @dec2 /* C */ +export /* D */ default /* E */ class /* F */ { /* G */ } /* H */ diff --git a/packages/babel-generator/test/fixtures/comments/decorators-before-export/output.js b/packages/babel-generator/test/fixtures/comments/decorators-before-export/output.js index 9443cc496b8d..3e4b2ded9524 100644 --- a/packages/babel-generator/test/fixtures/comments/decorators-before-export/output.js +++ b/packages/babel-generator/test/fixtures/comments/decorators-before-export/output.js @@ -1,3 +1,10 @@ +/* 3 */ /* 1 */@dec1 /* 2 */@dec2 -/* 3 */export /* 4 */class /* 5 */C /* 6 */ {/* 7 */} /* 8 */ \ No newline at end of file +export /* 4 */class /* 5 */C /* 6 */ {/* 7 */} /* 8 */ + +/* A */ +/* C */ +@dec1 +/* B */@dec2 +export default /* E */class /* F */{/* G */} /* H */ \ No newline at end of file diff --git a/packages/babel-generator/test/fixtures/comments/decorators-legacy-before-export/input.js b/packages/babel-generator/test/fixtures/comments/decorators-legacy-before-export/input.js index 1f74bcfc3941..83739b654ed7 100644 --- a/packages/babel-generator/test/fixtures/comments/decorators-legacy-before-export/input.js +++ b/packages/babel-generator/test/fixtures/comments/decorators-legacy-before-export/input.js @@ -1,2 +1,5 @@ /* 1 */ @dec1 /* 2 */ @dec2 /* 3 */ export /* 4 */ class /* 5 */ C /* 6 */ { /* 7 */ } /* 8 */ + +/* A */ @dec1 /* B */ @dec2 /* C */ +export /* D */ default /* E */ class /* F */ { /* G */ } /* H */ diff --git a/packages/babel-generator/test/fixtures/comments/decorators-legacy-before-export/output.js b/packages/babel-generator/test/fixtures/comments/decorators-legacy-before-export/output.js index 9443cc496b8d..3e4b2ded9524 100644 --- a/packages/babel-generator/test/fixtures/comments/decorators-legacy-before-export/output.js +++ b/packages/babel-generator/test/fixtures/comments/decorators-legacy-before-export/output.js @@ -1,3 +1,10 @@ +/* 3 */ /* 1 */@dec1 /* 2 */@dec2 -/* 3 */export /* 4 */class /* 5 */C /* 6 */ {/* 7 */} /* 8 */ \ No newline at end of file +export /* 4 */class /* 5 */C /* 6 */ {/* 7 */} /* 8 */ + +/* A */ +/* C */ +@dec1 +/* B */@dec2 +export default /* E */class /* F */{/* G */} /* H */ \ No newline at end of file From 6d0bc46af8c4e24beeac2049a0a2808154b36bf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Tue, 25 Oct 2022 17:21:45 +0200 Subject: [PATCH 06/10] Simplify --- packages/babel-parser/src/parser/statement.ts | 33 ++++++------------- 1 file changed, 10 insertions(+), 23 deletions(-) diff --git a/packages/babel-parser/src/parser/statement.ts b/packages/babel-parser/src/parser/statement.ts index 9d9f43f621ad..dab246d503e9 100644 --- a/packages/babel-parser/src/parser/statement.ts +++ b/packages/babel-parser/src/parser/statement.ts @@ -393,13 +393,12 @@ export default abstract class StatementParser extends ExpressionParser { !context, ); - case tt._class: { + case tt._class: if (context) this.unexpected(); return this.maybeTakeDecorators( decorators, this.parseClass(node as Undone, true), ); - } case tt._if: return this.parseIfStatement(node as Undone); @@ -2182,33 +2181,21 @@ export default abstract class StatementParser extends ExpressionParser { } if (isFromRequired || hasSpecifiers || hasDeclaration) { - this.checkExport( - node as Undone, - true, - false, - !!(node as Undone).source, - ); - const finished = this.finishNode( - node as Undone, - "ExportNamedDeclaration", - ); - if (finished.declaration?.type === "ClassDeclaration") { - this.maybeTakeDecorators(decorators, finished.declaration); + const node2 = node as Undone; + this.checkExport(node2, true, false, !!node2.source); + if (node2.declaration?.type === "ClassDeclaration") { + this.maybeTakeDecorators(decorators, node2.declaration); } else if (decorators) { throw this.raise(Errors.UnsupportedDecoratorExport, { at: node }); } - return finished; + return this.finishNode(node2, "ExportNamedDeclaration"); } if (this.eat(tt._default)) { + const node2 = node as Undone; // export default ... const decl = this.parseExportDefaultExpression(); - (node as Undone).declaration = decl; - - const finished = this.finishNode( - node as Undone, - "ExportDefaultDeclaration", - ); + node2.declaration = decl; if (decl.type === "ClassDeclaration") { this.maybeTakeDecorators(decorators, decl as N.ClassDeclaration); @@ -2216,9 +2203,9 @@ export default abstract class StatementParser extends ExpressionParser { throw this.raise(Errors.UnsupportedDecoratorExport, { at: node }); } - this.checkExport(finished, true, true); + this.checkExport(node2, true, true); - return finished; + return this.finishNode(node2, "ExportDefaultDeclaration"); } throw this.unexpected(null, tt.braceL); From 3c014915fc36cfdccd840dad47ac26c7f5b97971 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Tue, 25 Oct 2022 17:24:40 +0200 Subject: [PATCH 07/10] Fix range of export declaration --- .../decorators-before-export/output.js | 6 +- .../decorators-legacy-before-export/output.js | 6 +- packages/babel-parser/src/parser/statement.ts | 14 ++-- .../decorators-before-export/output.json | 64 ++++++++----------- .../output.json | 64 ++++++++----------- .../export-decorators-on-class/output.json | 26 ++++---- .../output.json | 18 +++--- .../output.json | 26 ++++---- .../output.json | 26 ++++---- .../decoratorsBeforeExport-export/output.json | 26 ++++---- .../no-export-decorators-on-class/output.json | 18 +++--- 11 files changed, 132 insertions(+), 162 deletions(-) diff --git a/packages/babel-generator/test/fixtures/comments/decorators-before-export/output.js b/packages/babel-generator/test/fixtures/comments/decorators-before-export/output.js index 3e4b2ded9524..bb8b96d83a49 100644 --- a/packages/babel-generator/test/fixtures/comments/decorators-before-export/output.js +++ b/packages/babel-generator/test/fixtures/comments/decorators-before-export/output.js @@ -1,10 +1,8 @@ -/* 3 */ /* 1 */@dec1 /* 2 */@dec2 -export /* 4 */class /* 5 */C /* 6 */ {/* 7 */} /* 8 */ +/* 3 */export /* 4 */class /* 5 */C /* 6 */ {/* 7 */} /* 8 */ /* A */ -/* C */ @dec1 /* B */@dec2 -export default /* E */class /* F */{/* G */} /* H */ \ No newline at end of file +/* C */export default /* E */class /* F */{/* G */} /* H */ \ No newline at end of file diff --git a/packages/babel-generator/test/fixtures/comments/decorators-legacy-before-export/output.js b/packages/babel-generator/test/fixtures/comments/decorators-legacy-before-export/output.js index 3e4b2ded9524..bb8b96d83a49 100644 --- a/packages/babel-generator/test/fixtures/comments/decorators-legacy-before-export/output.js +++ b/packages/babel-generator/test/fixtures/comments/decorators-legacy-before-export/output.js @@ -1,10 +1,8 @@ -/* 3 */ /* 1 */@dec1 /* 2 */@dec2 -export /* 4 */class /* 5 */C /* 6 */ {/* 7 */} /* 8 */ +/* 3 */export /* 4 */class /* 5 */C /* 6 */ {/* 7 */} /* 8 */ /* A */ -/* C */ @dec1 /* B */@dec2 -export default /* E */class /* F */{/* G */} /* H */ \ No newline at end of file +/* C */export default /* E */class /* F */{/* G */} /* H */ \ No newline at end of file diff --git a/packages/babel-parser/src/parser/statement.ts b/packages/babel-parser/src/parser/statement.ts index dab246d503e9..517bf722dfa2 100644 --- a/packages/babel-parser/src/parser/statement.ts +++ b/packages/babel-parser/src/parser/statement.ts @@ -549,13 +549,15 @@ export default abstract class StatementParser extends ExpressionParser { maybeTakeDecorators( maybeDecorators: N.Decorator[] | null, - node: T, + classNode: T, + exportNode?: Undone, ): T { if (maybeDecorators) { - node.decorators = maybeDecorators; - this.resetStartLocationFromNode(node, maybeDecorators[0]); + classNode.decorators = maybeDecorators; + this.resetStartLocationFromNode(classNode, maybeDecorators[0]); + if (exportNode) this.resetStartLocationFromNode(exportNode, classNode); } - return node; + return classNode; } canHaveLeadingDecorator(): boolean { @@ -2184,7 +2186,7 @@ export default abstract class StatementParser extends ExpressionParser { const node2 = node as Undone; this.checkExport(node2, true, false, !!node2.source); if (node2.declaration?.type === "ClassDeclaration") { - this.maybeTakeDecorators(decorators, node2.declaration); + this.maybeTakeDecorators(decorators, node2.declaration, node2); } else if (decorators) { throw this.raise(Errors.UnsupportedDecoratorExport, { at: node }); } @@ -2198,7 +2200,7 @@ export default abstract class StatementParser extends ExpressionParser { node2.declaration = decl; if (decl.type === "ClassDeclaration") { - this.maybeTakeDecorators(decorators, decl as N.ClassDeclaration); + this.maybeTakeDecorators(decorators, decl as N.ClassDeclaration, node2); } else if (decorators) { throw this.raise(Errors.UnsupportedDecoratorExport, { at: node }); } diff --git a/packages/babel-parser/test/fixtures/comments/decorators/decorators-before-export/output.json b/packages/babel-parser/test/fixtures/comments/decorators/decorators-before-export/output.json index ef21aaef6329..416965a2800d 100644 --- a/packages/babel-parser/test/fixtures/comments/decorators/decorators-before-export/output.json +++ b/packages/babel-parser/test/fixtures/comments/decorators/decorators-before-export/output.json @@ -9,7 +9,7 @@ "body": [ { "type": "ExportNamedDeclaration", - "start":36,"end":86,"loc":{"start":{"line":2,"column":0,"index":36},"end":{"line":2,"column":50,"index":86}}, + "start":8,"end":86,"loc":{"start":{"line":1,"column":8,"index":8},"end":{"line":2,"column":50,"index":86}}, "specifiers": [], "source": null, "declaration": { @@ -54,13 +54,6 @@ } ] }, - "leadingComments": [ - { - "type": "CommentBlock", - "value": " 4 ", - "start":43,"end":50,"loc":{"start":{"line":2,"column":7,"index":43},"end":{"line":2,"column":14,"index":50}} - } - ], "decorators": [ { "type": "Decorator", @@ -76,13 +69,6 @@ "value": " 2 ", "start":14,"end":21,"loc":{"start":{"line":1,"column":14,"index":14},"end":{"line":1,"column":21,"index":21}} } - ], - "leadingComments": [ - { - "type": "CommentBlock", - "value": " 1 ", - "start":0,"end":7,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":7,"index":7}} - } ] }, { @@ -108,6 +94,13 @@ } ] } + ], + "leadingComments": [ + { + "type": "CommentBlock", + "value": " 4 ", + "start":43,"end":50,"loc":{"start":{"line":2,"column":7,"index":43},"end":{"line":2,"column":14,"index":50}} + } ] }, "trailingComments": [ @@ -125,14 +118,14 @@ "leadingComments": [ { "type": "CommentBlock", - "value": " 3 ", - "start":28,"end":35,"loc":{"start":{"line":1,"column":28,"index":28},"end":{"line":1,"column":35,"index":35}} + "value": " 1 ", + "start":0,"end":7,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":7,"index":7}} } ] }, { "type": "ExportDefaultDeclaration", - "start":132,"end":188,"loc":{"start":{"line":5,"column":0,"index":132},"end":{"line":5,"column":56,"index":188}}, + "start":104,"end":188,"loc":{"start":{"line":4,"column":8,"index":104},"end":{"line":5,"column":56,"index":188}}, "declaration": { "type": "ClassDeclaration", "start":104,"end":188,"loc":{"start":{"line":4,"column":8,"index":104},"end":{"line":5,"column":56,"index":188}}, @@ -157,13 +150,6 @@ } ] }, - "leadingComments": [ - { - "type": "CommentBlock", - "value": " E ", - "start":155,"end":162,"loc":{"start":{"line":5,"column":23,"index":155},"end":{"line":5,"column":30,"index":162}} - } - ], "decorators": [ { "type": "Decorator", @@ -179,18 +165,6 @@ "value": " B ", "start":110,"end":117,"loc":{"start":{"line":4,"column":14,"index":110},"end":{"line":4,"column":21,"index":117}} } - ], - "leadingComments": [ - { - "type": "CommentBlock", - "value": " 8 ", - "start":87,"end":94,"loc":{"start":{"line":2,"column":51,"index":87},"end":{"line":2,"column":58,"index":94}} - }, - { - "type": "CommentBlock", - "value": " A ", - "start":96,"end":103,"loc":{"start":{"line":4,"column":0,"index":96},"end":{"line":4,"column":7,"index":103}} - } ] }, { @@ -216,6 +190,13 @@ } ] } + ], + "leadingComments": [ + { + "type": "CommentBlock", + "value": " E ", + "start":155,"end":162,"loc":{"start":{"line":5,"column":23,"index":155},"end":{"line":5,"column":30,"index":162}} + } ] }, "innerComments": [ @@ -235,8 +216,13 @@ "leadingComments": [ { "type": "CommentBlock", - "value": " C ", - "start":124,"end":131,"loc":{"start":{"line":4,"column":28,"index":124},"end":{"line":4,"column":35,"index":131}} + "value": " 8 ", + "start":87,"end":94,"loc":{"start":{"line":2,"column":51,"index":87},"end":{"line":2,"column":58,"index":94}} + }, + { + "type": "CommentBlock", + "value": " A ", + "start":96,"end":103,"loc":{"start":{"line":4,"column":0,"index":96},"end":{"line":4,"column":7,"index":103}} } ] } diff --git a/packages/babel-parser/test/fixtures/comments/decorators/decorators-legacy-before-export/output.json b/packages/babel-parser/test/fixtures/comments/decorators/decorators-legacy-before-export/output.json index ef21aaef6329..416965a2800d 100644 --- a/packages/babel-parser/test/fixtures/comments/decorators/decorators-legacy-before-export/output.json +++ b/packages/babel-parser/test/fixtures/comments/decorators/decorators-legacy-before-export/output.json @@ -9,7 +9,7 @@ "body": [ { "type": "ExportNamedDeclaration", - "start":36,"end":86,"loc":{"start":{"line":2,"column":0,"index":36},"end":{"line":2,"column":50,"index":86}}, + "start":8,"end":86,"loc":{"start":{"line":1,"column":8,"index":8},"end":{"line":2,"column":50,"index":86}}, "specifiers": [], "source": null, "declaration": { @@ -54,13 +54,6 @@ } ] }, - "leadingComments": [ - { - "type": "CommentBlock", - "value": " 4 ", - "start":43,"end":50,"loc":{"start":{"line":2,"column":7,"index":43},"end":{"line":2,"column":14,"index":50}} - } - ], "decorators": [ { "type": "Decorator", @@ -76,13 +69,6 @@ "value": " 2 ", "start":14,"end":21,"loc":{"start":{"line":1,"column":14,"index":14},"end":{"line":1,"column":21,"index":21}} } - ], - "leadingComments": [ - { - "type": "CommentBlock", - "value": " 1 ", - "start":0,"end":7,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":7,"index":7}} - } ] }, { @@ -108,6 +94,13 @@ } ] } + ], + "leadingComments": [ + { + "type": "CommentBlock", + "value": " 4 ", + "start":43,"end":50,"loc":{"start":{"line":2,"column":7,"index":43},"end":{"line":2,"column":14,"index":50}} + } ] }, "trailingComments": [ @@ -125,14 +118,14 @@ "leadingComments": [ { "type": "CommentBlock", - "value": " 3 ", - "start":28,"end":35,"loc":{"start":{"line":1,"column":28,"index":28},"end":{"line":1,"column":35,"index":35}} + "value": " 1 ", + "start":0,"end":7,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":7,"index":7}} } ] }, { "type": "ExportDefaultDeclaration", - "start":132,"end":188,"loc":{"start":{"line":5,"column":0,"index":132},"end":{"line":5,"column":56,"index":188}}, + "start":104,"end":188,"loc":{"start":{"line":4,"column":8,"index":104},"end":{"line":5,"column":56,"index":188}}, "declaration": { "type": "ClassDeclaration", "start":104,"end":188,"loc":{"start":{"line":4,"column":8,"index":104},"end":{"line":5,"column":56,"index":188}}, @@ -157,13 +150,6 @@ } ] }, - "leadingComments": [ - { - "type": "CommentBlock", - "value": " E ", - "start":155,"end":162,"loc":{"start":{"line":5,"column":23,"index":155},"end":{"line":5,"column":30,"index":162}} - } - ], "decorators": [ { "type": "Decorator", @@ -179,18 +165,6 @@ "value": " B ", "start":110,"end":117,"loc":{"start":{"line":4,"column":14,"index":110},"end":{"line":4,"column":21,"index":117}} } - ], - "leadingComments": [ - { - "type": "CommentBlock", - "value": " 8 ", - "start":87,"end":94,"loc":{"start":{"line":2,"column":51,"index":87},"end":{"line":2,"column":58,"index":94}} - }, - { - "type": "CommentBlock", - "value": " A ", - "start":96,"end":103,"loc":{"start":{"line":4,"column":0,"index":96},"end":{"line":4,"column":7,"index":103}} - } ] }, { @@ -216,6 +190,13 @@ } ] } + ], + "leadingComments": [ + { + "type": "CommentBlock", + "value": " E ", + "start":155,"end":162,"loc":{"start":{"line":5,"column":23,"index":155},"end":{"line":5,"column":30,"index":162}} + } ] }, "innerComments": [ @@ -235,8 +216,13 @@ "leadingComments": [ { "type": "CommentBlock", - "value": " C ", - "start":124,"end":131,"loc":{"start":{"line":4,"column":28,"index":124},"end":{"line":4,"column":35,"index":131}} + "value": " 8 ", + "start":87,"end":94,"loc":{"start":{"line":2,"column":51,"index":87},"end":{"line":2,"column":58,"index":94}} + }, + { + "type": "CommentBlock", + "value": " A ", + "start":96,"end":103,"loc":{"start":{"line":4,"column":0,"index":96},"end":{"line":4,"column":7,"index":103}} } ] } diff --git a/packages/babel-parser/test/fixtures/experimental/decorators-legacy/export-decorators-on-class/output.json b/packages/babel-parser/test/fixtures/experimental/decorators-legacy/export-decorators-on-class/output.json index 9d20bae87a35..64e76a94ac0b 100644 --- a/packages/babel-parser/test/fixtures/experimental/decorators-legacy/export-decorators-on-class/output.json +++ b/packages/babel-parser/test/fixtures/experimental/decorators-legacy/export-decorators-on-class/output.json @@ -9,23 +9,12 @@ "body": [ { "type": "ExportNamedDeclaration", - "start":5,"end":22,"loc":{"start":{"line":2,"column":0,"index":5},"end":{"line":2,"column":17,"index":22}}, + "start":0,"end":22,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":2,"column":17,"index":22}}, "specifiers": [], "source": null, "declaration": { "type": "ClassDeclaration", "start":0,"end":22,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":2,"column":17,"index":22}}, - "decorators": [ - { - "type": "Decorator", - "start":0,"end":4,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":4,"index":4}}, - "expression": { - "type": "Identifier", - "start":1,"end":4,"loc":{"start":{"line":1,"column":1,"index":1},"end":{"line":1,"column":4,"index":4},"identifierName":"foo"}, - "name": "foo" - } - } - ], "id": { "type": "Identifier", "start":18,"end":19,"loc":{"start":{"line":2,"column":13,"index":18},"end":{"line":2,"column":14,"index":19},"identifierName":"A"}, @@ -36,7 +25,18 @@ "type": "ClassBody", "start":20,"end":22,"loc":{"start":{"line":2,"column":15,"index":20},"end":{"line":2,"column":17,"index":22}}, "body": [] - } + }, + "decorators": [ + { + "type": "Decorator", + "start":0,"end":4,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":4,"index":4}}, + "expression": { + "type": "Identifier", + "start":1,"end":4,"loc":{"start":{"line":1,"column":1,"index":1},"end":{"line":1,"column":4,"index":4},"identifierName":"foo"}, + "name": "foo" + } + } + ] } } ], diff --git a/packages/babel-parser/test/fixtures/experimental/decorators-legacy/export-default-decorators-on-class/output.json b/packages/babel-parser/test/fixtures/experimental/decorators-legacy/export-default-decorators-on-class/output.json index 83645ba2321c..7127a662debc 100644 --- a/packages/babel-parser/test/fixtures/experimental/decorators-legacy/export-default-decorators-on-class/output.json +++ b/packages/babel-parser/test/fixtures/experimental/decorators-legacy/export-default-decorators-on-class/output.json @@ -9,10 +9,17 @@ "body": [ { "type": "ExportDefaultDeclaration", - "start":5,"end":28,"loc":{"start":{"line":2,"column":0,"index":5},"end":{"line":2,"column":23,"index":28}}, + "start":0,"end":28,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":2,"column":23,"index":28}}, "declaration": { "type": "ClassDeclaration", "start":0,"end":28,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":2,"column":23,"index":28}}, + "id": null, + "superClass": null, + "body": { + "type": "ClassBody", + "start":26,"end":28,"loc":{"start":{"line":2,"column":21,"index":26},"end":{"line":2,"column":23,"index":28}}, + "body": [] + }, "decorators": [ { "type": "Decorator", @@ -23,14 +30,7 @@ "name": "foo" } } - ], - "id": null, - "superClass": null, - "body": { - "type": "ClassBody", - "start":26,"end":28,"loc":{"start":{"line":2,"column":21,"index":26},"end":{"line":2,"column":23,"index":28}}, - "body": [] - } + ] } } ], diff --git a/packages/babel-parser/test/fixtures/experimental/decorators-legacy/export-default-with-nested-class/output.json b/packages/babel-parser/test/fixtures/experimental/decorators-legacy/export-default-with-nested-class/output.json index ff21aa7dea8e..fb492bc67c09 100644 --- a/packages/babel-parser/test/fixtures/experimental/decorators-legacy/export-default-with-nested-class/output.json +++ b/packages/babel-parser/test/fixtures/experimental/decorators-legacy/export-default-with-nested-class/output.json @@ -9,21 +9,10 @@ "body": [ { "type": "ExportDefaultDeclaration", - "start":17,"end":109,"loc":{"start":{"line":2,"column":0,"index":17},"end":{"line":7,"column":1,"index":109}}, + "start":0,"end":109,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":7,"column":1,"index":109}}, "declaration": { "type": "ClassDeclaration", "start":0,"end":109,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":7,"column":1,"index":109}}, - "decorators": [ - { - "type": "Decorator", - "start":0,"end":16,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":16,"index":16}}, - "expression": { - "type": "Identifier", - "start":1,"end":16,"loc":{"start":{"line":1,"column":1,"index":1},"end":{"line":1,"column":16,"index":16},"identifierName":"ParentDecorator"}, - "name": "ParentDecorator" - } - } - ], "id": { "type": "Identifier", "start":38,"end":49,"loc":{"start":{"line":2,"column":21,"index":38},"end":{"line":2,"column":32,"index":49},"identifierName":"ParentClass"}, @@ -73,7 +62,18 @@ } } ] - } + }, + "decorators": [ + { + "type": "Decorator", + "start":0,"end":16,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":16,"index":16}}, + "expression": { + "type": "Identifier", + "start":1,"end":16,"loc":{"start":{"line":1,"column":1,"index":1},"end":{"line":1,"column":16,"index":16},"identifierName":"ParentDecorator"}, + "name": "ParentDecorator" + } + } + ] } } ], diff --git a/packages/babel-parser/test/fixtures/experimental/decorators/decoratorsBeforeExport-export-default/output.json b/packages/babel-parser/test/fixtures/experimental/decorators/decoratorsBeforeExport-export-default/output.json index 4a0f55b9b6ed..c6a48d26b178 100644 --- a/packages/babel-parser/test/fixtures/experimental/decorators/decoratorsBeforeExport-export-default/output.json +++ b/packages/babel-parser/test/fixtures/experimental/decorators/decoratorsBeforeExport-export-default/output.json @@ -9,21 +9,10 @@ "body": [ { "type": "ExportDefaultDeclaration", - "start":11,"end":38,"loc":{"start":{"line":2,"column":0,"index":11},"end":{"line":2,"column":27,"index":38}}, + "start":0,"end":38,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":2,"column":27,"index":38}}, "declaration": { "type": "ClassDeclaration", "start":0,"end":38,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":2,"column":27,"index":38}}, - "decorators": [ - { - "type": "Decorator", - "start":0,"end":10,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":10,"index":10}}, - "expression": { - "type": "Identifier", - "start":1,"end":10,"loc":{"start":{"line":1,"column":1,"index":1},"end":{"line":1,"column":10,"index":10},"identifierName":"decorator"}, - "name": "decorator" - } - } - ], "id": { "type": "Identifier", "start":32,"end":35,"loc":{"start":{"line":2,"column":21,"index":32},"end":{"line":2,"column":24,"index":35},"identifierName":"Foo"}, @@ -34,7 +23,18 @@ "type": "ClassBody", "start":36,"end":38,"loc":{"start":{"line":2,"column":25,"index":36},"end":{"line":2,"column":27,"index":38}}, "body": [] - } + }, + "decorators": [ + { + "type": "Decorator", + "start":0,"end":10,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":10,"index":10}}, + "expression": { + "type": "Identifier", + "start":1,"end":10,"loc":{"start":{"line":1,"column":1,"index":1},"end":{"line":1,"column":10,"index":10},"identifierName":"decorator"}, + "name": "decorator" + } + } + ] } } ], diff --git a/packages/babel-parser/test/fixtures/experimental/decorators/decoratorsBeforeExport-export/output.json b/packages/babel-parser/test/fixtures/experimental/decorators/decoratorsBeforeExport-export/output.json index 0cc486e341f1..6e2ccfcb4cf0 100644 --- a/packages/babel-parser/test/fixtures/experimental/decorators/decoratorsBeforeExport-export/output.json +++ b/packages/babel-parser/test/fixtures/experimental/decorators/decoratorsBeforeExport-export/output.json @@ -9,23 +9,12 @@ "body": [ { "type": "ExportNamedDeclaration", - "start":11,"end":30,"loc":{"start":{"line":2,"column":0,"index":11},"end":{"line":2,"column":19,"index":30}}, + "start":0,"end":30,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":2,"column":19,"index":30}}, "specifiers": [], "source": null, "declaration": { "type": "ClassDeclaration", "start":0,"end":30,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":2,"column":19,"index":30}}, - "decorators": [ - { - "type": "Decorator", - "start":0,"end":10,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":10,"index":10}}, - "expression": { - "type": "Identifier", - "start":1,"end":10,"loc":{"start":{"line":1,"column":1,"index":1},"end":{"line":1,"column":10,"index":10},"identifierName":"decorator"}, - "name": "decorator" - } - } - ], "id": { "type": "Identifier", "start":24,"end":27,"loc":{"start":{"line":2,"column":13,"index":24},"end":{"line":2,"column":16,"index":27},"identifierName":"Foo"}, @@ -36,7 +25,18 @@ "type": "ClassBody", "start":28,"end":30,"loc":{"start":{"line":2,"column":17,"index":28},"end":{"line":2,"column":19,"index":30}}, "body": [] - } + }, + "decorators": [ + { + "type": "Decorator", + "start":0,"end":10,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":10,"index":10}}, + "expression": { + "type": "Identifier", + "start":1,"end":10,"loc":{"start":{"line":1,"column":1,"index":1},"end":{"line":1,"column":10,"index":10},"identifierName":"decorator"}, + "name": "decorator" + } + } + ] } } ], diff --git a/packages/babel-parser/test/fixtures/experimental/decorators/no-export-decorators-on-class/output.json b/packages/babel-parser/test/fixtures/experimental/decorators/no-export-decorators-on-class/output.json index bebb8ae7a9b9..4f2b0e7f3213 100644 --- a/packages/babel-parser/test/fixtures/experimental/decorators/no-export-decorators-on-class/output.json +++ b/packages/babel-parser/test/fixtures/experimental/decorators/no-export-decorators-on-class/output.json @@ -12,10 +12,17 @@ "body": [ { "type": "ExportDefaultDeclaration", - "start":5,"end":28,"loc":{"start":{"line":2,"column":0,"index":5},"end":{"line":2,"column":23,"index":28}}, + "start":0,"end":28,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":2,"column":23,"index":28}}, "declaration": { "type": "ClassDeclaration", "start":0,"end":28,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":2,"column":23,"index":28}}, + "id": null, + "superClass": null, + "body": { + "type": "ClassBody", + "start":26,"end":28,"loc":{"start":{"line":2,"column":21,"index":26},"end":{"line":2,"column":23,"index":28}}, + "body": [] + }, "decorators": [ { "type": "Decorator", @@ -26,14 +33,7 @@ "name": "foo" } } - ], - "id": null, - "superClass": null, - "body": { - "type": "ClassBody", - "start":26,"end":28,"loc":{"start":{"line":2,"column":21,"index":26},"end":{"line":2,"column":23,"index":28}}, - "body": [] - } + ] } } ], From 4007d8c46dcd20af8350cc08ceb43c2e9bc54f1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Tue, 25 Oct 2022 17:30:41 +0200 Subject: [PATCH 08/10] Print inner comments in `export default` --- packages/babel-generator/src/generators/modules.ts | 1 + .../test/fixtures/comments/decorators-after-export/output.js | 3 ++- .../test/fixtures/comments/decorators-before-export/output.js | 3 ++- .../comments/decorators-legacy-before-export/output.js | 3 ++- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/babel-generator/src/generators/modules.ts b/packages/babel-generator/src/generators/modules.ts index abffa0c1a1fc..33b754920382 100644 --- a/packages/babel-generator/src/generators/modules.ts +++ b/packages/babel-generator/src/generators/modules.ts @@ -186,6 +186,7 @@ export function ExportDefaultDeclaration( } this.word("export"); + this.printInnerComments(node); this.space(); this.word("default"); this.space(); diff --git a/packages/babel-generator/test/fixtures/comments/decorators-after-export/output.js b/packages/babel-generator/test/fixtures/comments/decorators-after-export/output.js index ec4d468c88bc..2ff05e44e72b 100644 --- a/packages/babel-generator/test/fixtures/comments/decorators-after-export/output.js +++ b/packages/babel-generator/test/fixtures/comments/decorators-after-export/output.js @@ -3,6 +3,7 @@ class /* 5 */C /* 6 */ {/* 7 */} /* 8 */ /* A */ -export default /* E */ /* C */@dec1 +export /* B */ +default /* E */ /* C */@dec1 /* D */@dec2 class /* F */{/* G */} /* H */ \ No newline at end of file diff --git a/packages/babel-generator/test/fixtures/comments/decorators-before-export/output.js b/packages/babel-generator/test/fixtures/comments/decorators-before-export/output.js index bb8b96d83a49..eded9751d133 100644 --- a/packages/babel-generator/test/fixtures/comments/decorators-before-export/output.js +++ b/packages/babel-generator/test/fixtures/comments/decorators-before-export/output.js @@ -5,4 +5,5 @@ /* A */ @dec1 /* B */@dec2 -/* C */export default /* E */class /* F */{/* G */} /* H */ \ No newline at end of file +/* C */export + /* D */ default /* E */class /* F */{/* G */} /* H */ \ No newline at end of file diff --git a/packages/babel-generator/test/fixtures/comments/decorators-legacy-before-export/output.js b/packages/babel-generator/test/fixtures/comments/decorators-legacy-before-export/output.js index bb8b96d83a49..eded9751d133 100644 --- a/packages/babel-generator/test/fixtures/comments/decorators-legacy-before-export/output.js +++ b/packages/babel-generator/test/fixtures/comments/decorators-legacy-before-export/output.js @@ -5,4 +5,5 @@ /* A */ @dec1 /* B */@dec2 -/* C */export default /* E */class /* F */{/* G */} /* H */ \ No newline at end of file +/* C */export + /* D */ default /* E */class /* F */{/* G */} /* H */ \ No newline at end of file From 8f1ba1d5c73b59958aa4ff9726073a7b5d1b3b90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Tue, 25 Oct 2022 17:40:53 +0200 Subject: [PATCH 09/10] Final fix --- .../decorators-after-export/output.js | 8 +- .../babel-parser/src/parser/expression.ts | 6 +- packages/babel-parser/src/parser/statement.ts | 27 +++- .../decorators-after-export/output.json | 142 ++++++++---------- 4 files changed, 91 insertions(+), 92 deletions(-) diff --git a/packages/babel-generator/test/fixtures/comments/decorators-after-export/output.js b/packages/babel-generator/test/fixtures/comments/decorators-after-export/output.js index 2ff05e44e72b..f10c90922bd6 100644 --- a/packages/babel-generator/test/fixtures/comments/decorators-after-export/output.js +++ b/packages/babel-generator/test/fixtures/comments/decorators-after-export/output.js @@ -1,9 +1,9 @@ -/* 1 */export /* 4 */ /* 2 */@dec1 +/* 1 */export /* 2 */@dec1 /* 3 */@dec2 -class /* 5 */C /* 6 */ {/* 7 */} /* 8 */ +/* 4 */class /* 5 */C /* 6 */ {/* 7 */} /* 8 */ /* A */ export /* B */ -default /* E */ /* C */@dec1 +default /* C */@dec1 /* D */@dec2 -class /* F */{/* G */} /* H */ \ No newline at end of file +/* E */class /* F */{/* G */} /* H */ \ No newline at end of file diff --git a/packages/babel-parser/src/parser/expression.ts b/packages/babel-parser/src/parser/expression.ts index 2318aad454fa..426e28b1b9d3 100644 --- a/packages/babel-parser/src/parser/expression.ts +++ b/packages/babel-parser/src/parser/expression.ts @@ -1201,9 +1201,9 @@ export default abstract class ExpressionParser extends LValParser { decorators = this.parseDecorators(); // fall through case tt._class: - return this.maybeTakeDecorators( - decorators, - this.parseClass(this.startNode(), false), + return this.parseClass( + this.maybeTakeDecorators(decorators, this.startNode()), + false, ); case tt._new: diff --git a/packages/babel-parser/src/parser/statement.ts b/packages/babel-parser/src/parser/statement.ts index 517bf722dfa2..1fd9d654a1e0 100644 --- a/packages/babel-parser/src/parser/statement.ts +++ b/packages/babel-parser/src/parser/statement.ts @@ -395,9 +395,12 @@ export default abstract class StatementParser extends ExpressionParser { case tt._class: if (context) this.unexpected(); - return this.maybeTakeDecorators( - decorators, - this.parseClass(node as Undone, true), + return this.parseClass( + this.maybeTakeDecorators( + decorators, + node as Undone, + ), + true, ); case tt._if: @@ -547,7 +550,13 @@ export default abstract class StatementParser extends ExpressionParser { ); } - maybeTakeDecorators( + // Attach the decorators to the given class. + // NOTE: This method changes the .start location of the class, and thus + // can affect comment attachment. Calling it before or after finalizing + // the class node (and thus finalizing its comments) changes how comments + // before the `class` keyword or before the final .start location of the + // class are attached. + maybeTakeDecorators>( maybeDecorators: N.Decorator[] | null, classNode: T, exportNode?: Undone, @@ -2318,9 +2327,13 @@ export default abstract class StatementParser extends ExpressionParser { ) { this.raise(Errors.DecoratorBeforeExport, { at: this.state.startLoc }); } - return this.maybeTakeDecorators( - this.parseDecorators(false), - this.parseClass(this.startNode(), true, true), + return this.parseClass( + this.maybeTakeDecorators( + this.parseDecorators(false), + this.startNode(), + ), + true, + true, ); } diff --git a/packages/babel-parser/test/fixtures/comments/decorators/decorators-after-export/output.json b/packages/babel-parser/test/fixtures/comments/decorators/decorators-after-export/output.json index a97646fedb65..636dddcb25e8 100644 --- a/packages/babel-parser/test/fixtures/comments/decorators/decorators-after-export/output.json +++ b/packages/babel-parser/test/fixtures/comments/decorators/decorators-after-export/output.json @@ -15,45 +15,6 @@ "declaration": { "type": "ClassDeclaration", "start":23,"end":86,"loc":{"start":{"line":1,"column":23,"index":23},"end":{"line":2,"column":43,"index":86}}, - "id": { - "type": "Identifier", - "start":65,"end":66,"loc":{"start":{"line":2,"column":22,"index":65},"end":{"line":2,"column":23,"index":66},"identifierName":"C"}, - "name": "C", - "trailingComments": [ - { - "type": "CommentBlock", - "value": " 6 ", - "start":67,"end":74,"loc":{"start":{"line":2,"column":24,"index":67},"end":{"line":2,"column":31,"index":74}} - } - ], - "leadingComments": [ - { - "type": "CommentBlock", - "value": " 5 ", - "start":57,"end":64,"loc":{"start":{"line":2,"column":14,"index":57},"end":{"line":2,"column":21,"index":64}} - } - ] - }, - "superClass": null, - "body": { - "type": "ClassBody", - "start":75,"end":86,"loc":{"start":{"line":2,"column":32,"index":75},"end":{"line":2,"column":43,"index":86}}, - "body": [], - "innerComments": [ - { - "type": "CommentBlock", - "value": " 7 ", - "start":77,"end":84,"loc":{"start":{"line":2,"column":34,"index":77},"end":{"line":2,"column":41,"index":84}} - } - ], - "leadingComments": [ - { - "type": "CommentBlock", - "value": " 6 ", - "start":67,"end":74,"loc":{"start":{"line":2,"column":24,"index":67},"end":{"line":2,"column":31,"index":74}} - } - ] - }, "decorators": [ { "type": "Decorator", @@ -69,13 +30,6 @@ "value": " 3 ", "start":29,"end":36,"loc":{"start":{"line":1,"column":29,"index":29},"end":{"line":1,"column":36,"index":36}} } - ], - "leadingComments": [ - { - "type": "CommentBlock", - "value": " 2 ", - "start":15,"end":22,"loc":{"start":{"line":1,"column":15,"index":15},"end":{"line":1,"column":22,"index":22}} - } ] }, { @@ -102,11 +56,50 @@ ] } ], + "id": { + "type": "Identifier", + "start":65,"end":66,"loc":{"start":{"line":2,"column":22,"index":65},"end":{"line":2,"column":23,"index":66},"identifierName":"C"}, + "name": "C", + "trailingComments": [ + { + "type": "CommentBlock", + "value": " 6 ", + "start":67,"end":74,"loc":{"start":{"line":2,"column":24,"index":67},"end":{"line":2,"column":31,"index":74}} + } + ], + "leadingComments": [ + { + "type": "CommentBlock", + "value": " 5 ", + "start":57,"end":64,"loc":{"start":{"line":2,"column":14,"index":57},"end":{"line":2,"column":21,"index":64}} + } + ] + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start":75,"end":86,"loc":{"start":{"line":2,"column":32,"index":75},"end":{"line":2,"column":43,"index":86}}, + "body": [], + "innerComments": [ + { + "type": "CommentBlock", + "value": " 7 ", + "start":77,"end":84,"loc":{"start":{"line":2,"column":34,"index":77},"end":{"line":2,"column":41,"index":84}} + } + ], + "leadingComments": [ + { + "type": "CommentBlock", + "value": " 6 ", + "start":67,"end":74,"loc":{"start":{"line":2,"column":24,"index":67},"end":{"line":2,"column":31,"index":74}} + } + ] + }, "leadingComments": [ { "type": "CommentBlock", - "value": " 4 ", - "start":43,"end":50,"loc":{"start":{"line":2,"column":0,"index":43},"end":{"line":2,"column":7,"index":50}} + "value": " 2 ", + "start":15,"end":22,"loc":{"start":{"line":1,"column":15,"index":15},"end":{"line":1,"column":22,"index":22}} } ] }, @@ -136,27 +129,6 @@ "declaration": { "type": "ClassDeclaration", "start":135,"end":188,"loc":{"start":{"line":4,"column":39,"index":135},"end":{"line":5,"column":33,"index":188}}, - "id": null, - "superClass": null, - "body": { - "type": "ClassBody", - "start":177,"end":188,"loc":{"start":{"line":5,"column":22,"index":177},"end":{"line":5,"column":33,"index":188}}, - "body": [], - "innerComments": [ - { - "type": "CommentBlock", - "value": " G ", - "start":179,"end":186,"loc":{"start":{"line":5,"column":24,"index":179},"end":{"line":5,"column":31,"index":186}} - } - ], - "leadingComments": [ - { - "type": "CommentBlock", - "value": " F ", - "start":169,"end":176,"loc":{"start":{"line":5,"column":14,"index":169},"end":{"line":5,"column":21,"index":176}} - } - ] - }, "decorators": [ { "type": "Decorator", @@ -172,13 +144,6 @@ "value": " D ", "start":141,"end":148,"loc":{"start":{"line":4,"column":45,"index":141},"end":{"line":4,"column":52,"index":148}} } - ], - "leadingComments": [ - { - "type": "CommentBlock", - "value": " C ", - "start":127,"end":134,"loc":{"start":{"line":4,"column":31,"index":127},"end":{"line":4,"column":38,"index":134}} - } ] }, { @@ -205,11 +170,32 @@ ] } ], + "id": null, + "superClass": null, + "body": { + "type": "ClassBody", + "start":177,"end":188,"loc":{"start":{"line":5,"column":22,"index":177},"end":{"line":5,"column":33,"index":188}}, + "body": [], + "innerComments": [ + { + "type": "CommentBlock", + "value": " G ", + "start":179,"end":186,"loc":{"start":{"line":5,"column":24,"index":179},"end":{"line":5,"column":31,"index":186}} + } + ], + "leadingComments": [ + { + "type": "CommentBlock", + "value": " F ", + "start":169,"end":176,"loc":{"start":{"line":5,"column":14,"index":169},"end":{"line":5,"column":21,"index":176}} + } + ] + }, "leadingComments": [ { "type": "CommentBlock", - "value": " E ", - "start":155,"end":162,"loc":{"start":{"line":5,"column":0,"index":155},"end":{"line":5,"column":7,"index":162}} + "value": " C ", + "start":127,"end":134,"loc":{"start":{"line":4,"column":31,"index":127},"end":{"line":4,"column":38,"index":134}} } ] }, From 775781df0b320a41ed6e84906c99c86d006e43a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Tue, 25 Oct 2022 18:00:20 +0200 Subject: [PATCH 10/10] Update packages/babel-parser/src/parser/statement.ts Co-authored-by: liuxingbaoyu <30521560+liuxingbaoyu@users.noreply.github.com> --- packages/babel-parser/src/parser/statement.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/babel-parser/src/parser/statement.ts b/packages/babel-parser/src/parser/statement.ts index 1fd9d654a1e0..8fe7f45e423f 100644 --- a/packages/babel-parser/src/parser/statement.ts +++ b/packages/babel-parser/src/parser/statement.ts @@ -1121,7 +1121,7 @@ export default abstract class StatementParser extends ExpressionParser { parseExpressionStatement( node: Undone, expr: N.Expression, - /* eslint-disable @typescript-eslint/no-unused-vars -- used in TypeScript parser */ + /* eslint-disable-next-line @typescript-eslint/no-unused-vars -- used in TypeScript parser */ decorators: N.Decorator[] | null, ) { node.expression = expr;