Various fixes with destructuring default, JSX, and more; all tests pass!

master
James Long 2016-12-30 17:00:11 -05:00
parent 649e8a1efe
commit 7ea2348b03
9 changed files with 58 additions and 194 deletions

View File

@ -27,7 +27,8 @@
"jsfmt\\.spec\\.js$" "jsfmt\\.spec\\.js$"
], ],
"testPathIgnorePatterns": [ "testPathIgnorePatterns": [
"tests/new_react" "tests/new_react",
"tests/more_react"
] ]
} }
} }

View File

@ -320,7 +320,8 @@ FPp.needsParens = function(assumeExpressionContext) {
return parent.type === "ArrayTypeAnnotation"; return parent.type === "ArrayTypeAnnotation";
case "FunctionTypeAnnotation": case "FunctionTypeAnnotation":
return parent.type === "UnionTypeAnnotation"; return parent.type === "UnionTypeAnnotation" ||
parent.type === "IntersectionTypeAnnotation";
case "Literal": case "Literal":
return parent.type === "MemberExpression" return parent.type === "MemberExpression"
@ -351,7 +352,8 @@ FPp.needsParens = function(assumeExpressionContext) {
&& parent.object === node; && parent.object === node;
default: default:
return false; return n.ObjectPattern.check(node.left) &&
this.firstInStatement();
} }
case "ArrowFunctionExpression": case "ArrowFunctionExpression":
@ -439,7 +441,9 @@ FPp.canBeFirstInStatement = function() {
var node = this.getNode(); var node = this.getNode();
return !n.FunctionExpression.check(node) return !n.FunctionExpression.check(node)
&& !n.ObjectExpression.check(node) && !n.ObjectExpression.check(node)
&& !n.ClassExpression.check(node); && !n.ClassExpression.check(node)
&& !(n.AssignmentExpression.check(node) &&
n.ObjectPattern.check(node.left));
}; };
FPp.firstInStatement = function() { FPp.firstInStatement = function() {

View File

@ -165,7 +165,7 @@ function genericPrint(path, options, printPath) {
var linesWithoutParens = var linesWithoutParens =
genericPrintNoParens(path, options, printPath); genericPrintNoParens(path, options, printPath);
if (! node || isEmpty(linesWithoutParens)) { if (!node || isEmpty(linesWithoutParens)) {
return linesWithoutParens; return linesWithoutParens;
} }
@ -668,15 +668,18 @@ function genericPrintNoParens(path, options, print) {
return printMethod(path, options, print); return printMethod(path, options, print);
} }
var key = path.call(print, "key");
if (n.computed) { if (n.computed) {
parts.push("[", key, "]"); parts.push("[", path.call(print, "key"), "]")
} else { }
parts.push(key); else {
parts.push(path.call(print, n.shorthand ? "value" : "key"));
} }
if (! n.shorthand) { if(!n.shorthand) {
parts.push(": ", path.call(print, "value")); parts.push(
": ",
path.call(print, "value")
);
} }
return concat(parts); return concat(parts);
@ -1082,19 +1085,27 @@ function genericPrintNoParens(path, options, print) {
return openingLines; return openingLines;
} }
var children = path.map(function(childPath) { var children = [];
path.map(function(childPath) {
var child = childPath.getValue(); var child = childPath.getValue();
if (namedTypes.Literal.check(child) && if (namedTypes.Literal.check(child) &&
typeof child.value === "string") { typeof child.value === "string") {
if (/\S/.test(child.value)) { if (/\S/.test(child.value)) {
return child.value.replace(/^\s+|\s+$/g, "").replace(/\n/, hardline); const beginBreak = child.value.match(/^\s*\n/);
const endBreak = child.value.match(/\n\s*$/);
children.push(
beginBreak ? hardline : "",
child.value.replace(/^\s+|\s+$/g, ""),
endBreak ? hardline : ""
);
} else if (/\n/.test(child.value)) { } else if (/\n/.test(child.value)) {
return hardline; children.push(hardline);
} }
} }
else {
return print(childPath); children.push(print(childPath));
}
}, "children"); }, "children");
var mostChildren = children.slice(0, -1); var mostChildren = children.slice(0, -1);
@ -1120,10 +1131,10 @@ function genericPrintNoParens(path, options, print) {
return concat(["</", path.call(print, "name"), ">"]); return concat(["</", path.call(print, "name"), ">"]);
case "JSXText": case "JSXText":
return fromString(n.value, options); throw new Error("JSXTest should be handled by JSXElement");
case "JSXEmptyExpression": case "JSXEmptyExpression":
return fromString(""); return "";
case "TypeAnnotatedIdentifier": case "TypeAnnotatedIdentifier":
return concat([ return concat([
@ -1425,7 +1436,11 @@ function genericPrintNoParens(path, options, print) {
return fromString("number", options); return fromString("number", options);
case "ObjectTypeCallProperty": case "ObjectTypeCallProperty":
return path.call(print, "value"); if(n.static) {
parts.push("static ");
}
parts.push(path.call(print, "value"));
return concat(parts);
case "ObjectTypeIndexer": case "ObjectTypeIndexer":
var variance = var variance =
@ -1808,12 +1823,12 @@ function printExportDeclaration(path, options, print) {
} else if (decl.specifiers && } else if (decl.specifiers &&
decl.specifiers.length > 0) { decl.specifiers.length > 0) {
if (decl.specifiers.length === 1 && if (decl.specifiers.length === 1 &&
decl.specifiers[0].type === "ExportBatchSpecifier") { decl.specifiers[0].type === "ExportBatchSpecifier") {
parts.push("*"); parts.push("*");
} else { } else {
parts.push( parts.push(
decl.exportKind === "type" ? "type " : "",
shouldPrintSpaces ? "{ " : "{", shouldPrintSpaces ? "{ " : "{",
join(", ", path.map(print, "specifiers")), join(", ", path.map(print, "specifiers")),
shouldPrintSpaces ? " }" : "}" shouldPrintSpaces ? " }" : "}"

View File

@ -40,7 +40,11 @@ Foo.prototype = {
}; };
exports.Foo = Foo; exports.Foo = Foo;
interface IFooPrototype { m(): number } interface IFooPrototype { m(): number }
interface IFoo extends IFooPrototype { (): void; x: boolean; static y: boolean } interface IFoo extends IFooPrototype {
static (): void;
x: boolean;
static y: boolean
}
exports.Foo2 = (Foo: Class<IFoo>); exports.Foo2 = (Foo: Class<IFoo>);
" "
`; `;

View File

@ -180,7 +180,7 @@ function default_expr_scope({a, b = a}) {}
// ok // ok
// union-like upper bounds preserved through destructuring // union-like upper bounds preserved through destructuring
// TODO: union-of-objects upper bounds preserved through destructuring // TODO: union-of-objects upper bounds preserved through destructuring
function obj_prop_fun({ p: { q } = { q: true } } = { p: { q: \"\" } }) { function obj_prop_fun({ p: { q = 0 } = { q: true } } = { p: { q: \"\" } }) {
(q: void); (q: void);
} }
obj_prop_fun(); obj_prop_fun();
@ -188,7 +188,7 @@ obj_prop_fun({});
obj_prop_fun({ p: {} }); obj_prop_fun({ p: {} });
obj_prop_fun({ p: { q: null } }); obj_prop_fun({ p: { q: null } });
function obj_prop_var(o = { p: { q: \"\" } }) { function obj_prop_var(o = { p: { q: \"\" } }) {
var { p: { q } = { q: true } } = o; var { p: { q = 0 } = { q: true } } = o;
(q: void); (q: void);
} }
obj_prop_var(); obj_prop_var();
@ -204,10 +204,10 @@ obj_rest();
obj_rest({}); obj_rest({});
obj_rest({ p: {} }); obj_rest({ p: {} });
obj_rest({ p: { q: 0, r: null } }); obj_rest({ p: { q: 0, r: null } });
function obj_prop_annot({ p }: { p: string } = { p: 0 }) { function obj_prop_annot({ p = true }: { p: string } = { p: 0 }) {
(p: void); (p: void);
} }
var { p }: { p: string } = { p: 0 }; var { p = true }: { p: string } = { p: 0 };
(p: void); (p: void);
function obj_prop_err({ x: { y } } = null) { function obj_prop_err({ x: { y } } = null) {
@ -221,7 +221,7 @@ function arr_elem_err([ x ] = null) {
function arr_rest_err([ ...a ] = null) { function arr_rest_err([ ...a ] = null) {
} }
function gen<T>(x: T, { p }: { p: T }): T { function gen<T>(x: T, { p = x }: { p: T }): T {
return p; return p;
} }
obj_prop_fun(({}: { p?: { q?: null } })); obj_prop_fun(({}: { p?: { q?: null } }));
@ -238,7 +238,7 @@ function obj_prop_union({ p }: { p: number | string } = { p: true }) {
function obj_prop_union2({ p }: { p: number } | { p: string } = { p: true }) { function obj_prop_union2({ p }: { p: number } | { p: string } = { p: true }) {
} }
function default_expr_scope({ a, b }) { function default_expr_scope({ a, b = a }) {
} }
" "
@ -330,9 +330,9 @@ declare var b: string;
declare var c: string; declare var c: string;
[ { a1: a, b }, c ] = [ { a1: 0, b: 1 }, 2 ]; [ { a1: a, b }, c ] = [ { a1: 0, b: 1 }, 2 ];
var { m } = { m: 0 }; var { m } = { m: 0 };
{ m } = { m: m }; ({ m } = { m: m });
var obj; var obj;
{ n: obj.x } = { n: 3 }; ({ n: obj.x } = { n: 3 });
[ obj.x ] = [ \"foo\" ]; [ obj.x ] = [ \"foo\" ];
function foo({ p, z: [ r ] }) { function foo({ p, z: [ r ] }) {
a = p; a = p;
@ -420,7 +420,7 @@ exports[`test eager.js 1`] = `
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// error, property \`x\` can not be accessed on \`null\` // error, property \`x\` can not be accessed on \`null\`
var x; var x;
{ x } = null; ({ x } = null);
" "
`; `;

View File

@ -99,10 +99,10 @@ export type inlinedType1 = number;
var a: inlinedType1 = 42; var a: inlinedType1 = 42;
var b: inlinedType1 = \"asdf\"; var b: inlinedType1 = \"asdf\";
type standaloneType1 = number; type standaloneType1 = number;
export { standaloneType1 } export type { standaloneType1 }
type standaloneType2 = number; type standaloneType2 = number;
export { standaloneType2 } export { standaloneType2 }
export { talias1, talias2 as talias3, IFoo2 } from \"./types_only2\" export type { talias1, talias2 as talias3, IFoo2 } from \"./types_only2\"
export interface IFoo { prop: number } export interface IFoo { prop: number }
" "
`; `;

View File

@ -45,7 +45,7 @@ import type {Foo} from \'./types\';
// Follows non-destructured property access of \`require(\'Parent\')\` // Follows non-destructured property access of \`require(\'Parent\')\`
var Parent = require(\"./Parent\"); var Parent = require(\"./Parent\");
let ParentFoo; let ParentFoo;
{ ParentFoo } = Parent; ({ ParentFoo } = Parent);
ParentFoo; ParentFoo;
let ParentFoo2; let ParentFoo2;
ParentFoo2 = Parent; ParentFoo2 = Parent;

View File

@ -147,7 +147,7 @@ type FG = (_: ObjA | ObjB) => void;
declare var fun1: F & G; declare var fun1: F & G;
(fun1: FG); (fun1: FG);
var fun2: FG = fun1; var fun2: FG = fun1;
declare var f: (_: number) => void & (_: string) => void; declare var f: ((_: number) => void) & ((_: string) => void);
var g: (_: number | string) => void = f; var g: (_: number | string) => void = f;
" "
`; `;

View File

@ -1,160 +0,0 @@
exports[`test API.react.js 1`] = `
"
var app = require(\'JSX\');
app.setProps({y:42}); // error, y:number but foo expects string in App.react
app.setState({z:42}); // error, z:number but foo expects string in App.react
function bar(x:number) { }
bar(app.props.children); // No error, App doesn\'t specify propTypes so anything goes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// error, y:number but foo expects string in App.react
// error, z:number but foo expects string in App.react
// No error, App doesn\'t specify propTypes so anything goes
var app = require(\"JSX\");
app.setProps({ y: 42 });
app.setState({ z: 42 });
function bar(x: number) {
}
bar(app.props.children);
"
`;
exports[`test App.react.js 1`] = `
"
/**
* @providesModule App.react
* @jsx React.DOM
*/
var React = require(\'react\');
// expect args to be strings
function foo(p:string,q:string):string { return p+q; }
var App = React.createClass({
getDefaultProps: function(): { y: string } {
return {y:\"\"}; // infer props.y: string
},
getInitialState: function() {
return {z:0}; // infer state.z: number
},
handler: function() {
this.setState({z:42}); // ok
},
render: function() {
var x = this.props.x;
var y = this.props.y;
var z = this.state.z;
//this.state;
return (
<div>
{foo(x,y)}
{foo(z,x)} // error, since z: number
</div>
);
}
});
module.exports = App;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* @providesModule App.react
* @jsx React.DOM
*/
// expect args to be strings
// infer props.y: string
// infer state.z: number
// ok
//this.state;
var React = require(\"react\");
function foo(p: string, q: string): string {
return p + q;
}
var App = React.createClass({
getDefaultProps: function(): { y: string } {
return { y: \"\" };
},
getInitialState: function() {
return { z: 0 };
},
handler: function() {
this.setState({ z: 42 });
},
render: function() {
var x = this.props.x;
var y = this.props.y;
var z = this.state.z;
return (
<div>
{foo(x, y)}
{foo(z, x)}// error, since z: number</div>
);
}
});
module.exports = App;
"
`;
exports[`test JSX.js 1`] = `
"
/* @providesModule JSX */
var React = require(\'react\');
var App = require(\'App.react\');
var app =
<App y={42}> // error, y: number but foo expects string in App.react
Some text.
</App>;
module.exports = app;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @providesModule JSX */
var React = require(\"react\");
var App = require(\"App.react\");
var app = <App y={42}>// error, y: number but foo expects string in App.react[object Object] Some text.</App>;
module.exports = app;
"
`;
exports[`test propTypes.js 1`] = `
"var React = require(\'React\');
var C = React.createClass({
propTypes: {
title: React.PropTypes.string.isRequired,
}
});
var D = React.createClass({
propTypes: {
name: React.PropTypes.string.isRequired,
...C.propTypes,
}
});
<D
namee=\'foo\' // error (as usual)
titlee=\'bar\' // OK (error ignored when spread is used)
/>;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* error (as usual)*/
/* OK (error ignored when spread is used)*/
var React = require(\"React\");
var C = React.createClass({
propTypes: { title: React.PropTypes.string.isRequired }
});
var D = React.createClass({
propTypes: { name: React.PropTypes.string.isRequired, ...C.propTypes }
});
<D namee=\"foo\" titlee=\"bar\"/>;
"
`;