Fix unstable trailing comment on a nested parenthesized assignment (#19893)

Co-authored-by: fisker <lionkay@gmail.com>
This commit is contained in:
Miodrag Obradovicandfisker authored and GitHub committed 2026-08-20 12:28:29 +08:00
1 parent 52d170534e
commit 24a616d0b7
7 files changed
+69 -26

No files matched your search

+16
View File
@@ -0,0 +1,16 @@
#### Fix unstable trailing comment on a nested parenthesized assignment (#19893 by @Kjubikstronk)
<!-- prettier-ignore -->
```jsx
// Input
assigned = (a = c /* comment */);
// Prettier stable (First format)
assigned = a = c /* comment */;
// Prettier stable (Second format)
assigned = a = c; /* comment */
// Prettier main
assigned = a = c; /* comment */
```
+40 -1
View File
@@ -55,6 +55,7 @@ import {
precedingNode: Node,
enclosingNode: Node,
followingNode: Node,
ancestors: readonly Node[],
text: string,
options: any,
ast: NodeMap["File"] | NodeMap["Program"],
@@ -1177,6 +1178,22 @@ function handleArrowExpressionComments({
return false;
}
function getEnclosingAssignmentChainExpressionStatement(node, ancestors) {
let child = node;
for (const ancestor of ancestors) {
if (ancestor.type === "AssignmentExpression" && ancestor.right === child) {
child = ancestor;
continue;
}
return ancestor.type === "ExpressionStatement" &&
ancestor.expression === child
? ancestor
: undefined;
}
}
function handleSequenceExpressionLeadingComment({
comment,
enclosingNode,
@@ -1200,6 +1217,7 @@ function handleParenthesizedExpressionTrailingComment({
enclosingNode,
precedingNode,
followingNode,
ancestors,
}) {
if (!followingNode && enclosingNode && precedingNode) {
if (
@@ -1210,9 +1228,30 @@ function handleParenthesizedExpressionTrailingComment({
return true;
}
const isSequence = precedingNode.type === "SequenceExpression";
const isAssignment = precedingNode.type === "AssignmentExpression";
// `a = (b = c /* comment */);` drops the parentheses, so the comment ends
// up trailing the whole statement anyway. Attach it there right away
// instead of leaving it on `c` for the next format to move.
if (
isAssignment &&
enclosingNode.type === "AssignmentExpression" &&
enclosingNode.right === precedingNode
) {
const expressionStatement =
getEnclosingAssignmentChainExpressionStatement(
enclosingNode,
ancestors.slice(1),
);
if (expressionStatement) {
addTrailingComment(expressionStatement, comment);
return true;
}
}
const isSequence = precedingNode.type === "SequenceExpression";
if (
(isSequence || isAssignment) &&
((enclosingNode.type === "ArrowFunctionExpression" &&
+1 -1
View File
@@ -106,7 +106,7 @@ function decorateComment(
}
}
return { enclosingNode, precedingNode, followingNode };
return { enclosingNode, precedingNode, followingNode, ancestors };
}
const returnFalse = () => false;
@@ -30,7 +30,6 @@ const unstableTests = new Map(
"typescript/call/callee-comments.ts",
"js/arrows/arrow-chain-with-trailing-comments.js",
"typescript/as/comments/18160.ts",
"js/sequence-expression/parenthesized-trailing-comment-unstable.js",
"typescript/union/consistent-with-flow/single-type.ts",
].map((fixture) => {
const [file, isUnstable = () => true] = Array.isArray(fixture)
@@ -168,7 +168,10 @@ const x22 = (a = c) /* comment */;
assigned = (a, b, c /* comment */);
assigned = (a, b, c) /* comment */;
// assigned = (a = c /* comment */);
assigned = (a = c /* comment */);
x = y = (a = c /* comment */);
obj.p = (a = c /* comment */);
assigned = ((a = c) /* comment */);
function f() {
return (a, b, c /* comment */);
@@ -205,7 +208,10 @@ foo(); /* comment */
assigned = (a, b, c /* comment */);
assigned = (a, b, c); /* comment */
// assigned = (a = c /* comment */);
assigned = a = c; /* comment */
x = y = a = c; /* comment */
obj.p = a = c; /* comment */
assigned = a = c; /* comment */
function f() {
return (a, b, c /* comment */);
@@ -216,23 +222,6 @@ function f() {
================================================================================
`;
exports[`parenthesized-trailing-comment-unstable.js format 1`] = `
====================================options=====================================
parsers: ["babel", "flow", "typescript"]
printWidth: 80 (default) |
=====================================input======================================
// TODO: Enable tests in parenthesized-trailing-comment.js when they are stable
assigned = (a = c /* comment */);
=====================================output=====================================
// TODO: Enable tests in parenthesized-trailing-comment.js when they are stable
assigned = a = c /* comment */;
================================================================================
`;
exports[`return.js format 1`] = `
====================================options=====================================
parsers: ["babel", "flow", "typescript"]
@@ -1,3 +0,0 @@
// TODO: Enable tests in parenthesized-trailing-comment.js when they are stable
assigned = (a = c /* comment */);
@@ -34,7 +34,10 @@ const x22 = (a = c) /* comment */;
assigned = (a, b, c /* comment */);
assigned = (a, b, c) /* comment */;
// assigned = (a = c /* comment */);
assigned = (a = c /* comment */);
x = y = (a = c /* comment */);
obj.p = (a = c /* comment */);
assigned = ((a = c) /* comment */);
function f() {
return (a, b, c /* comment */);