From 7d3ff5d2fccd825c16e9fff7f638be7dd5f4bc50 Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Fri, 31 Oct 2025 02:43:23 +0800 Subject: [PATCH] Fix comment around `as`/`satisfies` expression (#18162) --- changelog_unreleased/typescript/18162.md | 28 ++++ src/language-js/comments/handle-comments.js | 26 ++++ .../__snapshots__/format.test.js.snap | 37 ----- .../format/typescript/as/as-const/as-const.ts | 19 --- tests/format/typescript/as/comments/18160.ts | 58 ++++++++ .../__snapshots__/format.test.js.snap | 134 ++++++++++++++++++ .../typescript/as/comments/format.test.js | 3 + 7 files changed, 249 insertions(+), 56 deletions(-) create mode 100644 changelog_unreleased/typescript/18162.md create mode 100644 tests/format/typescript/as/comments/18160.ts create mode 100644 tests/format/typescript/as/comments/__snapshots__/format.test.js.snap create mode 100644 tests/format/typescript/as/comments/format.test.js diff --git a/changelog_unreleased/typescript/18162.md b/changelog_unreleased/typescript/18162.md new file mode 100644 index 000000000..7cb64c8c3 --- /dev/null +++ b/changelog_unreleased/typescript/18162.md @@ -0,0 +1,28 @@ +#### Fix comment around `as`/`satisfies` expression (#18162 by @fisker) + + +```tsx +// Input +1 as /* +comment +*/ +const; + +// Prettier stable (First format) +1 /* +comment +*/ as const; + +// Prettier stable (Second format) +SyntaxError: Unexpected keyword or identifier. (3:4) + 1 | 1 /* + 2 | comment +> 3 | */ as const; + | ^ + 4 | + +// Prettier main +1 as const /* +comment +*/; +``` diff --git a/src/language-js/comments/handle-comments.js b/src/language-js/comments/handle-comments.js index 8963f9cd5..bd59c9800 100644 --- a/src/language-js/comments/handle-comments.js +++ b/src/language-js/comments/handle-comments.js @@ -13,6 +13,7 @@ import { createTypeCheckFunction, getCallArguments, getFunctionParameters, + isBinaryCastExpression, isCallExpression, isCallLikeExpression, isConditionalType, @@ -71,6 +72,7 @@ function handleOwnLineComment(context) { handleNestedConditionalExpressionComments, handleCommentsInDestructuringPattern, handleTSMappedTypeComments, + handleBinaryCastExpressionComment, ].some((fn) => fn(context)); } @@ -99,6 +101,7 @@ function handleEndOfLineComment(context) { handleLastBinaryOperatorOperand, handleTSMappedTypeComments, handlePropertySignatureComments, + handleBinaryCastExpressionComment, ].some((fn) => fn(context)); } @@ -118,6 +121,7 @@ function handleRemainingComment(context) { handleFunctionNameComments, handleBreakAndContinueStatementComments, handleTSFunctionTrailingComments, + handleBinaryCastExpressionComment, ].some((fn) => fn(context)); } @@ -1121,6 +1125,28 @@ function handlePropertySignatureComments({ } } +function handleBinaryCastExpressionComment({ + enclosingNode, + precedingNode, + followingNode, + comment, + text, +}) { + // Avoid break before `as` and `satisfies` + if ( + isBinaryCastExpression(enclosingNode) && + precedingNode === enclosingNode.expression && + !isSingleLineComment(comment, text) + ) { + if (followingNode) { + addLeadingComment(followingNode, comment); + } else { + addTrailingComment(enclosingNode, comment); + } + return true; + } +} + /** * @param {Node} node * @returns {boolean} diff --git a/tests/format/typescript/as/as-const/__snapshots__/format.test.js.snap b/tests/format/typescript/as/as-const/__snapshots__/format.test.js.snap index 0b3b271c6..02567228e 100644 --- a/tests/format/typescript/as/as-const/__snapshots__/format.test.js.snap +++ b/tests/format/typescript/as/as-const/__snapshots__/format.test.js.snap @@ -21,25 +21,6 @@ const; 1 as /* comment */ not_const; -// https://github.com/prettier/prettier/issues/18160 -// 1 as /* -// 1 -// */ const; -1 as -/* -2 -*/ const; -// https://github.com/prettier/prettier/issues/18160 -// 1 as /* -// 3 -// */ -// const; -1 as -/* -4 -*/ -const; - =====================================output===================================== 1 /* comment */ as const; 1 /* comment */ as const; @@ -53,23 +34,5 @@ const; 1 as /* comment */ not_const; -// https://github.com/prettier/prettier/issues/18160 -// 1 as /* -// 1 -// */ const; -1 as const; -/* -2 -*/ -// https://github.com/prettier/prettier/issues/18160 -// 1 as /* -// 3 -// */ -// const; -1 as const; -/* -4 -*/ - ================================================================================ `; diff --git a/tests/format/typescript/as/as-const/as-const.ts b/tests/format/typescript/as/as-const/as-const.ts index 79a8b8d31..57ae4fe39 100644 --- a/tests/format/typescript/as/as-const/as-const.ts +++ b/tests/format/typescript/as/as-const/as-const.ts @@ -12,22 +12,3 @@ const; 1 as const; // comment 1 as /* comment */ not_const; - -// https://github.com/prettier/prettier/issues/18160 -// 1 as /* -// 1 -// */ const; -1 as -/* -2 -*/ const; -// https://github.com/prettier/prettier/issues/18160 -// 1 as /* -// 3 -// */ -// const; -1 as -/* -4 -*/ -const; diff --git a/tests/format/typescript/as/comments/18160.ts b/tests/format/typescript/as/comments/18160.ts new file mode 100644 index 000000000..cae8affff --- /dev/null +++ b/tests/format/typescript/as/comments/18160.ts @@ -0,0 +1,58 @@ +1 as /* +comment +*/const; +1 as /* +comment +*/Foo; +1 satisfies /* +comment +*/Foo; + +1 as +/* +comment +*/const; +1 as +/* +comment +*/Foo; +1 satisfies +/* +comment +*/Foo; + +1 as /* +comment +*/ +const; +1 as /* +comment +*/ +Foo; +1 satisfies /* +comment +*/ +Foo; + +1 as +/* +comment +*/ +const; +1 as +/* +comment +*/ +Foo; +1 satisfies +/* +comment +*/ +Foo; + +1 as // comment +const; +1 as // comment +Foo; +1 satisfies // comment +Foo; diff --git a/tests/format/typescript/as/comments/__snapshots__/format.test.js.snap b/tests/format/typescript/as/comments/__snapshots__/format.test.js.snap new file mode 100644 index 000000000..a1d914a13 --- /dev/null +++ b/tests/format/typescript/as/comments/__snapshots__/format.test.js.snap @@ -0,0 +1,134 @@ +// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing + +exports[`18160.ts [hermes] format 1`] = ` +"';' expected (7:2) + 5 | comment + 6 | */Foo; +> 7 | 1 satisfies /* + | ^ + 8 | comment + 9 | */Foo; + 10 | +Cause: ';' expected (7:2) +1 satisfies /* + ^" +`; + +exports[`18160.ts format 1`] = ` +====================================options===================================== +parsers: ["typescript", "flow"] +printWidth: 80 + | printWidth +=====================================input====================================== +1 as /* +comment +*/const; +1 as /* +comment +*/Foo; +1 satisfies /* +comment +*/Foo; + +1 as +/* +comment +*/const; +1 as +/* +comment +*/Foo; +1 satisfies +/* +comment +*/Foo; + +1 as /* +comment +*/ +const; +1 as /* +comment +*/ +Foo; +1 satisfies /* +comment +*/ +Foo; + +1 as +/* +comment +*/ +const; +1 as +/* +comment +*/ +Foo; +1 satisfies +/* +comment +*/ +Foo; + +1 as // comment +const; +1 as // comment +Foo; +1 satisfies // comment +Foo; + +=====================================output===================================== +1 as const /* +comment +*/; +1 as /* +comment +*/ Foo; +1 satisfies /* +comment +*/ Foo; + +1 as const; +/* +comment +*/ +1 as /* +comment +*/ Foo; +1 satisfies /* +comment +*/ Foo; + +1 as const /* +comment +*/; +1 as /* +comment +*/ +Foo; +1 satisfies /* +comment +*/ +Foo; + +1 as const; +/* +comment +*/ +1 as /* +comment +*/ +Foo; +1 satisfies /* +comment +*/ +Foo; + +1 as const; // comment +1 as Foo; // comment +1 satisfies Foo; // comment + +================================================================================ +`; diff --git a/tests/format/typescript/as/comments/format.test.js b/tests/format/typescript/as/comments/format.test.js new file mode 100644 index 000000000..abdcaa93a --- /dev/null +++ b/tests/format/typescript/as/comments/format.test.js @@ -0,0 +1,3 @@ +runFormatTest(import.meta, ["typescript", "flow"], { + errors: { hermes: ["18160.ts"] }, +});