Simplify the special-case printing of single-param arrow functions (#13204)

* Simplify the special-case printing of single-param arrow functions

* Update test fixtures with single-param arrow functions

* Add some explicit snapshot tests for known edge-cases
This commit is contained in:
Stuart Cook 2021-04-27 00:26:45 +10:00 committed by GitHub
parent 10f4d08efb
commit 3d4b801bb9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 152 additions and 41 deletions

View File

@ -112,32 +112,18 @@ export function ArrowFunctionExpression(
const firstParam = node.params[0]; 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.
if ( if (
!this.format.retainLines &&
// Auxiliary comments can introduce unexpected newlines
!this.format.auxiliaryCommentBefore &&
!this.format.auxiliaryCommentAfter &&
node.params.length === 1 && node.params.length === 1 &&
t.isIdentifier(firstParam) && t.isIdentifier(firstParam) &&
!hasTypes(node, firstParam) !hasTypesOrComments(node, firstParam)
) { ) {
if ( this.print(firstParam, node);
(this.format.retainLines || node.async) &&
((node.loc &&
node.body.loc &&
node.loc.start.line < node.body.loc.start.line) ||
firstParam.leadingComments?.length ||
firstParam.trailingComments?.length)
) {
this.token("(");
if (firstParam.loc && firstParam.loc.start.line > node.loc.start.line) {
this.indent();
this.print(firstParam, node);
this.dedent();
this._catchUp("start", node.body.loc);
} else {
this.print(firstParam, node);
}
this.token(")");
} else {
this.print(firstParam, node);
}
} else { } else {
this._params(node); this._params(node);
} }
@ -151,12 +137,18 @@ export function ArrowFunctionExpression(
this.print(node.body, node); this.print(node.body, node);
} }
function hasTypes(node, param) { function hasTypesOrComments(
return ( node: t.ArrowFunctionExpression,
param: t.Identifier,
): boolean {
return !!(
node.typeParameters || node.typeParameters ||
node.returnType || node.returnType ||
// @ts-expect-error
node.predicate ||
param.typeAnnotation || param.typeAnnotation ||
param.optional || param.optional ||
param.trailingComments param.leadingComments?.length ||
param.trailingComments?.length
); );
} }

View File

@ -0,0 +1,119 @@
import generate from "../lib";
import { parse } from "@babel/parser";
describe("parameter parentheses", () => {
// Common source text for several snapshot tests
const source = `
() => {};
a => {};
(a, b) => {};
async () => {};
async a => {};
async (a, b) => {};
`;
// Apply a callback function to each parameter in the AST of the above source
function forEachParam(ast, callbackFn) {
ast.program.body.forEach(s => {
s.expression.params.forEach(p => {
callbackFn(p);
});
});
}
it("auxiliaryCommentBefore", () => {
const ast = parse(source);
forEachParam(ast, p => (p.loc = null));
const output = generate(ast, { auxiliaryCommentBefore: "BEFORE" }).code;
expect(output).toMatchInlineSnapshot(`
"() => {};
(
/*BEFORE*/
a) => {};
(
/*BEFORE*/
a,
/*BEFORE*/
b) => {};
async () => {};
async (
/*BEFORE*/
a) => {};
async (
/*BEFORE*/
a,
/*BEFORE*/
b) => {};"
`);
});
it("auxiliaryCommentAfter", () => {
const ast = parse(source);
forEachParam(ast, p => (p.loc = null));
const output = generate(ast, { auxiliaryCommentAfter: "AFTER" }).code;
expect(output).toMatchInlineSnapshot(`
"() => {};
(a
/*AFTER*/
) => {};
(a
/*AFTER*/
, b
/*AFTER*/
) => {};
async () => {};
async (a
/*AFTER*/
) => {};
async (a
/*AFTER*/
, b
/*AFTER*/
) => {};"
`);
});
it("empty leadingComments array", () => {
const ast = parse(source);
forEachParam(ast, p => (p.leadingComments = []));
const output = generate(ast).code;
expect(output).toMatchInlineSnapshot(`
"() => {};
a => {};
(a, b) => {};
async () => {};
async a => {};
async (a, b) => {};"
`);
});
it("empty trailingComments array", () => {
const ast = parse(source);
forEachParam(ast, p => (p.trailingComments = []));
const output = generate(ast).code;
expect(output).toMatchInlineSnapshot(`
"() => {};
a => {};
(a, b) => {};
async () => {};
async a => {};
async (a, b) => {};"
`);
});
});

View File

@ -1,11 +1,11 @@
var fn = async ( var fn = async (
arg arg) =>
) => {}; {};
async (x) => async (x) =>
{}; {};
async x => {}; async (x) => {};
async (x) => async (x) =>
{}; {};

View File

@ -14,4 +14,4 @@ var f = (x: mixed): %checks => typeof x === "string";
const foo2 = (x: mixed): boolean %checks => typeof x === "string"; const foo2 = (x: mixed): boolean %checks => typeof x === "string";
x: %checks => x !== null; (x): %checks => x !== null;

View File

@ -1,8 +1,8 @@
const x = async ( // some comment const x = async ( // some comment
a) => { a) => {
return foo(await a); return foo(await a);
}; };
function foo(a) { function foo(a) {
return a; return a;
} }

View File

@ -1,7 +1,7 @@
var _ref2; var _ref2;
const { const {
[(_ref) => { [_ref => {
let rest = babelHelpers.extends({}, _ref); let rest = babelHelpers.extends({}, _ref);
let b = babelHelpers.extends({}, {}); let b = babelHelpers.extends({}, {});
}]: a, }]: a,

View File

@ -1,7 +1,7 @@
var _ref2; var _ref2;
const { const {
a = (_ref) => { a = _ref => {
let rest = babelHelpers.extends({}, _ref); let rest = babelHelpers.extends({}, _ref);
let b = babelHelpers.extends({}, {}); let b = babelHelpers.extends({}, {});
}, },

View File

@ -1,4 +1,4 @@
(_ref) => { _ref => {
let R = babelHelpers.extends({}, _ref); let R = babelHelpers.extends({}, _ref);
let a = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : R; let a = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : R;
}; };
@ -32,7 +32,7 @@
}(); }();
}; };
(_ref6) => { _ref6 => {
let R = babelHelpers.extends({}, _ref6); let R = babelHelpers.extends({}, _ref6);
let a = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : f(R); let a = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : f(R);
}; };

View File

@ -15,7 +15,7 @@ const _bar = bar(),
const { const {
a a
} = foo((_ref) => { } = foo(_ref => {
let { let {
b b
} = _ref, } = _ref,

View File

@ -3,7 +3,7 @@ const get = () => {
return 3; return 3;
}; };
const f = (_ref) => { const f = _ref => {
let { let {
a = get(), a = get(),
b b

View File

@ -1,5 +1,5 @@
// Edge // Edge
(_ref) => { _ref => {
var { var {
x = 2 x = 2
} = _ref; } = _ref;

View File

@ -1,4 +1,4 @@
(_ref) => { _ref => {
var { var {
x = 2 x = 2
} = _ref; } = _ref;

View File

@ -1,4 +1,4 @@
(_ref) => { _ref => {
let _ref$x = _ref.x, let _ref$x = _ref.x,
x = _ref$x === void 0 ? 2 : _ref$x; x = _ref$x === void 0 ? 2 : _ref$x;
}; };

View File

@ -1,4 +1,4 @@
(_ref) => { _ref => {
let { let {
x = 2 x = 2
} = _ref; } = _ref;