Make curried arrow function and normal arrow function consistent (#14633)

Co-authored-by: fisker Cheung <lionkay@gmail.com>
This commit is contained in:
Seiyaandfisker Cheung authored and GitHub committed 2023-04-27 11:01:35 +08:00
1 parent 27f7723bf9
commit 7f64e920de
12 files changed
+1392 -231

No files matched your search

+16
View File
@@ -0,0 +1,16 @@
#### Improve consistency between curried and non-curried arrow function (#14633 by @seiyab, @fisker)
<!-- prettier-ignore -->
```jsx
// Input
Y(() => a ? b : c);
Y(() => () => a ? b : c);
// Prettier stable
Y(() => (a ? b : c));
Y(() => () => a ? b : c);
// Prettier main
Y(() => (a ? b : c));
Y(() => () => (a ? b : c));
```
+329
View File
@@ -0,0 +1,329 @@
import {
printDanglingComments,
printCommentsSeparately,
} from "../../main/comments/print.js";
import getNextNonSpaceNonCommentCharacterIndex from "../../utils/get-next-non-space-non-comment-character-index.js";
import {
line,
softline,
group,
indent,
ifBreak,
join,
indentIfBreak,
} from "../../document/builders.js";
import { removeLines, willBreak } from "../../document/utils.js";
import { ArgExpansionBailout } from "../../common/errors.js";
import {
getFunctionParameters,
hasLeadingOwnLineComment,
isJsxElement,
isTemplateOnItsOwnLine,
shouldPrintComma,
startsWithNoLookaheadToken,
isBinaryish,
hasComment,
isCallLikeExpression,
isArrayOrTupleExpression,
isObjectOrRecordExpression,
} from "../utils/index.js";
import { locEnd } from "../loc.js";
import { printFunctionParameters } from "./function-parameters.js";
import { printReturnType, shouldPrintParamsWithoutParens } from "./function.js";
/**
* @typedef {import("../../common/ast-path.js").default} AstPath
* @typedef {import("../../document/builders.js").Doc} Doc
*/
// In order to avoid confusion between
// a => a ? a : a
// a <= a ? a : a
const shouldAddParensIfNotBreakCache = new WeakMap();
function shouldAddParensIfNotBreak(node) {
if (!shouldAddParensIfNotBreakCache.has(node)) {
shouldAddParensIfNotBreakCache.set(
node,
node.type === "ConditionalExpression" &&
!startsWithNoLookaheadToken(
node,
(node) => node.type === "ObjectExpression"
)
);
}
return shouldAddParensIfNotBreakCache.get(node);
}
// We handle sequence expressions as the body of arrows specially,
// so that the required parentheses end up on their own lines.
const shouldAlwaysAddParens = (node) => node.type === "SequenceExpression";
function printArrowFunction(path, options, print, args = {}) {
/** @type {Doc[]} */
const signatureDocs = [];
/** @type {Doc} */
let bodyDoc;
/** @type {Doc[]} */
const bodyComments = [];
let shouldBreakChain = false;
const shouldPrintAsChain =
!args.expandLastArg && path.node.body.type === "ArrowFunctionExpression";
let functionBody;
(function rec() {
const { node } = path;
const signatureDoc = printArrowFunctionSignature(
path,
options,
print,
args
);
if (signatureDocs.length === 0) {
signatureDocs.push(signatureDoc);
} else {
const { leading, trailing } = printCommentsSeparately(path, options);
signatureDocs.push([leading, signatureDoc]);
bodyComments.unshift(trailing);
}
if (shouldPrintAsChain) {
shouldBreakChain ||=
// Always break the chain if:
(node.returnType && getFunctionParameters(node).length > 0) ||
node.typeParameters ||
getFunctionParameters(node).some(
(param) => param.type !== "Identifier"
);
}
if (!shouldPrintAsChain || node.body.type !== "ArrowFunctionExpression") {
bodyDoc = print("body", args);
functionBody = node.body;
} else {
path.call(rec, "body");
}
})();
// We want to always keep these types of nodes on the same line
// as the arrow.
const shouldPutBodyOnSameLine =
!hasLeadingOwnLineComment(options.originalText, functionBody) &&
(shouldAlwaysAddParens(functionBody) ||
mayBreakAfterShortPrefix(functionBody, bodyDoc, options) ||
(!shouldBreakChain && shouldAddParensIfNotBreak(functionBody)));
const isCallee = path.key === "callee" && isCallLikeExpression(path.parent);
const chainGroupId = Symbol("arrow-chain");
const signaturesDoc = printArrowFunctionSignatures(path, args, {
signatureDocs,
shouldBreak: shouldBreakChain,
});
let shouldBreakSignatures;
let shouldIndentSignatures = false;
if (
shouldPrintAsChain &&
(isCallee ||
// isAssignmentRhs
args.assignmentLayout)
) {
shouldIndentSignatures = true;
shouldBreakSignatures =
args.assignmentLayout === "chain-tail-arrow-chain" ||
(isCallee && !shouldPutBodyOnSameLine);
}
bodyDoc = printArrowFunctionBody(path, options, args, {
bodyDoc,
bodyComments,
functionBody,
shouldPutBodyOnSameLine,
});
return group([
group(
shouldIndentSignatures
? indent([softline, signaturesDoc])
: signaturesDoc,
{ shouldBreak: shouldBreakSignatures, id: chainGroupId }
),
" =>",
shouldPrintAsChain
? indentIfBreak(bodyDoc, { groupId: chainGroupId })
: group(bodyDoc),
shouldPrintAsChain && isCallee
? ifBreak(softline, "", { groupId: chainGroupId })
: "",
]);
}
function printArrowFunctionSignature(path, options, print, args) {
const { node } = path;
const parts = [];
if (node.async) {
parts.push("async ");
}
if (shouldPrintParamsWithoutParens(path, options)) {
parts.push(print(["params", 0]));
} else {
const expandArg = args.expandLastArg || args.expandFirstArg;
let returnTypeDoc = printReturnType(path, print);
if (expandArg) {
if (willBreak(returnTypeDoc)) {
throw new ArgExpansionBailout();
}
returnTypeDoc = group(removeLines(returnTypeDoc));
}
parts.push(
group([
printFunctionParameters(
path,
print,
options,
expandArg,
/* printTypeParams */ true
),
returnTypeDoc,
])
);
}
const dangling = printDanglingComments(path, options, {
filter(comment) {
const nextCharacter = getNextNonSpaceNonCommentCharacterIndex(
options.originalText,
locEnd(comment)
);
return (
nextCharacter !== false &&
options.originalText.slice(nextCharacter, nextCharacter + 2) === "=>"
);
},
});
if (dangling) {
parts.push(" ", dangling);
}
return parts;
}
/**
*
* @param {*} functionBody
* @param {*} bodyDoc
* @param {*} options
* @returns {boolean}
*/
function mayBreakAfterShortPrefix(functionBody, bodyDoc, options) {
return (
isArrayOrTupleExpression(functionBody) ||
isObjectOrRecordExpression(functionBody) ||
functionBody.type === "ArrowFunctionExpression" ||
functionBody.type === "DoExpression" ||
functionBody.type === "BlockStatement" ||
isJsxElement(functionBody) ||
(bodyDoc.label?.hug !== false &&
(bodyDoc.label?.embed ||
isTemplateOnItsOwnLine(functionBody, options.originalText)))
);
}
/**
* @param {AstPath} path
* @param {*} args
* @param {Object} arrowFunctionSignaturesPrintOptions
* @param {Doc[]} arrowFunctionSignaturesPrintOptions.signatureDocs
* @param {boolean} arrowFunctionSignaturesPrintOptions.shouldBreak
* @returns {Doc}
*/
function printArrowFunctionSignatures(
path,
args,
{ signatureDocs, shouldBreak }
) {
if (signatureDocs.length === 1) {
return signatureDocs[0];
}
const { parent, key } = path;
if (
(key !== "callee" && isCallLikeExpression(parent)) ||
isBinaryish(parent)
) {
return group(
[
signatureDocs[0],
" =>",
indent([line, join([" =>", line], signatureDocs.slice(1))]),
],
{ shouldBreak }
);
}
if (
(key === "callee" && isCallLikeExpression(parent)) ||
// isAssignmentRhs
args.assignmentLayout
) {
return group(join([" =>", line], signatureDocs), { shouldBreak });
}
return group(indent(join([" =>", line], signatureDocs)), { shouldBreak });
}
/**
* @param {AstPath} path
* @param {*} options
* @param {*} args
* @param {Object} arrowFunctionBodyPrintOptions
* @param {Doc} arrowFunctionBodyPrintOptions.bodyDoc
* @param {Doc[]} arrowFunctionBodyPrintOptions.bodyComments
* @param {*} arrowFunctionBodyPrintOptions.functionBody
* @param {boolean} arrowFunctionBodyPrintOptions.shouldPutBodyOnSameLine
*/
function printArrowFunctionBody(
path,
options,
args,
{ bodyDoc, bodyComments, functionBody, shouldPutBodyOnSameLine }
) {
const { node, parent } = path;
const trailingComma =
args.expandLastArg && shouldPrintComma(options, "all") ? ifBreak(",") : "";
// if the arrow function is expanded as last argument, we are adding a
// level of indentation and need to add a softline to align the closing )
// with the opening (, or if it's inside a JSXExpression (e.g. an attribute)
// we should align the expression's closing } with the line with the opening {.
const trailingSpace =
(args.expandLastArg || parent.type === "JSXExpressionContainer") &&
!hasComment(node)
? softline
: "";
if (shouldPutBodyOnSameLine && shouldAddParensIfNotBreak(functionBody)) {
return [
" ",
group([
ifBreak("", "("),
indent([softline, bodyDoc]),
ifBreak("", ")"),
trailingComma,
trailingSpace,
]),
bodyComments,
];
}
if (shouldAlwaysAddParens(functionBody)) {
bodyDoc = group(["(", indent([softline, bodyDoc]), softline, ")"]);
}
return shouldPutBodyOnSameLine
? [" ", bodyDoc, bodyComments]
: [indent([line, bodyDoc, bodyComments]), trailingComma, trailingSpace];
}
export { printArrowFunction };
+7 -230
View File
@@ -1,43 +1,23 @@
/** @typedef {import("../../document/builders.js").Doc} Doc */
import assert from "node:assert";
import { printDanglingComments } from "../../main/comments/print.js";
import {
printDanglingComments,
printCommentsSeparately,
} from "../../main/comments/print.js";
import getNextNonSpaceNonCommentCharacterIndex from "../../utils/get-next-non-space-non-comment-character-index.js";
import {
line,
softline,
group,
indent,
dedent,
ifBreak,
hardline,
join,
indentIfBreak,
} from "../../document/builders.js";
import { removeLines, willBreak } from "../../document/utils.js";
import { ArgExpansionBailout } from "../../common/errors.js";
import {
getFunctionParameters,
hasLeadingOwnLineComment,
isJsxElement,
isTemplateOnItsOwnLine,
shouldPrintComma,
startsWithNoLookaheadToken,
isBinaryish,
hasComment,
CommentCheckFlags,
isCallLikeExpression,
isCallExpression,
getCallArguments,
hasNakedLeftSide,
getLeftSide,
isArrayOrTupleExpression,
isObjectOrRecordExpression,
} from "../utils/index.js";
import { locEnd } from "../loc.js";
import {
printFunctionParameters,
shouldGroupFunctionParameters,
@@ -47,6 +27,11 @@ import { printPropertyKey } from "./property.js";
import { printFunctionTypeParameters, printDeclareToken } from "./misc.js";
import { printTypeAnnotationProperty } from "./type-annotation.js";
/**
* @typedef {import("../../common/ast-path.js").default} AstPath
* @typedef {import("../../document/builders.js").Doc} Doc
*/
const isMethod = (node) =>
node.type === "ObjectMethod" ||
node.type === "ClassMethod" ||
@@ -198,214 +183,6 @@ function printMethodValue(path, options, print) {
return parts;
}
function printArrowFunctionSignature(path, options, print, args) {
const { node } = path;
const parts = [];
if (node.async) {
parts.push("async ");
}
if (shouldPrintParamsWithoutParens(path, options)) {
parts.push(print(["params", 0]));
} else {
const expandArg = args?.expandLastArg || args?.expandFirstArg;
let returnTypeDoc = printReturnType(path, print);
if (expandArg) {
if (willBreak(returnTypeDoc)) {
throw new ArgExpansionBailout();
}
returnTypeDoc = group(removeLines(returnTypeDoc));
}
parts.push(
group([
printFunctionParameters(
path,
print,
options,
expandArg,
/* printTypeParams */ true
),
returnTypeDoc,
])
);
}
const dangling = printDanglingComments(path, options, {
filter(comment) {
const nextCharacter = getNextNonSpaceNonCommentCharacterIndex(
options.originalText,
locEnd(comment)
);
return (
nextCharacter !== false &&
options.originalText.slice(nextCharacter, nextCharacter + 2) === "=>"
);
},
});
if (dangling) {
parts.push(" ", dangling);
}
return parts;
}
function printArrowChain(
path,
args,
signatures,
shouldBreak,
bodyDoc,
tailNode
) {
const { parent, key } = path;
const isCallee = isCallLikeExpression(parent) && key === "callee";
const isAssignmentRhs = Boolean(args?.assignmentLayout);
const shouldPutBodyOnSeparateLine =
tailNode.body.type !== "BlockStatement" &&
!isObjectOrRecordExpression(tailNode.body) &&
tailNode.body.type !== "SequenceExpression";
const shouldBreakBeforeChain =
(isCallee && shouldPutBodyOnSeparateLine) ||
args?.assignmentLayout === "chain-tail-arrow-chain";
const groupId = Symbol("arrow-chain");
if ((isCallLikeExpression(parent) && !isCallee) || isBinaryish(parent)) {
signatures = [dedent(signatures[0]), ...signatures.slice(1)];
}
// We handle sequence expressions as the body of arrows specially,
// so that the required parentheses end up on their own lines.
if (tailNode.body.type === "SequenceExpression") {
bodyDoc = group(["(", indent([softline, bodyDoc]), softline, ")"]);
}
return group([
group(
indent([
isCallee || isAssignmentRhs ? softline : "",
group(join([" =>", line], signatures), { shouldBreak }),
]),
{ id: groupId, shouldBreak: shouldBreakBeforeChain }
),
" =>",
indentIfBreak(
shouldPutBodyOnSeparateLine ? indent([line, bodyDoc]) : [" ", bodyDoc],
{ groupId }
),
isCallee ? ifBreak(softline, "", { groupId }) : "",
]);
}
function printArrowFunction(path, options, print, args) {
let { node } = path;
/** @type {Doc[]} */
const signatures = [];
const body = [];
let chainShouldBreak = false;
(function rec() {
const doc = printArrowFunctionSignature(path, options, print, args);
if (signatures.length === 0) {
signatures.push(doc);
} else {
const { leading, trailing } = printCommentsSeparately(path, options);
signatures.push([leading, doc]);
body.unshift(trailing);
}
chainShouldBreak =
chainShouldBreak ||
// Always break the chain if:
(node.returnType && getFunctionParameters(node).length > 0) ||
node.typeParameters ||
getFunctionParameters(node).some((param) => param.type !== "Identifier");
if (node.body.type !== "ArrowFunctionExpression" || args?.expandLastArg) {
body.unshift(print("body", args));
} else {
node = node.body;
path.call(rec, "body");
}
})();
if (signatures.length > 1) {
return printArrowChain(
path,
args,
signatures,
chainShouldBreak,
body,
node
);
}
const parts = signatures;
parts.push(" =>");
// We want to always keep these types of nodes on the same line
// as the arrow.
if (
!hasLeadingOwnLineComment(options.originalText, node.body) &&
(isArrayOrTupleExpression(node.body) ||
isObjectOrRecordExpression(node.body) ||
node.body.type === "BlockStatement" ||
isJsxElement(node.body) ||
(body[0].label?.hug !== false &&
(body[0].label?.embed ||
isTemplateOnItsOwnLine(node.body, options.originalText))) ||
node.body.type === "ArrowFunctionExpression" ||
node.body.type === "DoExpression")
) {
return group([...parts, " ", body]);
}
// We handle sequence expressions as the body of arrows specially,
// so that the required parentheses end up on their own lines.
if (node.body.type === "SequenceExpression") {
return group([
...parts,
group([" (", indent([softline, body]), softline, ")"]),
]);
}
// if the arrow function is expanded as last argument, we are adding a
// level of indentation and need to add a softline to align the closing )
// with the opening (, or if it's inside a JSXExpression (e.g. an attribute)
// we should align the expression's closing } with the line with the opening {.
const shouldAddSoftLine =
(args?.expandLastArg || path.parent.type === "JSXExpressionContainer") &&
!hasComment(node);
const printTrailingComma =
args?.expandLastArg && shouldPrintComma(options, "all");
// In order to avoid confusion between
// a => a ? a : a
// a <= a ? a : a
const shouldAddParens =
node.body.type === "ConditionalExpression" &&
!startsWithNoLookaheadToken(
node.body,
(node) => node.type === "ObjectExpression"
);
return group([
...parts,
group([
indent([
line,
shouldAddParens ? ifBreak("", "(") : "",
body,
shouldAddParens ? ifBreak("", ")") : "",
]),
shouldAddSoftLine
? [ifBreak(printTrailingComma ? "," : ""), softline]
: "",
]),
]);
}
function canPrintParamsWithoutParens(node) {
const parameters = getFunctionParameters(node);
return (
@@ -530,10 +307,10 @@ function returnArgumentHasLeadingComment(options, argument) {
export {
printFunction,
printArrowFunction,
printMethod,
printReturnStatement,
printThrowStatement,
printMethodValue,
printReturnType,
shouldPrintParamsWithoutParens,
};
+1 -1
View File
@@ -65,11 +65,11 @@ import {
import { printProperty } from "./print/property.js";
import {
printFunction,
printArrowFunction,
printMethod,
printReturnStatement,
printThrowStatement,
} from "./print/function.js";
import { printArrowFunction } from "./print/arrow-function.js";
import { printCallExpression } from "./print/call-expression.js";
import {
printVariableDeclarator,
@@ -2334,6 +2334,27 @@ export const bem = block =>
data={data}
/>
func(() => // comment
a);
func(() => () => // comment
a);
func(() => () => () => // comment
a);
func(() => // comment
a ? b : c);
func(() => () => // comment
a ? b : c);
func(() => () => () => // comment
a ? b : c);
func(() => // comment
(a , b , c))
func(() => () => // comment
(a , b , c))
func(() => () => () => // comment
(a , b , c))
=====================================output=====================================
/**
* Curried function that ends with a BEM CSS Selector
@@ -2367,6 +2388,59 @@ export const bem =
data={data}
/>;
func(
() =>
// comment
a,
);
func(
() => () =>
// comment
a,
);
func(
() => () => () =>
// comment
a,
);
func(() =>
// comment
a ? b : c,
);
func(
() => () =>
// comment
a ? b : c,
);
func(
() => () => () =>
// comment
a ? b : c,
);
func(
() =>
(
// comment
a, b, c
),
);
func(
() => () =>
(
// comment
a, b, c
),
);
func(
() => () => () =>
(
// comment
a, b, c
),
);
================================================================================
`;
@@ -2408,6 +2482,27 @@ export const bem = block =>
data={data}
/>
func(() => // comment
a);
func(() => () => // comment
a);
func(() => () => () => // comment
a);
func(() => // comment
a ? b : c);
func(() => () => // comment
a ? b : c);
func(() => () => () => // comment
a ? b : c);
func(() => // comment
(a , b , c))
func(() => () => // comment
(a , b , c))
func(() => () => () => // comment
(a , b , c))
=====================================output=====================================
/**
* Curried function that ends with a BEM CSS Selector
@@ -2441,6 +2536,59 @@ export const bem =
data={data}
/>;
func(
() =>
// comment
a,
);
func(
() => () =>
// comment
a,
);
func(
() => () => () =>
// comment
a,
);
func(() =>
// comment
a ? b : c,
);
func(
() => () =>
// comment
a ? b : c,
);
func(
() => () => () =>
// comment
a ? b : c,
);
func(
() =>
(
// comment
a, b, c
),
);
func(
() => () =>
(
// comment
a, b, c
),
);
func(
() => () => () =>
(
// comment
a, b, c
),
);
================================================================================
`;
@@ -3666,6 +3814,370 @@ function f(
================================================================================
`;
exports[`currying-4.js - {"arrowParens":"always"} format 1`] = `
====================================options=====================================
arrowParens: "always"
parsers: ["babel", "typescript"]
printWidth: 80
| printWidth
=====================================input======================================
Y(() => a ? b : c);
Y(() => () => a ? b : c);
Y(() => () => () => a ? b : c);
Y(() => longlonglonglonglonglonglonglonglonglongCondition ? 'Prettier is an opinionated code formatter.' : 'Prettier takes your code and reprints it from scratch by taking the line length into account.')
Y(() => () => longlonglonglonglonglonglonglonglonglongCondition ? 'Prettier is an opinionated code formatter.' : 'Prettier takes your code and reprints it from scratch by taking the line length into account.')
Y(() => () => () => longlonglonglonglonglonglonglonglonglongCondition ? 'Prettier is an opinionated code formatter.' : 'Prettier takes your code and reprints it from scratch by taking the line length into account.')
const x1 = (() => ['The', 'green', 'dragon', 'liked', 'to', 'knit', 'sweaters', 'for', 'the', 'fluffy', 'clouds', 'in', 'the', 'sky.'])
const x2 = (() => () => ['The', 'green', 'dragon', 'liked', 'to', 'knit', 'sweaters', 'for', 'the', 'fluffy', 'clouds', 'in', 'the', 'sky.'])
const x3 = (() => () => () => ['The', 'green', 'dragon', 'liked', 'to', 'knit', 'sweaters', 'for', 'the', 'fluffy', 'clouds', 'in', 'the', 'sky.'])
f((a) => (1, 2, 3) /* a */);
f((a) => (
(b) => (1, 2, 3) /* b */
) /* a */);
f((a) => (
(b) => (
(c) => (1, 2, 3) /* c */
) /* b */
) /* a */);
f((a) => (1 ? 2 : 3) /* a */);
f((a) => (
(b) => (1 ? 2 : 3) /* b */
) /* a */);
f((a) => (
(b) => (
(c) => (1 ? 2 : 3) /* c */
) /* b */
) /* a */);
a(
"",
"",
({}) =>
() =>
() =>
() =>
() =>
() =>
() => test,
);
a(
"",
"",
({}) =>
() =>
() =>
() =>
() =>
() =>
() => (test ? 1 : 2),
);
=====================================output=====================================
Y(() => (a ? b : c));
Y(() => () => (a ? b : c));
Y(() => () => () => (a ? b : c));
Y(() =>
longlonglonglonglonglonglonglonglonglongCondition
? "Prettier is an opinionated code formatter."
: "Prettier takes your code and reprints it from scratch by taking the line length into account.",
);
Y(
() => () =>
longlonglonglonglonglonglonglonglonglongCondition
? "Prettier is an opinionated code formatter."
: "Prettier takes your code and reprints it from scratch by taking the line length into account.",
);
Y(
() => () => () =>
longlonglonglonglonglonglonglonglonglongCondition
? "Prettier is an opinionated code formatter."
: "Prettier takes your code and reprints it from scratch by taking the line length into account.",
);
const x1 = () => [
"The",
"green",
"dragon",
"liked",
"to",
"knit",
"sweaters",
"for",
"the",
"fluffy",
"clouds",
"in",
"the",
"sky.",
];
const x2 = () => () => [
"The",
"green",
"dragon",
"liked",
"to",
"knit",
"sweaters",
"for",
"the",
"fluffy",
"clouds",
"in",
"the",
"sky.",
];
const x3 = () => () => () => [
"The",
"green",
"dragon",
"liked",
"to",
"knit",
"sweaters",
"for",
"the",
"fluffy",
"clouds",
"in",
"the",
"sky.",
];
f((a) => (1, 2, 3) /* a */);
f((a) => (b) => (1, 2, 3) /* b */ /* a */);
f((a) => (b) => (c) => (1, 2, 3) /* c */ /* b */ /* a */);
f((a) => (1 ? 2 : 3) /* a */);
f((a) => (b) => (1 ? 2 : 3) /* b */ /* a */);
f((a) => (b) => (c) => (1 ? 2 : 3) /* c */ /* b */ /* a */);
a(
"",
"",
({}) =>
() =>
() =>
() =>
() =>
() =>
() =>
test,
);
a(
"",
"",
({}) =>
() =>
() =>
() =>
() =>
() =>
() =>
test ? 1 : 2,
);
================================================================================
`;
exports[`currying-4.js - {"arrowParens":"avoid"} format 1`] = `
====================================options=====================================
arrowParens: "avoid"
parsers: ["babel", "typescript"]
printWidth: 80
| printWidth
=====================================input======================================
Y(() => a ? b : c);
Y(() => () => a ? b : c);
Y(() => () => () => a ? b : c);
Y(() => longlonglonglonglonglonglonglonglonglongCondition ? 'Prettier is an opinionated code formatter.' : 'Prettier takes your code and reprints it from scratch by taking the line length into account.')
Y(() => () => longlonglonglonglonglonglonglonglonglongCondition ? 'Prettier is an opinionated code formatter.' : 'Prettier takes your code and reprints it from scratch by taking the line length into account.')
Y(() => () => () => longlonglonglonglonglonglonglonglonglongCondition ? 'Prettier is an opinionated code formatter.' : 'Prettier takes your code and reprints it from scratch by taking the line length into account.')
const x1 = (() => ['The', 'green', 'dragon', 'liked', 'to', 'knit', 'sweaters', 'for', 'the', 'fluffy', 'clouds', 'in', 'the', 'sky.'])
const x2 = (() => () => ['The', 'green', 'dragon', 'liked', 'to', 'knit', 'sweaters', 'for', 'the', 'fluffy', 'clouds', 'in', 'the', 'sky.'])
const x3 = (() => () => () => ['The', 'green', 'dragon', 'liked', 'to', 'knit', 'sweaters', 'for', 'the', 'fluffy', 'clouds', 'in', 'the', 'sky.'])
f((a) => (1, 2, 3) /* a */);
f((a) => (
(b) => (1, 2, 3) /* b */
) /* a */);
f((a) => (
(b) => (
(c) => (1, 2, 3) /* c */
) /* b */
) /* a */);
f((a) => (1 ? 2 : 3) /* a */);
f((a) => (
(b) => (1 ? 2 : 3) /* b */
) /* a */);
f((a) => (
(b) => (
(c) => (1 ? 2 : 3) /* c */
) /* b */
) /* a */);
a(
"",
"",
({}) =>
() =>
() =>
() =>
() =>
() =>
() => test,
);
a(
"",
"",
({}) =>
() =>
() =>
() =>
() =>
() =>
() => (test ? 1 : 2),
);
=====================================output=====================================
Y(() => (a ? b : c));
Y(() => () => (a ? b : c));
Y(() => () => () => (a ? b : c));
Y(() =>
longlonglonglonglonglonglonglonglonglongCondition
? "Prettier is an opinionated code formatter."
: "Prettier takes your code and reprints it from scratch by taking the line length into account.",
);
Y(
() => () =>
longlonglonglonglonglonglonglonglonglongCondition
? "Prettier is an opinionated code formatter."
: "Prettier takes your code and reprints it from scratch by taking the line length into account.",
);
Y(
() => () => () =>
longlonglonglonglonglonglonglonglonglongCondition
? "Prettier is an opinionated code formatter."
: "Prettier takes your code and reprints it from scratch by taking the line length into account.",
);
const x1 = () => [
"The",
"green",
"dragon",
"liked",
"to",
"knit",
"sweaters",
"for",
"the",
"fluffy",
"clouds",
"in",
"the",
"sky.",
];
const x2 = () => () => [
"The",
"green",
"dragon",
"liked",
"to",
"knit",
"sweaters",
"for",
"the",
"fluffy",
"clouds",
"in",
"the",
"sky.",
];
const x3 = () => () => () => [
"The",
"green",
"dragon",
"liked",
"to",
"knit",
"sweaters",
"for",
"the",
"fluffy",
"clouds",
"in",
"the",
"sky.",
];
f(a => (1, 2, 3) /* a */);
f(a => b => (1, 2, 3) /* b */ /* a */);
f(a => b => c => (1, 2, 3) /* c */ /* b */ /* a */);
f(a => (1 ? 2 : 3) /* a */);
f(a => b => (1 ? 2 : 3) /* b */ /* a */);
f(a => b => c => (1 ? 2 : 3) /* c */ /* b */ /* a */);
a(
"",
"",
({}) =>
() =>
() =>
() =>
() =>
() =>
() =>
test,
);
a(
"",
"",
({}) =>
() =>
() =>
() =>
() =>
() =>
() =>
test ? 1 : 2,
);
================================================================================
`;
exports[`issue-1389-curry.js - {"arrowParens":"always"} format 1`] = `
====================================options=====================================
arrowParens: "always"
@@ -3928,6 +4440,9 @@ foo(a => b, d)
foo(a => (0, 1));
foo(a => b => (0, 1));
() => ({} ? 1 : 2);
() => () => ({} ? 1 : 2);
=====================================output=====================================
promise.then(
(result) => result,
@@ -3956,6 +4471,9 @@ foo((a) => b, d);
foo((a) => (0, 1));
foo((a) => (b) => (0, 1));
() => ({}) ? 1 : 2;
() => () => ({}) ? 1 : 2;
================================================================================
`;
@@ -3985,6 +4503,9 @@ foo(a => b, d)
foo(a => (0, 1));
foo(a => b => (0, 1));
() => ({} ? 1 : 2);
() => () => ({} ? 1 : 2);
=====================================output=====================================
promise.then(
result => result,
@@ -4013,6 +4534,9 @@ foo(a => b, d);
foo(a => (0, 1));
foo(a => b => (0, 1));
() => ({}) ? 1 : 2;
() => () => ({}) ? 1 : 2;
================================================================================
`;
+21
View File
@@ -28,3 +28,24 @@ export const bem = block =>
) => <span>{info.item.widget.missingProp}</span>}
data={data}
/>
func(() => // comment
a);
func(() => () => // comment
a);
func(() => () => () => // comment
a);
func(() => // comment
a ? b : c);
func(() => () => // comment
a ? b : c);
func(() => () => () => // comment
a ? b : c);
func(() => // comment
(a , b , c))
func(() => () => // comment
(a , b , c))
func(() => () => () => // comment
(a , b , c))
+60
View File
@@ -0,0 +1,60 @@
Y(() => a ? b : c);
Y(() => () => a ? b : c);
Y(() => () => () => a ? b : c);
Y(() => longlonglonglonglonglonglonglonglonglongCondition ? 'Prettier is an opinionated code formatter.' : 'Prettier takes your code and reprints it from scratch by taking the line length into account.')
Y(() => () => longlonglonglonglonglonglonglonglonglongCondition ? 'Prettier is an opinionated code formatter.' : 'Prettier takes your code and reprints it from scratch by taking the line length into account.')
Y(() => () => () => longlonglonglonglonglonglonglonglonglongCondition ? 'Prettier is an opinionated code formatter.' : 'Prettier takes your code and reprints it from scratch by taking the line length into account.')
const x1 = (() => ['The', 'green', 'dragon', 'liked', 'to', 'knit', 'sweaters', 'for', 'the', 'fluffy', 'clouds', 'in', 'the', 'sky.'])
const x2 = (() => () => ['The', 'green', 'dragon', 'liked', 'to', 'knit', 'sweaters', 'for', 'the', 'fluffy', 'clouds', 'in', 'the', 'sky.'])
const x3 = (() => () => () => ['The', 'green', 'dragon', 'liked', 'to', 'knit', 'sweaters', 'for', 'the', 'fluffy', 'clouds', 'in', 'the', 'sky.'])
f((a) => (1, 2, 3) /* a */);
f((a) => (
(b) => (1, 2, 3) /* b */
) /* a */);
f((a) => (
(b) => (
(c) => (1, 2, 3) /* c */
) /* b */
) /* a */);
f((a) => (1 ? 2 : 3) /* a */);
f((a) => (
(b) => (1 ? 2 : 3) /* b */
) /* a */);
f((a) => (
(b) => (
(c) => (1 ? 2 : 3) /* c */
) /* b */
) /* a */);
a(
"",
"",
({}) =>
() =>
() =>
() =>
() =>
() =>
() => test,
);
a(
"",
"",
({}) =>
() =>
() =>
() =>
() =>
() =>
() => (test ? 1 : 2),
);
+3
View File
@@ -16,3 +16,6 @@ foo(a => b, d)
foo(a => (0, 1));
foo(a => b => (0, 1));
() => ({} ? 1 : 2);
() => () => ({} ? 1 : 2);
@@ -213,6 +213,20 @@ function foo() {
}
};
() => ( ) => do {
var obj = { foo: "bar", bar: "foo" };
for (var key in obj) {
obj[key];
}
};
a =>b=> c => do {
var obj = { foo: "bar", bar: "foo" };
for (var key in obj) {
obj[key];
}
};
=====================================output=====================================
const envSpecific = {
domain: do {
@@ -272,5 +286,19 @@ function foo() {
}
};
() => () => do {
var obj = { foo: "bar", bar: "foo" };
for (var key in obj) {
obj[key];
}
};
(a) => (b) => (c) => do {
var obj = { foo: "bar", bar: "foo" };
for (var key in obj) {
obj[key];
}
};
================================================================================
`;
+14
View File
@@ -52,3 +52,17 @@ function foo() {
obj[key];
}
};
() => ( ) => do {
var obj = { foo: "bar", bar: "foo" };
for (var key in obj) {
obj[key];
}
};
a =>b=> c => do {
var obj = { foo: "bar", bar: "foo" };
for (var key in obj) {
obj[key];
}
};
@@ -312,6 +312,374 @@ const TodoList = ({ todos }) => (
================================================================================
`;
exports[`arrow.js - {"singleQuote":false,"jsxSingleQuote":false} format 1`] = `
====================================options=====================================
jsxSingleQuote: false
parsers: ["flow", "babel", "typescript"]
printWidth: 80
singleQuote: false
| printWidth
=====================================input======================================
() => <Component><Children/></Component>;
() => () => <Component><Children/></Component>;
() => () => () => <Component><Children/></Component>;
() => <div>Some text here</div>;
() => () => <div>Some text here</div>;
() => () => () => <div>Some text here</div>;
() => <div>Long long long long long, very very long text. And more text. Another text.</div>;
() => () => <div>Long long long long long, very very long text. And more text. Another text.</div>;
() => () => () => <div>Long long long long long, very very long text. And more text. Another text.</div>;
<Prettier>
{We => 'The purple monkey danced with a tambourine made of cheese.' + 'The robot chef cooked a cake that tasted like rainbows.' + 'The talking pineapple sang a lullaby to the sleepy giraffe.'}
</Prettier>;
<Prettier>
{We => love => 'The purple monkey danced with a tambourine made of cheese.' + 'The robot chef cooked a cake that tasted like rainbows.' + 'The talking pineapple sang a lullaby to the sleepy giraffe.'}
</Prettier>;
<Prettier>
{We => love => currying => 'The purple monkey danced with a tambourine made of cheese.' + 'The robot chef cooked a cake that tasted like rainbows.' + 'The talking pineapple sang a lullaby to the sleepy giraffe.'}
</Prettier>;
=====================================output=====================================
() => (
<Component>
<Children />
</Component>
);
() => () => (
<Component>
<Children />
</Component>
);
() => () => () => (
<Component>
<Children />
</Component>
);
() => <div>Some text here</div>;
() => () => <div>Some text here</div>;
() => () => () => <div>Some text here</div>;
() => (
<div>
Long long long long long, very very long text. And more text. Another text.
</div>
);
() => () => (
<div>
Long long long long long, very very long text. And more text. Another text.
</div>
);
() => () => () => (
<div>
Long long long long long, very very long text. And more text. Another text.
</div>
);
<Prettier>
{(We) =>
"The purple monkey danced with a tambourine made of cheese." +
"The robot chef cooked a cake that tasted like rainbows." +
"The talking pineapple sang a lullaby to the sleepy giraffe."
}
</Prettier>;
<Prettier>
{(We) => (love) =>
"The purple monkey danced with a tambourine made of cheese." +
"The robot chef cooked a cake that tasted like rainbows." +
"The talking pineapple sang a lullaby to the sleepy giraffe."
}
</Prettier>;
<Prettier>
{(We) => (love) => (currying) =>
"The purple monkey danced with a tambourine made of cheese." +
"The robot chef cooked a cake that tasted like rainbows." +
"The talking pineapple sang a lullaby to the sleepy giraffe."
}
</Prettier>;
================================================================================
`;
exports[`arrow.js - {"singleQuote":false,"jsxSingleQuote":true} format 1`] = `
====================================options=====================================
jsxSingleQuote: true
parsers: ["flow", "babel", "typescript"]
printWidth: 80
singleQuote: false
| printWidth
=====================================input======================================
() => <Component><Children/></Component>;
() => () => <Component><Children/></Component>;
() => () => () => <Component><Children/></Component>;
() => <div>Some text here</div>;
() => () => <div>Some text here</div>;
() => () => () => <div>Some text here</div>;
() => <div>Long long long long long, very very long text. And more text. Another text.</div>;
() => () => <div>Long long long long long, very very long text. And more text. Another text.</div>;
() => () => () => <div>Long long long long long, very very long text. And more text. Another text.</div>;
<Prettier>
{We => 'The purple monkey danced with a tambourine made of cheese.' + 'The robot chef cooked a cake that tasted like rainbows.' + 'The talking pineapple sang a lullaby to the sleepy giraffe.'}
</Prettier>;
<Prettier>
{We => love => 'The purple monkey danced with a tambourine made of cheese.' + 'The robot chef cooked a cake that tasted like rainbows.' + 'The talking pineapple sang a lullaby to the sleepy giraffe.'}
</Prettier>;
<Prettier>
{We => love => currying => 'The purple monkey danced with a tambourine made of cheese.' + 'The robot chef cooked a cake that tasted like rainbows.' + 'The talking pineapple sang a lullaby to the sleepy giraffe.'}
</Prettier>;
=====================================output=====================================
() => (
<Component>
<Children />
</Component>
);
() => () => (
<Component>
<Children />
</Component>
);
() => () => () => (
<Component>
<Children />
</Component>
);
() => <div>Some text here</div>;
() => () => <div>Some text here</div>;
() => () => () => <div>Some text here</div>;
() => (
<div>
Long long long long long, very very long text. And more text. Another text.
</div>
);
() => () => (
<div>
Long long long long long, very very long text. And more text. Another text.
</div>
);
() => () => () => (
<div>
Long long long long long, very very long text. And more text. Another text.
</div>
);
<Prettier>
{(We) =>
"The purple monkey danced with a tambourine made of cheese." +
"The robot chef cooked a cake that tasted like rainbows." +
"The talking pineapple sang a lullaby to the sleepy giraffe."
}
</Prettier>;
<Prettier>
{(We) => (love) =>
"The purple monkey danced with a tambourine made of cheese." +
"The robot chef cooked a cake that tasted like rainbows." +
"The talking pineapple sang a lullaby to the sleepy giraffe."
}
</Prettier>;
<Prettier>
{(We) => (love) => (currying) =>
"The purple monkey danced with a tambourine made of cheese." +
"The robot chef cooked a cake that tasted like rainbows." +
"The talking pineapple sang a lullaby to the sleepy giraffe."
}
</Prettier>;
================================================================================
`;
exports[`arrow.js - {"singleQuote":true,"jsxSingleQuote":false} format 1`] = `
====================================options=====================================
jsxSingleQuote: false
parsers: ["flow", "babel", "typescript"]
printWidth: 80
singleQuote: true
| printWidth
=====================================input======================================
() => <Component><Children/></Component>;
() => () => <Component><Children/></Component>;
() => () => () => <Component><Children/></Component>;
() => <div>Some text here</div>;
() => () => <div>Some text here</div>;
() => () => () => <div>Some text here</div>;
() => <div>Long long long long long, very very long text. And more text. Another text.</div>;
() => () => <div>Long long long long long, very very long text. And more text. Another text.</div>;
() => () => () => <div>Long long long long long, very very long text. And more text. Another text.</div>;
<Prettier>
{We => 'The purple monkey danced with a tambourine made of cheese.' + 'The robot chef cooked a cake that tasted like rainbows.' + 'The talking pineapple sang a lullaby to the sleepy giraffe.'}
</Prettier>;
<Prettier>
{We => love => 'The purple monkey danced with a tambourine made of cheese.' + 'The robot chef cooked a cake that tasted like rainbows.' + 'The talking pineapple sang a lullaby to the sleepy giraffe.'}
</Prettier>;
<Prettier>
{We => love => currying => 'The purple monkey danced with a tambourine made of cheese.' + 'The robot chef cooked a cake that tasted like rainbows.' + 'The talking pineapple sang a lullaby to the sleepy giraffe.'}
</Prettier>;
=====================================output=====================================
() => (
<Component>
<Children />
</Component>
);
() => () => (
<Component>
<Children />
</Component>
);
() => () => () => (
<Component>
<Children />
</Component>
);
() => <div>Some text here</div>;
() => () => <div>Some text here</div>;
() => () => () => <div>Some text here</div>;
() => (
<div>
Long long long long long, very very long text. And more text. Another text.
</div>
);
() => () => (
<div>
Long long long long long, very very long text. And more text. Another text.
</div>
);
() => () => () => (
<div>
Long long long long long, very very long text. And more text. Another text.
</div>
);
<Prettier>
{(We) =>
'The purple monkey danced with a tambourine made of cheese.' +
'The robot chef cooked a cake that tasted like rainbows.' +
'The talking pineapple sang a lullaby to the sleepy giraffe.'
}
</Prettier>;
<Prettier>
{(We) => (love) =>
'The purple monkey danced with a tambourine made of cheese.' +
'The robot chef cooked a cake that tasted like rainbows.' +
'The talking pineapple sang a lullaby to the sleepy giraffe.'
}
</Prettier>;
<Prettier>
{(We) => (love) => (currying) =>
'The purple monkey danced with a tambourine made of cheese.' +
'The robot chef cooked a cake that tasted like rainbows.' +
'The talking pineapple sang a lullaby to the sleepy giraffe.'
}
</Prettier>;
================================================================================
`;
exports[`arrow.js - {"singleQuote":true,"jsxSingleQuote":true} format 1`] = `
====================================options=====================================
jsxSingleQuote: true
parsers: ["flow", "babel", "typescript"]
printWidth: 80
singleQuote: true
| printWidth
=====================================input======================================
() => <Component><Children/></Component>;
() => () => <Component><Children/></Component>;
() => () => () => <Component><Children/></Component>;
() => <div>Some text here</div>;
() => () => <div>Some text here</div>;
() => () => () => <div>Some text here</div>;
() => <div>Long long long long long, very very long text. And more text. Another text.</div>;
() => () => <div>Long long long long long, very very long text. And more text. Another text.</div>;
() => () => () => <div>Long long long long long, very very long text. And more text. Another text.</div>;
<Prettier>
{We => 'The purple monkey danced with a tambourine made of cheese.' + 'The robot chef cooked a cake that tasted like rainbows.' + 'The talking pineapple sang a lullaby to the sleepy giraffe.'}
</Prettier>;
<Prettier>
{We => love => 'The purple monkey danced with a tambourine made of cheese.' + 'The robot chef cooked a cake that tasted like rainbows.' + 'The talking pineapple sang a lullaby to the sleepy giraffe.'}
</Prettier>;
<Prettier>
{We => love => currying => 'The purple monkey danced with a tambourine made of cheese.' + 'The robot chef cooked a cake that tasted like rainbows.' + 'The talking pineapple sang a lullaby to the sleepy giraffe.'}
</Prettier>;
=====================================output=====================================
() => (
<Component>
<Children />
</Component>
);
() => () => (
<Component>
<Children />
</Component>
);
() => () => () => (
<Component>
<Children />
</Component>
);
() => <div>Some text here</div>;
() => () => <div>Some text here</div>;
() => () => () => <div>Some text here</div>;
() => (
<div>
Long long long long long, very very long text. And more text. Another text.
</div>
);
() => () => (
<div>
Long long long long long, very very long text. And more text. Another text.
</div>
);
() => () => () => (
<div>
Long long long long long, very very long text. And more text. Another text.
</div>
);
<Prettier>
{(We) =>
'The purple monkey danced with a tambourine made of cheese.' +
'The robot chef cooked a cake that tasted like rainbows.' +
'The talking pineapple sang a lullaby to the sleepy giraffe.'
}
</Prettier>;
<Prettier>
{(We) => (love) =>
'The purple monkey danced with a tambourine made of cheese.' +
'The robot chef cooked a cake that tasted like rainbows.' +
'The talking pineapple sang a lullaby to the sleepy giraffe.'
}
</Prettier>;
<Prettier>
{(We) => (love) => (currying) =>
'The purple monkey danced with a tambourine made of cheese.' +
'The robot chef cooked a cake that tasted like rainbows.' +
'The talking pineapple sang a lullaby to the sleepy giraffe.'
}
</Prettier>;
================================================================================
`;
exports[`attr-comments.js - {"singleQuote":false,"jsxSingleQuote":false} format 1`] = `
====================================options=====================================
jsxSingleQuote: false
+21
View File
@@ -0,0 +1,21 @@
() => <Component><Children/></Component>;
() => () => <Component><Children/></Component>;
() => () => () => <Component><Children/></Component>;
() => <div>Some text here</div>;
() => () => <div>Some text here</div>;
() => () => () => <div>Some text here</div>;
() => <div>Long long long long long, very very long text. And more text. Another text.</div>;
() => () => <div>Long long long long long, very very long text. And more text. Another text.</div>;
() => () => () => <div>Long long long long long, very very long text. And more text. Another text.</div>;
<Prettier>
{We => 'The purple monkey danced with a tambourine made of cheese.' + 'The robot chef cooked a cake that tasted like rainbows.' + 'The talking pineapple sang a lullaby to the sleepy giraffe.'}
</Prettier>;
<Prettier>
{We => love => 'The purple monkey danced with a tambourine made of cheese.' + 'The robot chef cooked a cake that tasted like rainbows.' + 'The talking pineapple sang a lullaby to the sleepy giraffe.'}
</Prettier>;
<Prettier>
{We => love => currying => 'The purple monkey danced with a tambourine made of cheese.' + 'The robot chef cooked a cake that tasted like rainbows.' + 'The talking pineapple sang a lullaby to the sleepy giraffe.'}
</Prettier>;