Improve formatting of TS casts with generics and unions (#4219)
* Add tests showing existing behavior of various TS casts. * Improve formatting of TS casts with generics and unions. By adding a soft break between the cast and the expression. Also includes wrapping parentheses for clarity as suggested in #4171. Avoids changing behavior at all though if casting an array or object literal because those already have good behavior where the array or object literal breaks before the cast does so including them would just result in a pointless extra layer of parentheses that would add no clarity. * Update tests in prepation for updating long cast format. * Update so nested breaks inside type cast are indented. * Add tests where expression being cast is too long itself. * Update cast formatting to only sometimes break after cast. Specifically it will break after the cast if that makes the cast itself fit on a single line. If the cast itself won't fit on a single line then the expression being cast will be placed directly after the `>` at the end of the cast.master
parent
ed18f9f7d7
commit
c6e7c1966e
|
@ -487,13 +487,37 @@ function printPathNoParens(path, options, print, args) {
|
|||
" = ",
|
||||
path.call(print, "right")
|
||||
]);
|
||||
case "TSTypeAssertionExpression":
|
||||
return concat([
|
||||
case "TSTypeAssertionExpression": {
|
||||
const shouldBreakAfterCast = !(
|
||||
n.expression.type === "ArrayExpression" ||
|
||||
n.expression.type === "ObjectExpression"
|
||||
);
|
||||
|
||||
const castGroup = group(
|
||||
concat([
|
||||
"<",
|
||||
path.call(print, "typeAnnotation"),
|
||||
">",
|
||||
path.call(print, "expression")
|
||||
indent(concat([softline, path.call(print, "typeAnnotation")])),
|
||||
softline,
|
||||
">"
|
||||
])
|
||||
);
|
||||
|
||||
const exprContents = concat([
|
||||
ifBreak("("),
|
||||
indent(concat([softline, path.call(print, "expression")])),
|
||||
softline,
|
||||
ifBreak(")")
|
||||
]);
|
||||
|
||||
if (shouldBreakAfterCast) {
|
||||
return conditionalGroup([
|
||||
concat([castGroup, path.call(print, "expression")]),
|
||||
concat([castGroup, group(exprContents, { shouldBreak: true })]),
|
||||
concat([castGroup, path.call(print, "expression")])
|
||||
]);
|
||||
}
|
||||
return group(concat([castGroup, path.call(print, "expression")]));
|
||||
}
|
||||
case "MemberExpression": {
|
||||
const parent = path.getParentNode();
|
||||
let firstNonMemberParent;
|
||||
|
@ -2506,6 +2530,7 @@ function printPathNoParens(path, options, print, args) {
|
|||
// | C
|
||||
|
||||
const parent = path.getParentNode();
|
||||
const parentParent = path.getParentNode(1);
|
||||
|
||||
// If there's a leading comment, the parent is doing the indentation
|
||||
const shouldIndent =
|
||||
|
@ -2514,6 +2539,8 @@ function printPathNoParens(path, options, print, args) {
|
|||
parent.type !== "GenericTypeAnnotation" &&
|
||||
parent.type !== "TSTypeReference" &&
|
||||
!(parent.type === "FunctionTypeParam" && !parent.name) &&
|
||||
parentParent.type !== "TSTypeAssertionExpression" &&
|
||||
|
||||
!(
|
||||
(parent.type === "TypeAlias" ||
|
||||
parent.type === "VariableDeclarator") &&
|
||||
|
|
|
@ -1,5 +1,251 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`generic-cast.ts 1`] = `
|
||||
// https://github.com/prettier/prettier/issues/4171
|
||||
function y() {
|
||||
|
||||
const fits = <Immutable.Map<string, any>>fits();
|
||||
const fitsObjLiteral = <Immutable.Map<string, any>>{ a: "test" };
|
||||
const fitsArrayLiteral = <Immutable.Map<string, any>>["test", "test2"]
|
||||
|
||||
const breakAfterCast = <Immutable.Map<string, any>>someExistingConfigMap.mergeDeep(fallbackOpts);
|
||||
|
||||
const stillTooLong = <Immutable.Map<string, boolean, number, object, null, undefined, any, void, never>>someExistingConfigMap.mergeDeep(fallbackOptions);
|
||||
|
||||
const stillTooLong2 = <Immutable.Map<string, boolean, number, object, null, undefined, any, void, never> | undefined>someExistingConfigMap.mergeDeep(fallbackOptions);
|
||||
|
||||
const stillTooLong3 = <Immutable.Map<string>>someExistingConfigMap.mergeDeep(fallbackOptions.someMethodWithLongName(param1, param2));
|
||||
|
||||
const stillTooLong4 = <Immutable.Map<string, boolean, number, object, null, undefined, any, void, never> | undefined>someExistingConfigMap.mergeDeep(fallbackOptions.someMethodWithLongName(param1, param2));
|
||||
|
||||
const testObjLiteral = <Immutable.Map<string, any>>{ property1: "myPropertyVal" };
|
||||
|
||||
const testObjLiteral2 = <Immutable.Map<string, any, number, boolean, object, null, undefined, never, "extra long">>{ property1: "myPropertyVal" };
|
||||
|
||||
const testArrayLiteral = <Immutable.Map<string, any>>["first", "second", "third"];
|
||||
|
||||
const testArrayLiteral2 = <Immutable.Map<string, any, number, boolean, object, null, undefined, never, "extra long">>["first", "second", "third"];
|
||||
|
||||
const insideFuncCall = myFunc(param1, <Immutable.Map<string, any>>param2, param3)
|
||||
}
|
||||
|
||||
// https://github.com/prettier/prettier/issues/4168
|
||||
function x() {
|
||||
const fits = <PermissionsChecker<any> | undefined>(<any>permissions)[type];
|
||||
const fitsObjLiteral = <PermissionsChecker<any> | undefined>{ a: "test" };
|
||||
const fitsArrayLiteral = <PermissionsChecker<any> | undefined>["t1", "t2"];
|
||||
|
||||
const breakAfterCast = <PermissionsChecker<any> | undefined>(<any>permissions)[receiverType];
|
||||
|
||||
const stillTooLong = <PermissionsChecker<object> | undefined | number | string | boolean>(<any>permissions)[receiverType];
|
||||
|
||||
const stillTooLong2 = <PermissionsChecker<object> | undefined | number | string | boolean | null | never>(<any>permissions)[receiverType];
|
||||
|
||||
const stillTooLong3 = <PermissionsChecker<object> | undefined>(<any>permissions.someMethodWithLongName(parameter1, parameter2))[receiverTypeLongName];
|
||||
|
||||
const stillTooLong4 = <PermissionsChecker<object> | undefined | number | string | boolean | null | never>(<any>permissions.someMethodWithLongName(parameter1, parameter2))[receiverTypeLongName];
|
||||
|
||||
const testObjLiteral = <PermissionsChecker<any> | undefined>{ prop1: "myPropVal" };
|
||||
|
||||
const testObjLiteral2 = <PermissionsChecker<object> | undefined | number | string | boolean | null | never | object>{ prop1: "myPropVal" };
|
||||
|
||||
const testArrayLiteral = <PermissionsChecker<any> | undefined>["first", "second", "third"];
|
||||
|
||||
const testArrayLiteral2 = <PermissionsChecker<object> | undefined | number | string | boolean | null | never | object>["first", "second", "third"];
|
||||
|
||||
const insideFuncCall = myFunc(param1, <PermissionsChecker<any> | undefined>param2, param3)
|
||||
}
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// https://github.com/prettier/prettier/issues/4171
|
||||
function y() {
|
||||
const fits = <Immutable.Map<string, any>>fits();
|
||||
const fitsObjLiteral = <Immutable.Map<string, any>>{ a: "test" };
|
||||
const fitsArrayLiteral = <Immutable.Map<string, any>>["test", "test2"];
|
||||
|
||||
const breakAfterCast = <Immutable.Map<string, any>>(
|
||||
someExistingConfigMap.mergeDeep(fallbackOpts)
|
||||
);
|
||||
|
||||
const stillTooLong = <
|
||||
Immutable.Map<
|
||||
string,
|
||||
boolean,
|
||||
number,
|
||||
object,
|
||||
null,
|
||||
undefined,
|
||||
any,
|
||||
void,
|
||||
never
|
||||
>
|
||||
>someExistingConfigMap.mergeDeep(fallbackOptions);
|
||||
|
||||
const stillTooLong2 = <
|
||||
| Immutable.Map<
|
||||
string,
|
||||
boolean,
|
||||
number,
|
||||
object,
|
||||
null,
|
||||
undefined,
|
||||
any,
|
||||
void,
|
||||
never
|
||||
>
|
||||
| undefined
|
||||
>someExistingConfigMap.mergeDeep(fallbackOptions);
|
||||
|
||||
const stillTooLong3 = <Immutable.Map<string>>(
|
||||
someExistingConfigMap.mergeDeep(
|
||||
fallbackOptions.someMethodWithLongName(param1, param2)
|
||||
)
|
||||
);
|
||||
|
||||
const stillTooLong4 = <
|
||||
| Immutable.Map<
|
||||
string,
|
||||
boolean,
|
||||
number,
|
||||
object,
|
||||
null,
|
||||
undefined,
|
||||
any,
|
||||
void,
|
||||
never
|
||||
>
|
||||
| undefined
|
||||
>someExistingConfigMap.mergeDeep(
|
||||
fallbackOptions.someMethodWithLongName(param1, param2)
|
||||
);
|
||||
|
||||
const testObjLiteral = <Immutable.Map<string, any>>{
|
||||
property1: "myPropertyVal"
|
||||
};
|
||||
|
||||
const testObjLiteral2 = <
|
||||
Immutable.Map<
|
||||
string,
|
||||
any,
|
||||
number,
|
||||
boolean,
|
||||
object,
|
||||
null,
|
||||
undefined,
|
||||
never,
|
||||
"extra long"
|
||||
>
|
||||
>{ property1: "myPropertyVal" };
|
||||
|
||||
const testArrayLiteral = <Immutable.Map<string, any>>[
|
||||
"first",
|
||||
"second",
|
||||
"third"
|
||||
];
|
||||
|
||||
const testArrayLiteral2 = <
|
||||
Immutable.Map<
|
||||
string,
|
||||
any,
|
||||
number,
|
||||
boolean,
|
||||
object,
|
||||
null,
|
||||
undefined,
|
||||
never,
|
||||
"extra long"
|
||||
>
|
||||
>["first", "second", "third"];
|
||||
|
||||
const insideFuncCall = myFunc(
|
||||
param1,
|
||||
<Immutable.Map<string, any>>param2,
|
||||
param3
|
||||
);
|
||||
}
|
||||
|
||||
// https://github.com/prettier/prettier/issues/4168
|
||||
function x() {
|
||||
const fits = <PermissionsChecker<any> | undefined>(<any>permissions)[type];
|
||||
const fitsObjLiteral = <PermissionsChecker<any> | undefined>{ a: "test" };
|
||||
const fitsArrayLiteral = <PermissionsChecker<any> | undefined>["t1", "t2"];
|
||||
|
||||
const breakAfterCast = <PermissionsChecker<any> | undefined>(
|
||||
(<any>permissions)[receiverType]
|
||||
);
|
||||
|
||||
const stillTooLong = <
|
||||
PermissionsChecker<object> | undefined | number | string | boolean
|
||||
>(<any>permissions)[receiverType];
|
||||
|
||||
const stillTooLong2 = <
|
||||
| PermissionsChecker<object>
|
||||
| undefined
|
||||
| number
|
||||
| string
|
||||
| boolean
|
||||
| null
|
||||
| never
|
||||
>(<any>permissions)[receiverType];
|
||||
|
||||
const stillTooLong3 = <PermissionsChecker<object> | undefined>(
|
||||
(<any>permissions.someMethodWithLongName(parameter1, parameter2))[
|
||||
receiverTypeLongName
|
||||
]
|
||||
);
|
||||
|
||||
const stillTooLong4 = <
|
||||
| PermissionsChecker<object>
|
||||
| undefined
|
||||
| number
|
||||
| string
|
||||
| boolean
|
||||
| null
|
||||
| never
|
||||
>(<any>permissions.someMethodWithLongName(parameter1, parameter2))[
|
||||
receiverTypeLongName
|
||||
];
|
||||
|
||||
const testObjLiteral = <PermissionsChecker<any> | undefined>{
|
||||
prop1: "myPropVal"
|
||||
};
|
||||
|
||||
const testObjLiteral2 = <
|
||||
| PermissionsChecker<object>
|
||||
| undefined
|
||||
| number
|
||||
| string
|
||||
| boolean
|
||||
| null
|
||||
| never
|
||||
| object
|
||||
>{ prop1: "myPropVal" };
|
||||
|
||||
const testArrayLiteral = <PermissionsChecker<any> | undefined>[
|
||||
"first",
|
||||
"second",
|
||||
"third"
|
||||
];
|
||||
|
||||
const testArrayLiteral2 = <
|
||||
| PermissionsChecker<object>
|
||||
| undefined
|
||||
| number
|
||||
| string
|
||||
| boolean
|
||||
| null
|
||||
| never
|
||||
| object
|
||||
>["first", "second", "third"];
|
||||
|
||||
const insideFuncCall = myFunc(
|
||||
param1,
|
||||
<PermissionsChecker<any> | undefined>param2,
|
||||
param3
|
||||
);
|
||||
}
|
||||
|
||||
`;
|
||||
|
||||
exports[`hug-args.ts 1`] = `
|
||||
postMessage(
|
||||
<IActionMessage>{
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
// https://github.com/prettier/prettier/issues/4171
|
||||
function y() {
|
||||
|
||||
const fits = <Immutable.Map<string, any>>fits();
|
||||
const fitsObjLiteral = <Immutable.Map<string, any>>{ a: "test" };
|
||||
const fitsArrayLiteral = <Immutable.Map<string, any>>["test", "test2"]
|
||||
|
||||
const breakAfterCast = <Immutable.Map<string, any>>someExistingConfigMap.mergeDeep(fallbackOpts);
|
||||
|
||||
const stillTooLong = <Immutable.Map<string, boolean, number, object, null, undefined, any, void, never>>someExistingConfigMap.mergeDeep(fallbackOptions);
|
||||
|
||||
const stillTooLong2 = <Immutable.Map<string, boolean, number, object, null, undefined, any, void, never> | undefined>someExistingConfigMap.mergeDeep(fallbackOptions);
|
||||
|
||||
const stillTooLong3 = <Immutable.Map<string>>someExistingConfigMap.mergeDeep(fallbackOptions.someMethodWithLongName(param1, param2));
|
||||
|
||||
const stillTooLong4 = <Immutable.Map<string, boolean, number, object, null, undefined, any, void, never> | undefined>someExistingConfigMap.mergeDeep(fallbackOptions.someMethodWithLongName(param1, param2));
|
||||
|
||||
const testObjLiteral = <Immutable.Map<string, any>>{ property1: "myPropertyVal" };
|
||||
|
||||
const testObjLiteral2 = <Immutable.Map<string, any, number, boolean, object, null, undefined, never, "extra long">>{ property1: "myPropertyVal" };
|
||||
|
||||
const testArrayLiteral = <Immutable.Map<string, any>>["first", "second", "third"];
|
||||
|
||||
const testArrayLiteral2 = <Immutable.Map<string, any, number, boolean, object, null, undefined, never, "extra long">>["first", "second", "third"];
|
||||
|
||||
const insideFuncCall = myFunc(param1, <Immutable.Map<string, any>>param2, param3)
|
||||
}
|
||||
|
||||
// https://github.com/prettier/prettier/issues/4168
|
||||
function x() {
|
||||
const fits = <PermissionsChecker<any> | undefined>(<any>permissions)[type];
|
||||
const fitsObjLiteral = <PermissionsChecker<any> | undefined>{ a: "test" };
|
||||
const fitsArrayLiteral = <PermissionsChecker<any> | undefined>["t1", "t2"];
|
||||
|
||||
const breakAfterCast = <PermissionsChecker<any> | undefined>(<any>permissions)[receiverType];
|
||||
|
||||
const stillTooLong = <PermissionsChecker<object> | undefined | number | string | boolean>(<any>permissions)[receiverType];
|
||||
|
||||
const stillTooLong2 = <PermissionsChecker<object> | undefined | number | string | boolean | null | never>(<any>permissions)[receiverType];
|
||||
|
||||
const stillTooLong3 = <PermissionsChecker<object> | undefined>(<any>permissions.someMethodWithLongName(parameter1, parameter2))[receiverTypeLongName];
|
||||
|
||||
const stillTooLong4 = <PermissionsChecker<object> | undefined | number | string | boolean | null | never>(<any>permissions.someMethodWithLongName(parameter1, parameter2))[receiverTypeLongName];
|
||||
|
||||
const testObjLiteral = <PermissionsChecker<any> | undefined>{ prop1: "myPropVal" };
|
||||
|
||||
const testObjLiteral2 = <PermissionsChecker<object> | undefined | number | string | boolean | null | never | object>{ prop1: "myPropVal" };
|
||||
|
||||
const testArrayLiteral = <PermissionsChecker<any> | undefined>["first", "second", "third"];
|
||||
|
||||
const testArrayLiteral2 = <PermissionsChecker<object> | undefined | number | string | boolean | null | never | object>["first", "second", "third"];
|
||||
|
||||
const insideFuncCall = myFunc(param1, <PermissionsChecker<any> | undefined>param2, param3)
|
||||
}
|
Loading…
Reference in New Issue