From 153d2d0570a19b490bf79f0eba3aa76e6fc77c4a Mon Sep 17 00:00:00 2001 From: Ika Date: Tue, 22 Jan 2019 21:07:10 +0800 Subject: [PATCH] fix(typescript): stable parens for function type in arrow return type (#5790) --- CHANGELOG.unreleased.md | 26 +++++++++++++++++++ src/language-js/needs-parens.js | 20 ++++++++++++++ .../__snapshots__/jsfmt.spec.js.snap | 19 ++++++++++++++ tests/typescript_function_type/jsfmt.spec.js | 1 + .../type-annotation.ts | 3 +++ 5 files changed, 69 insertions(+) create mode 100644 tests/typescript_function_type/__snapshots__/jsfmt.spec.js.snap create mode 100644 tests/typescript_function_type/jsfmt.spec.js create mode 100644 tests/typescript_function_type/type-annotation.ts diff --git a/CHANGELOG.unreleased.md b/CHANGELOG.unreleased.md index 38d0f085..5e3e12ff 100644 --- a/CHANGELOG.unreleased.md +++ b/CHANGELOG.unreleased.md @@ -121,8 +121,34 @@ Examples: _foo bar_ ``` +- TypeScript: Stable parentheses for function type in the return type of arrow function ([#5790] by [@ikatyang]) + + There's a regression introduced in 1.16 that + parentheses for function type in the return type of arrow function were kept adding/removing. + Their parentheses are always printed now. + + + ```ts + // Input + const foo = (): (() => void) => (): void => null; + const bar = (): () => void => (): void => null; + + // First Output (Prettier stable) + const foo = (): () => void => (): void => null; + const bar = (): (() => void) => (): void => null; + + // Second Output (Prettier stable) + const foo = (): (() => void) => (): void => null; + const bar = (): () => void => (): void => null; + + // Output (Prettier master) + const foo = (): (() => void) => (): void => null; + const bar = (): (() => void) => (): void => null; + ``` + [@ikatyang]: https://github.com/ikatyang [@simenb]: https://github.com/SimenB [#5778]: https://github.com/prettier/prettier/pull/5778 [#5783]: https://github.com/prettier/prettier/pull/5783 [#5785]: https://github.com/prettier/prettier/pull/5785 +[#5790]: https://github.com/prettier/prettier/pull/5790 diff --git a/src/language-js/needs-parens.js b/src/language-js/needs-parens.js index 4a6a5097..47714279 100644 --- a/src/language-js/needs-parens.js +++ b/src/language-js/needs-parens.js @@ -353,6 +353,20 @@ function needsParens(path, options) { case "TSParenthesizedType": { const grandParent = path.getParentNode(1); + + /** + * const foo = (): (() => void) => (): void => null; + * ^ ^ + */ + if ( + getUnparenthesizedNode(node).type === "TSFunctionType" && + parent.type === "TSTypeAnnotation" && + grandParent.type === "ArrowFunctionExpression" && + grandParent.returnType === parent + ) { + return true; + } + if ( (parent.type === "TSTypeParameter" || parent.type === "TypeParameter" || @@ -719,6 +733,12 @@ function isStatement(node) { ); } +function getUnparenthesizedNode(node) { + return node.type === "TSParenthesizedType" + ? getUnparenthesizedNode(node.typeAnnotation) + : node; +} + function endsWithRightBracket(node) { switch (node.type) { case "ObjectExpression": diff --git a/tests/typescript_function_type/__snapshots__/jsfmt.spec.js.snap b/tests/typescript_function_type/__snapshots__/jsfmt.spec.js.snap new file mode 100644 index 00000000..f03a65c2 --- /dev/null +++ b/tests/typescript_function_type/__snapshots__/jsfmt.spec.js.snap @@ -0,0 +1,19 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-annotation.ts 1`] = ` +====================================options===================================== +parsers: ["typescript"] +printWidth: 80 + | printWidth +=====================================input====================================== +const foo = (): () => void => (): void => null; +const bar = (): (() => void) => (): void => null; +const baz = (): ((() => void)) => (): void => null; + +=====================================output===================================== +const foo = (): (() => void) => (): void => null; +const bar = (): (() => void) => (): void => null; +const baz = (): (() => void) => (): void => null; + +================================================================================ +`; diff --git a/tests/typescript_function_type/jsfmt.spec.js b/tests/typescript_function_type/jsfmt.spec.js new file mode 100644 index 00000000..2ea3bb6e --- /dev/null +++ b/tests/typescript_function_type/jsfmt.spec.js @@ -0,0 +1 @@ +run_spec(__dirname, ["typescript"]); diff --git a/tests/typescript_function_type/type-annotation.ts b/tests/typescript_function_type/type-annotation.ts new file mode 100644 index 00000000..5ea614ce --- /dev/null +++ b/tests/typescript_function_type/type-annotation.ts @@ -0,0 +1,3 @@ +const foo = (): () => void => (): void => null; +const bar = (): (() => void) => (): void => null; +const baz = (): ((() => void)) => (): void => null;