Break inline object first in function arguments (#1453) (#1173)

This is getting subtle where the groups need to be in a precise position but that works :)

Fixes #1409
master
Christopher Chedeau 2017-05-01 19:12:53 -07:00 committed by GitHub
parent 8f9bb3a223
commit f59aeef865
5 changed files with 61 additions and 36 deletions

View File

@ -737,7 +737,7 @@ function genericPrintNoParens(path, options, print, args) {
case "ObjectPattern":
case "ObjectTypeAnnotation":
case "TSInterfaceDeclaration":
case "TSTypeLiteral":
case "TSTypeLiteral": {
var isTypeAnnotation = n.type === "ObjectTypeAnnotation";
var isTypeScriptTypeAnnotaion = n.type === "TSTypeLiteral";
var isTypeScriptInterfaceDeclaration = n.type === "TSInterfaceDeclaration";
@ -849,11 +849,16 @@ function genericPrintNoParens(path, options, print, args) {
// If we inline the object as first argument of the parent, we don't want
// to create another group so that the object breaks before the return
// type
const parentParentParent = path.getParentNode(2);
if (
n.type === "ObjectPattern" &&
parent.params &&
parent.params.length === 1 &&
parent.params[0] === n
(n.type === "ObjectPattern" &&
parent &&
shouldHugArguments(parent) &&
parent.params[0] === n) ||
(n.type === "ObjectTypeAnnotation" &&
parentParentParent &&
shouldHugArguments(parentParentParent) &&
parentParentParent.params[0].typeAnnotation.typeAnnotation === n)
) {
return content;
}
@ -867,7 +872,7 @@ function genericPrintNoParens(path, options, print, args) {
);
return group(content, { shouldBreak });
}
case "PropertyPattern":
return concat([
path.call(print, "key"),
@ -2636,15 +2641,7 @@ function printFunctionParams(path, print, options, expandArg) {
// b,
// c
// }) {}
if (
fun.params &&
fun.params.length === 1 &&
!fun.params[0].comments &&
(fun.params[0].type === "ObjectPattern" ||
(fun.params[0].type === "FunctionTypeParam" &&
fun.params[0].typeAnnotation.type === "ObjectTypeAnnotation")) &&
!fun.rest
) {
if (shouldHugArguments(fun)) {
return concat(["(", join(", ", printed), ")"]);
}
@ -3912,6 +3909,23 @@ function isNodeStartingWithDeclare(node, options) {
);
}
function shouldHugArguments(fun) {
return (
fun &&
fun.params &&
fun.params.length === 1 &&
!fun.params[0].comments &&
(fun.params[0].type === "ObjectPattern" ||
(fun.params[0].type === "Identifier" &&
fun.params[0].typeAnnotation &&
fun.params[0].typeAnnotation.type === "TypeAnnotation" &&
fun.params[0].typeAnnotation.typeAnnotation.type === "ObjectTypeAnnotation") ||
fun.params[0].type === "FunctionTypeParam" &&
fun.params[0].typeAnnotation.type === "ObjectTypeAnnotation") &&
!fun.rest
);
}
function printArrayItems(path, options, printPath, print) {
const printedElements = [];
let separatorParts = [];

View File

@ -43,9 +43,9 @@ function foo0(
return x;
}
function foo2(
x: { [key: string]: number }
): { [key: string]: number, +toString: () => string } {
function foo2(x: {
[key: string]: number
}): { [key: string]: number, +toString: () => string } {
// x's prototype has a toString method
return x;
}
@ -448,9 +448,9 @@ function mix_with_declared_props(o: { [k: number]: X, p: Y }, x: X, y: Y) {
}
// Indeed, dict types are still Objects and have Object.prototype stuff
function object_prototype(
o: { [k: string]: number }
): { [k: string]: number, +toString: () => string } {
function object_prototype(o: {
[k: string]: number
}): { [k: string]: number, +toString: () => string } {
(o.toString(): boolean); // error: string ~> boolean
return o; // ok
}
@ -458,9 +458,10 @@ function object_prototype(
// **UNSOUND**
// Because we support non-string props w/ bracket notation, it's possible to
// write into a declared prop unsoundly.
function unsound_string_conversion_alias_declared_prop(
o: { [k: number]: any, "0": X }
) {
function unsound_string_conversion_alias_declared_prop(o: {
[k: number]: any,
"0": X
}) {
o[0] = "not-x"; // a["0"] no longer X
}
@ -748,9 +749,9 @@ function foo3(x: { [key: string]: number }): { foo: number } {
}
// error: foo can't exist in x
function foo4(
x: { [key: string]: number }
): { [key: string]: number, foo: string } {
function foo4(x: {
[key: string]: number
}): { [key: string]: number, foo: string } {
return x;
}

View File

@ -30,15 +30,13 @@ function union2keys(s: Union): Keys { return s; } // ok
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/** @flow */
function isActive(
ad: {
state: $Keys<{
PAUSED: string,
ACTIVE: string,
DELETED: string
}>
}
): boolean {
function isActive(ad: {
state: $Keys<{
PAUSED: string,
ACTIVE: string,
DELETED: string
}>
}): boolean {
return ad.state === "ACTIVE";
}
isActive({ state: "PAUSE" });

View File

@ -61,6 +61,11 @@ type T = ({
title: number,
items: number,
}) => void;
const X = (props: {
a: boolean,
}) =>
<A />;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function StatelessFunctionalComponent({
isActive,
@ -123,4 +128,6 @@ type T = ({
items: number
}) => void;
const X = (props: { a: boolean }) => <A />;
`;

View File

@ -58,3 +58,8 @@ type T = ({
title: number,
items: number,
}) => void;
const X = (props: {
a: boolean,
}) =>
<A />;