diff --git a/changelog_unreleased/javascript/18206.md b/changelog_unreleased/javascript/18206.md new file mode 100644 index 000000000..5168bb10c --- /dev/null +++ b/changelog_unreleased/javascript/18206.md @@ -0,0 +1,40 @@ +#### Fix inconsistent print between `CallExpression` and `NewExpression` (#18206 by @fisker) + + +```jsx +// Input +TelemetryTrustedValue( + instance.capabilities.get( + TerminalCapability?.PromptTypeDetection + )?.promptType +) + +new TelemetryTrustedValue( + instance.capabilities.get( + TerminalCapability?.PromptTypeDetection + )?.promptType +) + +// Prettier stable +TelemetryTrustedValue( + instance.capabilities.get(TerminalCapability?.PromptTypeDetection) + ?.promptType, +); + +new TelemetryTrustedValue( + instance.capabilities.get( + TerminalCapability?.PromptTypeDetection, + )?.promptType, +); + +// Prettier main +TelemetryTrustedValue( + instance.capabilities.get(TerminalCapability?.PromptTypeDetection) + ?.promptType, +); + +new TelemetryTrustedValue( + instance.capabilities.get(TerminalCapability?.PromptTypeDetection) + ?.promptType, +) +``` diff --git a/src/language-js/print/member.js b/src/language-js/print/member.js index 71f657c83..05f12c09c 100644 --- a/src/language-js/print/member.js +++ b/src/language-js/print/member.js @@ -14,6 +14,25 @@ const isCallExpressionWithArguments = (node) => { return isCallExpression(node) && getCallArguments(node).length > 0; }; +function shouldInlineNewExpressionCallee(path) { + let { node: child, ancestors } = path; + for (const ancestor of ancestors) { + if ( + !( + (isMemberExpression(ancestor) && ancestor.object === child) || + (ancestor.type === "TSNonNullExpression" && + ancestor.expression === child) + ) + ) { + return ancestor.type === "NewExpression" && ancestor.callee === child; + } + + child = ancestor; + } + + return false; +} + function printMemberExpression(path, options, print) { const objectDoc = print("object"); const lookupDoc = printMemberLookup(path, options, print); @@ -29,10 +48,10 @@ function printMemberExpression(path, options, print) { const shouldInline = (firstNonMemberParent && - (firstNonMemberParent.type === "NewExpression" || - firstNonMemberParent.type === "BindExpression" || + (firstNonMemberParent.type === "BindExpression" || (firstNonMemberParent.type === "AssignmentExpression" && firstNonMemberParent.left.type !== "Identifier"))) || + shouldInlineNewExpressionCallee(path) || node.computed || (node.object.type === "Identifier" && node.property.type === "Identifier" && diff --git a/tests/format/js/method-chain/18171.js b/tests/format/js/method-chain/18171.js new file mode 100644 index 000000000..baec279c2 --- /dev/null +++ b/tests/format/js/method-chain/18171.js @@ -0,0 +1,14 @@ +callExprssion( + instance.capabilities.get(TerminalCapability?.PromptTypeDetection) + ?.promptType, +); + +optionalCallExprssion?.( + instance.capabilities.get(TerminalCapability?.PromptTypeDetection) + ?.promptType, +); + +new NewExpression( + instance.capabilities.get(TerminalCapability?.PromptTypeDetection) + ?.promptType, +); diff --git a/tests/format/js/method-chain/__snapshots__/format.test.js.snap b/tests/format/js/method-chain/__snapshots__/format.test.js.snap index 9465b6117..13717488f 100644 --- a/tests/format/js/method-chain/__snapshots__/format.test.js.snap +++ b/tests/format/js/method-chain/__snapshots__/format.test.js.snap @@ -28,6 +28,46 @@ foo(a--).bar().leet(); ================================================================================ `; +exports[`18171.js format 1`] = ` +====================================options===================================== +parsers: ["babel", "flow", "typescript"] +printWidth: 80 + | printWidth +=====================================input====================================== +callExprssion( + instance.capabilities.get(TerminalCapability?.PromptTypeDetection) + ?.promptType, +); + +optionalCallExprssion?.( + instance.capabilities.get(TerminalCapability?.PromptTypeDetection) + ?.promptType, +); + +new NewExpression( + instance.capabilities.get(TerminalCapability?.PromptTypeDetection) + ?.promptType, +); + +=====================================output===================================== +callExprssion( + instance.capabilities.get(TerminalCapability?.PromptTypeDetection) + ?.promptType, +); + +optionalCallExprssion?.( + instance.capabilities.get(TerminalCapability?.PromptTypeDetection) + ?.promptType, +); + +new NewExpression( + instance.capabilities.get(TerminalCapability?.PromptTypeDetection) + ?.promptType, +); + +================================================================================ +`; + exports[`array-and-object.js format 1`] = ` ====================================options===================================== parsers: ["babel", "flow", "typescript"] diff --git a/tests/format/js/new-expression/__snapshots__/format.test.js.snap b/tests/format/js/new-expression/__snapshots__/format.test.js.snap index 4b6c8fda8..65aef5175 100644 --- a/tests/format/js/new-expression/__snapshots__/format.test.js.snap +++ b/tests/format/js/new-expression/__snapshots__/format.test.js.snap @@ -67,6 +67,13 @@ function functionName() { } } +foo = new long_long_member.long_long_member.long_long_member.long_long_member.long_long_member(); +new long_long_member.long_long_member.long_long_member.long_long_member.long_long_member(); +new long_long_member.long_long_member.long_long_member.long_long_member.long_long_member(x); +foo = long_long_member.long_long_member.long_long_member.long_long_member.long_long_member(); +long_long_member.long_long_member.long_long_member.long_long_member.long_long_member(); +long_long_member.long_long_member.long_long_member.long_long_member.long_long_member(x); + =====================================output===================================== function functionName() { // indent to make the line break @@ -79,5 +86,18 @@ function functionName() { } } +foo = + new long_long_member.long_long_member.long_long_member.long_long_member.long_long_member(); +new long_long_member.long_long_member.long_long_member.long_long_member.long_long_member(); +new long_long_member.long_long_member.long_long_member.long_long_member.long_long_member( + x, +); +foo = + long_long_member.long_long_member.long_long_member.long_long_member.long_long_member(); +long_long_member.long_long_member.long_long_member.long_long_member.long_long_member(); +long_long_member.long_long_member.long_long_member.long_long_member.long_long_member( + x, +); + ================================================================================ `; diff --git a/tests/format/js/new-expression/with-member-expression.js b/tests/format/js/new-expression/with-member-expression.js index b05c47135..49af34cd1 100644 --- a/tests/format/js/new-expression/with-member-expression.js +++ b/tests/format/js/new-expression/with-member-expression.js @@ -8,3 +8,10 @@ function functionName() { ); } } + +foo = new long_long_member.long_long_member.long_long_member.long_long_member.long_long_member(); +new long_long_member.long_long_member.long_long_member.long_long_member.long_long_member(); +new long_long_member.long_long_member.long_long_member.long_long_member.long_long_member(x); +foo = long_long_member.long_long_member.long_long_member.long_long_member.long_long_member(); +long_long_member.long_long_member.long_long_member.long_long_member.long_long_member(); +long_long_member.long_long_member.long_long_member.long_long_member.long_long_member(x); diff --git a/tests/format/typescript/new/__snapshots__/format.test.js.snap b/tests/format/typescript/new/__snapshots__/format.test.js.snap index ad133f262..52e779702 100644 --- a/tests/format/typescript/new/__snapshots__/format.test.js.snap +++ b/tests/format/typescript/new/__snapshots__/format.test.js.snap @@ -140,3 +140,53 @@ interface TimerConstructor { ================================================================================ `; + +exports[`with-member-expression.ts format 1`] = ` +====================================options===================================== +parsers: ["typescript"] +printWidth: 80 + | printWidth +=====================================input====================================== +foo = new long_long_member.long_long_member.long_long_member.long_long_member.long_long_member(); +new long_long_member.long_long_member.long_long_member.long_long_member.long_long_member(); +new long_long_member.long_long_member.long_long_member.long_long_member.long_long_member(x); +foo = new long_long_member!.long_long_member.long_long_member.long_long_member.long_long_member(); +new long_long_member!.long_long_member.long_long_member.long_long_member.long_long_member(); +new long_long_member!.long_long_member.long_long_member.long_long_member.long_long_member(x); + +foo = long_long_member.long_long_member.long_long_member.long_long_member.long_long_member(); +long_long_member.long_long_member.long_long_member.long_long_member.long_long_member(); +long_long_member.long_long_member.long_long_member.long_long_member.long_long_member(x); +foo = long_long_member!.long_long_member.long_long_member.long_long_member.long_long_member(); +long_long_member!.long_long_member.long_long_member.long_long_member.long_long_member(); +long_long_member!.long_long_member.long_long_member.long_long_member.long_long_member(x); + +=====================================output===================================== +foo = + new long_long_member.long_long_member.long_long_member.long_long_member.long_long_member(); +new long_long_member.long_long_member.long_long_member.long_long_member.long_long_member(); +new long_long_member.long_long_member.long_long_member.long_long_member.long_long_member( + x, +); +foo = + new long_long_member!.long_long_member.long_long_member.long_long_member.long_long_member(); +new long_long_member!.long_long_member.long_long_member.long_long_member.long_long_member(); +new long_long_member!.long_long_member.long_long_member.long_long_member.long_long_member( + x, +); + +foo = + long_long_member.long_long_member.long_long_member.long_long_member.long_long_member(); +long_long_member.long_long_member.long_long_member.long_long_member.long_long_member(); +long_long_member.long_long_member.long_long_member.long_long_member.long_long_member( + x, +); +foo = + long_long_member!.long_long_member.long_long_member.long_long_member.long_long_member(); +long_long_member!.long_long_member.long_long_member.long_long_member.long_long_member(); +long_long_member!.long_long_member.long_long_member.long_long_member.long_long_member( + x, +); + +================================================================================ +`; diff --git a/tests/format/typescript/new/with-member-expression.ts b/tests/format/typescript/new/with-member-expression.ts new file mode 100644 index 000000000..8be615797 --- /dev/null +++ b/tests/format/typescript/new/with-member-expression.ts @@ -0,0 +1,13 @@ +foo = new long_long_member.long_long_member.long_long_member.long_long_member.long_long_member(); +new long_long_member.long_long_member.long_long_member.long_long_member.long_long_member(); +new long_long_member.long_long_member.long_long_member.long_long_member.long_long_member(x); +foo = new long_long_member!.long_long_member.long_long_member.long_long_member.long_long_member(); +new long_long_member!.long_long_member.long_long_member.long_long_member.long_long_member(); +new long_long_member!.long_long_member.long_long_member.long_long_member.long_long_member(x); + +foo = long_long_member.long_long_member.long_long_member.long_long_member.long_long_member(); +long_long_member.long_long_member.long_long_member.long_long_member.long_long_member(); +long_long_member.long_long_member.long_long_member.long_long_member.long_long_member(x); +foo = long_long_member!.long_long_member.long_long_member.long_long_member.long_long_member(); +long_long_member!.long_long_member.long_long_member.long_long_member.long_long_member(); +long_long_member!.long_long_member.long_long_member.long_long_member.long_long_member(x);