From 5920393f61502bd7bde0e90b1f2c30ad5a141f9d Mon Sep 17 00:00:00 2001 From: Ziad EL KHOURY HANNA Date: Tue, 13 Aug 2019 11:15:00 +0200 Subject: [PATCH 1/5] Fix issues in flow-comments to preserve comments and there order (fixes #10324) --- .../src/index.js | 43 ++++++++++++++++--- .../preserve-comments-order/input.js | 3 ++ .../preserve-comments-order/output.js | 4 ++ .../flow-comments/preserve-comments/input.js | 2 + .../flow-comments/preserve-comments/output.js | 3 ++ 5 files changed, 49 insertions(+), 6 deletions(-) create mode 100644 packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/preserve-comments-order/input.js create mode 100644 packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/preserve-comments-order/output.js create mode 100644 packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/preserve-comments/input.js create mode 100644 packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/preserve-comments/output.js diff --git a/packages/babel-plugin-transform-flow-comments/src/index.js b/packages/babel-plugin-transform-flow-comments/src/index.js index 2d54ae9d9854..67cc8cdf61fa 100644 --- a/packages/babel-plugin-transform-flow-comments/src/index.js +++ b/packages/babel-plugin-transform-flow-comments/src/index.js @@ -6,15 +6,46 @@ import generateCode from "@babel/generator"; export default declare(api => { api.assertVersion(7); + /** + * Removes the node at the given path while conserving the comments attached + * to it. + * @param {Path} path - The path of the node to remove + */ + function removeTypeAnnotation(path) { + const node = path.node; + const parentPath = path.parentPath; + const prevPath = path.getPrevSibling(); + const nextPath = path.getNextSibling(); + if (node.leadingComments && !prevPath.node) { + if (prevPath.node) { + nextPath.addComments("leading", node.leadingComments); + } else { + parentPath.addComments("inner", node.leadingComments); + } + } + if (node.trailingComments && !nextPath.node) { + if (prevPath.node) { + prevPath.addComments("trailing", node.trailingComments); + } else { + parentPath.addComments("inner", node.trailingComments); + } + } + path.remove(); + } + function attachComment(path, comment) { let attach = path.getPrevSibling(); let where = "trailing"; + if (!attach.node) { + attach = path.getNextSibling(); + where = "leading"; + } if (!attach.node) { attach = path.parentPath; where = "inner"; } + removeTypeAnnotation(path); attach.addComment(where, comment); - path.remove(); } function wrapInFlowComment(path, parent) { @@ -58,7 +89,7 @@ export default declare(api => { if (node.typeAnnotation) { const typeAnnotation = path.get("typeAnnotation"); path.addComment("trailing", generateComment(typeAnnotation, node)); - typeAnnotation.remove(); + removeTypeAnnotation(typeAnnotation); if (node.optional) { node.optional = false; } @@ -89,7 +120,7 @@ export default declare(api => { "leading", generateComment(returnType, typeAnnotation.node), ); - returnType.remove(); + removeTypeAnnotation(returnType); } if (node.typeParameters) { const typeParameters = path.get("typeParameters"); @@ -98,7 +129,7 @@ export default declare(api => { "trailing", generateComment(typeParameters, typeParameters.node), ); - typeParameters.remove(); + removeTypeAnnotation(typeParameters); } }, @@ -115,7 +146,7 @@ export default declare(api => { "trailing", generateComment(typeAnnotation, typeAnnotation.node), ); - typeAnnotation.remove(); + removeTypeAnnotation(typeAnnotation); } }, @@ -167,7 +198,7 @@ export default declare(api => { "trailing", generateComment(typeAnnotation, typeAnnotation.node), ); - typeAnnotation.remove(); + removeTypeAnnotation(typeAnnotation); } }, diff --git a/packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/preserve-comments-order/input.js b/packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/preserve-comments-order/input.js new file mode 100644 index 000000000000..da751daaa64f --- /dev/null +++ b/packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/preserve-comments-order/input.js @@ -0,0 +1,3 @@ +/**/ +type Foo = number; +X diff --git a/packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/preserve-comments-order/output.js b/packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/preserve-comments-order/output.js new file mode 100644 index 000000000000..e64fb34b5c43 --- /dev/null +++ b/packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/preserve-comments-order/output.js @@ -0,0 +1,4 @@ +/**/ + +/*:: type Foo = number;*/ +X; diff --git a/packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/preserve-comments/input.js b/packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/preserve-comments/input.js new file mode 100644 index 000000000000..4de529bb0fda --- /dev/null +++ b/packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/preserve-comments/input.js @@ -0,0 +1,2 @@ +/**/ +type Foo = number; diff --git a/packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/preserve-comments/output.js b/packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/preserve-comments/output.js new file mode 100644 index 000000000000..95b2dd0f9cbf --- /dev/null +++ b/packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/preserve-comments/output.js @@ -0,0 +1,3 @@ +/**/ + +/*:: type Foo = number;*/ From 5578e3b44e9bccf8b983e23e8fc1668ff230bae7 Mon Sep 17 00:00:00 2001 From: Ziad EL KHOURY HANNA Date: Tue, 13 Aug 2019 11:38:48 +0200 Subject: [PATCH 2/5] Add support in flow-comments for extends in class declarations (fixes #10323, #10321) --- .../src/index.js | 70 +++++++++++++------ .../class-extends-type-parameter/input.js | 1 + .../class-extends-type-parameter/output.js | 3 + .../input.js | 1 + .../output.js | 5 ++ .../class-type-parameter-extends/input.js | 1 + .../class-type-parameter-extends/output.js | 3 + 7 files changed, 62 insertions(+), 22 deletions(-) create mode 100644 packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/class-extends-type-parameter/input.js create mode 100644 packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/class-extends-type-parameter/output.js create mode 100644 packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/class-type-parameter-extends-type-parameter/input.js create mode 100644 packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/class-type-parameter-extends-type-parameter/output.js create mode 100644 packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/class-type-parameter-extends/input.js create mode 100644 packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/class-type-parameter-extends/output.js diff --git a/packages/babel-plugin-transform-flow-comments/src/index.js b/packages/babel-plugin-transform-flow-comments/src/index.js index 67cc8cdf61fa..8a25e3502fdf 100644 --- a/packages/babel-plugin-transform-flow-comments/src/index.js +++ b/packages/babel-plugin-transform-flow-comments/src/index.js @@ -209,31 +209,57 @@ export default declare(api => { Class(path) { const { node } = path; - if (node.typeParameters || node.implements) { - const comments = []; - if (node.typeParameters) { - const typeParameters = path.get("typeParameters"); - comments.push( - generateComment(typeParameters, typeParameters.node).replace( - /^:: /, - "", - ), - ); - typeParameters.remove(); + let typeParametersComment = ""; + if (node.typeParameters) { + const typeParameters = path.get("typeParameters"); + typeParametersComment = generateComment( + typeParameters, + typeParameters.node, + ); + removeTypeAnnotation(typeParameters); + } + + let superTypeParametersComment = ""; + if (node.superTypeParameters) { + const superTypeParameters = path.get("superTypeParameters"); + superTypeParametersComment = generateComment( + superTypeParameters, + superTypeParameters.node, + ); + removeTypeAnnotation(superTypeParameters); + } + + let implementsComment = ""; + if (node.implements) { + const impls = path.get("implements"); + implementsComment = + "implements " + + impls + .map(impl => generateComment(impl).replace(/^:: /, "")) + .join(", "); + delete node["implements"]; + } + + let bodyComment = ""; + if (node.superClass) { + if (typeParametersComment) { + const id = path.get("id"); + id.addComment("trailing", typeParametersComment); } - if (node.implements) { - const impls = path.get("implements"); - comments.push( - "implements " + - impls - .map(impl => generateComment(impl).replace(/^:: /, "")) - .join(", "), - ); - delete node["implements"]; + bodyComment = superTypeParametersComment; + } else { + bodyComment = typeParametersComment; + } + if (implementsComment) { + if (bodyComment) { + bodyComment += " " + implementsComment; + } else { + bodyComment = ":: " + implementsComment; } - + } + if (bodyComment) { const block = path.get("body"); - block.addComment("leading", ":: " + comments.join(" ")); + block.addComment("leading", bodyComment); } }, }, diff --git a/packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/class-extends-type-parameter/input.js b/packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/class-extends-type-parameter/input.js new file mode 100644 index 000000000000..c75d5b793b2e --- /dev/null +++ b/packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/class-extends-type-parameter/input.js @@ -0,0 +1 @@ +class Foo extends Bar {} diff --git a/packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/class-extends-type-parameter/output.js b/packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/class-extends-type-parameter/output.js new file mode 100644 index 000000000000..b4f9a9dba49c --- /dev/null +++ b/packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/class-extends-type-parameter/output.js @@ -0,0 +1,3 @@ +class Foo extends Bar +/*:: */ +{} diff --git a/packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/class-type-parameter-extends-type-parameter/input.js b/packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/class-type-parameter-extends-type-parameter/input.js new file mode 100644 index 000000000000..d5dcbe39c572 --- /dev/null +++ b/packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/class-type-parameter-extends-type-parameter/input.js @@ -0,0 +1 @@ +class Foo extends Bar {} diff --git a/packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/class-type-parameter-extends-type-parameter/output.js b/packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/class-type-parameter-extends-type-parameter/output.js new file mode 100644 index 000000000000..c8f48adfedc7 --- /dev/null +++ b/packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/class-type-parameter-extends-type-parameter/output.js @@ -0,0 +1,5 @@ +class Foo +/*:: */ +extends Bar +/*:: */ +{} diff --git a/packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/class-type-parameter-extends/input.js b/packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/class-type-parameter-extends/input.js new file mode 100644 index 000000000000..3fb5906c3afc --- /dev/null +++ b/packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/class-type-parameter-extends/input.js @@ -0,0 +1 @@ +class Foo extends Bar {} diff --git a/packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/class-type-parameter-extends/output.js b/packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/class-type-parameter-extends/output.js new file mode 100644 index 000000000000..47ca6593757d --- /dev/null +++ b/packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/class-type-parameter-extends/output.js @@ -0,0 +1,3 @@ +class Foo +/*:: */ +extends Bar {} From 3e1f9a3ae85e644e591decbf1bab040f3ecd1d53 Mon Sep 17 00:00:00 2001 From: Ziad EL KHOURY HANNA Date: Tue, 13 Aug 2019 14:19:15 +0200 Subject: [PATCH 3/5] Refactoring and cleanup of flow-comments plugin --- .../src/index.js | 164 ++++++++++-------- 1 file changed, 88 insertions(+), 76 deletions(-) diff --git a/packages/babel-plugin-transform-flow-comments/src/index.js b/packages/babel-plugin-transform-flow-comments/src/index.js index 8a25e3502fdf..53001351af15 100644 --- a/packages/babel-plugin-transform-flow-comments/src/index.js +++ b/packages/babel-plugin-transform-flow-comments/src/index.js @@ -33,31 +33,45 @@ export default declare(api => { path.remove(); } - function attachComment(path, comment) { - let attach = path.getPrevSibling(); - let where = "trailing"; - if (!attach.node) { - attach = path.getNextSibling(); + function attachComment({ + ofPath, + toPath, + where = "trailing", + optional = false, + comment = generateComment(ofPath, optional), + keepType = false, + }) { + if (!toPath || !toPath.node) { + toPath = ofPath.getPrevSibling(); + where = "trailing"; + } + if (!toPath.node) { + toPath = ofPath.getNextSibling(); where = "leading"; } - if (!attach.node) { - attach = path.parentPath; + if (!toPath.node) { + toPath = ofPath.parentPath; where = "inner"; } - removeTypeAnnotation(path); - attach.addComment(where, comment); + if (ofPath && !keepType) { + removeTypeAnnotation(ofPath); + } + toPath.addComment(where, comment); } - function wrapInFlowComment(path, parent) { - attachComment(path, generateComment(path, parent)); + function wrapInFlowComment(path) { + attachComment({ + ofPath: path, + comment: generateComment(path, path.parent.optional), + }); } - function generateComment(path, parent) { + function generateComment(path, optional) { let comment = path .getSource() .replace(/\*-\//g, "*-ESCAPED/") .replace(/\*\//g, "*-/"); - if (parent && parent.optional) comment = "?" + comment; + if (optional) comment = "?" + comment; if (comment[0] !== ":") comment = ":: " + comment; return comment; } @@ -73,28 +87,32 @@ export default declare(api => { visitor: { TypeCastExpression(path) { const { node } = path; - path - .get("expression") - .addComment("trailing", generateComment(path.get("typeAnnotation"))); + attachComment({ + ofPath: path.get("typeAnnotation"), + toPath: path.get("expression"), + keepType: true, + }); path.replaceWith(t.parenthesizedExpression(node.expression)); }, // support function a(b?) {} Identifier(path) { - if (path.parentPath.isFlow()) { - return; - } - + if (path.parentPath.isFlow()) return; const { node } = path; if (node.typeAnnotation) { - const typeAnnotation = path.get("typeAnnotation"); - path.addComment("trailing", generateComment(typeAnnotation, node)); - removeTypeAnnotation(typeAnnotation); + attachComment({ + ofPath: path.get("typeAnnotation"), + toPath: path, + optional: node.optional || node.typeAnnotation.optional, + }); if (node.optional) { node.optional = false; } } else if (node.optional) { - path.addComment("trailing", ":: ?"); + attachComment({ + toPath: path, + comment: ":: ?", + }); node.optional = false; } }, @@ -112,58 +130,51 @@ export default declare(api => { Function(path) { if (path.isDeclareFunction()) return; const { node } = path; - if (node.returnType) { - const returnType = path.get("returnType"); - const typeAnnotation = returnType.get("typeAnnotation"); - const block = path.get("body"); - block.addComment( - "leading", - generateComment(returnType, typeAnnotation.node), - ); - removeTypeAnnotation(returnType); - } if (node.typeParameters) { - const typeParameters = path.get("typeParameters"); - const id = path.get("id"); - id.addComment( - "trailing", - generateComment(typeParameters, typeParameters.node), - ); - removeTypeAnnotation(typeParameters); + attachComment({ + ofPath: path.get("typeParameters"), + toPath: path.get("id"), + optional: node.typeParameters.optional, + }); + } + if (node.returnType) { + attachComment({ + ofPath: path.get("returnType"), + toPath: path.get("body"), + where: "leading", + optional: node.returnType.typeAnnotation.optional, + }); } }, // support for `class X { foo: string }` - #4622 ClassProperty(path) { - const { node, parent } = path; + const { node } = path; if (!node.value) { - wrapInFlowComment(path, parent); + wrapInFlowComment(path); } else if (node.typeAnnotation) { - const typeAnnotation = path.get("typeAnnotation"); - path - .get("key") - .addComment( - "trailing", - generateComment(typeAnnotation, typeAnnotation.node), - ); - removeTypeAnnotation(typeAnnotation); + attachComment({ + ofPath: path.get("typeAnnotation"), + toPath: path.get("key"), + optional: node.typeAnnotation.optional, + }); } }, // support `export type a = {}` - #8 Error: You passed path.replaceWith() a falsy node ExportNamedDeclaration(path) { - const { node, parent } = path; + const { node } = path; if (node.exportKind !== "type" && !t.isFlow(node.declaration)) { return; } - wrapInFlowComment(path, parent); + wrapInFlowComment(path); }, // support `import type A` and `import typeof A` #10 ImportDeclaration(path) { - const { node, parent } = path; + const { node } = path; if (isTypeImport(node.importKind)) { - wrapInFlowComment(path, parent); + wrapInFlowComment(path); return; } @@ -179,32 +190,28 @@ export default declare(api => { if (typeSpecifiers.length > 0) { const typeImportNode = t.cloneNode(node); typeImportNode.specifiers = typeSpecifiers; + const comment = `:: ${generateCode(typeImportNode).code}`; if (nonTypeSpecifiers.length > 0) { - path.addComment( - "trailing", - `:: ${generateCode(typeImportNode).code}`, - ); + attachComment({ toPath: path, comment }); } else { - attachComment(path, `:: ${generateCode(typeImportNode).code}`); + attachComment({ ofPath: path, comment }); } } }, ObjectPattern(path) { const { node } = path; if (node.typeAnnotation) { - const typeAnnotation = path.get("typeAnnotation"); - path.addComment( - "trailing", - generateComment(typeAnnotation, typeAnnotation.node), - ); - removeTypeAnnotation(typeAnnotation); + attachComment({ + ofPath: path.get("typeAnnotation"), + toPath: path, + optional: node.optional || node.typeAnnotation.optional, + }); } }, Flow(path) { - const { parent } = path; - wrapInFlowComment(path, parent); + wrapInFlowComment(path); }, Class(path) { @@ -214,7 +221,7 @@ export default declare(api => { const typeParameters = path.get("typeParameters"); typeParametersComment = generateComment( typeParameters, - typeParameters.node, + typeParameters.node.optional, ); removeTypeAnnotation(typeParameters); } @@ -224,7 +231,7 @@ export default declare(api => { const superTypeParameters = path.get("superTypeParameters"); superTypeParametersComment = generateComment( superTypeParameters, - superTypeParameters.node, + superTypeParameters.node.optional, ); removeTypeAnnotation(superTypeParameters); } @@ -243,8 +250,10 @@ export default declare(api => { let bodyComment = ""; if (node.superClass) { if (typeParametersComment) { - const id = path.get("id"); - id.addComment("trailing", typeParametersComment); + attachComment({ + toPath: path.get("id"), + comment: typeParametersComment, + }); } bodyComment = superTypeParametersComment; } else { @@ -252,14 +261,17 @@ export default declare(api => { } if (implementsComment) { if (bodyComment) { - bodyComment += " " + implementsComment; + bodyComment += ` ${implementsComment}`; } else { - bodyComment = ":: " + implementsComment; + bodyComment = `:: ${implementsComment}`; } } if (bodyComment) { - const block = path.get("body"); - block.addComment("leading", bodyComment); + attachComment({ + toPath: path.get("body"), + where: "leading", + comment: bodyComment, + }); } }, }, From fb12b89716c8ce95ce264b44e09e7bf2d0f3dda1 Mon Sep 17 00:00:00 2001 From: Ziad EL KHOURY HANNA Date: Tue, 13 Aug 2019 18:05:22 +0200 Subject: [PATCH 4/5] Fix comments preservation logic of flow-comments --- .../src/index.js | 55 ++++++++----------- .../preserve-comments-order/input.js | 8 ++- .../preserve-comments-order/output.js | 11 +++- 3 files changed, 38 insertions(+), 36 deletions(-) diff --git a/packages/babel-plugin-transform-flow-comments/src/index.js b/packages/babel-plugin-transform-flow-comments/src/index.js index 53001351af15..facbd7713c58 100644 --- a/packages/babel-plugin-transform-flow-comments/src/index.js +++ b/packages/babel-plugin-transform-flow-comments/src/index.js @@ -6,33 +6,6 @@ import generateCode from "@babel/generator"; export default declare(api => { api.assertVersion(7); - /** - * Removes the node at the given path while conserving the comments attached - * to it. - * @param {Path} path - The path of the node to remove - */ - function removeTypeAnnotation(path) { - const node = path.node; - const parentPath = path.parentPath; - const prevPath = path.getPrevSibling(); - const nextPath = path.getNextSibling(); - if (node.leadingComments && !prevPath.node) { - if (prevPath.node) { - nextPath.addComments("leading", node.leadingComments); - } else { - parentPath.addComments("inner", node.leadingComments); - } - } - if (node.trailingComments && !nextPath.node) { - if (prevPath.node) { - prevPath.addComments("trailing", node.trailingComments); - } else { - parentPath.addComments("inner", node.trailingComments); - } - } - path.remove(); - } - function attachComment({ ofPath, toPath, @@ -53,10 +26,28 @@ export default declare(api => { toPath = ofPath.parentPath; where = "inner"; } - if (ofPath && !keepType) { - removeTypeAnnotation(ofPath); + if (!keepType && ofPath && ofPath.node) { + // Removes the node at `ofPath` while conserving the comments attached + // to it. + const node = ofPath.node; + const parent = ofPath.parentPath; + const prev = ofPath.getPrevSibling(); + const next = ofPath.getNextSibling(); + const isSingleChild = !(prev.node || next.node); + const leading = node.leadingComments; + const trailing = node.trailingComments; + + if (isSingleChild && leading) { + parent.addComments("inner", leading); + } + toPath.addComment(where, comment); + ofPath.remove(); + if (isSingleChild && trailing) { + parent.addComments("inner", trailing); + } + } else { + toPath.addComment(where, comment); } - toPath.addComment(where, comment); } function wrapInFlowComment(path) { @@ -223,7 +214,7 @@ export default declare(api => { typeParameters, typeParameters.node.optional, ); - removeTypeAnnotation(typeParameters); + typeParameters.remove(); } let superTypeParametersComment = ""; @@ -233,7 +224,7 @@ export default declare(api => { superTypeParameters, superTypeParameters.node.optional, ); - removeTypeAnnotation(superTypeParameters); + superTypeParameters.remove(); } let implementsComment = ""; diff --git a/packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/preserve-comments-order/input.js b/packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/preserve-comments-order/input.js index da751daaa64f..e21008c2f7d7 100644 --- a/packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/preserve-comments-order/input.js +++ b/packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/preserve-comments-order/input.js @@ -1,3 +1,7 @@ -/**/ +/*a*/ type Foo = number; -X +/*b*/ +var foo; +/*c*/ +type Bar = number; +/*d*/ diff --git a/packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/preserve-comments-order/output.js b/packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/preserve-comments-order/output.js index e64fb34b5c43..8365f7d536e2 100644 --- a/packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/preserve-comments-order/output.js +++ b/packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/preserve-comments-order/output.js @@ -1,4 +1,11 @@ -/**/ +/*a*/ /*:: type Foo = number;*/ -X; + +/*b*/ +var foo; +/*c*/ + +/*:: type Bar = number;*/ + +/*d*/ From 422685f08570e8a7b6041da98d5d0d31e8b56de5 Mon Sep 17 00:00:00 2001 From: Ziad EL KHOURY HANNA Date: Wed, 14 Aug 2019 14:21:49 +0200 Subject: [PATCH 5/5] Fix flow-comments where comments are class identifier and extends keyword --- .../src/index.js | 90 ++++++++++--------- .../input.js | 4 +- .../output.js | 25 ++++++ 3 files changed, 78 insertions(+), 41 deletions(-) diff --git a/packages/babel-plugin-transform-flow-comments/src/index.js b/packages/babel-plugin-transform-flow-comments/src/index.js index facbd7713c58..742db1f0f263 100644 --- a/packages/babel-plugin-transform-flow-comments/src/index.js +++ b/packages/babel-plugin-transform-flow-comments/src/index.js @@ -6,12 +6,18 @@ import generateCode from "@babel/generator"; export default declare(api => { api.assertVersion(7); + function commentFromString(comment) { + return typeof comment === "string" + ? { type: "CommentBlock", value: comment } + : comment; + } + function attachComment({ ofPath, toPath, where = "trailing", optional = false, - comment = generateComment(ofPath, optional), + comments = generateComment(ofPath, optional), keepType = false, }) { if (!toPath || !toPath.node) { @@ -26,6 +32,10 @@ export default declare(api => { toPath = ofPath.parentPath; where = "inner"; } + if (!Array.isArray(comments)) { + comments = [comments]; + } + comments = comments.map(commentFromString); if (!keepType && ofPath && ofPath.node) { // Removes the node at `ofPath` while conserving the comments attached // to it. @@ -40,20 +50,20 @@ export default declare(api => { if (isSingleChild && leading) { parent.addComments("inner", leading); } - toPath.addComment(where, comment); + toPath.addComments(where, comments); ofPath.remove(); if (isSingleChild && trailing) { parent.addComments("inner", trailing); } } else { - toPath.addComment(where, comment); + toPath.addComments(where, comments); } } function wrapInFlowComment(path) { attachComment({ ofPath: path, - comment: generateComment(path, path.parent.optional), + comments: generateComment(path, path.parent.optional), }); } @@ -102,7 +112,7 @@ export default declare(api => { } else if (node.optional) { attachComment({ toPath: path, - comment: ":: ?", + comments: ":: ?", }); node.optional = false; } @@ -184,9 +194,9 @@ export default declare(api => { const comment = `:: ${generateCode(typeImportNode).code}`; if (nonTypeSpecifiers.length > 0) { - attachComment({ toPath: path, comment }); + attachComment({ toPath: path, comments: comment }); } else { - attachComment({ ofPath: path, comment }); + attachComment({ ofPath: path, comments: comment }); } } }, @@ -207,61 +217,61 @@ export default declare(api => { Class(path) { const { node } = path; - let typeParametersComment = ""; + let comments = []; if (node.typeParameters) { const typeParameters = path.get("typeParameters"); - typeParametersComment = generateComment( - typeParameters, - typeParameters.node.optional, + comments.push( + generateComment(typeParameters, node.typeParameters.optional), ); + const trailingComments = node.typeParameters.trailingComments; + if (trailingComments) { + comments.push(...trailingComments); + } typeParameters.remove(); } - let superTypeParametersComment = ""; - if (node.superTypeParameters) { - const superTypeParameters = path.get("superTypeParameters"); - superTypeParametersComment = generateComment( - superTypeParameters, - superTypeParameters.node.optional, - ); - superTypeParameters.remove(); + if (node.superClass) { + if (comments.length > 0) { + attachComment({ + toPath: path.get("id"), + comments: comments, + }); + comments = []; + } + + if (node.superTypeParameters) { + const superTypeParameters = path.get("superTypeParameters"); + comments.push( + generateComment( + superTypeParameters, + superTypeParameters.node.optional, + ), + ); + superTypeParameters.remove(); + } } - let implementsComment = ""; if (node.implements) { const impls = path.get("implements"); - implementsComment = + const comment = "implements " + impls .map(impl => generateComment(impl).replace(/^:: /, "")) .join(", "); delete node["implements"]; - } - let bodyComment = ""; - if (node.superClass) { - if (typeParametersComment) { - attachComment({ - toPath: path.get("id"), - comment: typeParametersComment, - }); - } - bodyComment = superTypeParametersComment; - } else { - bodyComment = typeParametersComment; - } - if (implementsComment) { - if (bodyComment) { - bodyComment += ` ${implementsComment}`; + if (comments.length === 1) { + comments[0] += ` ${comment}`; } else { - bodyComment = `:: ${implementsComment}`; + comments.push(`:: ${comment}`); } } - if (bodyComment) { + + if (comments.length > 0) { attachComment({ toPath: path.get("body"), where: "leading", - comment: bodyComment, + comments: comments, }); } }, diff --git a/packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/class-type-parameter-extends-type-parameter/input.js b/packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/class-type-parameter-extends-type-parameter/input.js index d5dcbe39c572..7a7673af94cc 100644 --- a/packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/class-type-parameter-extends-type-parameter/input.js +++ b/packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/class-type-parameter-extends-type-parameter/input.js @@ -1 +1,3 @@ -class Foo extends Bar {} +class Foo /* inner */ extends Bar {} + +/*a*/class /*b*/Baz/*c*//*d*/extends /*e*/Bar/*f*//*g*/ {/*h*/}/*i*/ diff --git a/packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/class-type-parameter-extends-type-parameter/output.js b/packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/class-type-parameter-extends-type-parameter/output.js index c8f48adfedc7..45e9c5e696fa 100644 --- a/packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/class-type-parameter-extends-type-parameter/output.js +++ b/packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/class-type-parameter-extends-type-parameter/output.js @@ -1,5 +1,30 @@ class Foo /*:: */ + +/* inner */ extends Bar /*:: */ {} +/*a*/ + + +class +/*b*/ +Baz +/*c*/ + +/*:: */ + +/*d*/ +extends +/*e*/ +Bar +/*f*/ + +/*:: */ + +/*g*/ +{} +/*h*/ + +/*i*/