From cb8d1899a0faaf26a1e4e8004fb365047cd5a569 Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Wed, 24 Jun 2026 20:53:59 +0800 Subject: [PATCH] Further improve comments in "assignment like" node (#19445) --- src/language-js/comments/attach/union-type.js | 35 ++++++++++ src/language-js/comments/handle-comments.js | 69 +++++++------------ .../__snapshots__/format.test.js.snap | 32 ++++++--- .../__snapshots__/format.test.js.snap | 36 ++++++---- .../consistent-with-flow/single-member.ts | 14 ++-- .../__snapshots__/format.test.js.snap | 3 +- .../__snapshots__/format.test.js.snap | 9 ++- .../__snapshots__/format.test.js.snap | 9 ++- 8 files changed, 125 insertions(+), 82 deletions(-) create mode 100644 src/language-js/comments/attach/union-type.js diff --git a/src/language-js/comments/attach/union-type.js b/src/language-js/comments/attach/union-type.js new file mode 100644 index 000000000..6bc654ea3 --- /dev/null +++ b/src/language-js/comments/attach/union-type.js @@ -0,0 +1,35 @@ +import { addLeadingComment } from "../../../main/comments/utilities.js"; +import { locEnd, locStart } from "../../location/index.js"; +import { isBlockComment } from "../../utilities/comment-types.js"; +import { isPrettierIgnoreComment } from "../../utilities/is-prettier-ignore-comment.js"; +import { isUnionType } from "../../utilities/node-types.js"; +import { stripComments } from "../../utilities/strip-comments.js"; +import { isSingleLineComment } from "../attach/utilities.js"; + +function shouldAttachToUnionTypeFirstElement(node, { comment, text, options }) { + if ( + isUnionType(node) && + isBlockComment(comment) && + isSingleLineComment(comment, text) && + !isPrettierIgnoreComment(comment) + ) { + const text = stripComments(options); + const textBetween = text.slice(locEnd(comment), locStart(node)); + return /^[ \t]*$/.test(textBetween); + } + + return false; +} + +function addLeadingCommentToPossibleUnionType(node, context) { + addLeadingComment( + shouldAttachToUnionTypeFirstElement(node, context) ? node.types[0] : node, + context.comment, + ); + return true; +} + +export { + addLeadingCommentToPossibleUnionType, + shouldAttachToUnionTypeFirstElement, +}; diff --git a/src/language-js/comments/handle-comments.js b/src/language-js/comments/handle-comments.js index 8f21b1763..e737f57b3 100644 --- a/src/language-js/comments/handle-comments.js +++ b/src/language-js/comments/handle-comments.js @@ -32,6 +32,10 @@ import { stripComments } from "../utilities/strip-comments.js"; import { handleForXStatementComments } from "./attach/handle-for-x-statement-comments.js"; import { handleIfStatementComments } from "./attach/handle-if-statement-comments.js"; import { handleWhileLikeComments } from "./attach/handle-while-like-comments.js"; +import { + addLeadingCommentToPossibleUnionType, + shouldAttachToUnionTypeFirstElement, +} from "./attach/union-type.js"; import { addBlockOrNotComment, addBlockStatementFirstComment, @@ -107,7 +111,7 @@ function handleEndOfLineComment(context) { handleCallExpressionComments, handlePropertyComments, handleOnlyComments, - handleVariableDeclaratorComments, + handleAssignmentLikeComments, handleSwitchDefaultCaseComments, handleLastUnionElementInExpression, handleLastBinaryOperatorOperand, @@ -132,6 +136,7 @@ function handleRemainingComment(context) { handleForXStatementComments, handleMethodNameComments, handleOnlyComments, + handleAssignmentLikeComments, handleTSMappedTypeComments, handleCommentAfterArrowParams, handleFunctionNameComments, @@ -139,7 +144,6 @@ function handleRemainingComment(context) { handleParenthesizedExpressionTrailingComment, handleBinaryCastExpressionComment, handleUnionTypeLeadingComments, - handleAssignmentLikeAnnotationLeadingComments, ].some((fn) => fn(context)); } @@ -759,6 +763,7 @@ const isAssignmentLikeNode = createTypeCheckFunction([ "TypeAlias", "TSTypeAliasDeclaration", ]); + const isComplexExprNode = createTypeCheckFunction([ "ObjectExpression", "ArrayExpression", @@ -767,38 +772,27 @@ const isComplexExprNode = createTypeCheckFunction([ "ObjectTypeAnnotation", "TSTypeLiteral", ]); -function handleVariableDeclaratorComments({ - comment, - enclosingNode, - followingNode, -}) { - if ( - isAssignmentLikeNode(enclosingNode) && - followingNode && - (isComplexExprNode(followingNode) || isBlockComment(comment)) - ) { - addLeadingComment(followingNode, comment); - return true; - } - return false; -} -function handleAssignmentLikeAnnotationLeadingComments({ - comment, - enclosingNode, - followingNode, - options, -}) { +/** @param {CommentContext} context */ +function handleAssignmentLikeComments(context) { + const { comment, enclosingNode, followingNode, options, placement } = context; if (isAssignmentLikeNode(enclosingNode) && followingNode) { + if ( + placement === "endOfLine" && + (isComplexExprNode(followingNode) || isBlockComment(comment)) + ) { + return addLeadingCommentToPossibleUnionType(followingNode, context); + } + // @ts-expect-error -- Safe const leftSide = enclosingNode.id ?? enclosingNode.left; const equalsTokenIndex = stripComments(options).indexOf( "=", locEnd(leftSide), ); + if (locStart(comment) >= equalsTokenIndex) { - addLeadingComment(followingNode, comment); - return true; + return addLeadingCommentToPossibleUnionType(followingNode, context); } } @@ -1142,24 +1136,13 @@ function handleParenthesizedExpressionTrailingComment({ * @param {CommentContext} context * @returns {boolean} */ -function handleUnionTypeLeadingComments({ - followingNode, - comment, - text, - options, -}) { - if ( - isUnionType(followingNode) && - isBlockComment(comment) && - isSingleLineComment(comment, text) && - !isPrettierIgnoreComment(comment) - ) { - const text = stripComments(options); - const textBetween = text.slice(locEnd(comment), locStart(followingNode)); - if (/^[ \t]*$/.test(textBetween)) { - addLeadingComment(followingNode.types[0], comment); - return true; - } +function handleUnionTypeLeadingComments(context) { + const { followingNode, comment } = context; + + if (shouldAttachToUnionTypeFirstElement(followingNode, context)) { + // @ts-expect-error -- safe + addLeadingComment(followingNode.types[0], comment); + return true; } return false; diff --git a/tests/format/js/assignment-comments/__snapshots__/format.test.js.snap b/tests/format/js/assignment-comments/__snapshots__/format.test.js.snap index 30e67b19e..a98ccfe86 100644 --- a/tests/format/js/assignment-comments/__snapshots__/format.test.js.snap +++ b/tests/format/js/assignment-comments/__snapshots__/format.test.js.snap @@ -19,7 +19,8 @@ if (true) if (true) if (true) if (true) - longVariableName1 = // @ts-ignore + longVariableName1 = + // @ts-ignore (variable01 + veryLongVariableNameNumber2).method(); ================================================================================ @@ -34,7 +35,8 @@ const kochabCooieGameOnOboleUnweave = // ??? rhubarbRhubarb(annularCooeedSplicesWalksWayWay); =====================================output===================================== -const kochabCooieGameOnOboleUnweave = // ??? +const kochabCooieGameOnOboleUnweave = + // ??? rhubarbRhubarb(annularCooeedSplicesWalksWayWay); ================================================================================ @@ -121,7 +123,8 @@ f3 = ( a = b, //comment ) => {}; -f4 = // Comment +f4 = + // Comment () => {}; f5 = @@ -149,7 +152,8 @@ let f3 = ( a = b, //comment ) => {}; -let f4 = // Comment +let f4 = + // Comment () => {}; let f5 = @@ -181,10 +185,12 @@ const bifornCringerMoshedPerplexSawder = // !!! anodyneCondosMalateOverateRetinol; =====================================output===================================== -const kochabCooieGameOnOboleUnweave = // ??? +const kochabCooieGameOnOboleUnweave = + // ??? annularCooeedSplicesWalksWayWay; -const bifornCringerMoshedPerplexSawder = // !!! +const bifornCringerMoshedPerplexSawder = + // !!! glimseGlyphsHazardNoopsTieTie + averredBathersBoxroomBuggyNurl - anodyneCondosMalateOverateRetinol; @@ -428,11 +434,14 @@ fnString = "long" + "string"; -fnString = // Comment0 +fnString = + // Comment0 // Comment1 "some" + "long" + "string"; -fnString = "some" + "long" + "string"; // Comment +fnString = + // Comment + "some" + "long" + "string"; fnString = // Comment @@ -472,11 +481,14 @@ var fnString = "long" + "string"; -var fnString = // Comment0 +var fnString = + // Comment0 // Comment1 "some" + "long" + "string"; -var fnString = "some" + "long" + "string"; // Comment +var fnString = + // Comment + "some" + "long" + "string"; ================================================================================ `; diff --git a/tests/format/typescript/intersection/consistent-with-flow/__snapshots__/format.test.js.snap b/tests/format/typescript/intersection/consistent-with-flow/__snapshots__/format.test.js.snap index 5419da062..deaca5400 100644 --- a/tests/format/typescript/intersection/consistent-with-flow/__snapshots__/format.test.js.snap +++ b/tests/format/typescript/intersection/consistent-with-flow/__snapshots__/format.test.js.snap @@ -120,8 +120,8 @@ parsers: ["typescript", "flow"] =====================================input====================================== // https://github.com/oxc-project/oxc/pull/21915 -// export type aType = & // Comment -// "VALUE"; +export type aType = & // Comment +"VALUE"; export type bType = & // Comment @@ -133,8 +133,8 @@ export type cType = & /* Comment */ export type dType = /* Comment */ & "VALUE"; -// export type eType = // Comment -// & "VALUE"; +export type eType = // Comment +& "VALUE"; export type fType = & /* Comment */ @@ -168,15 +168,16 @@ export type nType = // Comment & /* Comment */ "VALUE"; -// type oType = // Comment -// & // Comment -// "VALUE" +type oType = // Comment +& // Comment +"VALUE" =====================================output===================================== // https://github.com/oxc-project/oxc/pull/21915 -// export type aType = & // Comment -// "VALUE"; +export type aType = + // Comment + "VALUE"; export type bType = // Comment @@ -186,8 +187,9 @@ export type cType = /* Comment */ "VALUE"; export type dType = /* Comment */ "VALUE"; -// export type eType = // Comment -// & "VALUE"; +export type eType = + // Comment + "VALUE"; export type fType = /* Comment */ @@ -215,11 +217,15 @@ export type lType = export type mType = "VALUE"; /* Comment */ -export type nType = /* Comment */ "VALUE"; // Comment +export type nType = + // Comment + /* Comment */ + "VALUE"; -// type oType = // Comment -// & // Comment -// "VALUE" +type oType = + // Comment + // Comment + "VALUE"; ================================================================================ `; diff --git a/tests/format/typescript/intersection/consistent-with-flow/single-member.ts b/tests/format/typescript/intersection/consistent-with-flow/single-member.ts index 8b25ce496..06995eb1e 100644 --- a/tests/format/typescript/intersection/consistent-with-flow/single-member.ts +++ b/tests/format/typescript/intersection/consistent-with-flow/single-member.ts @@ -1,7 +1,7 @@ // https://github.com/oxc-project/oxc/pull/21915 -// export type aType = & // Comment -// "VALUE"; +export type aType = & // Comment +"VALUE"; export type bType = & // Comment @@ -13,8 +13,8 @@ export type cType = & /* Comment */ export type dType = /* Comment */ & "VALUE"; -// export type eType = // Comment -// & "VALUE"; +export type eType = // Comment +& "VALUE"; export type fType = & /* Comment */ @@ -48,6 +48,6 @@ export type nType = // Comment & /* Comment */ "VALUE"; -// type oType = // Comment -// & // Comment -// "VALUE" +type oType = // Comment +& // Comment +"VALUE" diff --git a/tests/format/typescript/union/comments/__snapshots__/format.test.js.snap b/tests/format/typescript/union/comments/__snapshots__/format.test.js.snap index 1135f6f79..a7aab2d33 100644 --- a/tests/format/typescript/union/comments/__snapshots__/format.test.js.snap +++ b/tests/format/typescript/union/comments/__snapshots__/format.test.js.snap @@ -67,7 +67,8 @@ export class DirectiveArgumentNode12 extends ArrayExpression { | [string, ExpressionNode, ExpressionNode, ObjectExpression] = 1; } -type A = // dir, exp, arg, modifiers +type A = + // dir, exp, arg, modifiers | [string] | [string, ExpressionNode] | [string, ExpressionNode, ExpressionNode] diff --git a/tests/format/typescript/union/consistent-with-flow/__snapshots__/format.test.js.snap b/tests/format/typescript/union/consistent-with-flow/__snapshots__/format.test.js.snap index 21eff6eb5..093054358 100644 --- a/tests/format/typescript/union/consistent-with-flow/__snapshots__/format.test.js.snap +++ b/tests/format/typescript/union/consistent-with-flow/__snapshots__/format.test.js.snap @@ -181,13 +181,15 @@ type SuperLongTypeNameLoremIpsumLoremIpsumBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBl2 = =====================================output===================================== type A1 = /* 4 */ (A | B)[]; -type A2 = // dir, exp, arg, modifiers +type A2 = + // dir, exp, arg, modifiers | [string] | [string, ExpressionNode] | [string, ExpressionNode, ExpressionNode] | [string, ExpressionNode, ExpressionNode, ObjectExpression]; -type A3 = // dir, exp, arg, modifiers +type A3 = + // dir, exp, arg, modifiers [string] & [string, ExpressionNode] & [string, ExpressionNode, ExpressionNode] & @@ -433,7 +435,8 @@ type T2 = | /* comment */ "A" | /* A comment long enough to make the union type break into multiple lines */ B; -type T3 = // comment +type T3 = + // comment | "A" | /* A comment long enough to make the union type break into multiple lines */ B; diff --git a/tests/format/typescript/union/single-type/__snapshots__/format.test.js.snap b/tests/format/typescript/union/single-type/__snapshots__/format.test.js.snap index e57829c98..e278edf37 100644 --- a/tests/format/typescript/union/single-type/__snapshots__/format.test.js.snap +++ b/tests/format/typescript/union/single-type/__snapshots__/format.test.js.snap @@ -73,19 +73,22 @@ type LongType = | // This is a really long comment that might exceed the print w =====================================output===================================== // https://github.com/oxc-project/oxc/pull/21915 -export type myType = // Comment +export type myType = + // Comment "A"; // Block comment same-line after pipe type BlockComment = /* block */ "B"; // Same-line comment then own-line comment -type Mixed = // first +type Mixed = + // first // second "C"; // Long line comment that exceeds printWidth on the \`=\` line -type LongType = // This is a really long comment that might exceed the print width limit +type LongType = + // This is a really long comment that might exceed the print width limit "A"; ================================================================================