Avoid to break after assignment for call expression that has complex type parameters (#10949)

* Avoid break-after-operator when call expr has complex type params

* Add tests

* Add changelog

* Fix issue number

* Update snapshpts

* Address review

* Support Flow

* Rename parameters => arguments

* Remove isCallExpression
This commit is contained in:
Sosuke Suzuki authored and GitHub committed 2021-05-28 10:40:33 +09:00
1 parent 81a1c46311
commit 84f72be9dc
6 files changed
+308 -1

No files matched your search

+27
View File
@@ -0,0 +1,27 @@
#### Avoid breaking call expressions after assignments with complex type arguments (#10949 by @sosukesuzuki)
<!-- prettier-ignore -->
```ts
// Input
const foo = call<{
prop1: string;
prop2: string;
prop3: string;
}>();
// Prettier stable
const foo =
call<{
prop1: string;
prop2: string;
prop3: string;
}>();
// Prettier main
const foo = call<{
prop1: string;
prop2: string;
prop3: string;
}>();
```
+39 -1
View File
@@ -3,7 +3,7 @@
const { isNonEmptyArray, getStringWidth } = require("../../common/util");
const {
builders: { line, group, indent, indentIfBreak },
utils: { cleanDoc },
utils: { cleanDoc, willBreak },
} = require("../../document");
const {
hasLeadingOwnLineComment,
@@ -345,6 +345,10 @@ function isPoorlyBreakableMemberOrCallChain(
return false;
}
if (isCallExpressionWithComplexTypeArguments(node, print)) {
return false;
}
return path.call(goDeeper, "callee");
}
@@ -415,6 +419,40 @@ function isObjectPropertyWithShortKey(node, keyDoc, options) {
);
}
function isCallExpressionWithComplexTypeArguments(node, print) {
const typeArgs = getTypeArgumentsFromCallExpression(node);
if (isNonEmptyArray(typeArgs)) {
if (typeArgs.length > 1) {
return true;
}
if (typeArgs.length === 1) {
const firstArg = typeArgs[0];
if (
firstArg.type === "TSUnionType" ||
firstArg.type === "UnionTypeAnnotation" ||
firstArg.type === "TSIntersectionType" ||
firstArg.type === "IntersectionTypeAnnotation"
) {
return true;
}
}
const typeArgsKeyName = node.typeParameters
? "typeParameters"
: "typeArguments";
if (willBreak(print(typeArgsKeyName))) {
return true;
}
}
return false;
}
function getTypeArgumentsFromCallExpression(node) {
return (
(node.typeParameters && node.typeParameters.params) ||
(node.typeArguments && node.typeArguments.params)
);
}
module.exports = {
printVariableDeclarator,
printAssignmentExpression,
@@ -1,5 +1,88 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`issue-10846.js format 1`] = `
====================================options=====================================
parsers: ["babel-flow", "flow"]
printWidth: 80
| printWidth
=====================================input======================================
const foo1 =
call<{
prop1: string;
prop2: string;
prop3: string;
}>();
export const CallRecorderContext1 =
createContext<{
deleteRecording: (id: string) => void;
deleteAll: () => void;
} | null>(null);
export const CallRecorderContext2 = createContext<{
deleteRecording: (id: string) => void;
deleteAll: () => void;
} | null>(null, "useless");
const foo2 =
call<Foooooo, Foooooo, Foooooo, Foooooo, Foooooo, Foooooo, Foooooo>();
const foo3 =
call<
| Foooooooooooo
| Foooooooooooo
| Foooooooooooo
| Foooooooooooo
| Foooooooooooo
>();
const foo4 =
call<
Foooooooooooo &
Foooooooooooo &
Foooooooooooo &
Foooooooooooo &
Foooooooooooo
>();
=====================================output=====================================
const foo1 = call<{
prop1: string,
prop2: string,
prop3: string,
}>();
export const CallRecorderContext1 = createContext<{
deleteRecording: (id: string) => void,
deleteAll: () => void,
} | null>(null);
export const CallRecorderContext2 = createContext<{
deleteRecording: (id: string) => void,
deleteAll: () => void,
} | null>(null, "useless");
const foo2 = call<
Foooooo,
Foooooo,
Foooooo,
Foooooo,
Foooooo,
Foooooo,
Foooooo
>();
const foo3 = call<
Foooooooooooo | Foooooooooooo | Foooooooooooo | Foooooooooooo | Foooooooooooo
>();
const foo4 = call<
Foooooooooooo & Foooooooooooo & Foooooooooooo & Foooooooooooo & Foooooooooooo
>();
================================================================================
`;
exports[`issue-10850.js format 1`] = `
====================================options=====================================
parsers: ["babel-flow", "flow"]
@@ -0,0 +1,38 @@
const foo1 =
call<{
prop1: string;
prop2: string;
prop3: string;
}>();
export const CallRecorderContext1 =
createContext<{
deleteRecording: (id: string) => void;
deleteAll: () => void;
} | null>(null);
export const CallRecorderContext2 = createContext<{
deleteRecording: (id: string) => void;
deleteAll: () => void;
} | null>(null, "useless");
const foo2 =
call<Foooooo, Foooooo, Foooooo, Foooooo, Foooooo, Foooooo, Foooooo>();
const foo3 =
call<
| Foooooooooooo
| Foooooooooooo
| Foooooooooooo
| Foooooooooooo
| Foooooooooooo
>();
const foo4 =
call<
Foooooooooooo &
Foooooooooooo &
Foooooooooooo &
Foooooooooooo &
Foooooooooooo
>();
@@ -180,6 +180,89 @@ const firestorePersonallyIdentifiablePaths: Array<Collections.Users.Entity> =
================================================================================
`;
exports[`issue-10846.ts format 1`] = `
====================================options=====================================
parsers: ["typescript"]
printWidth: 80
| printWidth
=====================================input======================================
const foo = call<{
prop1: string;
prop2: string;
prop3: string;
}>();
export const CallRecorderContext =
createContext<{
deleteRecording: (id: string) => void;
deleteAll: () => void;
} | null>(null);
export const CallRecorderContext =
createContext<{
deleteRecording: (id: string) => void;
deleteAll: () => void;
} | null>(null, "useless");
const foo =
call<Foooooo, Foooooo, Foooooo, Foooooo, Foooooo, Foooooo, Foooooo>();
const foo =
call<
| Foooooooooooo
| Foooooooooooo
| Foooooooooooo
| Foooooooooooo
| Foooooooooooo
>();
const foo =
call<
Foooooooooooo &
Foooooooooooo &
Foooooooooooo &
Foooooooooooo &
Foooooooooooo
>();
=====================================output=====================================
const foo = call<{
prop1: string;
prop2: string;
prop3: string;
}>();
export const CallRecorderContext = createContext<{
deleteRecording: (id: string) => void;
deleteAll: () => void;
} | null>(null);
export const CallRecorderContext = createContext<{
deleteRecording: (id: string) => void;
deleteAll: () => void;
} | null>(null, "useless");
const foo = call<
Foooooo,
Foooooo,
Foooooo,
Foooooo,
Foooooo,
Foooooo,
Foooooo
>();
const foo = call<
Foooooooooooo | Foooooooooooo | Foooooooooooo | Foooooooooooo | Foooooooooooo
>();
const foo = call<
Foooooooooooo & Foooooooooooo & Foooooooooooo & Foooooooooooo & Foooooooooooo
>();
================================================================================
`;
exports[`issue-10850.ts format 1`] = `
====================================options=====================================
parsers: ["typescript"]
@@ -0,0 +1,38 @@
const foo = call<{
prop1: string;
prop2: string;
prop3: string;
}>();
export const CallRecorderContext =
createContext<{
deleteRecording: (id: string) => void;
deleteAll: () => void;
} | null>(null);
export const CallRecorderContext =
createContext<{
deleteRecording: (id: string) => void;
deleteAll: () => void;
} | null>(null, "useless");
const foo =
call<Foooooo, Foooooo, Foooooo, Foooooo, Foooooo, Foooooo, Foooooo>();
const foo =
call<
| Foooooooooooo
| Foooooooooooo
| Foooooooooooo
| Foooooooooooo
| Foooooooooooo
>();
const foo =
call<
Foooooooooooo &
Foooooooooooo &
Foooooooooooo &
Foooooooooooo &
Foooooooooooo
>();