Inline | null and | void (#1734)
TypeScript doesn't have the concept of `?` for nullable options and instead you have to write `| null` and `| void`. This is annoying to have it use the long form, so we're now inlining them. While working on this, I found out a few issues with the way we deal with those: - We only align objects if the parent is a union. This means that if you have `Array<{ object }>`, the object is not aligned properly. The fix is to move the alignment logic to the union, and not the child. - When doing so, it messes up with the comment alignment, so we have to manually handle children comment printing in the union code. It doesn't yet fix #1727 because the hardcoded type names are different, i'll follow up in a PR.master
parent
62679f20f0
commit
fe49650700
|
@ -817,7 +817,7 @@ function genericPrintNoParens(path, options, print, args) {
|
|||
const leftBrace = n.exact ? "{|" : "{";
|
||||
const rightBrace = n.exact ? "|}" : "}";
|
||||
const parent = path.getParentNode(0);
|
||||
const parentIsUnionTypeAnnotation = parent.type === "UnionTypeAnnotation";
|
||||
|
||||
let propertiesField;
|
||||
|
||||
if (n.type === "TSTypeLiteral") {
|
||||
|
@ -881,10 +881,7 @@ function genericPrintNoParens(path, options, print, args) {
|
|||
content = concat([
|
||||
leftBrace,
|
||||
indent(
|
||||
align(
|
||||
parentIsUnionTypeAnnotation ? 2 : 0,
|
||||
concat([options.bracketSpacing ? line : softline, concat(props)])
|
||||
)
|
||||
concat([options.bracketSpacing ? line : softline, concat(props)])
|
||||
),
|
||||
ifBreak(
|
||||
canHaveTrailingSeparator &&
|
||||
|
@ -892,10 +889,7 @@ function genericPrintNoParens(path, options, print, args) {
|
|||
? separator
|
||||
: ""
|
||||
),
|
||||
align(
|
||||
parentIsUnionTypeAnnotation ? 2 : 0,
|
||||
concat([options.bracketSpacing ? line : softline, rightBrace])
|
||||
),
|
||||
concat([options.bracketSpacing ? line : softline, rightBrace]),
|
||||
n.typeAnnotation ? ": " : "",
|
||||
path.call(print, "typeAnnotation")
|
||||
]);
|
||||
|
@ -910,7 +904,7 @@ function genericPrintNoParens(path, options, print, args) {
|
|||
parent &&
|
||||
shouldHugArguments(parent) &&
|
||||
parent.params[0] === n) ||
|
||||
(n.type === "ObjectTypeAnnotation" &&
|
||||
(shouldHugType(n) &&
|
||||
parentParentParent &&
|
||||
shouldHugArguments(parentParentParent) &&
|
||||
parentParentParent.params[0].typeAnnotation.typeAnnotation === n)
|
||||
|
@ -1994,10 +1988,31 @@ function genericPrintNoParens(path, options, print, args) {
|
|||
!(parent.type === "TypeAlias" &&
|
||||
hasLeadingOwnLineComment(options.originalText, n));
|
||||
|
||||
//const token = isIntersection ? "&" : "|";
|
||||
// {
|
||||
// a: string
|
||||
// } | null | void
|
||||
// should be inlined and not be printed in the multi-line variant
|
||||
const shouldHug = shouldHugType(n);
|
||||
|
||||
// We want to align the children but without its comment, so it looks like
|
||||
// | child1
|
||||
// // comment
|
||||
// | child2
|
||||
const printed = path.map(typePath => {
|
||||
let printedType = typePath.call(print);
|
||||
if (!shouldHug && shouldIndent) {
|
||||
printedType = align(2, printedType);
|
||||
}
|
||||
return comments.printComments(typePath, () => printedType, options);
|
||||
}, "types");
|
||||
|
||||
if (shouldHug) {
|
||||
return join(" | ", printed);
|
||||
}
|
||||
|
||||
const code = concat([
|
||||
ifBreak(concat([shouldIndent ? line : "", "| "])),
|
||||
join(concat([line, "| "]), path.map(print, "types"))
|
||||
join(concat([line, "| "]), printed)
|
||||
]);
|
||||
|
||||
return group(shouldIndent ? indent(code) : code);
|
||||
|
@ -3341,7 +3356,7 @@ function printTypeParameters(path, options, print, paramsKey) {
|
|||
|
||||
const shouldInline =
|
||||
n[paramsKey].length === 1 &&
|
||||
(n[paramsKey][0].type === "ObjectTypeAnnotation" ||
|
||||
(shouldHugType(n[paramsKey][0]) ||
|
||||
n[paramsKey][0].type === "NullableTypeAnnotation");
|
||||
|
||||
if (shouldInline) {
|
||||
|
@ -4479,6 +4494,25 @@ function isNodeStartingWithDeclare(node, options) {
|
|||
);
|
||||
}
|
||||
|
||||
function shouldHugType(node) {
|
||||
if (node.type === "ObjectTypeAnnotation") {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (node.type === "UnionTypeAnnotation") {
|
||||
const count = node.types.filter(
|
||||
n =>
|
||||
n.type === "VoidTypeAnnotation" ||
|
||||
n.type === "NullLiteralTypeAnnotation"
|
||||
).length;
|
||||
|
||||
if (node.types.length - 1 === count) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function shouldHugArguments(fun) {
|
||||
return (
|
||||
fun &&
|
||||
|
@ -4489,10 +4523,9 @@ function shouldHugArguments(fun) {
|
|||
(fun.params[0].type === "Identifier" &&
|
||||
fun.params[0].typeAnnotation &&
|
||||
fun.params[0].typeAnnotation.type === "TypeAnnotation" &&
|
||||
fun.params[0].typeAnnotation.typeAnnotation.type ===
|
||||
"ObjectTypeAnnotation") ||
|
||||
shouldHugType(fun.params[0].typeAnnotation.typeAnnotation)) ||
|
||||
(fun.params[0].type === "FunctionTypeParam" &&
|
||||
fun.params[0].typeAnnotation.type === "ObjectTypeAnnotation")) &&
|
||||
shouldHugType(fun.params[0].typeAnnotation))) &&
|
||||
!fun.rest
|
||||
);
|
||||
}
|
||||
|
@ -4557,8 +4590,13 @@ function printAstToDoc(ast, options, addAlignmentSize) {
|
|||
|
||||
function printGenerically(path, args) {
|
||||
const node = path.getValue();
|
||||
const parent = path.getParentNode(0);
|
||||
// We let JSXElement print its comments itself because it adds () around
|
||||
if (node && node.type === "JSXElement") {
|
||||
// UnionTypeAnnotation has to align the child without the comments
|
||||
if (
|
||||
(node && node.type === "JSXElement") ||
|
||||
(parent && parent.type === "UnionTypeAnnotation")
|
||||
) {
|
||||
return genericPrint(path, options, printGenerically, args);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`union.js 1`] = `
|
||||
interface RelayProps {
|
||||
articles: Array<{
|
||||
__id: string,
|
||||
} | null> | null | void | 1,
|
||||
}
|
||||
|
||||
interface RelayProps {
|
||||
articles: Array<{
|
||||
__id: string,
|
||||
} | null> | null | void,
|
||||
}
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
interface RelayProps {
|
||||
articles:
|
||||
| Array<{
|
||||
__id: string
|
||||
} | null>
|
||||
| null
|
||||
| void
|
||||
| 1
|
||||
}
|
||||
|
||||
interface RelayProps {
|
||||
articles: Array<{
|
||||
__id: string
|
||||
} | null> | null | void
|
||||
}
|
||||
|
||||
`;
|
|
@ -0,0 +1 @@
|
|||
run_spec(__dirname, null, ["babylon"]);
|
|
@ -0,0 +1,11 @@
|
|||
interface RelayProps {
|
||||
articles: Array<{
|
||||
__id: string,
|
||||
} | null> | null | void | 1,
|
||||
}
|
||||
|
||||
interface RelayProps {
|
||||
articles: Array<{
|
||||
__id: string,
|
||||
} | null> | null | void,
|
||||
}
|
Loading…
Reference in New Issue