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$"
],
"testPathIgnorePatterns": [
"tests/new_react"
"tests/new_react",
"tests/more_react"
]
}
}

View File

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

View File

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

View File

@ -40,7 +40,11 @@ Foo.prototype = {
};
exports.Foo = Foo;
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>);
"
`;

View File

@ -180,7 +180,7 @@ function default_expr_scope({a, b = a}) {}
// ok
// union-like 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);
}
obj_prop_fun();
@ -188,7 +188,7 @@ obj_prop_fun({});
obj_prop_fun({ p: {} });
obj_prop_fun({ p: { q: null } });
function obj_prop_var(o = { p: { q: \"\" } }) {
var { p: { q } = { q: true } } = o;
var { p: { q = 0 } = { q: true } } = o;
(q: void);
}
obj_prop_var();
@ -204,10 +204,10 @@ obj_rest();
obj_rest({});
obj_rest({ p: {} });
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);
}
var { p }: { p: string } = { p: 0 };
var { p = true }: { p: string } = { p: 0 };
(p: void);
function obj_prop_err({ x: { y } } = null) {
@ -221,7 +221,7 @@ function arr_elem_err([ x ] = 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;
}
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 default_expr_scope({ a, b }) {
function default_expr_scope({ a, b = a }) {
}
"
@ -330,9 +330,9 @@ declare var b: string;
declare var c: string;
[ { a1: a, b }, c ] = [ { a1: 0, b: 1 }, 2 ];
var { m } = { m: 0 };
{ m } = { m: m };
({ m } = { m: m });
var obj;
{ n: obj.x } = { n: 3 };
({ n: obj.x } = { n: 3 });
[ obj.x ] = [ \"foo\" ];
function foo({ p, z: [ r ] }) {
a = p;
@ -420,7 +420,7 @@ exports[`test eager.js 1`] = `
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// error, property \`x\` can not be accessed on \`null\`
var x;
{ x } = null;
({ x } = null);
"
`;

View File

@ -99,10 +99,10 @@ export type inlinedType1 = number;
var a: inlinedType1 = 42;
var b: inlinedType1 = \"asdf\";
type standaloneType1 = number;
export { standaloneType1 }
export type { standaloneType1 }
type standaloneType2 = number;
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 }
"
`;

View File

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

View File

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