diff --git a/packages/babel-generator/src/generators/expressions.ts b/packages/babel-generator/src/generators/expressions.ts index 82680bca7868..be0779be5f7d 100644 --- a/packages/babel-generator/src/generators/expressions.ts +++ b/packages/babel-generator/src/generators/expressions.ts @@ -28,7 +28,10 @@ export function UnaryExpression(this: Printer, node: t.UnaryExpression) { export function DoExpression(this: Printer, node: t.DoExpression) { if (node.async) { this.word("async"); - this.space(); + this.ensureNoLineTerminator(() => { + this.printInnerComments(node); + this.space(); + }); } this.word("do"); this.space(); @@ -230,12 +233,20 @@ export function YieldExpression(this: Printer, node: t.YieldExpression) { this.word("yield"); if (node.delegate) { + this.ensureNoLineTerminator(() => { + this.printInnerComments(node); + }); this.token("*"); - } - - if (node.argument) { - this.space(); - this.printTerminatorless(node.argument, node, false); + if (node.argument) { + this.space(); + // line terminators are allowed after yield* + this.print(node.argument, node); + } + } else { + if (node.argument) { + this.space(); + this.printTerminatorless(node.argument, node, false); + } } } diff --git a/packages/babel-generator/src/generators/methods.ts b/packages/babel-generator/src/generators/methods.ts index 51bcdadcfae5..4cfeaf151c16 100644 --- a/packages/babel-generator/src/generators/methods.ts +++ b/packages/babel-generator/src/generators/methods.ts @@ -25,7 +25,8 @@ export function _parameters( | t.TSFunctionType | t.TSConstructorType, ) { - for (let i = 0; i < parameters.length; i++) { + const paramLength = parameters.length; + for (let i = 0; i < paramLength; i++) { this._param(parameters[i], parent); if (i < parameters.length - 1) { @@ -33,6 +34,9 @@ export function _parameters( this.space(); } } + if (paramLength === 0) { + this.printInnerComments(parent); + } } export function _param( @@ -71,9 +75,10 @@ export function _methodHead(this: Printer, node: t.Method | t.TSDeclareMethod) { this.space(); } + const { _noLineTerminator } = this; if (node.async) { - // ensure `async` is in the same line with property name - this._catchUp("start", key.loc); + // ensure no line terminator between async and class element name / * + this._noLineTerminator = true; this.word("async"); this.space(); } @@ -84,16 +89,23 @@ export function _methodHead(this: Printer, node: t.Method | t.TSDeclareMethod) { kind === "init" ) { if (node.generator) { + if (node.async) { + this.printInnerComments(node); + } this.token("*"); + this._noLineTerminator = _noLineTerminator; } } if (node.computed) { this.token("["); + this._noLineTerminator = _noLineTerminator; this.print(key, node); this.token("]"); + this.printInnerComments(node); } else { this.print(key, node); + this._noLineTerminator = _noLineTerminator; } if ( @@ -158,33 +170,36 @@ export function ArrowFunctionExpression( this: Printer, node: t.ArrowFunctionExpression, ) { + const { _noLineTerminator } = this; if (node.async) { + this._noLineTerminator = true; this.word("async"); this.space(); } - const firstParam = node.params[0]; - // Try to avoid printing parens in simple cases, but only if we're pretty // sure that they aren't needed by type annotations or potential newlines. + let firstParam; if ( !this.format.retainLines && - // Auxiliary comments can introduce unexpected newlines - !this.format.auxiliaryCommentBefore && - !this.format.auxiliaryCommentAfter && node.params.length === 1 && - isIdentifier(firstParam) && + isIdentifier((firstParam = node.params[0])) && !hasTypesOrComments(node, firstParam) ) { this.print(firstParam, node); + this._noLineTerminator = _noLineTerminator; } else { + this._noLineTerminator = _noLineTerminator; this._params(node); } this._predicate(node); + this.ensureNoLineTerminator(() => { + this.space(); + this.printInnerComments(node); + this.token("=>"); + }); - this.space(); - this.token("=>"); this.space(); this.print(node.body, node); @@ -200,6 +215,7 @@ function hasTypesOrComments( node.predicate || param.typeAnnotation || param.optional || + // Flow does not support `foo /*: string*/ => {};` param.leadingComments?.length || param.trailingComments?.length ); diff --git a/packages/babel-generator/src/generators/modules.ts b/packages/babel-generator/src/generators/modules.ts index 08c47bc17d9f..abffa0c1a1fc 100644 --- a/packages/babel-generator/src/generators/modules.ts +++ b/packages/babel-generator/src/generators/modules.ts @@ -80,9 +80,19 @@ export function ExportAllDeclaration( this.space(); this.word("from"); this.space(); - this.print(node.source, node); // @ts-expect-error Fixme: assertions is not defined in DeclareExportAllDeclaration - this.printAssertions(node); + if (node.assertions?.length) { + this.ensureNoLineTerminator(() => { + this.print(node.source, node); + this.space(); + this.word("assert"); + }); + // @ts-expect-error Fixme: assertions is not defined in DeclareExportAllDeclaration + this.printAssertions(node); + } else { + this.print(node.source, node); + } + this.semicolon(); } @@ -146,8 +156,16 @@ export function ExportNamedDeclaration( this.space(); this.word("from"); this.space(); - this.print(node.source, node); - this.printAssertions(node); + if (node.assertions?.length) { + this.ensureNoLineTerminator(() => { + this.print(node.source, node); + this.space(); + this.word("assert"); + }); + this.printAssertions(node); + } else { + this.print(node.source, node); + } } this.semicolon(); @@ -220,9 +238,16 @@ export function ImportDeclaration(this: Printer, node: t.ImportDeclaration) { this.space(); } - this.print(node.source, node); - - this.printAssertions(node); + if (node.assertions?.length) { + this.print(node.source, node, true); + this.ensureNoLineTerminator(() => { + this.space(); + this.word("assert"); + }); + this.printAssertions(node); + } else { + this.print(node.source, node); + } if (!process.env.BABEL_8_BREAKING) { // @ts-ignore(Babel 7 vs Babel 8) Babel 7 supports module attributes if (node.attributes?.length) { diff --git a/packages/babel-generator/src/printer.ts b/packages/babel-generator/src/printer.ts index 1d1c30c33712..7d39d5c7e7c3 100644 --- a/packages/babel-generator/src/printer.ts +++ b/packages/babel-generator/src/printer.ts @@ -1070,18 +1070,14 @@ class Printer { } } } - // todo(flow->ts): was Node printAssertions(node: Extract) { - if (node.assertions?.length) { - this.space(); - this.word("assert"); - this.space(); - this.token("{"); - this.space(); - this.printList(node.assertions, node); - this.space(); - this.token("}"); - } + this.space(); + this.printInnerComments(node); + this.token("{"); + this.space(); + this.printList(node.assertions, node); + this.space(); + this.token("}"); } } diff --git a/packages/babel-generator/test/arrow-functions.js b/packages/babel-generator/test/arrow-functions.js index ec9cdc3c4b2b..537ca0c8da59 100644 --- a/packages/babel-generator/test/arrow-functions.js +++ b/packages/babel-generator/test/arrow-functions.js @@ -28,18 +28,15 @@ describe("parameter parentheses", () => { const output = generate(ast, { auxiliaryCommentBefore: "BEFORE" }).code; expect(output).toMatchInlineSnapshot(` "() => {}; - ( /*BEFORE*/ - a) => {}; + a => {}; ( /*BEFORE*/ a, /*BEFORE*/ b) => {}; async () => {}; - async ( - /*BEFORE*/ - a) => {}; + async /*BEFORE*/a => {}; async ( /*BEFORE*/ a, @@ -53,18 +50,14 @@ describe("parameter parentheses", () => { const output = generate(ast, { auxiliaryCommentAfter: "AFTER" }).code; expect(output).toMatchInlineSnapshot(` "() => {}; - (a - /*AFTER*/ - ) => {}; + a /*AFTER*/=> {}; (a /*AFTER*/ , b /*AFTER*/ ) => {}; async () => {}; - async (a - /*AFTER*/ - ) => {}; + async a /*AFTER*/=> {}; async (a /*AFTER*/ , b diff --git a/packages/babel-generator/test/fixtures/async-do-expressions/inner-comments/input.js b/packages/babel-generator/test/fixtures/async-do-expressions/inner-comments/input.js new file mode 100644 index 000000000000..6f070e80c4a6 --- /dev/null +++ b/packages/babel-generator/test/fixtures/async-do-expressions/inner-comments/input.js @@ -0,0 +1 @@ +async /* 1 */ do /* 2 */ { /* 3 */ } diff --git a/packages/babel-generator/test/fixtures/async-do-expressions/inner-comments/output.js b/packages/babel-generator/test/fixtures/async-do-expressions/inner-comments/output.js new file mode 100644 index 000000000000..a9654126b38b --- /dev/null +++ b/packages/babel-generator/test/fixtures/async-do-expressions/inner-comments/output.js @@ -0,0 +1 @@ +async /* 1 */ do /* 2 */{/* 3 */}; \ No newline at end of file diff --git a/packages/babel-generator/test/fixtures/comments/arrow-single-param-comment/input.js b/packages/babel-generator/test/fixtures/comments/arrow-single-param-comment/input.js new file mode 100644 index 000000000000..3429c0b66900 --- /dev/null +++ b/packages/babel-generator/test/fixtures/comments/arrow-single-param-comment/input.js @@ -0,0 +1 @@ +(x)/* 1 */=>{} diff --git a/packages/babel-generator/test/fixtures/comments/arrow-single-param-comment/output.js b/packages/babel-generator/test/fixtures/comments/arrow-single-param-comment/output.js new file mode 100644 index 000000000000..286aeba5d144 --- /dev/null +++ b/packages/babel-generator/test/fixtures/comments/arrow-single-param-comment/output.js @@ -0,0 +1 @@ +x /* 1 */=> {}; \ No newline at end of file diff --git a/packages/babel-generator/test/fixtures/comments/async-class-method-comment/input.js b/packages/babel-generator/test/fixtures/comments/async-class-method-comment/input.js new file mode 100644 index 000000000000..41537f60553c --- /dev/null +++ b/packages/babel-generator/test/fixtures/comments/async-class-method-comment/input.js @@ -0,0 +1,3 @@ +class C { + async /* 1 */ foo(/* 2 */) /* 3 */ {} +} diff --git a/packages/babel-generator/test/fixtures/comments/async-class-method-comment/output.js b/packages/babel-generator/test/fixtures/comments/async-class-method-comment/output.js new file mode 100644 index 000000000000..8302e190cd10 --- /dev/null +++ b/packages/babel-generator/test/fixtures/comments/async-class-method-comment/output.js @@ -0,0 +1,3 @@ +class C { + async /* 1 */foo( /* 2 */) /* 3 */{} +} \ No newline at end of file diff --git a/packages/babel-generator/test/fixtures/comments/async-class-method-computed-key-comment/input.js b/packages/babel-generator/test/fixtures/comments/async-class-method-computed-key-comment/input.js new file mode 100644 index 000000000000..08504fa88eb9 --- /dev/null +++ b/packages/babel-generator/test/fixtures/comments/async-class-method-computed-key-comment/input.js @@ -0,0 +1,3 @@ +class C { + async /* 1 */ [ /* 2 */ foo /* 3 */] /* 4 */ (/* 5 */) {} +} diff --git a/packages/babel-generator/test/fixtures/comments/async-class-method-computed-key-comment/output.js b/packages/babel-generator/test/fixtures/comments/async-class-method-computed-key-comment/output.js new file mode 100644 index 000000000000..dbca0b9748d5 --- /dev/null +++ b/packages/babel-generator/test/fixtures/comments/async-class-method-computed-key-comment/output.js @@ -0,0 +1,3 @@ +class C { + async [/* 2 */foo /* 3 */] /* 1 */ /* 4 */ /* 5 */() {} +} \ No newline at end of file diff --git a/packages/babel-generator/test/fixtures/comments/async-generator-class-method-comment/input.js b/packages/babel-generator/test/fixtures/comments/async-generator-class-method-comment/input.js new file mode 100644 index 000000000000..0dd6805e1e51 --- /dev/null +++ b/packages/babel-generator/test/fixtures/comments/async-generator-class-method-comment/input.js @@ -0,0 +1,3 @@ +class C { + async /* 1 */ * /* 2 */ foo /* 3 */ (/* 4 */) /* 5 */ {} +} diff --git a/packages/babel-generator/test/fixtures/comments/async-generator-class-method-comment/output.js b/packages/babel-generator/test/fixtures/comments/async-generator-class-method-comment/output.js new file mode 100644 index 000000000000..89f3e529357b --- /dev/null +++ b/packages/babel-generator/test/fixtures/comments/async-generator-class-method-comment/output.js @@ -0,0 +1,3 @@ +class C { + async /* 1 */ /* 4 */* /* 2 */foo /* 3 */() /* 5 */{} +} \ No newline at end of file diff --git a/packages/babel-generator/test/fixtures/comments/async-generator-class-method-computed-key-comment/input.js b/packages/babel-generator/test/fixtures/comments/async-generator-class-method-computed-key-comment/input.js new file mode 100644 index 000000000000..8d4ee08883c1 --- /dev/null +++ b/packages/babel-generator/test/fixtures/comments/async-generator-class-method-computed-key-comment/input.js @@ -0,0 +1,3 @@ +class C { + async /* 1 */ * /* 2 */ [ /* 3 */ foo /* 4 */] /* 5 */ (/* 6 */) {} +} diff --git a/packages/babel-generator/test/fixtures/comments/async-generator-class-method-computed-key-comment/output.js b/packages/babel-generator/test/fixtures/comments/async-generator-class-method-computed-key-comment/output.js new file mode 100644 index 000000000000..46783d555037 --- /dev/null +++ b/packages/babel-generator/test/fixtures/comments/async-generator-class-method-computed-key-comment/output.js @@ -0,0 +1,3 @@ +class C { + async /* 1 */ /* 2 */ /* 5 */ /* 6 */*[/* 3 */foo /* 4 */]() {} +} \ No newline at end of file diff --git a/packages/babel-generator/test/fixtures/comments/import-assertion-inner-comment/input.js b/packages/babel-generator/test/fixtures/comments/import-assertion-inner-comment/input.js new file mode 100644 index 000000000000..a682899803dd --- /dev/null +++ b/packages/babel-generator/test/fixtures/comments/import-assertion-inner-comment/input.js @@ -0,0 +1 @@ +import "foo" /* 1 */ assert /* 2 */ { type: "json" } diff --git a/packages/babel-generator/test/fixtures/comments/import-assertion-inner-comment/options.json b/packages/babel-generator/test/fixtures/comments/import-assertion-inner-comment/options.json new file mode 100644 index 000000000000..a3a80a8b1511 --- /dev/null +++ b/packages/babel-generator/test/fixtures/comments/import-assertion-inner-comment/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["importAssertions"] +} diff --git a/packages/babel-generator/test/fixtures/comments/import-assertion-inner-comment/output.js b/packages/babel-generator/test/fixtures/comments/import-assertion-inner-comment/output.js new file mode 100644 index 000000000000..15516625752a --- /dev/null +++ b/packages/babel-generator/test/fixtures/comments/import-assertion-inner-comment/output.js @@ -0,0 +1 @@ +import "foo" /* 1 */ assert /* 2 */{ type: "json" }; \ No newline at end of file diff --git a/packages/babel-generator/test/fixtures/comments/yield-star-inner-comment/input.js b/packages/babel-generator/test/fixtures/comments/yield-star-inner-comment/input.js new file mode 100644 index 000000000000..2da4cbddc5c2 --- /dev/null +++ b/packages/babel-generator/test/fixtures/comments/yield-star-inner-comment/input.js @@ -0,0 +1,3 @@ +function * loop() { + yield /* 1 */ * /* 2 */ loop(); +} diff --git a/packages/babel-generator/test/fixtures/comments/yield-star-inner-comment/output.js b/packages/babel-generator/test/fixtures/comments/yield-star-inner-comment/output.js new file mode 100644 index 000000000000..81c6fdfccdcf --- /dev/null +++ b/packages/babel-generator/test/fixtures/comments/yield-star-inner-comment/output.js @@ -0,0 +1,3 @@ +function* loop() { + yield /* 1 */* /* 2 */loop(); +} \ No newline at end of file