Add type parameters on anon functions

master
James Long 2016-12-30 13:41:45 -05:00
parent e972a7f0b6
commit ed57110ef5
7 changed files with 74 additions and 74 deletions

View File

@ -340,12 +340,12 @@ function genericPrintNoParens(path, options, print) {
if (n.id) {
parts.push(
" ",
path.call(print, "id"),
path.call(print, "typeParameters")
path.call(print, "id")
);
}
parts.push(
path.call(print, "typeParameters"),
group(concat([
"(",
indent(options.tabWidth,

View File

@ -265,7 +265,7 @@ function insertMany<K, V>(
}
class Foo<A> {
bar<B>() {
return function(a: A, b: B, c: C): void {
return function<C>(a: A, b: B, c: C): void {
([ a, b, c ]: [A, B, C]);
};
}

View File

@ -187,7 +187,7 @@ class C {
var e = async function() {
};
var et = async function(a: T) {
var et = async function<T>(a: T) {
};
var n = new async function() {
@ -487,7 +487,7 @@ class C {
var e = async function() {
await 1;
};
var et = async function(a: T) {
var et = async function<T>(a: T) {
await 1;
};
var n = new async function() {

View File

@ -78,7 +78,7 @@ async function* readLines(path) {
}
async function f() {
for await (const line of readLines(\"/path/to/file\")) {
for await (const line of readLines("/path/to/file")) {
(line: void); // error: string ~> void
}
}
@ -97,7 +97,7 @@ async function* readLines(path) {
}
}
async function f() {
for await (const line of readLines(\"/path/to/file\")) {
for await (const line of readLines("/path/to/file")) {
(line: void);
}
}
@ -107,13 +107,13 @@ async function f() {
exports[`test return.js 1`] = `
"declare var gen: AsyncGenerator<void,string,void>;
// You can pass whatever you like to return, it doesn\'t need to be related to
// the AsyncGenerator\'s return type
// You can pass whatever you like to return, it doesn't need to be related to
// the AsyncGenerator's return type
gen.return(0).then(result => {
(result.value: void); // error: string | number ~> void
});
// However, a generator can \"refuse\" the return by catching an exception and
// However, a generator can "refuse" the return by catching an exception and
// yielding or returning internally.
async function *refuse_return() {
try {
@ -122,16 +122,16 @@ async function *refuse_return() {
return 0;
}
}
refuse_return().return(\"string\").then(result => {
refuse_return().return("string").then(result => {
if (result.done) {
(result.value: string); // error: number | void ~> string
}
});
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// You can pass whatever you like to return, it doesn\'t need to be related to
// the AsyncGenerator\'s return type
// You can pass whatever you like to return, it doesn't need to be related to
// the AsyncGenerator's return type
// error: string | number ~> void
// However, a generator can \"refuse\" the return by catching an exception and
// However, a generator can "refuse" the return by catching an exception and
// yielding or returning internally.
// error: number | void ~> string
declare var gen: AsyncGenerator<void, string, void>;
@ -147,7 +147,7 @@ async function* refuse_return() {
return 0;
}
}
refuse_return().return(\"string\").then(
refuse_return().return("string").then(
result => {
if (result.done) {
(result.value: string);
@ -167,7 +167,7 @@ exports[`test throw.js 1`] = `
}
(async () => {
catch_return().throw(\"\").then(({value}) => {
catch_return().throw("").then(({value}) => {
if (value !== undefined) {
(value: void); // error: number ~> void
}
@ -184,7 +184,7 @@ async function *yield_return() {
}
(async () => {
yield_return().throw(\"\").then(({value}) => {
yield_return().throw("").then(({value}) => {
if (value !== undefined) {
(value: void); // error: number ~> void
}
@ -201,7 +201,7 @@ async function* catch_return() {
}
}
async () => {
catch_return().throw(\"\").then(
catch_return().throw("").then(
({ value }) => {
if (value !== undefined) {
(value: void);
@ -218,7 +218,7 @@ async function* yield_return() {
}
}
async () => {
yield_return().throw(\"\").then(
yield_return().throw("").then(
({ value }) => {
if (value !== undefined) {
(value: void);

View File

@ -38,13 +38,13 @@ function foo8<U>(x:U,y):U {
/*
foo8(0,void 0);
*/
var foo1 = function(x: T): T {
var foo1 = function<T>(x: T): T {
return x;
};
function foo2<T, S>(x: T): S {
return x;
}
var foo3 = function(x: T): T {
var foo3 = function<T>(x: T): T {
return foo3(x);
};
function foo4<T, S>(x: T): S {
@ -54,7 +54,7 @@ var x = [ ];
function foo5<T>(): Array<T> {
return x;
}
var foo6 = function(x: R): R {
var foo6 = function<R>(x: R): R {
return foo1(x);
};
function foo7<R>(x: R): R {

View File

@ -10,7 +10,7 @@ const barr = my_filter(arr, is_string);
(barr: Array<string>);
function is_string(x): %checks {
return typeof x === \"string\";
return typeof x === "string";
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow
@ -21,7 +21,7 @@ declare var arr: Array<mixed>;
const barr = my_filter(arr, is_string);
(barr: Array<string>);
function is_string(x): %checks {
return typeof x === \"string\";
return typeof x === "string";
}
"
`;
@ -34,16 +34,16 @@ exports[`test filter-union.js 1`] = `
declare function my_filter<T, P: $Pred<1>>(v: Array<T>, cb: P): Array<$Refine<T,P,1>>;
type A = { kind: \'A\', u: number }
type B = { kind: \'B\', v: string }
type C = { kind: \'C\', y: boolean }
type D = { kind: \'D\', x: boolean }
type E = { kind: \'E\', y: boolean }
type A = { kind: 'A', u: number }
type B = { kind: 'B', v: string }
type C = { kind: 'C', y: boolean }
type D = { kind: 'D', x: boolean }
type E = { kind: 'E', y: boolean }
declare var ab: Array<A|B|C>;
(my_filter(ab, (x): %checks => x.kind === \'A\'): Array<A>); // OK
(my_filter(ab, (x): %checks => x.kind !== \'A\'): Array<B|C>); // OK
(my_filter(ab, (x): %checks => x.kind === 'A'): Array<A>); // OK
(my_filter(ab, (x): %checks => x.kind !== 'A'): Array<B|C>); // OK
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow
// Filter the contents of an array
@ -51,14 +51,14 @@ declare var ab: Array<A|B|C>;
// OK
declare function my_filter<T, P: $Pred<1>>(v: Array<T>,
cb: P): Array<$Refine<T, P, 1>>;
type A = { kind: \"A\"; u: number };
type B = { kind: \"B\"; v: string };
type C = { kind: \"C\"; y: boolean };
type D = { kind: \"D\"; x: boolean };
type E = { kind: \"E\"; y: boolean };
type A = { kind: "A"; u: number };
type B = { kind: "B"; v: string };
type C = { kind: "C"; y: boolean };
type D = { kind: "D"; x: boolean };
type E = { kind: "E"; y: boolean };
declare var ab: Array<A | B | C>;
(my_filter(ab, (x): %checks => x.kind === \"A\"): Array<A>);
(my_filter(ab, (x): %checks => x.kind !== \"A\"): Array<B | C>);
(my_filter(ab, (x): %checks => x.kind === "A"): Array<A>);
(my_filter(ab, (x): %checks => x.kind !== "A"): Array<B | C>);
"
`;
@ -66,7 +66,7 @@ exports[`test refine.js 1`] = `
"// @flow
/*
$Pred<N> is an \"abstract predicate type\", i.e. denotes a (function) type that
$Pred<N> is an "abstract predicate type", i.e. denotes a (function) type that
refines N variables. So if \`cb\` is a function, then it should be refining
exactly N argument. It is abstract in that we do not need to specify:
(a) which variables are going to be refined (just the number), or (b) what
@ -103,16 +103,16 @@ declare function refine2<T, P: $Pred<2>>(v: T, w: T, cb: P): $Refine<T,P,1>;
// { if (cb(v, w)) { return w; } else { throw new Error(); } }
function is_string(x): boolean %checks {
return typeof x === \"string\";
return typeof x === "string";
}
function is_string_and_number(x, y): %checks {
return typeof x === \"string\" && typeof y === \"number\";
return typeof x === "string" && typeof y === "number";
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow
/*
$Pred<N> is an \"abstract predicate type\", i.e. denotes a (function) type that
$Pred<N> is an "abstract predicate type", i.e. denotes a (function) type that
refines N variables. So if \`cb\` is a function, then it should be refining
exactly N argument. It is abstract in that we do not need to specify:
(a) which variables are going to be refined (just the number), or (b) what
@ -143,10 +143,10 @@ var e = refine2(c, d, is_string_and_number);
(e: string);
declare function refine2<T, P: $Pred<2>>(v: T, w: T, cb: P): $Refine<T, P, 1>;
function is_string(x): boolean %checks {
return typeof x === \"string\";
return typeof x === "string";
}
function is_string_and_number(x, y): %checks {
return typeof x === \"string\" && typeof y === \"number\";
return typeof x === "string" && typeof y === "number";
}
"
`;
@ -168,11 +168,11 @@ const d = my_filter(c, is_string_regular);
(d: Array<string>);
function is_string(x): boolean %checks {
return typeof x === \"string\";
return typeof x === "string";
}
function is_string_regular(x): boolean {
return typeof x === \"string\";
return typeof x === "string";
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow
@ -187,10 +187,10 @@ declare var c: Array<mixed>;
const d = my_filter(c, is_string_regular);
(d: Array<string>);
function is_string(x): boolean %checks {
return typeof x === \"string\";
return typeof x === "string";
}
function is_string_regular(x): boolean {
return typeof x === \"string\";
return typeof x === "string";
}
"
`;
@ -203,16 +203,16 @@ exports[`test sanity-filter-union.js 1`] = `
declare function my_filter<T, P: $Pred<1>>(v: Array<T>, cb: P): Array<$Refine<T,P,1>>;
type A = { kind: \'A\', u: number }
type B = { kind: \'B\', v: string }
type C = { kind: \'C\', y: boolean }
type D = { kind: \'D\', x: boolean }
type E = { kind: \'E\', y: boolean }
type A = { kind: 'A', u: number }
type B = { kind: 'B', v: string }
type C = { kind: 'C', y: boolean }
type D = { kind: 'D', x: boolean }
type E = { kind: 'E', y: boolean }
declare var ab: Array<A|B|C>;
(my_filter(ab, (x): %checks => x.kind === \'A\'): Array<B>); // ERROR
(my_filter(ab, (x): %checks => x.kind !== \'A\'): Array<A|C>); // ERROR
(my_filter(ab, (x): %checks => x.kind === 'A'): Array<B>); // ERROR
(my_filter(ab, (x): %checks => x.kind !== 'A'): Array<A|C>); // ERROR
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow
// Filter the contents of an array
@ -220,14 +220,14 @@ declare var ab: Array<A|B|C>;
// ERROR
declare function my_filter<T, P: $Pred<1>>(v: Array<T>,
cb: P): Array<$Refine<T, P, 1>>;
type A = { kind: \"A\"; u: number };
type B = { kind: \"B\"; v: string };
type C = { kind: \"C\"; y: boolean };
type D = { kind: \"D\"; x: boolean };
type E = { kind: \"E\"; y: boolean };
type A = { kind: "A"; u: number };
type B = { kind: "B"; v: string };
type C = { kind: "C"; y: boolean };
type D = { kind: "D"; x: boolean };
type E = { kind: "E"; y: boolean };
declare var ab: Array<A | B | C>;
(my_filter(ab, (x): %checks => x.kind === \"A\"): Array<B>);
(my_filter(ab, (x): %checks => x.kind !== \"A\"): Array<A | C>);
(my_filter(ab, (x): %checks => x.kind === "A"): Array<B>);
(my_filter(ab, (x): %checks => x.kind !== "A"): Array<A | C>);
"
`;
@ -254,7 +254,7 @@ var e = refine3(c, d, e, is_string_and_number);
(e: string);
function is_string_and_number(x, y): %checks {
return typeof x === \"string\" && typeof y === \"number\";
return typeof x === "string" && typeof y === "number";
}
@ -266,15 +266,15 @@ var e = refine(a, is_string_regular); // ERROR: is_string_regular is not a
////////////////////////////////////////////////////////////////////////////////
function is_string(x): %checks {
return typeof x === \"string\";
return typeof x === "string";
}
function is_string_regular(x) {
return typeof x === \"string\";
return typeof x === "string";
}
function is_string_and_number(x, y): %checks {
return typeof x === \"string\" && typeof y === \"number\";
return typeof x === "string" && typeof y === "number";
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow
@ -300,18 +300,18 @@ cb: P): $Refine<T, P, 1>;
var e = refine3(c, d, e, is_string_and_number);
(e: string);
function is_string_and_number(x, y): %checks {
return typeof x === \"string\" && typeof y === \"number\";
return typeof x === "string" && typeof y === "number";
}
var e = refine(a, is_string_regular);
(e: number);
function is_string(x): %checks {
return typeof x === \"string\";
return typeof x === "string";
}
function is_string_regular(x) {
return typeof x === \"string\";
return typeof x === "string";
}
function is_string_and_number(x, y): %checks {
return typeof x === \"string\" && typeof y === \"number\";
return typeof x === "string" && typeof y === "number";
}
"
`;

View File

@ -11,7 +11,7 @@ function run_spec(dirname) {
if (!RUN_AST_TESTS) {
const source = read(path);
const output = prettyprint(source);
const output = prettyprint(source, path);
test(filename, () => {
expect(source + '~'.repeat(80) + '\n' + output).toMatchSnapshot();
});
@ -24,7 +24,7 @@ function run_spec(dirname) {
let ppast;
let pperr = null;
try {
ppast = parse(prettyprint(source));
ppast = parse(prettyprint(source, path));
}
catch(e) {
pperr = e.stack;
@ -68,8 +68,8 @@ function parse(string) {
return stripLocation(flowParser.parse(string));
}
function prettyprint(src) {
return jscodefmt.format(src);
function prettyprint(src, filename) {
return jscodefmt.format(src, { filename });
}
function read(filename) {