Fix unstable comment in arrow function with sequence expression body (#19253)

Co-authored-by: itsybitsybootsy <lammlu19>
Co-authored-by: fisker Cheung <lionkay@gmail.com>
This commit is contained in:
authored and GitHub committed 2026-06-01 07:41:04 +08:00
1 parent 82955f1d02
commit e79c012e3b
5 files changed
+101 -3

No files matched your search

+13
View File
@@ -0,0 +1,13 @@
#### Fix unstable comment in arrow function with sequence expression body (#19253 by @itsybitsybootsy)
<!-- prettier-ignore -->
```jsx
// Input
const fn = () => (a, b, c /* abc */);
// Prettier stable
const fn = () => (a, b, c) /* abc */;
// Prettier main
const fn = () => (a, b, c /* abc */);
```
@@ -112,6 +112,7 @@ function handleEndOfLineComment(context) {
handleLastBinaryOperatorOperand,
handleTSMappedTypeComments,
handleArrowExpressionComments,
handleArrowBodySequenceExpressionTrailingComment,
handlePropertySignatureComments,
handleBinaryCastExpressionComment,
].some((fn) => fn(context));
@@ -134,6 +135,7 @@ function handleRemainingComment(context) {
handleCommentAfterArrowParams,
handleFunctionNameComments,
handleTSFunctionTrailingComments,
handleArrowBodySequenceExpressionTrailingComment,
handleBinaryCastExpressionComment,
].some((fn) => fn(context));
}
@@ -1071,6 +1073,31 @@ function handleArrowExpressionComments({
return false;
}
// A trailing comment inside the parentheses around a `SequenceExpression`
// arrow body would otherwise attach to the `SequenceExpression` itself.
// The AST node does not include those parentheses, so the comment then
// prints outside them and drifts further on each reformat (#18776, #14702).
// Re-attach to the last sequence element so it stays inside the parens.
function handleArrowBodySequenceExpressionTrailingComment({
comment,
enclosingNode,
precedingNode,
followingNode,
text,
}) {
if (
!followingNode &&
enclosingNode?.type === "ArrowFunctionExpression" &&
precedingNode?.type === "SequenceExpression" &&
enclosingNode.body === precedingNode &&
getNextNonSpaceNonCommentCharacter(text, locEnd(comment)) === ")"
) {
addTrailingComment(precedingNode.expressions.at(-1), comment);
return true;
}
return false;
}
const isRealFunctionLikeNode = createTypeCheckFunction([
"ArrowFunctionExpression",
"FunctionExpression",
@@ -33,7 +33,6 @@ const unstableTests = new Map(
"typescript/call/callee-comments.ts",
"js/arrows/arrow-chain-with-trailing-comments.js",
"typescript/as/comments/18160.ts",
"js/arrows/issue-14702.js",
].map((fixture) => {
const [file, isUnstable = () => true] = Array.isArray(fixture)
? fixture
@@ -4469,7 +4469,7 @@ parsers: ["babel", "typescript"]
a = () => (1, 2, 3 /* abc */);
=====================================output=====================================
a = () => (1, 2, 3) /* abc */;
a = () => (1, 2, 3 /* abc */);
================================================================================
`;
@@ -4483,7 +4483,7 @@ parsers: ["babel", "typescript"]
a = () => (1, 2, 3 /* abc */);
=====================================output=====================================
a = () => (1, 2, 3) /* abc */;
a = () => (1, 2, 3 /* abc */);
================================================================================
`;
@@ -4742,6 +4742,58 @@ a = () => /** @param {string} id */ id => id;
================================================================================
`;
exports[`issue-18776.js - {"arrowParens":"always"} format 1`] = `
====================================options=====================================
arrowParens: "always"
parsers: ["babel", "typescript"]
printWidth: 80 (default) |
=====================================input======================================
() => (a, b, c /* abc */);
let multilineCase = (someParameter) => (
someVeryLongExpressionName,
anotherVeryLongExpressionName,
yetAnotherVeryLongExpressionName /* abc */
);
=====================================output=====================================
() => (a, b, c /* abc */);
let multilineCase = (someParameter) => (
someVeryLongExpressionName,
anotherVeryLongExpressionName,
yetAnotherVeryLongExpressionName /* abc */
);
================================================================================
`;
exports[`issue-18776.js - {"arrowParens":"avoid"} format 1`] = `
====================================options=====================================
arrowParens: "avoid"
parsers: ["babel", "typescript"]
printWidth: 80 (default) |
=====================================input======================================
() => (a, b, c /* abc */);
let multilineCase = (someParameter) => (
someVeryLongExpressionName,
anotherVeryLongExpressionName,
yetAnotherVeryLongExpressionName /* abc */
);
=====================================output=====================================
() => (a, b, c /* abc */);
let multilineCase = someParameter => (
someVeryLongExpressionName,
anotherVeryLongExpressionName,
yetAnotherVeryLongExpressionName /* abc */
);
================================================================================
`;
exports[`long-call-no-args.js - {"arrowParens":"always"} format 1`] = `
====================================options=====================================
arrowParens: "always"
+7
View File
@@ -0,0 +1,7 @@
() => (a, b, c /* abc */);
let multilineCase = (someParameter) => (
someVeryLongExpressionName,
anotherVeryLongExpressionName,
yetAnotherVeryLongExpressionName /* abc */
);