Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support more inner comments #15008

Merged
merged 11 commits into from Oct 24, 2022
23 changes: 17 additions & 6 deletions packages/babel-generator/src/generators/expressions.ts
Expand Up @@ -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();
Expand Down Expand Up @@ -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);
}
}
}

Expand Down
38 changes: 27 additions & 11 deletions packages/babel-generator/src/generators/methods.ts
Expand Up @@ -25,14 +25,18 @@ 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) {
this.token(",");
this.space();
}
}
if (paramLength === 0) {
this.printInnerComments(parent);
}
}

export function _param(
Expand Down Expand Up @@ -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();
}
Expand All @@ -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 (
Expand Down Expand Up @@ -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);
Expand All @@ -200,6 +215,7 @@ function hasTypesOrComments(
node.predicate ||
param.typeAnnotation ||
param.optional ||
// Flow does not support `foo /*: string*/ => {};`
param.leadingComments?.length ||
param.trailingComments?.length
);
Expand Down
39 changes: 32 additions & 7 deletions packages/babel-generator/src/generators/modules.ts
Expand Up @@ -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();
}

Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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) {
Expand Down
18 changes: 7 additions & 11 deletions packages/babel-generator/src/printer.ts
Expand Up @@ -1070,18 +1070,14 @@ class Printer {
}
}
}
// todo(flow->ts): was Node
printAssertions(node: Extract<t.Node, { assertions?: t.ImportAttribute[] }>) {
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("}");
}
}

Expand Down
15 changes: 4 additions & 11 deletions packages/babel-generator/test/arrow-functions.js
Expand Up @@ -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,
Expand All @@ -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
Expand Down
@@ -0,0 +1 @@
async /* 1 */ do /* 2 */ { /* 3 */ }
@@ -0,0 +1 @@
async /* 1 */ do /* 2 */{/* 3 */};
@@ -0,0 +1 @@
(x)/* 1 */=>{}
@@ -0,0 +1 @@
x /* 1 */=> {};
@@ -0,0 +1,3 @@
class C {
async /* 1 */ foo(/* 2 */) /* 3 */ {}
}
@@ -0,0 +1,3 @@
class C {
async /* 1 */foo( /* 2 */) /* 3 */{}
}
@@ -0,0 +1,3 @@
class C {
async /* 1 */ [ /* 2 */ foo /* 3 */] /* 4 */ (/* 5 */) {}
}
@@ -0,0 +1,3 @@
class C {
async [/* 2 */foo /* 3 */] /* 1 */ /* 4 */ /* 5 */() {}
}
@@ -0,0 +1,3 @@
class C {
async /* 1 */ * /* 2 */ foo /* 3 */ (/* 4 */) /* 5 */ {}
}
@@ -0,0 +1,3 @@
class C {
async /* 1 */ /* 4 */* /* 2 */foo /* 3 */() /* 5 */{}
}
@@ -0,0 +1,3 @@
class C {
async /* 1 */ * /* 2 */ [ /* 3 */ foo /* 4 */] /* 5 */ (/* 6 */) {}
}
@@ -0,0 +1,3 @@
class C {
async /* 1 */ /* 2 */ /* 5 */ /* 6 */*[/* 3 */foo /* 4 */]() {}
}
@@ -0,0 +1 @@
import "foo" /* 1 */ assert /* 2 */ { type: "json" }
@@ -0,0 +1,3 @@
{
"plugins": ["importAssertions"]
}
@@ -0,0 +1 @@
import "foo" /* 1 */ assert /* 2 */{ type: "json" };
@@ -0,0 +1,3 @@
function * loop() {
yield /* 1 */ * /* 2 */ loop();
}
@@ -0,0 +1,3 @@
function* loop() {
yield /* 1 */* /* 2 */loop();
}