diff --git a/changelog_unreleased/typescript/16586.md b/changelog_unreleased/typescript/16586.md new file mode 100644 index 000000000..fad423933 --- /dev/null +++ b/changelog_unreleased/typescript/16586.md @@ -0,0 +1,28 @@ +#### Don't print an extra line break for arrow function with type parameter in assignment (#16586 by @sosukesuzuki) + +There was a bug where an extra line was inserted when assigning a chained arrow function with type parameters to a variable if there was a line comment above it. + +This change ensures that the extra line is no longer inserted. + + +```tsx +// Input +const foo1 = + // comment + () => () => 1; + +// Prettier stable +const foo1 = + // comment + + () => + () => + 1; + +// Prettier main +const foo1 = + // comment + () => + () => + 1; +``` diff --git a/src/language-js/print/arrow-function.js b/src/language-js/print/arrow-function.js index 38ac2a2c9..87805d9a6 100644 --- a/src/language-js/print/arrow-function.js +++ b/src/language-js/print/arrow-function.js @@ -16,6 +16,7 @@ import { import getNextNonSpaceNonCommentCharacterIndex from "../../utils/get-next-non-space-non-comment-character-index.js"; import { locEnd } from "../loc.js"; import { + CommentCheckFlags, getFunctionParameters, hasComment, hasLeadingOwnLineComment, @@ -119,8 +120,9 @@ function printArrowFunction(path, options, print, args = {}) { signatureDocs, shouldBreak: shouldBreakChain, }); - let shouldBreakSignatures; + let shouldBreakSignatures = false; let shouldIndentSignatures = false; + let shouldPrintSoftlineInIndent = false; if ( shouldPrintAsChain && (isCallee || @@ -128,6 +130,13 @@ function printArrowFunction(path, options, print, args = {}) { args.assignmentLayout) ) { shouldIndentSignatures = true; + // If the arrow function has a leading line comment, there should be a hardline above it + // so we should not print a softline in indent call + // https://github.com/prettier/prettier/issues/16067 + shouldPrintSoftlineInIndent = !hasComment( + path.node, + CommentCheckFlags.Leading & CommentCheckFlags.Line, + ); shouldBreakSignatures = args.assignmentLayout === "chain-tail-arrow-chain" || (isCallee && !shouldPutBodyOnSameLine); @@ -143,7 +152,7 @@ function printArrowFunction(path, options, print, args = {}) { return group([ group( shouldIndentSignatures - ? indent([softline, signaturesDoc]) + ? indent([shouldPrintSoftlineInIndent ? softline : "", signaturesDoc]) : signaturesDoc, { shouldBreak: shouldBreakSignatures, id: chainGroupId }, ), diff --git a/tests/format/typescript/arrow/16067.ts b/tests/format/typescript/arrow/16067.ts new file mode 100644 index 000000000..e8e76dfa5 --- /dev/null +++ b/tests/format/typescript/arrow/16067.ts @@ -0,0 +1,35 @@ +const foo1 = + // comment + () => () => 1; + +const foo2 = + // comment + () => () => 1; + +const foo3 = + // comment + () => 1; + +foo( + // comment + () => () => 1, +); + +a || + // comment + (() => () => 1); + +void + // comment + (() => () => 1); + +cond ? + // comment + () => () => 1 + : + // comment + () => () => 1; + +foo4 = + // comment + () => () => 1; diff --git a/tests/format/typescript/arrow/__snapshots__/format.test.js.snap b/tests/format/typescript/arrow/__snapshots__/format.test.js.snap index 7ec8edf51..4a4026248 100644 --- a/tests/format/typescript/arrow/__snapshots__/format.test.js.snap +++ b/tests/format/typescript/arrow/__snapshots__/format.test.js.snap @@ -1,5 +1,198 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`16067.ts - {"semi":false} format 1`] = ` +====================================options===================================== +parsers: ["typescript"] +printWidth: 80 +semi: false + | printWidth +=====================================input====================================== +const foo1 = + // comment + () => () => 1; + +const foo2 = + // comment + () => () => 1; + +const foo3 = + // comment + () => 1; + +foo( + // comment + () => () => 1, +); + +a || + // comment + (() => () => 1); + +void + // comment + (() => () => 1); + +cond ? + // comment + () => () => 1 + : + // comment + () => () => 1; + +foo4 = + // comment + () => () => 1; + +=====================================output===================================== +const foo1 = + // comment + () => + () => + 1 + +const foo2 = + // comment + () => () => 1 + +const foo3 = + // comment + () => 1 + +foo( + // comment + () => + () => + 1, +) + +a || + // comment + (() => + () => + 1) + +void ( + // comment + (() => + () => + 1) +) + +cond + ? // comment + () => + () => + 1 + : // comment + () => + () => + 1 + +foo4 = + // comment + () => + () => + 1 + +================================================================================ +`; + +exports[`16067.ts format 1`] = ` +====================================options===================================== +parsers: ["typescript"] +printWidth: 80 + | printWidth +=====================================input====================================== +const foo1 = + // comment + () => () => 1; + +const foo2 = + // comment + () => () => 1; + +const foo3 = + // comment + () => 1; + +foo( + // comment + () => () => 1, +); + +a || + // comment + (() => () => 1); + +void + // comment + (() => () => 1); + +cond ? + // comment + () => () => 1 + : + // comment + () => () => 1; + +foo4 = + // comment + () => () => 1; + +=====================================output===================================== +const foo1 = + // comment + () => + () => + 1; + +const foo2 = + // comment + () => () => 1; + +const foo3 = + // comment + () => 1; + +foo( + // comment + () => + () => + 1, +); + +a || + // comment + (() => + () => + 1); + +void ( + // comment + (() => + () => + 1) +); + +cond + ? // comment + () => + () => + 1 + : // comment + () => + () => + 1; + +foo4 = + // comment + () => + () => + 1; + +================================================================================ +`; + exports[`arrow_regression.ts - {"semi":false} format 1`] = ` ====================================options===================================== parsers: ["typescript"]