From 84ee9016ba4f99bb423cb144173d5ba679377de2 Mon Sep 17 00:00:00 2001 From: Seiya <20365512+seiyab@users.noreply.github.com> Date: Sun, 22 Jun 2025 00:51:13 +0900 Subject: [PATCH] Get JSX in arrow in method call to be consistent (#17616) * add failing test * fix #17489 * add more tests * refactor ...but perhaps get ugly? I'm not sure * Apply automated changes * utilize path.match * add changelog --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> --- changelog_unreleased/javascript/17616.md | 46 ++++++++++ src/language-js/print/jsx.js | 33 +++++-- .../__snapshots__/format.test.js.snap | 92 ++++++++++++++++++- .../optional-chaining/optional-chaining.jsx | 40 ++++++++ 4 files changed, 203 insertions(+), 8 deletions(-) create mode 100644 changelog_unreleased/javascript/17616.md diff --git a/changelog_unreleased/javascript/17616.md b/changelog_unreleased/javascript/17616.md new file mode 100644 index 000000000..775a9d050 --- /dev/null +++ b/changelog_unreleased/javascript/17616.md @@ -0,0 +1,46 @@ +#### Improve consistency for JSX in optional method call (#17616 by @seiyab) + + +```jsx +// Input + +
+ {Array(20) + .fill() + ?.map((_, i) => ( +

{i + 1}

+ ))} +
+
; + +// Prettier stable (ESTree based parsers like espree and typescript) + +
+ {Array(20) + .fill() + ?.map((_, i) =>

{i + 1}

)} +
+
; + +// Prettier stable (babel and babel-ts parser) + +
+ {Array(20) + .fill() + ?.map((_, i) => ( +

{i + 1}

+ ))} +
+
; + +// Prettier main (parsers of both types) + +
+ {Array(20) + .fill() + ?.map((_, i) => ( +

{i + 1}

+ ))} +
+
; +``` diff --git a/src/language-js/print/jsx.js b/src/language-js/print/jsx.js index a2a705491..20b106a7c 100644 --- a/src/language-js/print/jsx.js +++ b/src/language-js/print/jsx.js @@ -504,13 +504,7 @@ function maybeWrapJsxElementInParens(path, elem, options) { return elem; } - const shouldBreak = path.match( - undefined, - (node) => node.type === "ArrowFunctionExpression", - isCallExpression, - (node) => node.type === "JSXExpressionContainer", - ); - + const shouldBreak = shouldBreakJsxElement(path); const needsParens = pathNeedsParens(path, options); return group( @@ -524,6 +518,31 @@ function maybeWrapJsxElementInParens(path, elem, options) { ); } +function shouldBreakJsxElement(path) { + return ( + path.match( + undefined, + (node) => node.type === "ArrowFunctionExpression", + isCallExpression, + ) && + // Babel + (path.match( + undefined, + undefined, + undefined, + (node) => node.type === "JSXExpressionContainer", + ) || + // Estree + path.match( + undefined, + undefined, + undefined, + (node) => node.type === "ChainExpression", + (node) => node.type === "JSXExpressionContainer", + )) + ); +} + function printJsxAttribute(path, options, print) { const { node } = path; const parts = []; diff --git a/tests/format/jsx/optional-chaining/__snapshots__/format.test.js.snap b/tests/format/jsx/optional-chaining/__snapshots__/format.test.js.snap index 959f68a90..770ab4b71 100644 --- a/tests/format/jsx/optional-chaining/__snapshots__/format.test.js.snap +++ b/tests/format/jsx/optional-chaining/__snapshots__/format.test.js.snap @@ -1,4 +1,4 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP +// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing exports[`optional-chaining.jsx format 1`] = ` ====================================options===================================== @@ -18,6 +18,46 @@ function foo() { ) } +function Component( ) { + return ( +
+ {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa?.bbbbbbbbbbbbbbbbbbbbbbbbb.map( + (p, i) =>

{p}

+ )} +
+ ); +} + +function Component() { + return ( +
+ {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa?.bbbbbbbbbbbbbbbbbbbbbbbbb().map( + (p, i) =>

{p}

+ )} +
+ ); +} + +function Component() { + return ( +
+ {aaa?.aaa()?.aaa()?.map( + (p, i) =>

{p}

+ )} +
+ ); +} + +function Component() { + return ( +
+ {aaa?.aaa?.()?.aaa?.()?.map?.( + (p, i) =>

{p}

+ )} +
+ ); +} + =====================================output===================================== function foo() { // https://github.com/marmelab/react-admin/blob/5ae855aa958ba54438b144bf0907b1437c5a5d77/examples/demo/src/orders/Totals.tsx#L38-L43 @@ -31,5 +71,55 @@ function foo() { ); } +function Component() { + return ( +
+ {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa?.bbbbbbbbbbbbbbbbbbbbbbbbb.map( + (p, i) => ( +

{p}

+ ), + )} +
+ ); +} + +function Component() { + return ( +
+ {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + ?.bbbbbbbbbbbbbbbbbbbbbbbbb() + .map((p, i) => ( +

{p}

+ ))} +
+ ); +} + +function Component() { + return ( +
+ {aaa + ?.aaa() + ?.aaa() + ?.map((p, i) => ( +

{p}

+ ))} +
+ ); +} + +function Component() { + return ( +
+ {aaa + ?.aaa?.() + ?.aaa?.() + ?.map?.((p, i) => ( +

{p}

+ ))} +
+ ); +} + ================================================================================ `; diff --git a/tests/format/jsx/optional-chaining/optional-chaining.jsx b/tests/format/jsx/optional-chaining/optional-chaining.jsx index 3d5ffd50a..6b59a8bc1 100644 --- a/tests/format/jsx/optional-chaining/optional-chaining.jsx +++ b/tests/format/jsx/optional-chaining/optional-chaining.jsx @@ -9,3 +9,43 @@ function foo() { ) } + +function Component( ) { + return ( +
+ {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa?.bbbbbbbbbbbbbbbbbbbbbbbbb.map( + (p, i) =>

{p}

+ )} +
+ ); +} + +function Component() { + return ( +
+ {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa?.bbbbbbbbbbbbbbbbbbbbbbbbb().map( + (p, i) =>

{p}

+ )} +
+ ); +} + +function Component() { + return ( +
+ {aaa?.aaa()?.aaa()?.map( + (p, i) =>

{p}

+ )} +
+ ); +} + +function Component() { + return ( +
+ {aaa?.aaa?.()?.aaa?.()?.map?.( + (p, i) =>

{p}

+ )} +
+ ); +}