From af8686c146648bd21eebb376fa243567eb26175b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Wed, 17 May 2023 11:02:19 +0300 Subject: [PATCH] Fix comments attachment --- packages/babel-parser/src/parser/comments.ts | 34 ++++++ packages/babel-parser/src/parser/statement.ts | 1 + .../import-reflection/comments/input.mjs | 1 + .../import-reflection/comments/output.json | 112 ++++++++++++++++++ 4 files changed, 148 insertions(+) create mode 100644 packages/babel-parser/test/fixtures/experimental/import-reflection/comments/input.mjs create mode 100644 packages/babel-parser/test/fixtures/experimental/import-reflection/comments/output.json diff --git a/packages/babel-parser/src/parser/comments.ts b/packages/babel-parser/src/parser/comments.ts index 03e2db053db1..a81dfd6d58af 100644 --- a/packages/babel-parser/src/parser/comments.ts +++ b/packages/babel-parser/src/parser/comments.ts @@ -246,6 +246,40 @@ export default class CommentsParser extends BaseParser { } } + /* eslint-disable no-irregular-whitespace */ + /** + * Reset previous node leading comments. Used in import phase modifiers + * parsing. We parse `module` in `import module foo from ...` as an + * identifier but may reinterpret it into a phase modifier later. In this + * case the identifier is not part of the AST and we should sync the + * knowledge to commentStacks + * + * For example, when parsing + * ``` + * import /* 1 *​/ module a from "a"; + * ``` + * the comment whitespace `/* 1 *​/` has trailing node Identifier(module). When + * we see that `module` is not a default import binding, we mark `/* 1 *​/` as + * inner comments of the ImportDeclaration. So `/* 1 *​/` should be detached from + * the Identifier node. + * + * @param node the last finished AST node _before_ current token + */ + /* eslint-enable no-irregular-whitespace */ + resetPreviousNodeLeadingComments(node: Node) { + const { commentStack } = this.state; + const { length } = commentStack; + if (length === 0) return; + + for (let i = length - 1; i >= 0; i--) { + const commentWS = commentStack[i]; + if (commentWS.trailingNode === node) { + commentWS.trailingNode = null; + } + if (commentWS.end < node.start) break; + } + } + /** * Attach a node to the comment whitespaces right before/after * the given range. diff --git a/packages/babel-parser/src/parser/statement.ts b/packages/babel-parser/src/parser/statement.ts index 8a3282fd7b23..d057575ae9f4 100644 --- a/packages/babel-parser/src/parser/statement.ts +++ b/packages/babel-parser/src/parser/statement.ts @@ -2961,6 +2961,7 @@ export default abstract class StatementParser extends ExpressionParser { type !== tt.comma; if (isImportPhase) { + this.resetPreviousNodeLeadingComments(phaseIdentifier); this.applyImportPhase( node as Undone, isExport, diff --git a/packages/babel-parser/test/fixtures/experimental/import-reflection/comments/input.mjs b/packages/babel-parser/test/fixtures/experimental/import-reflection/comments/input.mjs new file mode 100644 index 000000000000..9726c2258813 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/import-reflection/comments/input.mjs @@ -0,0 +1 @@ +/* 0 */ import /* 1 */ module /* 2 */ Foo /* 3 */ from /* 4 */ "foo" /* 5 */; \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/experimental/import-reflection/comments/output.json b/packages/babel-parser/test/fixtures/experimental/import-reflection/comments/output.json new file mode 100644 index 000000000000..d96d9c5124d9 --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/import-reflection/comments/output.json @@ -0,0 +1,112 @@ +{ + "type": "File", + "start":0,"end":77,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":77,"index":77}}, + "program": { + "type": "Program", + "start":0,"end":77,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":77,"index":77}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ImportDeclaration", + "start":8,"end":77,"loc":{"start":{"line":1,"column":8,"index":8},"end":{"line":1,"column":77,"index":77}}, + "module": true, + "specifiers": [ + { + "type": "ImportDefaultSpecifier", + "start":38,"end":41,"loc":{"start":{"line":1,"column":38,"index":38},"end":{"line":1,"column":41,"index":41}}, + "local": { + "type": "Identifier", + "start":38,"end":41,"loc":{"start":{"line":1,"column":38,"index":38},"end":{"line":1,"column":41,"index":41},"identifierName":"Foo"}, + "name": "Foo" + }, + "trailingComments": [ + { + "type": "CommentBlock", + "value": " 3 ", + "start":42,"end":49,"loc":{"start":{"line":1,"column":42,"index":42},"end":{"line":1,"column":49,"index":49}} + } + ], + "leadingComments": [ + { + "type": "CommentBlock", + "value": " 2 ", + "start":30,"end":37,"loc":{"start":{"line":1,"column":30,"index":30},"end":{"line":1,"column":37,"index":37}} + } + ] + } + ], + "source": { + "type": "StringLiteral", + "start":63,"end":68,"loc":{"start":{"line":1,"column":63,"index":63},"end":{"line":1,"column":68,"index":68}}, + "extra": { + "rawValue": "foo", + "raw": "\"foo\"" + }, + "value": "foo", + "trailingComments": [ + { + "type": "CommentBlock", + "value": " 5 ", + "start":69,"end":76,"loc":{"start":{"line":1,"column":69,"index":69},"end":{"line":1,"column":76,"index":76}} + } + ], + "leadingComments": [ + { + "type": "CommentBlock", + "value": " 4 ", + "start":55,"end":62,"loc":{"start":{"line":1,"column":55,"index":55},"end":{"line":1,"column":62,"index":62}} + } + ] + }, + "innerComments": [ + { + "type": "CommentBlock", + "value": " 1 ", + "start":15,"end":22,"loc":{"start":{"line":1,"column":15,"index":15},"end":{"line":1,"column":22,"index":22}} + } + ], + "leadingComments": [ + { + "type": "CommentBlock", + "value": " 0 ", + "start":0,"end":7,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":7,"index":7}} + } + ] + } + ], + "directives": [] + }, + "comments": [ + { + "type": "CommentBlock", + "value": " 0 ", + "start":0,"end":7,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":7,"index":7}} + }, + { + "type": "CommentBlock", + "value": " 1 ", + "start":15,"end":22,"loc":{"start":{"line":1,"column":15,"index":15},"end":{"line":1,"column":22,"index":22}} + }, + { + "type": "CommentBlock", + "value": " 2 ", + "start":30,"end":37,"loc":{"start":{"line":1,"column":30,"index":30},"end":{"line":1,"column":37,"index":37}} + }, + { + "type": "CommentBlock", + "value": " 3 ", + "start":42,"end":49,"loc":{"start":{"line":1,"column":42,"index":42},"end":{"line":1,"column":49,"index":49}} + }, + { + "type": "CommentBlock", + "value": " 4 ", + "start":55,"end":62,"loc":{"start":{"line":1,"column":55,"index":55},"end":{"line":1,"column":62,"index":62}} + }, + { + "type": "CommentBlock", + "value": " 5 ", + "start":69,"end":76,"loc":{"start":{"line":1,"column":69,"index":69},"end":{"line":1,"column":76,"index":76}} + } + ] +}