add support for outputting flow types - fixes #665

This commit is contained in:
Sebastian McKenzie 2015-03-01 00:32:36 +11:00
parent fb04b2561f
commit e945f0d10f
61 changed files with 965 additions and 98 deletions

View File

@ -36,7 +36,7 @@
"test": "make test" "test": "make test"
}, },
"dependencies": { "dependencies": {
"acorn-babel": "0.11.1-35", "acorn-babel": "0.11.1-37",
"ast-types": "~0.6.1", "ast-types": "~0.6.1",
"chalk": "^1.0.0", "chalk": "^1.0.0",
"chokidar": "^0.12.6", "chokidar": "^0.12.6",

View File

@ -1,5 +1,4 @@
exports.ClassExpression = export function ClassDeclaration(node, print) {
exports.ClassDeclaration = function (node, print) {
this.push("class"); this.push("class");
if (node.id) { if (node.id) {
@ -7,14 +6,24 @@ exports.ClassDeclaration = function (node, print) {
print(node.id); print(node.id);
} }
print(node.typeParameters);
if (node.superClass) { if (node.superClass) {
this.push(" extends "); this.push(" extends ");
print(node.superClass); print(node.superClass);
print(node.superTypeParameters);
}
if (node.implements) {
this.push(" implements ");
print.join(node.implements, { separator: ", " });
} }
this.space(); this.space();
print(node.body); print(node.body);
}; }
export { ClassDeclaration as ClassExpression };
export function ClassBody(node, print) { export function ClassBody(node, print) {
if (node.body.length === 0) { if (node.body.length === 0) {

View File

@ -1,34 +1,226 @@
exports.AnyTypeAnnotation = import t from "../../types";
exports.ArrayTypeAnnotation =
exports.BooleanTypeAnnotation = export function AnyTypeAnnotation() {
exports.ClassProperty = this.push("any");
exports.DeclareClass = }
exports.DeclareFunction =
exports.DeclareModule = export function ArrayTypeAnnotation(node, print) {
exports.DeclareVariable = print(node.elementType);
exports.FunctionTypeAnnotation = this.push("[");
exports.FunctionTypeParam = this.push("]");
exports.GenericTypeAnnotation = }
exports.InterfaceExtends =
exports.InterfaceDeclaration = export function BooleanTypeAnnotation(node) {
exports.IntersectionTypeAnnotation = this.push("bool");
exports.NullableTypeAnnotation = }
exports.NumberTypeAnnotation =
exports.StringLiteralTypeAnnotation = export function ClassProperty(node, print) {
exports.StringTypeAnnotation = if (node.static) this.push("static ");
exports.TupleTypeAnnotation = print(node.key);
exports.TypeofTypeAnnotation = print(node.typeAnnotation);
exports.TypeAlias = this.semicolon();
exports.TypeAnnotation = }
exports.TypeParameterDeclaration =
exports.TypeParameterInstantiation = export function DeclareClass(node, print) {
exports.ObjectTypeAnnotation = this.push("declare class ");
exports.ObjectTypeCallProperty = this._interfaceish(node, print);
exports.ObjectTypeIndexer = }
exports.ObjectTypeProperty =
exports.QualifiedTypeIdentifier = export function DeclareFunction(node, print) {
exports.UnionTypeAnnotation = this.push("declare function ");
exports.TypeCastExpression = print(node.id);
exports.VoidTypeAnnotation = function () { print(node.id.typeAnnotation.typeAnnotation);
// todo: implement these once we have a `--keep-types` option this.semicolon();
}; }
export function DeclareModule(node, print) {
this.push("declare module ");
print(node.id);
this.space();
print(node.body);
}
export function DeclareVariable(node, print) {
this.push("declare var ");
print(node.id);
print(node.id.typeAnnotation);
this.semicolon();
}
export function FunctionTypeAnnotation(node, print, parent) {
print(node.typeParameters);
this.push("(");
print.list(node.params);
if (node.rest) {
if (node.params.length) {
this.push(",");
this.space();
}
this.push("...");
print(node.rest);
}
this.push(")");
// this node type is overloaded, not sure why but it makes it EXTREMELY annoying
if (parent.type === "ObjectTypeProperty" || parent.type === "ObjectTypeCallProperty" || parent.type === "DeclareFunction") {
this.push(":");
} else {
this.space();
this.push("=>");
}
this.space();
print(node.returnType);
}
export function FunctionTypeParam(node, print) {
print(node.name);
if (node.optional) this.push("?");
this.push(":");
this.space();
print(node.typeAnnotation);
}
export function InterfaceExtends(node, print) {
print(node.id);
print(node.typeParameters);
}
export { InterfaceExtends as ClassImplements, InterfaceExtends as GenericTypeAnnotation };
export function _interfaceish(node, print) {
print(node.id);
print(node.typeParameters);
if (node.extends.length) {
this.push(" extends ");
print.join(node.extends, { separator: ", " });
}
this.space();
print(node.body);
}
export function InterfaceDeclaration(node, print) {
this.push("interface ");
this._interfaceish(node, print);
}
export function IntersectionTypeAnnotation(node, print) {
print.join(node.types, { separator: " & " });
}
export function NullableTypeAnnotation(node, print) {
this.push("?");
print(node.typeAnnotation);
}
export function NumberTypeAnnotation() {
this.push("number");
}
export function StringLiteralTypeAnnotation(node) {
this._stringLiteral(node.value);
}
export function StringTypeAnnotation() {
this.push("string");
}
export function TupleTypeAnnotation(node, print) {
this.push("[");
print.join(node.types, { separator: ", " });
this.push("]");
}
export function TypeofTypeAnnotation(node, print) {
this.push("typeof ");
print(node.argument);
}
export function TypeAlias(node, print) {
this.push("type ");
print(node.id);
print(node.typeParameters);
this.space();
this.push("=");
this.space();
print(node.right);
this.semicolon();
}
export function TypeAnnotation(node, print) {
this.push(":");
this.space();
if (node.optional) this.push("?");
print(node.typeAnnotation);
}
export function TypeParameterInstantiation(node, print) {
this.push("<");
print.join(node.params, { separator: ", " });
this.push(">");
}
export { TypeParameterInstantiation as TypeParameterDeclaration };
export function ObjectTypeAnnotation(node, print) {
this.push("{");
var props = node.properties.concat(node.callProperties, node.indexers);
if (props.length) {
this.space();
print.list(props, { indent: true, separator: "; " });
this.space();
}
this.push("}");
}
export function ObjectTypeCallProperty(node, print) {
if (node.static) this.push("static ");
print(node.value);
}
export function ObjectTypeIndexer(node, print) {
if (node.static) this.push("static ");
this.push("[");
print(node.id);
this.push(":");
this.space();
print(node.key);
this.push("]");
this.push(":");
this.space();
print(node.value);
}
export function ObjectTypeProperty(node, print) {
if (node.static) this.push("static ");
print(node.key);
if (node.optional) this.push("?");
if (!t.isFunctionTypeAnnotation(node.value)) {
this.push(":");
this.space();
}
print(node.value);
}
export function QualifiedTypeIdentifier(node, print) {
print(node.qualification);
this.push(".");
print(node.id);
}
export function UnionTypeAnnotation(node, print) {
print.join(node.types, { separator: " | " });
}
export function TypeCastExpression(node, print) {
this.push("(");
print(node.expression);
print(node.typeAnnotation);
this.push(")");
}
export function VoidTypeAnnotation(node) {
this.push("void");
}

View File

@ -1,9 +1,19 @@
import t from "../../types"; import t from "../../types";
export function _params(node, print) { export function _params(node, print) {
print(node.typeParameters);
this.push("("); this.push("(");
print.list(node.params); print.list(node.params, {
iterator: (node) =>{
if (node.optional) this.push("?");
print(node.typeAnnotation);
}
});
this.push(")"); this.push(")");
if (node.returnType) {
print(node.returnType);
}
} }
export function _method(node, print) { export function _method(node, print) {

View File

@ -211,13 +211,12 @@ export function PrivateDeclaration(node, print) {
} }
export function VariableDeclarator(node, print) { export function VariableDeclarator(node, print) {
print(node.id);
print(node.id.typeAnnotation);
if (node.init) { if (node.init) {
print(node.id);
this.space(); this.space();
this.push("="); this.push("=");
this.space(); this.space();
print(node.init); print(node.init);
} else {
print(node.id);
} }
} }

View File

@ -83,14 +83,7 @@ export function Literal(node) {
var type = typeof val; var type = typeof val;
if (type === "string") { if (type === "string") {
val = JSON.stringify(val); this._stringLiteral(val);
// escape illegal js but valid json unicode characters
val = val.replace(/[\u000A\u000D\u2028\u2029]/g, function (c) {
return "\\u" + ("0000" + c.charCodeAt(0).toString(16)).slice(-4);
});
this.push(val);
} else if (type === "number") { } else if (type === "number") {
this.push(val + ""); this.push(val + "");
} else if (type === "boolean") { } else if (type === "boolean") {
@ -101,3 +94,14 @@ export function Literal(node) {
this.push("null"); this.push("null");
} }
} }
export function _stringLiteral(val) {
val = JSON.stringify(val);
// escape illegal js but valid json unicode characters
val = val.replace(/[\u000A\u000D\u2028\u2029]/g, function (c) {
return "\\u" + ("0000" + c.charCodeAt(0).toString(16)).slice(-4);
});
this.push(val);
}

View File

@ -117,7 +117,7 @@ class CodeGenerator {
} }
print(node, parent, opts = {}) { print(node, parent, opts = {}) {
if (!node) return ""; if (!node) return;
if (parent && parent._compact) { if (parent && parent._compact) {
node._compact = true; node._compact = true;

View File

@ -21,6 +21,12 @@ each([
}); });
}); });
export function NullableTypeAnnotation(node, parent) {
return t.isArrayTypeAnnotation(parent);
}
export { NullableTypeAnnotation as FunctionTypeAnnotation };
export function UpdateExpression(node, parent) { export function UpdateExpression(node, parent) {
if (t.isMemberExpression(parent) && parent.object === node) { if (t.isMemberExpression(parent) && parent.object === node) {
// (foo++).test() // (foo++).test()
@ -139,8 +145,7 @@ export function FunctionExpression(node, parent) {
} }
} }
exports.AssignmentExpression = export function ConditionalExpression(node, parent) {
exports.ConditionalExpression = function (node, parent) {
if (t.isUnaryLike(parent)) { if (t.isUnaryLike(parent)) {
return true; return true;
} }
@ -164,4 +169,6 @@ exports.ConditionalExpression = function (node, parent) {
} }
return false; return false;
}; }
export { ConditionalExpression as AssignmentExpression };

View File

@ -1,5 +1,15 @@
export function SequenceExpression(node) { export var SequenceExpression = {
if (node.expressions.length === 1) { exit(node) {
return node.expressions[0]; if (node.expressions.length === 1) {
return node.expressions[0];
} else if (!node.expressions.length) {
this.remove();
}
} }
} };
export var ExpressionStatement = {
exit(node) {
if (!node.expression) this.remove();
}
};

View File

@ -1,5 +1,18 @@
import t from "../../../types"; import t from "../../../types";
export function Flow(node) {
this.remove();
}
export function ClassProperty(node) {
node.typeAnnotation = null;
if (!node.value) this.remove();
}
export function Class(node) {
node.implements = null;
}
export function TypeCastExpression(node) { export function TypeCastExpression(node) {
return node.expression; return node.expression;
} }

View File

@ -43,7 +43,7 @@ export default class TraversalConext {
if (this.shouldFlatten) { if (this.shouldFlatten) {
node[key] = flatten(node[key]); node[key] = flatten(node[key]);
if (key === "body") { if (key === "body" || key === "expressions") {
// we can safely compact this // we can safely compact this
node[key] = compact(node[key]); node[key] = compact(node[key]);
} }

View File

@ -84,7 +84,7 @@ traverse.explode = function (obj) {
var aliases = t.FLIPPED_ALIAS_KEYS[type]; var aliases = t.FLIPPED_ALIAS_KEYS[type];
if (aliases) { if (aliases) {
for (var i = 0; i < aliases.length; i++) { for (var i = 0; i < aliases.length; i++) {
obj[aliases[i]] = fns; obj[aliases[i]] ||= fns;
} }
} }
} }

View File

@ -299,7 +299,7 @@ export default class Scope {
var info = this.getBindingInfo(name); var info = this.getBindingInfo(name);
if (!info) return; if (!info) return;
info.identifier.typeAnnotation = info.typeAnnotation = type; info.typeAnnotation = type;
} }
getTypeAnnotation(name, id, node) { getTypeAnnotation(name, id, node) {

View File

@ -71,6 +71,39 @@
"JSXMemberExpression": ["Expression"], "JSXMemberExpression": ["Expression"],
"YieldExpression": ["Expression"], "YieldExpression": ["Expression"],
"AnyTypeAnnotation": ["Flow"],
"ArrayTypeAnnotation": ["Flow"],
"BooleanTypeAnnotation": ["Flow"],
"ClassImplements": ["Flow"],
"DeclareClass": ["Flow"],
"DeclareFunction": ["Flow"],
"DeclareModule": ["Flow"],
"DeclareVariable": ["Flow"],
"FunctionTypeAnnotation": ["Flow"],
"FunctionTypeParam": ["Flow"],
"GenericTypeAnnotation": ["Flow"],
"InterfaceExtends": ["Flow"],
"InterfaceDeclaration": ["Flow"],
"IntersectionTypeAnnotation": ["Flow"],
"NullableTypeAnnotation": ["Flow"],
"NumberTypeAnnotation": ["Flow"],
"StringLiteralTypeAnnotation": ["Flow"],
"StringTypeAnnotation": ["Flow"],
"TupleTypeAnnotation": ["Flow"],
"TypeofTypeAnnotation": ["Flow"],
"TypeAlias": ["Flow"],
"TypeAnnotation": ["Flow"],
"TypeCastExpression": ["Flow"],
"TypeParameterDeclaration": ["Flow"],
"TypeParameterInstantiation": ["Flow"],
"ObjectTypeAnnotation": ["Flow"],
"ObjectTypeCallProperty": ["Flow"],
"ObjectTypeIndexer": ["Flow"],
"ObjectTypeProperty": ["Flow"],
"QualifiedTypeIdentifier": ["Flow"],
"UnionTypeAnnotation": ["Flow"],
"VoidTypeAnnotation": ["Flow"],
"JSXAttribute": ["JSX"], "JSXAttribute": ["JSX"],
"JSXClosingElement": ["JSX"], "JSXClosingElement": ["JSX"],
"JSXElement": ["JSX", "Expression"], "JSXElement": ["JSX", "Expression"],

View File

@ -709,6 +709,10 @@ t.inherits = function (child, parent) {
child.start = parent.start; child.start = parent.start;
child.loc = parent.loc; child.loc = parent.loc;
child.end = parent.end; child.end = parent.end;
child.typeAnnotation = parent.typeAnnotation;
child.returnType = parent.returnType;
t.inheritsComments(child, parent); t.inheritsComments(child, parent);
return child; return child;
}; };

View File

@ -1,7 +1,7 @@
{ {
"ArrayExpression": ["elements"], "ArrayExpression": ["elements"],
"ArrayPattern": ["elements"], "ArrayPattern": ["elements", "typeAnnotation"],
"ArrowFunctionExpression": ["params", "defaults", "rest", "body"], "ArrowFunctionExpression": ["params", "defaults", "rest", "body", "returnType"],
"AssignmentExpression": ["left", "right"], "AssignmentExpression": ["left", "right"],
"AssignmentPattern": ["left", "right"], "AssignmentPattern": ["left", "right"],
"AwaitExpression": ["argument"], "AwaitExpression": ["argument"],
@ -13,8 +13,8 @@
"CallExpression": ["callee", "arguments"], "CallExpression": ["callee", "arguments"],
"CatchClause": ["param", "body"], "CatchClause": ["param", "body"],
"ClassBody": ["body"], "ClassBody": ["body"],
"ClassDeclaration": ["id", "body", "superClass"], "ClassDeclaration": ["id", "body", "superClass", "typeParameters", "superTypeParameters", "implements"],
"ClassExpression": ["id", "body", "superClass"], "ClassExpression": ["id", "body", "superClass", "typeParameters", "superTypeParameters", "implements"],
"ComprehensionBlock": ["left", "right", "body"], "ComprehensionBlock": ["left", "right", "body"],
"ComprehensionExpression": ["filter", "blocks", "body"], "ComprehensionExpression": ["filter", "blocks", "body"],
"ConditionalExpression": ["test", "consequent", "alternate"], "ConditionalExpression": ["test", "consequent", "alternate"],
@ -30,9 +30,9 @@
"ForInStatement": ["left", "right", "body"], "ForInStatement": ["left", "right", "body"],
"ForOfStatement": ["left", "right", "body"], "ForOfStatement": ["left", "right", "body"],
"ForStatement": ["init", "test", "update", "body"], "ForStatement": ["init", "test", "update", "body"],
"FunctionDeclaration": ["id", "params", "defaults", "rest", "body"], "FunctionDeclaration": ["id", "params", "defaults", "rest", "body", "returnType", "typeParameters"],
"FunctionExpression": ["id", "params", "defaults", "rest", "body"], "FunctionExpression": ["id", "params", "defaults", "rest", "body", "returnType", "typeParameters"],
"Identifier": [], "Identifier": ["typeAnnotation"],
"IfStatement": ["test", "consequent", "alternate"], "IfStatement": ["test", "consequent", "alternate"],
"ImportBatchSpecifier": ["id"], "ImportBatchSpecifier": ["id"],
"ImportDeclaration": ["specifiers", "source"], "ImportDeclaration": ["specifiers", "source"],
@ -44,11 +44,11 @@
"MethodDefinition": ["key", "value"], "MethodDefinition": ["key", "value"],
"NewExpression": ["callee", "arguments"], "NewExpression": ["callee", "arguments"],
"ObjectExpression": ["properties"], "ObjectExpression": ["properties"],
"ObjectPattern": ["properties"], "ObjectPattern": ["properties", "typeAnnotation"],
"PrivateDeclaration": ["declarations"], "PrivateDeclaration": ["declarations"],
"Program": ["body"], "Program": ["body"],
"Property": ["key", "value"], "Property": ["key", "value"],
"RestElement": ["argument"], "RestElement": ["argument", "typeAnnotation"],
"ReturnStatement": ["argument"], "ReturnStatement": ["argument"],
"SequenceExpression": ["expressions"], "SequenceExpression": ["expressions"],
"SpreadElement": ["argument"], "SpreadElement": ["argument"],
@ -71,36 +71,37 @@
"YieldExpression": ["argument"], "YieldExpression": ["argument"],
"AnyTypeAnnotation": [], "AnyTypeAnnotation": [],
"ArrayTypeAnnotation": [], "ArrayTypeAnnotation": ["elementType"],
"BooleanTypeAnnotation": [], "BooleanTypeAnnotation": [],
"ClassProperty": ["key", "value"], "ClassImplements": ["id", "typeParameters"],
"DeclareClass": [], "ClassProperty": ["key", "value", "typeAnnotation"],
"DeclareFunction": [], "DeclareClass": ["id", "typeParameters", "extends", "body"],
"DeclareModule": [], "DeclareFunction": ["id"],
"DeclareVariable": [], "DeclareModule": ["id", "body"],
"FunctionTypeAnnotation": [], "DeclareVariable": ["id"],
"FunctionTypeParam": [], "FunctionTypeAnnotation": ["typeParameters", "params", "rest", "returnType"],
"GenericTypeAnnotation": [], "FunctionTypeParam": ["name", "typeAnnotation"],
"InterfaceExtends": [], "GenericTypeAnnotation": ["id", "typeParameters"],
"InterfaceDeclaration": [], "InterfaceExtends": ["id", "typeParameters"],
"IntersectionTypeAnnotation": [], "InterfaceDeclaration": ["id", "typeParameters", "extends", "body"],
"NullableTypeAnnotation": [], "IntersectionTypeAnnotation": ["types"],
"NullableTypeAnnotation": ["typeAnnotation"],
"NumberTypeAnnotation": [], "NumberTypeAnnotation": [],
"StringLiteralTypeAnnotation": [], "StringLiteralTypeAnnotation": [],
"StringTypeAnnotation": [], "StringTypeAnnotation": [],
"TupleTypeAnnotation": [], "TupleTypeAnnotation": ["types"],
"TypeofTypeAnnotation": [], "TypeofTypeAnnotation": ["argument"],
"TypeAlias": [], "TypeAlias": ["id", "typeParameters", "right"],
"TypeAnnotation": [], "TypeAnnotation": ["typeAnnotation"],
"TypeCastExpression": ["expression"], "TypeCastExpression": ["expression"],
"TypeParameterDeclaration": [], "TypeParameterDeclaration": ["params"],
"TypeParameterInstantiation": [], "TypeParameterInstantiation": ["params"],
"ObjectTypeAnnotation": [], "ObjectTypeAnnotation": ["key", "value"],
"ObjectTypeCallProperty": [], "ObjectTypeCallProperty": ["value"],
"ObjectTypeIndexer": [], "ObjectTypeIndexer": ["id", "key", "value"],
"ObjectTypeProperty": [], "ObjectTypeProperty": ["key", "value"],
"QualifiedTypeIdentifier": [], "QualifiedTypeIdentifier": ["id", "qualification"],
"UnionTypeAnnotation": [], "UnionTypeAnnotation": ["types"],
"VoidTypeAnnotation": [], "VoidTypeAnnotation": [],
"JSXAttribute": ["name", "value"], "JSXAttribute": ["name", "value"],

View File

@ -15,7 +15,7 @@ import has from "lodash/object/has";
import fs from "fs"; import fs from "fs";
import t from "./types"; import t from "./types";
export { inherits } from "util"; export { inherits, inspect } from "util";
export var debug = buildDebug("babel"); export var debug = buildDebug("babel");

View File

@ -24,7 +24,7 @@ exports.esvalid = function (ast, code, loc) {
if (errors.length) { if (errors.length) {
var msg = []; var msg = [];
_.each(errors, function (err) { _.each(errors, function (err) {
msg.push(err.message + " - " + JSON.stringify(err.node)); msg.push(err.message + " - " + util.inspect(err.node));
}); });
throw new Error(loc + ": " + msg.join(". ") + "\n" + code); throw new Error(loc + ": " + msg.join(". ") + "\n" + code);
} }

View File

@ -97,7 +97,7 @@ var run = function (task, done) {
if (!execCode || actualCode) { if (!execCode || actualCode) {
result = transform(actualCode, getOpts(actual)); result = transform(actualCode, getOpts(actual));
checkAst(result, actual); checkAst(result, actual);
actualCode = result.code; actualCode = result.code.trim();
try { try {
chai.expect(actualCode).to.be.equal(expectCode, actual.loc + " !== " + expect.loc); chai.expect(actualCode).to.be.equal(expectCode, actual.loc + " !== " + expect.loc);

View File

@ -0,0 +1,6 @@
var a: number[];
var a: ?number[];
var a: (?number)[];
var a: () => number[];
var a: (() => number)[];
var a: typeof A[];

View File

@ -0,0 +1,6 @@
var a: number[];
var a: ?number[];
var a: (?number)[];
var a: () => number[];
var a: (() => number)[];
var a: typeof A[];

View File

@ -0,0 +1,5 @@
var a: { (): number };
var a: { (): number; };
var a: { (): number; y: string; (x: string): string };
var a: { <T>(x: T): number; };
interface A { (): number; };

View File

@ -0,0 +1,5 @@
var a: { (): number };
var a: { (): number };
var a: { y: string; (): number; (x: string): string };
var a: { <T>(x: T): number };
interface A { (): number };

View File

@ -0,0 +1,5 @@
declare module A {}
declare module "./a/b.js" {}
declare module A { declare var x: number; }
declare module A { declare function foo(): number; }
declare module A { declare class B { foo(): number; } }

View File

@ -0,0 +1,11 @@
declare module A {}
declare module "./a/b.js" {}
declare module A {
declare var x: number;
}
declare module A {
declare function foo(): number;
}
declare module A {
declare class B { foo(): number }
}

View File

@ -0,0 +1,11 @@
declare var foo
declare var foo;
declare function foo(): void
declare function foo(): void;
declare function foo<T>(): void;
declare function foo(x: number, y: string): void;
declare class A {}
declare class A<T> extends B<T> { x: number }
declare class A { static foo(): number; static x : string }
declare class A { static [ indexer: number]: string }
declare class A { static () : number }

View File

@ -0,0 +1,11 @@
declare var foo;
declare var foo;
declare function foo(): void;
declare function foo(): void;
declare function foo<T>(): void;
declare function foo(x: number, y: string): void;
declare class A {}
declare class A<T> extends B<T> { x: number }
declare class A { static foo(): number; static x: string }
declare class A { static [indexer: number]: string }
declare class A { static (): number }

View File

@ -0,0 +1,9 @@
interface A {};
interface A extends B {};
interface A<T> extends B<T>, C<T> {};
interface A { foo: () => number; };
interface Dictionary { [index: string]: string; length: number; };
class Foo implements Bar {}
class Foo extends Bar implements Bat, Man<number> {}
class Foo extends class Bar implements Bat {} {}
class Foo extends class Bar implements Bat {} implements Man {}

View File

@ -0,0 +1,9 @@
interface A {};
interface A extends B {};
interface A<T> extends B<T>, C<T> {};
interface A { foo(): number };
interface Dictionary { length: number; [index: string]: string };
class Foo implements Bar {}
class Foo extends Bar implements Bat, Man<number> {}
class Foo extends class Bar implements Bat {} {}
class Foo extends class Bar implements Bat {} implements Man {}

View File

@ -0,0 +1,4 @@
var a: A.B;
var a: A.B.C;
var a: A.B<T>;
var a: typeof A.B<T>;

View File

@ -0,0 +1,4 @@
var a: A.B;
var a: A.B.C;
var a: A.B<T>;
var a: typeof A.B<T>;

View File

@ -0,0 +1,2 @@
function createElement(tagName: "div"): HTMLDivElement {}
function createElement(tagName: 'div'): HTMLDivElement {}

View File

@ -0,0 +1,2 @@
function createElement(tagName: "div"): HTMLDivElement {}
function createElement(tagName: "div"): HTMLDivElement {}

View File

@ -0,0 +1,4 @@
var a: [] = [];
var a: [Foo<T>] = [foo];
var a: [number,] = [123,];
var a: [number, string] = [123, "duck"];

View File

@ -0,0 +1,4 @@
var a: [] = [];
var a: [Foo<T>] = [foo];
var a: [number] = [123];
var a: [number, string] = [123, "duck"];

View File

@ -0,0 +1,3 @@
type FBID = number;
type Foo<T> = Bar<T>
export type Foo = number;

View File

@ -0,0 +1,3 @@
type FBID = number;
type Foo<T> = Bar<T>;
export type Foo = number;

View File

@ -0,0 +1,97 @@
function foo(numVal: any) {}
function foo(numVal: number) {}
function foo(numVal: number, strVal: string) {}
function foo(numVal: number, untypedVal) {}
function foo(untypedVal, numVal: number) {}
function foo(nullableNum: ?number) {}
function foo(callback: () => void) {}
function foo(callback: () => number) {}
function foo(callback: (_: bool) => number) {}
function foo(callback: (_1: bool, _2: string) => number) {}
function foo(callback: (_1: bool, ...foo: Array<number>) => number) {}
function foo(): number{}
function foo():() => void {}
function foo():(_:bool) => number{}
function foo():(_?:bool) => number{}
function foo(): {} {}
function foo<T>() {}
function foo<T,S>() {}
a = function<T,S>() {};
a = { set fooProp(value: number) {} };
a = { set fooProp(value: number): void {} };
a = { get fooProp():number{} };
a = { id<T>(x: T): T {} };
a = { *id<T>(x: T): T {} };
a = { async id<T>(x: T): T {} };
a = { 123<T>(x: T): T {} };
class Foo {
set fooProp(value: number) {}
}
class Foo {
set fooProp(value: number): void {}
}
class Foo {
get fooProp(): number {}
}
var numVal: number;
var numVal: number = otherNumVal;
var a: { numVal: number };
var a: { numVal: number; };
var a: { numVal: number; [indexer: string]: number };
var a: ?{ numVal: number };
var a: { numVal: number; strVal: string }
var a: { subObj: {strVal: string} }
var a: { subObj: ?{strVal: string} }
var a: { param1: number; param2: string }
var a: { param1: number; param2?: string }
var a: { [a: number]: string; [b: number]: string; };
var a: { add(x: number, ...y: Array<string>): void };
var a: { id<T>(x: T): T; };
var a:Array<number> = [1, 2, 3]
a = class Foo<T> {}
a = class Foo<T> extends Bar<T> {}
class Foo<T> {}
class Foo<T> extends Bar<T> {}
class Foo<T> extends mixin(Bar) {}
class Foo<T> {
bar<U>():number { return 42; }
}
class Foo {
"bar"<T>() {}
}
function foo(requiredParam, optParam?) {}
class Foo {
prop1: string;
prop2: number;
}
class Foo {
static prop1: string;
prop2: number;
}
var x: number | string = 4;
class Array { concat(items:number | string) {}; }
var x: () => number | () => string = fn;
var x: typeof Y = Y;
var x: typeof Y | number = Y;
var {x}: {x: string; } = { x: "hello" };
var {x}: {x: string } = { x: "hello" };
var [x]: Array<string> = [ "hello" ];
function foo({x}: { x: string; }) {}
function foo([x]: Array<string>) {}
function foo(...rest: Array<number>) {}
(function (...rest: Array<number>) {});
((...rest: Array<number>) => rest);
var a: Map<string, Array<string> >
var a: Map<string, Array<string>>
var a: number[]
var a: ?string[]
var a: Promise<bool>[]
var a:(...rest:Array<number>) => number
var identity: <T>(x: T) => T
var identity: <T>(x: T, ...y:T[]) => T
import type foo from "bar";
import type { foo, bar } from "baz";
import type { foo as bar } from "baz";
import type from "foo";
import type, { foo } from "bar";
import type * as namespace from "bar";

View File

@ -0,0 +1,101 @@
function foo(numVal: any) {}
function foo(numVal: number) {}
function foo(numVal: number, strVal: string) {}
function foo(numVal: number, untypedVal) {}
function foo(untypedVal, numVal: number) {}
function foo(nullableNum: ?number) {}
function foo(callback: () => void) {}
function foo(callback: () => number) {}
function foo(callback: (_: bool) => number) {}
function foo(callback: (_1: bool, _2: string) => number) {}
function foo(callback: (_1: bool, ...foo: Array<number>) => number) {}
function foo(): number {}
function foo(): () => void {}
function foo(): (_: bool) => number {}
function foo(): (_?: bool) => number {}
function foo(): {} {}
function foo<T>() {}
function foo<T, S>() {}
a = function <T, S>() {};
a = { set fooProp(value: number) {} };
a = { set fooProp(value: number): void {} };
a = { get fooProp(): number {} };
a = { id<T>(x: T): T {} };
a = { *id<T>(x: T): T {} };
a = { async id<T>(x: T): T {} };
a = { 123<T>(x: T): T {} };
class Foo {
set fooProp(value: number) {}
}
class Foo {
set fooProp(value: number): void {}
}
class Foo {
get fooProp(): number {}
}
var numVal: number;
var numVal: number = otherNumVal;
var a: { numVal: number };
var a: { numVal: number };
var a: { numVal: number; [indexer: string]: number };
var a: ?{ numVal: number };
var a: { numVal: number; strVal: string };
var a: { subObj: { strVal: string } };
var a: { subObj: ?{ strVal: string } };
var a: { param1: number; param2: string };
var a: { param1: number; param2?: string };
var a: { [a: number]: string; [b: number]: string };
var a: { add(x: number, ...y: Array<string>): void };
var a: { id<T>(x: T): T };
var a: Array<number> = [1, 2, 3];
a = class Foo<T> {};
a = class Foo<T> extends Bar<T> {};
class Foo<T> {}
class Foo<T> extends Bar<T> {}
class Foo<T> extends mixin(Bar) {}
class Foo<T> {
bar<U>(): number {
return 42;
}
}
class Foo {
"bar"<T>() {}
}
function foo(requiredParam, optParam?) {}
class Foo {
prop1: string;
prop2: number;
}
class Foo {
static prop1: string;
prop2: number;
}
var x: number | string = 4;
class Array {
concat(items: number | string) {}
}
var x: () => number | () => string = fn;
var x: typeof Y = Y;
var x: typeof Y | number = Y;
var { x }: { x: string } = { x: "hello" };
var { x }: { x: string } = { x: "hello" };
var [x]: Array<string> = ["hello"];
function foo({ x }: { x: string }) {}
function foo([x]: Array<string>) {}
function foo(...rest: Array<number>) {}
(function (...rest: Array<number>) {});
(...rest: Array<number>) => rest;
var a: Map<string, Array<string>>;
var a: Map<string, Array<string>>;
var a: number[];
var a: ?string[];
var a: Promise<bool>[];
var a: (...rest: Array<number>) => number;
var identity: <T>(x: T) => T;
var identity: <T>(x: T, ...y: T[]) => T;
import type foo from "bar";
import type { foo, bar } from "baz";
import type { foo as bar } from "baz";
import type from "foo";
import type, { foo } from "bar";
import type * as namespace from "bar";

View File

@ -0,0 +1,4 @@
(xxx: number);
({ xxx: 0, yyy: "hey" }: { xxx: number; yyy: string });
(xxx => xxx + 1: (xxx: number) => number);
((xxx: number), (yyy: string));

View File

@ -0,0 +1,4 @@
(xxx: number);
({ xxx: 0, yyy: "hey" }: { xxx: number; yyy: string });
(xxx => xxx + 1: (xxx: number) => number);
(xxx: number), (yyy: string);

View File

@ -0,0 +1,5 @@
{
"experimental": true,
"whitelist": ["flow"],
"noCheckAst": true
}

View File

@ -0,0 +1,6 @@
var a: number[];
var a: ?number[];
var a: (?number)[];
var a: () => number[];
var a: (() => number)[];
var a: typeof A[];

View File

@ -0,0 +1,6 @@
var a;
var a;
var a;
var a;
var a;
var a;

View File

@ -0,0 +1,5 @@
var a: { (): number };
var a: { (): number; };
var a: { (): number; y: string; (x: string): string };
var a: { <T>(x: T): number; };
interface A { (): number; }

View File

@ -0,0 +1,4 @@
var a;
var a;
var a;
var a;

View File

@ -0,0 +1,5 @@
declare module A {}
declare module "./a/b.js" {}
declare module A { declare var x: number; }
declare module A { declare function foo(): number; }
declare module A { declare class B { foo(): number; } }

View File

@ -0,0 +1,11 @@
declare var foo
declare var foo;
declare function foo(): void
declare function foo(): void;
declare function foo<T>(): void;
declare function foo(x: number, y: string): void;
declare class A {}
declare class A<T> extends B<T> { x: number }
declare class A { static foo(): number; static x : string }
declare class A { static [ indexer: number]: string }
declare class A { static () : number }

View File

@ -0,0 +1,9 @@
interface A {}
interface A extends B {}
interface A<T> extends B<T>, C<T> {}
interface A { foo: () => number; }
interface Dictionary { [index: string]: string; length: number; }
class Foo implements Bar {}
class Foo2 extends Bar implements Bat, Man<number> {}
class Foo3 extends class Bar implements Bat {} {}
class Foo4 extends class Bar implements Bat {} implements Man {}

View File

@ -0,0 +1,4 @@
class Foo {}
class Foo2 extends Bar {}
class Foo3 extends class Bar {} {}
class Foo4 extends class Bar {} {}

View File

@ -0,0 +1,4 @@
var a: A.B;
var a: A.B.C;
var a: A.B<T>;
var a: typeof A.B<T>;

View File

@ -0,0 +1,4 @@
var a;
var a;
var a;
var a;

View File

@ -0,0 +1,2 @@
function createElement(tagName: "div"): HTMLDivElement {}
function createElement(tagName: 'div'): HTMLDivElement {}

View File

@ -0,0 +1,2 @@
function createElement(tagName) {}
function createElement(tagName) {}

View File

@ -0,0 +1,4 @@
var a: [] = [];
var a: [Foo<T>] = [foo];
var a: [number,] = [123,];
var a: [number, string] = [123, "duck"];

View File

@ -0,0 +1,4 @@
var a = [];
var a = [foo];
var a = [123];
var a = [123, "duck"];

View File

@ -0,0 +1,3 @@
type FBID = number;
type Foo<T> = Bar<T>
export type Foo = number;

View File

@ -0,0 +1,97 @@
function foo(numVal: any) {}
function foo(numVal: number) {}
function foo(numVal: number, strVal: string) {}
function foo(numVal: number, untypedVal) {}
function foo(untypedVal, numVal: number) {}
function foo(nullableNum: ?number) {}
function foo(callback: () => void) {}
function foo(callback: () => number) {}
function foo(callback: (_: bool) => number) {}
function foo(callback: (_1: bool, _2: string) => number) {}
function foo(callback: (_1: bool, ...foo: Array<number>) => number) {}
function foo(): number{}
function foo():() => void {}
function foo():(_:bool) => number{}
function foo():(_?:bool) => number{}
function foo(): {} {}
function foo<T>() {}
function foo<T,S>() {}
a = function<T,S>() {};
a = { set fooProp(value: number) {} };
a = { set fooProp(value: number): void {} };
a = { get fooProp():number{} };
a = { id<T>(x: T): T {} };
a = { *id<T>(x: T): T {} };
a = { async id<T>(x: T): T {} };
a = { 123<T>(x: T): T {} };
class Foo {
set fooProp(value: number) {}
}
class Foo2 {
set fooProp(value: number): void {}
}
class Foo3 {
get fooProp(): number {}
}
var numVal: number;
var numVal: number = otherNumVal;
var a: { numVal: number };
var a: { numVal: number; };
var a: { numVal: number; [indexer: string]: number };
var a: ?{ numVal: number };
var a: { numVal: number; strVal: string }
var a: { subObj: {strVal: string} }
var a: { subObj: ?{strVal: string} }
var a: { param1: number; param2: string }
var a: { param1: number; param2?: string }
var a: { [a: number]: string; [b: number]: string; };
var a: { add(x: number, ...y: Array<string>): void };
var a: { id<T>(x: T): T; };
var a:Array<number> = [1, 2, 3]
a = class Foo<T> {}
a = class Foo<T> extends Bar<T> {}
class Foo4<T> {}
class Foo5<T> extends Bar<T> {}
class Foo6<T> extends mixin(Bar) {}
class Foo7<T> {
bar<U>():number { return 42; }
}
class Foo8 {
"bar"<T>() {}
}
function foo(requiredParam, optParam?) {}
class Foo9 {
prop1: string;
prop2: number;
}
class Foo10 {
static prop1: string;
prop2: number;
}
var x: number | string = 4;
class Array { concat(items:number | string) {}; }
var x: () => number | () => string = fn;
var x: typeof Y = Y;
var x: typeof Y | number = Y;
var {x}: {x: string; } = { x: "hello" };
var {x}: {x: string } = { x: "hello" };
var [x]: Array<string> = [ "hello" ];
function foo({x}: { x: string; }) {}
function foo([x]: Array<string>) {}
function foo(...rest: Array<number>) {}
(function (...rest: Array<number>) {});
((...rest: Array<number>) => rest);
var a: Map<string, Array<string> >
var a: Map<string, Array<string>>
var a: number[]
var a: ?string[]
var a: Promise<bool>[]
var a:(...rest:Array<number>) => number
var identity: <T>(x: T) => T
var identity: <T>(x: T, ...y:T[]) => T
import type foo from "bar";
import type { foo2, bar } from "baz";
import type { foo as bar2 } from "baz";
import type from "foo";
import type2, { foo3 } from "bar";
import type * as namespace from "bar";

View File

@ -0,0 +1,92 @@
function foo(numVal) {}
function foo(numVal) {}
function foo(numVal, strVal) {}
function foo(numVal, untypedVal) {}
function foo(untypedVal, numVal) {}
function foo(nullableNum) {}
function foo(callback) {}
function foo(callback) {}
function foo(callback) {}
function foo(callback) {}
function foo(callback) {}
function foo() {}
function foo() {}
function foo() {}
function foo() {}
function foo() {}
function foo() {}
function foo() {}
a = function () {};
a = { set fooProp(value) {} };
a = { set fooProp(value) {} };
a = { get fooProp() {} };
a = { id(x) {} };
a = { *id(x) {} };
a = { async id(x) {} };
a = { 123(x) {} };
class Foo {
set fooProp(value) {}
}
class Foo2 {
set fooProp(value) {}
}
class Foo3 {
get fooProp() {}
}
var numVal;
var numVal = otherNumVal;
var a;
var a;
var a;
var a;
var a;
var a;
var a;
var a;
var a;
var a;
var a;
var a;
var a = [1, 2, 3];
a = class Foo {};
a = class Foo extends Bar {};
class Foo4 {}
class Foo5 extends Bar {}
class Foo6 extends mixin(Bar) {}
class Foo7 {
bar() {
return 42;
}
}
class Foo8 {
"bar"() {}
}
function foo(requiredParam, optParam?) {}
class Foo9 {}
class Foo10 {}
var x = 4;
class Array {
concat(items) {}
}
var x = fn;
var x = Y;
var x = Y;
var { x } = { x: "hello" };
var { x } = { x: "hello" };
var [x] = ["hello"];
function foo({ x }) {}
function foo([x]) {}
function foo(...rest) {}
(function (...rest) {});
(...rest) => rest;
var a;
var a;
var a;
var a;
var a;
var a;
var identity;
var identity;
import type from "foo";
import type2, { foo3 } from "bar";

View File

@ -0,0 +1,4 @@
(xxx: number);
({ xxx: 0, yyy: "hey" }: { xxx: number; yyy: string });
(xxx => xxx + 1: (xxx: number) => number);
((xxx: number), (yyy: string));

View File

@ -0,0 +1,4 @@
xxx;
({ xxx: 0, yyy: "hey" });
xxx => xxx + 1;
xxx, yyy;