diff --git a/changelog_unreleased/flow/13396.md b/changelog_unreleased/flow/13396.md new file mode 100644 index 000000000..a2527ebf3 --- /dev/null +++ b/changelog_unreleased/flow/13396.md @@ -0,0 +1,21 @@ +#### An object type in a `declare function` signature now breaks before the return type (#13396 by @thorn0) + +This behavior has been unified with how TypeScript is formatted. + + +```jsx +// Input +declare function bla (props: { a: boolean, b: string, c: number }): Promise> + +// Prettier stable +declare function bla(props: { a: boolean, b: string, c: number }): Promise< + Array +>; + +// Prettier main +declare function bla(props: { + a: boolean; + b: string; + c: number; +}): Promise>; +``` diff --git a/src/language-js/print/function-parameters.js b/src/language-js/print/function-parameters.js index ae13bdf75..089becfa2 100644 --- a/src/language-js/print/function-parameters.js +++ b/src/language-js/print/function-parameters.js @@ -62,7 +62,7 @@ function printFunctionParameters( const parent = path.getParentNode(); const isParametersInTestCall = isTestCall(parent); - const shouldHugParameters = shouldHugFunctionParameters(functionNode); + const shouldHugParameters = shouldHugTheOnlyFunctionParameter(functionNode); const printed = []; iterateFunctionParametersPath(path, (parameterPath, index) => { const isLastParameter = index === parameters.length - 1; @@ -157,7 +157,7 @@ function printFunctionParameters( ]; } -function shouldHugFunctionParameters(node) { +function shouldHugTheOnlyFunctionParameter(node) { if (!node) { return false; } @@ -176,7 +176,8 @@ function shouldHugFunctionParameters(node) { parameter.typeAnnotation.type === "TSTypeAnnotation") && isObjectType(parameter.typeAnnotation.typeAnnotation)) || (parameter.type === "FunctionTypeParam" && - isObjectType(parameter.typeAnnotation)) || + isObjectType(parameter.typeAnnotation) && + parameter !== node.rest) || (parameter.type === "AssignmentPattern" && (parameter.left.type === "ObjectPattern" || parameter.left.type === "ArrayPattern") && @@ -283,6 +284,6 @@ function isDecoratedFunction(path) { export { printFunctionParameters, - shouldHugFunctionParameters, + shouldHugTheOnlyFunctionParameter, shouldGroupFunctionParameters, }; diff --git a/src/language-js/print/object.js b/src/language-js/print/object.js index bf680ee49..f9fcc43e8 100644 --- a/src/language-js/print/object.js +++ b/src/language-js/print/object.js @@ -19,12 +19,12 @@ import { getComments, CommentCheckFlags, isNextLineEmpty, + isObjectType, } from "../utils/index.js"; import { locStart, locEnd } from "../loc.js"; import { printOptionalToken, printTypeAnnotation } from "./misc.js"; -import { shouldHugFunctionParameters } from "./function-parameters.js"; -import { shouldHugType } from "./type-annotation.js"; +import { shouldHugTheOnlyFunctionParameter } from "./function-parameters.js"; import { printHardlineAfterHeritage } from "./class.js"; /** @typedef {import("../../document/builders.js").Doc} Doc */ @@ -201,26 +201,21 @@ function printObject(path, options, print) { if ( path.match( (node) => node.type === "ObjectPattern" && !node.decorators, - (node, name, number) => - shouldHugFunctionParameters(node) && - (name === "params" || - name === "parameters" || - name === "this" || - name === "rest") && - number === 0 - ) || - path.match( - shouldHugType, - (node, name) => name === "typeAnnotation", - (node, name) => name === "typeAnnotation", - (node, name, number) => - shouldHugFunctionParameters(node) && - (name === "params" || - name === "parameters" || - name === "this" || - name === "rest") && - number === 0 + shouldHugTheOnlyParameter ) || + (isObjectType(node) && + (path.match( + undefined, + (node, name) => name === "typeAnnotation", + (node, name) => name === "typeAnnotation", + shouldHugTheOnlyParameter + ) || + path.match( + undefined, + (node, name) => + node.type === "FunctionTypeParam" && name === "typeAnnotation", + shouldHugTheOnlyParameter + ))) || // Assignment printing logic (printAssignment) is responsible // for adding a group if needed (!shouldBreak && @@ -237,4 +232,14 @@ function printObject(path, options, print) { return group(content, { shouldBreak }); } +function shouldHugTheOnlyParameter(node, name) { + return ( + (name === "params" || + name === "parameters" || + name === "this" || + name === "rest") && + shouldHugTheOnlyFunctionParameter(node) + ); +} + export { printObject }; diff --git a/tests/format/flow/function-single-destructuring/__snapshots__/jsfmt.spec.js.snap b/tests/format/flow/function-single-destructuring/__snapshots__/jsfmt.spec.js.snap index ef137757e..3698f80ac 100644 --- a/tests/format/flow/function-single-destructuring/__snapshots__/jsfmt.spec.js.snap +++ b/tests/format/flow/function-single-destructuring/__snapshots__/jsfmt.spec.js.snap @@ -133,3 +133,45 @@ const X = (props: { a: boolean }) => ; ================================================================================ `; + +exports[`object-type-in-declare-function.js format 1`] = ` +====================================options===================================== +parsers: ["flow", "babel"] +printWidth: 80 + | printWidth +=====================================input====================================== +declare function foo(this: { a: boolean, b: string, c: number }): + Promise> + +declare function bazFlip({ a: boolean, b: string, c: number }): + Promise> + +declare function bar(...{ a: boolean, b: string, c: number }): + Promise> + +declare function bar(...x: { a: boolean, b: string, c: number }): + Promise> + +=====================================output===================================== +declare function foo(this: { + a: boolean, + b: string, + c: number, +}): Promise>; + +declare function bazFlip({ + a: boolean, + b: string, + c: number, +}): Promise>; + +declare function bar( + ...{ a: boolean, b: string, c: number } +): Promise>; + +declare function bar( + ...x: { a: boolean, b: string, c: number } +): Promise>; + +================================================================================ +`; diff --git a/tests/format/flow/function-single-destructuring/object-type-in-declare-function.js b/tests/format/flow/function-single-destructuring/object-type-in-declare-function.js new file mode 100644 index 000000000..b9c8b00db --- /dev/null +++ b/tests/format/flow/function-single-destructuring/object-type-in-declare-function.js @@ -0,0 +1,11 @@ +declare function foo(this: { a: boolean, b: string, c: number }): + Promise> + +declare function bazFlip({ a: boolean, b: string, c: number }): + Promise> + +declare function bar(...{ a: boolean, b: string, c: number }): + Promise> + +declare function bar(...x: { a: boolean, b: string, c: number }): + Promise> diff --git a/tests/format/typescript/declare/__snapshots__/jsfmt.spec.js.snap b/tests/format/typescript/declare/__snapshots__/jsfmt.spec.js.snap index d6699d8ac..bbf19f940 100644 --- a/tests/format/typescript/declare/__snapshots__/jsfmt.spec.js.snap +++ b/tests/format/typescript/declare/__snapshots__/jsfmt.spec.js.snap @@ -215,3 +215,45 @@ class C { ================================================================================ `; + +exports[`object-type-in-declare-function.ts format 1`] = ` +====================================options===================================== +parsers: ["typescript"] +printWidth: 80 + | printWidth +=====================================input====================================== +declare function foo(this: { a: boolean, b: string, c: number }): + Promise> + +declare function bazFlip({ a: boolean, b: string, c: number }): + Promise> + +declare function bar(...{ a: boolean, b: string, c: number }): + Promise> + +declare function bar(...x: { a: boolean, b: string, c: number }): + Promise> + +=====================================output===================================== +declare function foo(this: { + a: boolean; + b: string; + c: number; +}): Promise>; + +declare function bazFlip({ + a: boolean, + b: string, + c: number, +}): Promise>; + +declare function bar( + ...{ a: boolean, b: string, c: number } +): Promise>; + +declare function bar( + ...x: { a: boolean; b: string; c: number } +): Promise>; + +================================================================================ +`; diff --git a/tests/format/typescript/declare/object-type-in-declare-function.ts b/tests/format/typescript/declare/object-type-in-declare-function.ts new file mode 100644 index 000000000..b9c8b00db --- /dev/null +++ b/tests/format/typescript/declare/object-type-in-declare-function.ts @@ -0,0 +1,11 @@ +declare function foo(this: { a: boolean, b: string, c: number }): + Promise> + +declare function bazFlip({ a: boolean, b: string, c: number }): + Promise> + +declare function bar(...{ a: boolean, b: string, c: number }): + Promise> + +declare function bar(...x: { a: boolean, b: string, c: number }): + Promise>