diff --git a/src/language-js/printer-estree.js b/src/language-js/printer-estree.js index 8f4477047..1c16f6784 100644 --- a/src/language-js/printer-estree.js +++ b/src/language-js/printer-estree.js @@ -487,13 +487,37 @@ function printPathNoParens(path, options, print, args) { " = ", path.call(print, "right") ]); - case "TSTypeAssertionExpression": - return concat([ - "<", - path.call(print, "typeAnnotation"), - ">", - path.call(print, "expression") + case "TSTypeAssertionExpression": { + const shouldBreakAfterCast = !( + n.expression.type === "ArrayExpression" || + n.expression.type === "ObjectExpression" + ); + + const castGroup = group( + concat([ + "<", + 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") && diff --git a/tests/typescript_cast/__snapshots__/jsfmt.spec.js.snap b/tests/typescript_cast/__snapshots__/jsfmt.spec.js.snap index e6caf614b..a5e4244b6 100644 --- a/tests/typescript_cast/__snapshots__/jsfmt.spec.js.snap +++ b/tests/typescript_cast/__snapshots__/jsfmt.spec.js.snap @@ -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 = >fits(); + const fitsObjLiteral = >{ a: "test" }; + const fitsArrayLiteral = >["test", "test2"] + + const breakAfterCast = >someExistingConfigMap.mergeDeep(fallbackOpts); + + const stillTooLong = >someExistingConfigMap.mergeDeep(fallbackOptions); + + const stillTooLong2 = | undefined>someExistingConfigMap.mergeDeep(fallbackOptions); + + const stillTooLong3 = >someExistingConfigMap.mergeDeep(fallbackOptions.someMethodWithLongName(param1, param2)); + + const stillTooLong4 = | undefined>someExistingConfigMap.mergeDeep(fallbackOptions.someMethodWithLongName(param1, param2)); + + const testObjLiteral = >{ property1: "myPropertyVal" }; + + const testObjLiteral2 = >{ property1: "myPropertyVal" }; + + const testArrayLiteral = >["first", "second", "third"]; + + const testArrayLiteral2 = >["first", "second", "third"]; + + const insideFuncCall = myFunc(param1, >param2, param3) +} + +// https://github.com/prettier/prettier/issues/4168 +function x() { + const fits = | undefined>(permissions)[type]; + const fitsObjLiteral = | undefined>{ a: "test" }; + const fitsArrayLiteral = | undefined>["t1", "t2"]; + + const breakAfterCast = | undefined>(permissions)[receiverType]; + + const stillTooLong = | undefined | number | string | boolean>(permissions)[receiverType]; + + const stillTooLong2 = | undefined | number | string | boolean | null | never>(permissions)[receiverType]; + + const stillTooLong3 = | undefined>(permissions.someMethodWithLongName(parameter1, parameter2))[receiverTypeLongName]; + + const stillTooLong4 = | undefined | number | string | boolean | null | never>(permissions.someMethodWithLongName(parameter1, parameter2))[receiverTypeLongName]; + + const testObjLiteral = | undefined>{ prop1: "myPropVal" }; + + const testObjLiteral2 = | undefined | number | string | boolean | null | never | object>{ prop1: "myPropVal" }; + + const testArrayLiteral = | undefined>["first", "second", "third"]; + + const testArrayLiteral2 = | undefined | number | string | boolean | null | never | object>["first", "second", "third"]; + + const insideFuncCall = myFunc(param1, | undefined>param2, param3) +} +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// https://github.com/prettier/prettier/issues/4171 +function y() { + const fits = >fits(); + const fitsObjLiteral = >{ a: "test" }; + const fitsArrayLiteral = >["test", "test2"]; + + const breakAfterCast = >( + 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 = >( + 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 = >{ + property1: "myPropertyVal" + }; + + const testObjLiteral2 = < + Immutable.Map< + string, + any, + number, + boolean, + object, + null, + undefined, + never, + "extra long" + > + >{ property1: "myPropertyVal" }; + + const testArrayLiteral = >[ + "first", + "second", + "third" + ]; + + const testArrayLiteral2 = < + Immutable.Map< + string, + any, + number, + boolean, + object, + null, + undefined, + never, + "extra long" + > + >["first", "second", "third"]; + + const insideFuncCall = myFunc( + param1, + >param2, + param3 + ); +} + +// https://github.com/prettier/prettier/issues/4168 +function x() { + const fits = | undefined>(permissions)[type]; + const fitsObjLiteral = | undefined>{ a: "test" }; + const fitsArrayLiteral = | undefined>["t1", "t2"]; + + const breakAfterCast = | undefined>( + (permissions)[receiverType] + ); + + const stillTooLong = < + PermissionsChecker | undefined | number | string | boolean + >(permissions)[receiverType]; + + const stillTooLong2 = < + | PermissionsChecker + | undefined + | number + | string + | boolean + | null + | never + >(permissions)[receiverType]; + + const stillTooLong3 = | undefined>( + (permissions.someMethodWithLongName(parameter1, parameter2))[ + receiverTypeLongName + ] + ); + + const stillTooLong4 = < + | PermissionsChecker + | undefined + | number + | string + | boolean + | null + | never + >(permissions.someMethodWithLongName(parameter1, parameter2))[ + receiverTypeLongName + ]; + + const testObjLiteral = | undefined>{ + prop1: "myPropVal" + }; + + const testObjLiteral2 = < + | PermissionsChecker + | undefined + | number + | string + | boolean + | null + | never + | object + >{ prop1: "myPropVal" }; + + const testArrayLiteral = | undefined>[ + "first", + "second", + "third" + ]; + + const testArrayLiteral2 = < + | PermissionsChecker + | undefined + | number + | string + | boolean + | null + | never + | object + >["first", "second", "third"]; + + const insideFuncCall = myFunc( + param1, + | undefined>param2, + param3 + ); +} + +`; + exports[`hug-args.ts 1`] = ` postMessage( { diff --git a/tests/typescript_cast/generic-cast.ts b/tests/typescript_cast/generic-cast.ts new file mode 100644 index 000000000..8c5231293 --- /dev/null +++ b/tests/typescript_cast/generic-cast.ts @@ -0,0 +1,54 @@ +// https://github.com/prettier/prettier/issues/4171 +function y() { + + const fits = >fits(); + const fitsObjLiteral = >{ a: "test" }; + const fitsArrayLiteral = >["test", "test2"] + + const breakAfterCast = >someExistingConfigMap.mergeDeep(fallbackOpts); + + const stillTooLong = >someExistingConfigMap.mergeDeep(fallbackOptions); + + const stillTooLong2 = | undefined>someExistingConfigMap.mergeDeep(fallbackOptions); + + const stillTooLong3 = >someExistingConfigMap.mergeDeep(fallbackOptions.someMethodWithLongName(param1, param2)); + + const stillTooLong4 = | undefined>someExistingConfigMap.mergeDeep(fallbackOptions.someMethodWithLongName(param1, param2)); + + const testObjLiteral = >{ property1: "myPropertyVal" }; + + const testObjLiteral2 = >{ property1: "myPropertyVal" }; + + const testArrayLiteral = >["first", "second", "third"]; + + const testArrayLiteral2 = >["first", "second", "third"]; + + const insideFuncCall = myFunc(param1, >param2, param3) +} + +// https://github.com/prettier/prettier/issues/4168 +function x() { + const fits = | undefined>(permissions)[type]; + const fitsObjLiteral = | undefined>{ a: "test" }; + const fitsArrayLiteral = | undefined>["t1", "t2"]; + + const breakAfterCast = | undefined>(permissions)[receiverType]; + + const stillTooLong = | undefined | number | string | boolean>(permissions)[receiverType]; + + const stillTooLong2 = | undefined | number | string | boolean | null | never>(permissions)[receiverType]; + + const stillTooLong3 = | undefined>(permissions.someMethodWithLongName(parameter1, parameter2))[receiverTypeLongName]; + + const stillTooLong4 = | undefined | number | string | boolean | null | never>(permissions.someMethodWithLongName(parameter1, parameter2))[receiverTypeLongName]; + + const testObjLiteral = | undefined>{ prop1: "myPropVal" }; + + const testObjLiteral2 = | undefined | number | string | boolean | null | never | object>{ prop1: "myPropVal" }; + + const testArrayLiteral = | undefined>["first", "second", "third"]; + + const testArrayLiteral2 = | undefined | number | string | boolean | null | never | object>["first", "second", "third"]; + + const insideFuncCall = myFunc(param1, | undefined>param2, param3) +}