Bump babylon to 7.0.0-beta.8 (#1118)
* Bump babylon version * Enable flow predicate tests in babylonmaster
parent
96b0a33cff
commit
d9a4efcc35
|
@ -12,7 +12,7 @@
|
|||
"dependencies": {
|
||||
"ast-types": "0.9.8",
|
||||
"babel-code-frame": "6.22.0",
|
||||
"babylon": "7.0.0-beta.4",
|
||||
"babylon": "7.0.0-beta.8",
|
||||
"chalk": "1.1.3",
|
||||
"esutils": "2.0.2",
|
||||
"flow-parser": "0.40.0",
|
||||
|
|
|
@ -34,12 +34,87 @@ function is_string(x): %checks {
|
|||
"
|
||||
`;
|
||||
|
||||
exports[`filter.js 2`] = `
|
||||
"// @flow
|
||||
|
||||
// Filter the contents of an array
|
||||
|
||||
declare function my_filter<T, P: $Pred<1>>(v: Array<T>, cb: P): Array<$Refine<T,P,1>>;
|
||||
|
||||
declare var arr: Array<mixed>;
|
||||
const barr = my_filter(arr, is_string);
|
||||
(barr: Array<string>);
|
||||
|
||||
function is_string(x): %checks {
|
||||
return typeof x === \\"string\\";
|
||||
}
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// @flow
|
||||
|
||||
// Filter the contents of an array
|
||||
|
||||
declare function my_filter<T, P: $Pred<1>>(
|
||||
v: Array<T>,
|
||||
cb: P
|
||||
): Array<$Refine<T, P, 1>>;
|
||||
|
||||
declare var arr: Array<mixed>;
|
||||
const barr = my_filter(arr, is_string);
|
||||
(barr: Array<string>);
|
||||
|
||||
function is_string(x): %checks {
|
||||
return typeof x === \\"string\\";
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`filter-union.js 1`] = `
|
||||
"// @flow
|
||||
|
||||
// Filter the contents of an array
|
||||
|
||||
|
||||
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 }
|
||||
|
||||
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
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// @flow
|
||||
|
||||
// Filter the contents of an array
|
||||
|
||||
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 };
|
||||
|
||||
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
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`filter-union.js 2`] = `
|
||||
"// @flow
|
||||
|
||||
// Filter the contents of an array
|
||||
|
||||
|
||||
declare function my_filter<T, P: $Pred<1>>(v: Array<T>, cb: P): Array<$Refine<T,P,1>>;
|
||||
|
||||
type A = { kind: 'A', u: number }
|
||||
|
@ -110,6 +185,106 @@ 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 refine_fst(v, w, cb)
|
||||
// { if (cb(v, w)) { return w; } else { throw new Error(); } }
|
||||
|
||||
function is_string(x): boolean %checks {
|
||||
return typeof x === \\"string\\";
|
||||
}
|
||||
|
||||
function is_string_and_number(x, y): %checks {
|
||||
return typeof x === \\"string\\" && typeof y === \\"number\\";
|
||||
}
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// @flow
|
||||
|
||||
/*
|
||||
$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
|
||||
exactly the refinement (predicate) is going to be.
|
||||
|
||||
$Refine<T,P,k> is a refinement type, that refines type T with the k-th
|
||||
argument that gets refined by an abstract preficate type P.
|
||||
*/
|
||||
declare function refine<T, P: $Pred<1>>(v: T, cb: P): $Refine<T, P, 1>;
|
||||
// function refine(v, cb)
|
||||
// { if (cb(v)) { return v; } else { throw new Error(); } }
|
||||
|
||||
/*
|
||||
Use case
|
||||
*/
|
||||
declare var a: mixed;
|
||||
var b = refine(a, is_string);
|
||||
(b: string);
|
||||
|
||||
declare function refine_fst<T, P: $Pred<2>>(
|
||||
v: T,
|
||||
w: T,
|
||||
cb: P
|
||||
): $Refine<T, P, 1>;
|
||||
// function refine_fst(v, w, cb)
|
||||
// { if (cb(v, w)) { return v; } else { throw new Error(); } }
|
||||
|
||||
declare var c: mixed;
|
||||
declare var d: mixed;
|
||||
|
||||
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 refine_fst(v, w, cb)
|
||||
// { if (cb(v, w)) { return w; } else { throw new Error(); } }
|
||||
|
||||
function is_string(x): boolean %checks {
|
||||
return typeof x === \\"string\\";
|
||||
}
|
||||
|
||||
function is_string_and_number(x, y): %checks {
|
||||
return typeof x === \\"string\\" && typeof y === \\"number\\";
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`refine.js 2`] = `
|
||||
"// @flow
|
||||
|
||||
/*
|
||||
$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
|
||||
exactly the refinement (predicate) is going to be.
|
||||
|
||||
$Refine<T,P,k> is a refinement type, that refines type T with the k-th
|
||||
argument that gets refined by an abstract preficate type P.
|
||||
*/
|
||||
declare function refine<T, P: $Pred<1>>(v: T, cb: P): $Refine<T,P,1>;
|
||||
// function refine(v, cb)
|
||||
// { if (cb(v)) { return v; } else { throw new Error(); } }
|
||||
|
||||
/*
|
||||
Use case
|
||||
*/
|
||||
declare var a: mixed;
|
||||
var b = refine(a, is_string);
|
||||
(b: string);
|
||||
|
||||
declare function refine_fst<T, P: $Pred<2>>(v: T, w: T, cb: P): $Refine<T,P,1>;
|
||||
// function refine_fst(v, w, cb)
|
||||
// { if (cb(v, w)) { return v; } else { throw new Error(); } }
|
||||
|
||||
declare var c: mixed;
|
||||
declare var d: mixed;
|
||||
|
||||
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 refine_fst(v, w, cb)
|
||||
|
@ -186,6 +361,57 @@ const b = my_filter(a, is_string);
|
|||
(b: Array<number>);
|
||||
|
||||
|
||||
// Sanity check B: Passing non-predicate function to filter
|
||||
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\\";
|
||||
}
|
||||
|
||||
function is_string_regular(x): boolean {
|
||||
return typeof x === \\"string\\";
|
||||
}
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// @flow
|
||||
|
||||
declare function my_filter<T, P: $Pred<1>>(
|
||||
v: Array<T>,
|
||||
cb: P
|
||||
): Array<$Refine<T, P, 1>>;
|
||||
|
||||
// Sanity check A: filtering the wrong type
|
||||
declare var a: Array<mixed>;
|
||||
const b = my_filter(a, is_string);
|
||||
(b: Array<number>);
|
||||
|
||||
// Sanity check B: Passing non-predicate function to filter
|
||||
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\\";
|
||||
}
|
||||
|
||||
function is_string_regular(x): boolean {
|
||||
return typeof x === \\"string\\";
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`sanity-filter.js 2`] = `
|
||||
"// @flow
|
||||
|
||||
declare function my_filter<T, P: $Pred<1>>(v: Array<T>, cb: P): Array<$Refine<T,P,1>>;
|
||||
|
||||
// Sanity check A: filtering the wrong type
|
||||
declare var a: Array<mixed>;
|
||||
const b = my_filter(a, is_string);
|
||||
(b: Array<number>);
|
||||
|
||||
|
||||
// Sanity check B: Passing non-predicate function to filter
|
||||
declare var c: Array<mixed>;
|
||||
const d = my_filter(c, is_string_regular);
|
||||
|
@ -232,6 +458,47 @@ exports[`sanity-filter-union.js 1`] = `
|
|||
// Filter the contents of an array
|
||||
|
||||
|
||||
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 }
|
||||
|
||||
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
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// @flow
|
||||
|
||||
// Filter the contents of an array
|
||||
|
||||
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 };
|
||||
|
||||
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
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`sanity-filter-union.js 2`] = `
|
||||
"// @flow
|
||||
|
||||
// Filter the contents of an array
|
||||
|
||||
|
||||
declare function my_filter<T, P: $Pred<1>>(v: Array<T>, cb: P): Array<$Refine<T,P,1>>;
|
||||
|
||||
type A = { kind: 'A', u: number }
|
||||
|
@ -294,6 +561,102 @@ function is_string_and_number(x, y): %checks {
|
|||
}
|
||||
|
||||
|
||||
// Sanity check C: expecting a predicate function but passed a non-predicate one
|
||||
var e = refine(a, is_string_regular); // ERROR: is_string_regular is not a
|
||||
// predicate function
|
||||
(e: number);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function is_string(x): %checks {
|
||||
return typeof x === \\"string\\";
|
||||
}
|
||||
|
||||
function is_string_regular(x) {
|
||||
return typeof x === \\"string\\";
|
||||
}
|
||||
|
||||
function is_string_and_number(x, y): %checks {
|
||||
return typeof x === \\"string\\" && typeof y === \\"number\\";
|
||||
}
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// @flow
|
||||
|
||||
// Sanity check A: the refinment position index is outside of the allowed range
|
||||
declare function refine<T, P: $Pred<1>>(v: T, cb: P): $Refine<T, P, 2>;
|
||||
|
||||
declare var a: mixed;
|
||||
var b = refine(a, is_string); // ERROR: index out of bounds
|
||||
(b: string);
|
||||
|
||||
// Sanity check B: refine2 expects a function that accepts 3 arguments but
|
||||
// it is called with a function that takes 2
|
||||
declare var c: mixed;
|
||||
declare var d: mixed;
|
||||
declare var e: mixed;
|
||||
|
||||
declare function refine3<T, P: $Pred<3>>(
|
||||
u: T,
|
||||
v: T,
|
||||
w: T,
|
||||
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\\";
|
||||
}
|
||||
|
||||
// Sanity check C: expecting a predicate function but passed a non-predicate one
|
||||
var e = refine(a, is_string_regular); // ERROR: is_string_regular is not a
|
||||
// predicate function
|
||||
(e: number);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function is_string(x): %checks {
|
||||
return typeof x === \\"string\\";
|
||||
}
|
||||
|
||||
function is_string_regular(x) {
|
||||
return typeof x === \\"string\\";
|
||||
}
|
||||
|
||||
function is_string_and_number(x, y): %checks {
|
||||
return typeof x === \\"string\\" && typeof y === \\"number\\";
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`sanity-refine.js 2`] = `
|
||||
"// @flow
|
||||
|
||||
// Sanity check A: the refinment position index is outside of the allowed range
|
||||
declare function refine<T, P: $Pred<1>>(v: T, cb: P): $Refine<T,P,2>;
|
||||
|
||||
declare var a: mixed;
|
||||
var b = refine(a, is_string); // ERROR: index out of bounds
|
||||
(b: string);
|
||||
|
||||
|
||||
// Sanity check B: refine2 expects a function that accepts 3 arguments but
|
||||
// it is called with a function that takes 2
|
||||
declare var c: mixed;
|
||||
declare var d: mixed;
|
||||
declare var e: mixed;
|
||||
|
||||
declare function refine3<T, P: $Pred<3>>(u: T, v: T, w: T, 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\\";
|
||||
}
|
||||
|
||||
|
||||
// Sanity check C: expecting a predicate function but passed a non-predicate one
|
||||
var e = refine(a, is_string_regular); // ERROR: is_string_regular is not a
|
||||
// predicate function
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
run_spec(__dirname);
|
||||
run_spec(__dirname, { parser: "babylon" });
|
||||
|
|
|
@ -30,6 +30,92 @@ if (m.bind(o)) {
|
|||
}
|
||||
|
||||
|
||||
class D {
|
||||
m: Function;
|
||||
|
||||
n() {
|
||||
if(this.m({})) { }
|
||||
}
|
||||
}
|
||||
|
||||
declare var m: Function;
|
||||
const x = \\"\\";
|
||||
if (m.bind(this)(x)) { }
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// @flow
|
||||
|
||||
// Sanity checks:
|
||||
// - use of bind in a position of a function predicate.
|
||||
// (This case should fall through, as method calls
|
||||
// are currently not supported.) The original behavior
|
||||
// (including \`havoc\`) should be retained.
|
||||
|
||||
class C {
|
||||
m() {
|
||||
return true;
|
||||
}
|
||||
a: 1;
|
||||
|
||||
n() {
|
||||
if (this.m.bind(this)) {
|
||||
this.a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
declare var m: Function;
|
||||
const o = { a: 1 };
|
||||
|
||||
if (m.bind(o)) {
|
||||
o.a;
|
||||
}
|
||||
|
||||
class D {
|
||||
m: Function;
|
||||
|
||||
n() {
|
||||
if (this.m({})) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
declare var m: Function;
|
||||
const x = \\"\\";
|
||||
if (m.bind(this)(x)) {
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`function-bind.js 2`] = `
|
||||
"// @flow
|
||||
|
||||
// Sanity checks:
|
||||
// - use of bind in a position of a function predicate.
|
||||
// (This case should fall through, as method calls
|
||||
// are currently not supported.) The original behavior
|
||||
// (including \`havoc\`) should be retained.
|
||||
|
||||
class C {
|
||||
m() {
|
||||
return true;
|
||||
}
|
||||
a: 1;
|
||||
|
||||
n() {
|
||||
if(this.m.bind(this)) {
|
||||
this.a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
declare var m: Function;
|
||||
const o = { a: 1 };
|
||||
|
||||
if (m.bind(o)) {
|
||||
o.a;
|
||||
}
|
||||
|
||||
|
||||
class D {
|
||||
m: Function;
|
||||
|
||||
|
@ -126,6 +212,46 @@ function foo(x: number | string | Array<string>): number {
|
|||
"
|
||||
`;
|
||||
|
||||
exports[`function-union.js 2`] = `
|
||||
"// @flow
|
||||
|
||||
declare function f1(x: mixed): boolean %checks(typeof x === \\"string\\");
|
||||
declare function f2(x: mixed): boolean %checks(Array.isArray(x));
|
||||
|
||||
declare var cond: boolean;
|
||||
|
||||
// Feature check:
|
||||
function foo(x: number | string | Array<string>): number {
|
||||
|
||||
var f = (cond) ? f1 : f2;
|
||||
|
||||
if (f(x)) {
|
||||
return x.length;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// @flow
|
||||
|
||||
declare function f1(x: mixed): boolean %checks(typeof x === \\"string\\");
|
||||
declare function f2(x: mixed): boolean %checks(Array.isArray(x));
|
||||
|
||||
declare var cond: boolean;
|
||||
|
||||
// Feature check:
|
||||
function foo(x: number | string | Array<string>): number {
|
||||
var f = cond ? f1 : f2;
|
||||
|
||||
if (f(x)) {
|
||||
return x.length;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`is-string-decl.js 1`] = `
|
||||
"// @flow
|
||||
|
||||
|
@ -167,6 +293,47 @@ function foo(x: string | Array<string>): string {
|
|||
"
|
||||
`;
|
||||
|
||||
exports[`is-string-decl.js 2`] = `
|
||||
"// @flow
|
||||
|
||||
declare function is_string(x: mixed): boolean %checks(typeof x === \\"string\\");
|
||||
declare function is_number(x: mixed): boolean %checks(typeof x === \\"number\\");
|
||||
|
||||
// Feature check:
|
||||
function foo(x: string | Array<string>): string {
|
||||
if (is_string(x)) {
|
||||
// The use of \`is_string\` as a conditional check
|
||||
// should guarantee the narrowing of the type of \`x\`
|
||||
// to string.
|
||||
return x;
|
||||
} else {
|
||||
// Accordingly the negation of the above check
|
||||
// guarantees that \`x\` here is an Array<string>
|
||||
return x.join();
|
||||
}
|
||||
}
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// @flow
|
||||
|
||||
declare function is_string(x: mixed): boolean %checks(typeof x === \\"string\\");
|
||||
declare function is_number(x: mixed): boolean %checks(typeof x === \\"number\\");
|
||||
|
||||
// Feature check:
|
||||
function foo(x: string | Array<string>): string {
|
||||
if (is_string(x)) {
|
||||
// The use of \`is_string\` as a conditional check
|
||||
// should guarantee the narrowing of the type of \`x\`
|
||||
// to string.
|
||||
return x;
|
||||
} else {
|
||||
// Accordingly the negation of the above check
|
||||
// guarantees that \`x\` here is an Array<string>
|
||||
return x.join();
|
||||
}
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`logical-or.js 1`] = `
|
||||
"// @flow
|
||||
|
||||
|
@ -218,6 +385,57 @@ Number(dollars) || 0;
|
|||
"
|
||||
`;
|
||||
|
||||
exports[`logical-or.js 2`] = `
|
||||
"// @flow
|
||||
|
||||
// Sanity check:
|
||||
// - conditional functions do not affect behavior of conditional
|
||||
// expressions (e.g. \`||\`)
|
||||
|
||||
declare function r(x: string): number;
|
||||
var s = 'a';
|
||||
var n = r(s) || 1;
|
||||
(n: number);
|
||||
|
||||
var x = \\"\\";
|
||||
if (x = r(s) || 1) {
|
||||
(x: number);
|
||||
}
|
||||
|
||||
declare var dollars: mixed;
|
||||
|
||||
function foo(x: mixed) { return 1; }
|
||||
(foo(dollars) || 0);
|
||||
|
||||
(Number(dollars) || 0);
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// @flow
|
||||
|
||||
// Sanity check:
|
||||
// - conditional functions do not affect behavior of conditional
|
||||
// expressions (e.g. \`||\`)
|
||||
|
||||
declare function r(x: string): number;
|
||||
var s = \\"a\\";
|
||||
var n = r(s) || 1;
|
||||
(n: number);
|
||||
|
||||
var x = \\"\\";
|
||||
if ((x = r(s) || 1)) {
|
||||
(x: number);
|
||||
}
|
||||
|
||||
declare var dollars: mixed;
|
||||
|
||||
function foo(x: mixed) {
|
||||
return 1;
|
||||
}
|
||||
foo(dollars) || 0;
|
||||
|
||||
Number(dollars) || 0;
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`object-invariant.js 1`] = `
|
||||
"// @flow
|
||||
|
||||
|
@ -270,6 +488,58 @@ function f(_this: { m: ?Meeting }): string {
|
|||
"
|
||||
`;
|
||||
|
||||
exports[`object-invariant.js 2`] = `
|
||||
"// @flow
|
||||
|
||||
// Sanity check:
|
||||
// - preserving \`havoc\` semantics
|
||||
|
||||
type Meeting = {
|
||||
organizer: ?Invitee,
|
||||
es: Array<Invitee>
|
||||
}
|
||||
|
||||
type Invitee = {
|
||||
fbid: number
|
||||
}
|
||||
|
||||
function f(_this: { m: ?Meeting }): string {
|
||||
if (!_this.m) {
|
||||
return \\"0\\";
|
||||
}
|
||||
|
||||
if (_this.m.es.some((a) => a.fbid === 0)) {
|
||||
|
||||
}
|
||||
return \\"3\\";
|
||||
}
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// @flow
|
||||
|
||||
// Sanity check:
|
||||
// - preserving \`havoc\` semantics
|
||||
|
||||
type Meeting = {
|
||||
organizer: ?Invitee,
|
||||
es: Array<Invitee>
|
||||
};
|
||||
|
||||
type Invitee = {
|
||||
fbid: number
|
||||
};
|
||||
|
||||
function f(_this: { m: ?Meeting }): string {
|
||||
if (!_this.m) {
|
||||
return \\"0\\";
|
||||
}
|
||||
|
||||
if (_this.m.es.some(a => a.fbid === 0)) {
|
||||
}
|
||||
return \\"3\\";
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`orig-string-tag-check.js 1`] = `
|
||||
"// @flow
|
||||
|
||||
|
@ -298,6 +568,34 @@ function foo(x: string | Array<string>): string {
|
|||
"
|
||||
`;
|
||||
|
||||
exports[`orig-string-tag-check.js 2`] = `
|
||||
"// @flow
|
||||
|
||||
// The original first-order case
|
||||
|
||||
function foo(x: string | Array<string>): string {
|
||||
if (typeof x === \\"string\\") {
|
||||
return x; // [ERROR] x: Array<string> doesn't match return type
|
||||
}
|
||||
else {
|
||||
return x.join(); // [ERROR] x: string doesn't have .join method
|
||||
}
|
||||
}
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// @flow
|
||||
|
||||
// The original first-order case
|
||||
|
||||
function foo(x: string | Array<string>): string {
|
||||
if (typeof x === \\"string\\") {
|
||||
return x; // [ERROR] x: Array<string> doesn't match return type
|
||||
} else {
|
||||
return x.join(); // [ERROR] x: string doesn't have .join method
|
||||
}
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`sanity-fall-through.js 1`] = `
|
||||
"// @flow
|
||||
|
||||
|
@ -329,6 +627,37 @@ function foo(s: Array<string>): string {
|
|||
"
|
||||
`;
|
||||
|
||||
exports[`sanity-fall-through.js 2`] = `
|
||||
"// @flow
|
||||
|
||||
// Sanity check:
|
||||
// - we should still be getting an error at the second return statement
|
||||
|
||||
declare function pred<T>(x: T): boolean;
|
||||
|
||||
function foo(s: Array<string>): string {
|
||||
if (pred(s)) {
|
||||
return \\"1\\";
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// @flow
|
||||
|
||||
// Sanity check:
|
||||
// - we should still be getting an error at the second return statement
|
||||
|
||||
declare function pred<T>(x: T): boolean;
|
||||
|
||||
function foo(s: Array<string>): string {
|
||||
if (pred(s)) {
|
||||
return \\"1\\";
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`sanity-invalid-calls.js 1`] = `
|
||||
"// @flow
|
||||
|
||||
|
@ -371,6 +700,48 @@ function foo(s: Array<string>): string {
|
|||
"
|
||||
`;
|
||||
|
||||
exports[`sanity-invalid-calls.js 2`] = `
|
||||
"// @flow
|
||||
|
||||
// Sanity check:
|
||||
// - invalid calls at predicate positions
|
||||
|
||||
declare function pred<T>(x: T): boolean;
|
||||
|
||||
function foo(s: Array<string>): string {
|
||||
|
||||
if ((1)(s)) {
|
||||
return \\"1\\";
|
||||
}
|
||||
|
||||
if ((pred + 1)(\\"s\\")) {
|
||||
return \\"1\\";
|
||||
}
|
||||
|
||||
return \\"1\\"
|
||||
}
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// @flow
|
||||
|
||||
// Sanity check:
|
||||
// - invalid calls at predicate positions
|
||||
|
||||
declare function pred<T>(x: T): boolean;
|
||||
|
||||
function foo(s: Array<string>): string {
|
||||
if (1(s)) {
|
||||
return \\"1\\";
|
||||
}
|
||||
|
||||
if ((pred + 1)(\\"s\\")) {
|
||||
return \\"1\\";
|
||||
}
|
||||
|
||||
return \\"1\\";
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`sanity-is-string-bug.js 1`] = `
|
||||
"// @flow
|
||||
|
||||
|
@ -406,6 +777,41 @@ function bar(x: string | Array<string>): string {
|
|||
"
|
||||
`;
|
||||
|
||||
exports[`sanity-is-string-bug.js 2`] = `
|
||||
"// @flow
|
||||
|
||||
declare function is_string(x: mixed): boolean %checks(typeof x === \\"string\\");
|
||||
declare function is_number(x: mixed): boolean %checks(typeof x === \\"number\\");
|
||||
|
||||
// Sanity check:
|
||||
// - Erroneous logic
|
||||
|
||||
function bar(x: string | Array<string>): string {
|
||||
if (is_number(x)) {
|
||||
return x;
|
||||
} else {
|
||||
return x.join(); // error: both string and Array<string> can flow to x
|
||||
}
|
||||
}
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// @flow
|
||||
|
||||
declare function is_string(x: mixed): boolean %checks(typeof x === \\"string\\");
|
||||
declare function is_number(x: mixed): boolean %checks(typeof x === \\"number\\");
|
||||
|
||||
// Sanity check:
|
||||
// - Erroneous logic
|
||||
|
||||
function bar(x: string | Array<string>): string {
|
||||
if (is_number(x)) {
|
||||
return x;
|
||||
} else {
|
||||
return x.join(); // error: both string and Array<string> can flow to x
|
||||
}
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`sanity-parameter-mismatch.js 1`] = `
|
||||
"// @flow
|
||||
|
||||
|
@ -431,6 +837,31 @@ foo(3, 3);
|
|||
"
|
||||
`;
|
||||
|
||||
exports[`sanity-parameter-mismatch.js 2`] = `
|
||||
"// @flow
|
||||
|
||||
// Sanity check: make sure the parameters are checked as usual
|
||||
|
||||
declare function foo(
|
||||
input: mixed,
|
||||
types: string | Array<string>
|
||||
): boolean %checks(typeof input === \\"string\\" || Array.isArray(input));
|
||||
|
||||
foo(3, 3);
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// @flow
|
||||
|
||||
// Sanity check: make sure the parameters are checked as usual
|
||||
|
||||
declare function foo(
|
||||
input: mixed,
|
||||
types: string | Array<string>
|
||||
): boolean %checks(typeof input === \\"string\\" || Array.isArray(input));
|
||||
|
||||
foo(3, 3);
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`sanity-pred-with-body.js 1`] = `
|
||||
"// @flow
|
||||
|
||||
|
@ -467,6 +898,42 @@ function foo(x: string | Array<string>): string {
|
|||
"
|
||||
`;
|
||||
|
||||
exports[`sanity-pred-with-body.js 2`] = `
|
||||
"// @flow
|
||||
|
||||
// Sanity check:
|
||||
// - predicate functions cannot have bodies (can only be declarations)
|
||||
|
||||
function pred(x: mixed): boolean %checks(typeof x === \\"string\\") { // error: cannot use pred type here
|
||||
return typeof x === \\"string\\";
|
||||
}
|
||||
|
||||
function foo(x: string | Array<string>): string {
|
||||
if (pred(x)) {
|
||||
return x;
|
||||
}
|
||||
return \\"1\\"
|
||||
}
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// @flow
|
||||
|
||||
// Sanity check:
|
||||
// - predicate functions cannot have bodies (can only be declarations)
|
||||
|
||||
function pred(x: mixed): boolean %checks(typeof x === \\"string\\") {
|
||||
// error: cannot use pred type here
|
||||
return typeof x === \\"string\\";
|
||||
}
|
||||
|
||||
function foo(x: string | Array<string>): string {
|
||||
if (pred(x)) {
|
||||
return x;
|
||||
}
|
||||
return \\"1\\";
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`sanity-return-type.js 1`] = `
|
||||
"// @flow
|
||||
|
||||
|
@ -477,3 +944,14 @@ declare function f2(x: mixed): string %checks(Array.isArray(x));
|
|||
declare function f2(x: mixed): string %checks(Array.isArray(x));
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`sanity-return-type.js 2`] = `
|
||||
"// @flow
|
||||
|
||||
declare function f2(x: mixed): string %checks(Array.isArray(x));
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// @flow
|
||||
|
||||
declare function f2(x: mixed): string %checks(Array.isArray(x));
|
||||
"
|
||||
`;
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
run_spec(__dirname);
|
||||
run_spec(__dirname, { parser: 'babylon' });
|
||||
|
|
|
@ -59,6 +59,65 @@ function bak(z: string | number): number {
|
|||
"
|
||||
`;
|
||||
|
||||
exports[`sanity.js 2`] = `
|
||||
"// @flow
|
||||
|
||||
// Sanity check: shouldn't be allowed to declare a predicate AND use \`chekcs\`
|
||||
|
||||
function check(y): %checks(typeof y === \\"string\\") {
|
||||
return typeof y === \\"number\\";
|
||||
}
|
||||
|
||||
declare var y: number | boolean;
|
||||
|
||||
if (check(y)) {
|
||||
(y: number);
|
||||
}
|
||||
|
||||
// Sanity: disallowed body
|
||||
function indirect_is_number(y): %checks {
|
||||
var y = 1;
|
||||
return typeof y === \\"number\\";
|
||||
}
|
||||
|
||||
function bak(z: string | number): number {
|
||||
if (indirect_is_number(z)) {
|
||||
return z;
|
||||
} else {
|
||||
return z.length;
|
||||
}
|
||||
}
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// @flow
|
||||
|
||||
// Sanity check: shouldn't be allowed to declare a predicate AND use \`chekcs\`
|
||||
|
||||
function check(y): %checks(typeof y === \\"string\\") {
|
||||
return typeof y === \\"number\\";
|
||||
}
|
||||
|
||||
declare var y: number | boolean;
|
||||
|
||||
if (check(y)) {
|
||||
(y: number);
|
||||
}
|
||||
|
||||
// Sanity: disallowed body
|
||||
function indirect_is_number(y): %checks {
|
||||
var y = 1;
|
||||
return typeof y === \\"number\\";
|
||||
}
|
||||
|
||||
function bak(z: string | number): number {
|
||||
if (indirect_is_number(z)) {
|
||||
return z;
|
||||
} else {
|
||||
return z.length;
|
||||
}
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`sanity-multi-params.js 1`] = `
|
||||
"// @flow
|
||||
|
||||
|
@ -92,6 +151,39 @@ function foo(x: string | Array<string>): string {
|
|||
"
|
||||
`;
|
||||
|
||||
exports[`sanity-multi-params.js 2`] = `
|
||||
"// @flow
|
||||
|
||||
// Feature: multi params
|
||||
function multi_param(w,x,y,z): %checks {
|
||||
return typeof z === \\"string\\";
|
||||
}
|
||||
|
||||
function foo(x: string | Array<string>): string {
|
||||
if (multi_param(\\"1\\", \\"2\\", x, \\"3\\")) {
|
||||
return x;
|
||||
} else {
|
||||
return x.join();
|
||||
}
|
||||
}
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// @flow
|
||||
|
||||
// Feature: multi params
|
||||
function multi_param(w, x, y, z): %checks {
|
||||
return typeof z === \\"string\\";
|
||||
}
|
||||
|
||||
function foo(x: string | Array<string>): string {
|
||||
if (multi_param(\\"1\\", \\"2\\", x, \\"3\\")) {
|
||||
return x;
|
||||
} else {
|
||||
return x.join();
|
||||
}
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`sanity-ordering.js 1`] = `
|
||||
"// @flow
|
||||
|
||||
|
@ -133,6 +225,47 @@ function dotAccess(head, create) {
|
|||
"
|
||||
`;
|
||||
|
||||
exports[`sanity-ordering.js 2`] = `
|
||||
"// @flow
|
||||
|
||||
declare var key: string;
|
||||
declare var obj: { page: ?Object; };
|
||||
|
||||
if (dotAccess(obj)) {
|
||||
(obj.page: Object);
|
||||
}
|
||||
|
||||
function dotAccess(head, create) {
|
||||
const path = 'path.location';
|
||||
const stack = path.split('.');
|
||||
do {
|
||||
const key = stack.shift();
|
||||
head = head[key] || create && (head[key] = {});
|
||||
} while (stack.length && head);
|
||||
return head;
|
||||
}
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// @flow
|
||||
|
||||
declare var key: string;
|
||||
declare var obj: { page: ?Object };
|
||||
|
||||
if (dotAccess(obj)) {
|
||||
(obj.page: Object);
|
||||
}
|
||||
|
||||
function dotAccess(head, create) {
|
||||
const path = \\"path.location\\";
|
||||
const stack = path.split(\\".\\");
|
||||
do {
|
||||
const key = stack.shift();
|
||||
head = head[key] || (create && (head[key] = {}));
|
||||
} while (stack.length && head);
|
||||
return head;
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`sanity-unbound-var.js 1`] = `
|
||||
"// @flow
|
||||
|
||||
|
@ -172,6 +305,45 @@ function foo(x: string | Array<string>): string {
|
|||
"
|
||||
`;
|
||||
|
||||
exports[`sanity-unbound-var.js 2`] = `
|
||||
"// @flow
|
||||
|
||||
declare var y: mixed;
|
||||
|
||||
// Sanity check: this should fail, because the preficate function
|
||||
// checks \`y\` instead of \`x\`.
|
||||
function err(x): %checks {
|
||||
return typeof y === \\"string\\";
|
||||
}
|
||||
|
||||
function foo(x: string | Array<string>): string {
|
||||
if (err(x)) {
|
||||
return x;
|
||||
} else {
|
||||
return x.join();
|
||||
}
|
||||
}
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// @flow
|
||||
|
||||
declare var y: mixed;
|
||||
|
||||
// Sanity check: this should fail, because the preficate function
|
||||
// checks \`y\` instead of \`x\`.
|
||||
function err(x): %checks {
|
||||
return typeof y === \\"string\\";
|
||||
}
|
||||
|
||||
function foo(x: string | Array<string>): string {
|
||||
if (err(x)) {
|
||||
return x;
|
||||
} else {
|
||||
return x.join();
|
||||
}
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`simple-predicate-func.js 1`] = `
|
||||
"// @flow
|
||||
|
||||
|
@ -323,6 +495,157 @@ declare function from_two_strings(x: string, y: string): void;
|
|||
"
|
||||
`;
|
||||
|
||||
exports[`simple-predicate-func.js 2`] = `
|
||||
"// @flow
|
||||
|
||||
function is_string(y): %checks {
|
||||
return typeof y === \\"string\\";
|
||||
}
|
||||
|
||||
function is_bool(y): %checks {
|
||||
return typeof y === \\"boolean\\";
|
||||
}
|
||||
|
||||
function is_number(y): %checks {
|
||||
return typeof y === \\"number\\";
|
||||
}
|
||||
|
||||
// Feature check:
|
||||
function foo(x: string | Array<string>): string {
|
||||
if (is_string(x)) {
|
||||
// The use of \`is_string\` as a conditional check
|
||||
// should guarantee the narrowing of the type of \`x\`
|
||||
// to string.
|
||||
return x;
|
||||
} else {
|
||||
// Accordingly the negation of the above check
|
||||
// guarantees that \`x\` here is an Array<string>
|
||||
return x.join();
|
||||
}
|
||||
}
|
||||
|
||||
// Same as above but refining an offset
|
||||
function bar(z: { f: string | Array<string>}): string {
|
||||
if (is_string(z.f)) {
|
||||
return z.f;
|
||||
} else {
|
||||
return z.f.join();
|
||||
}
|
||||
}
|
||||
|
||||
function is_number_or_bool(y): %checks {
|
||||
return is_number(y) || is_bool(y);
|
||||
}
|
||||
|
||||
function baz(z: string | number): number {
|
||||
if (is_number_or_bool(z)) {
|
||||
return z;
|
||||
} else {
|
||||
return z.length;
|
||||
}
|
||||
}
|
||||
|
||||
// Feature: multi params
|
||||
function multi_param(w,x,y,z): %checks {
|
||||
return typeof z === \\"string\\";
|
||||
}
|
||||
|
||||
function foo(x: string | Array<string>): string {
|
||||
if (multi_param(\\"1\\", \\"2\\", \\"3\\", x)) {
|
||||
return x;
|
||||
} else {
|
||||
return x.join();
|
||||
}
|
||||
}
|
||||
|
||||
function foo(a, b) {
|
||||
if (two_strings(a, b)) {
|
||||
from_two_strings(a, b);
|
||||
}
|
||||
}
|
||||
|
||||
function two_strings(x,y): %checks {
|
||||
return is_string(x) && is_string(y) ;
|
||||
}
|
||||
|
||||
declare function from_two_strings(x: string, y: string): void;
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// @flow
|
||||
|
||||
function is_string(y): %checks {
|
||||
return typeof y === \\"string\\";
|
||||
}
|
||||
|
||||
function is_bool(y): %checks {
|
||||
return typeof y === \\"boolean\\";
|
||||
}
|
||||
|
||||
function is_number(y): %checks {
|
||||
return typeof y === \\"number\\";
|
||||
}
|
||||
|
||||
// Feature check:
|
||||
function foo(x: string | Array<string>): string {
|
||||
if (is_string(x)) {
|
||||
// The use of \`is_string\` as a conditional check
|
||||
// should guarantee the narrowing of the type of \`x\`
|
||||
// to string.
|
||||
return x;
|
||||
} else {
|
||||
// Accordingly the negation of the above check
|
||||
// guarantees that \`x\` here is an Array<string>
|
||||
return x.join();
|
||||
}
|
||||
}
|
||||
|
||||
// Same as above but refining an offset
|
||||
function bar(z: { f: string | Array<string> }): string {
|
||||
if (is_string(z.f)) {
|
||||
return z.f;
|
||||
} else {
|
||||
return z.f.join();
|
||||
}
|
||||
}
|
||||
|
||||
function is_number_or_bool(y): %checks {
|
||||
return is_number(y) || is_bool(y);
|
||||
}
|
||||
|
||||
function baz(z: string | number): number {
|
||||
if (is_number_or_bool(z)) {
|
||||
return z;
|
||||
} else {
|
||||
return z.length;
|
||||
}
|
||||
}
|
||||
|
||||
// Feature: multi params
|
||||
function multi_param(w, x, y, z): %checks {
|
||||
return typeof z === \\"string\\";
|
||||
}
|
||||
|
||||
function foo(x: string | Array<string>): string {
|
||||
if (multi_param(\\"1\\", \\"2\\", \\"3\\", x)) {
|
||||
return x;
|
||||
} else {
|
||||
return x.join();
|
||||
}
|
||||
}
|
||||
|
||||
function foo(a, b) {
|
||||
if (two_strings(a, b)) {
|
||||
from_two_strings(a, b);
|
||||
}
|
||||
}
|
||||
|
||||
function two_strings(x, y): %checks {
|
||||
return is_string(x) && is_string(y);
|
||||
}
|
||||
|
||||
declare function from_two_strings(x: string, y: string): void;
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`simple-predicate-func-post.js 1`] = `
|
||||
"// @flow
|
||||
|
||||
|
@ -369,3 +692,50 @@ function is_string(x): %checks {
|
|||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`simple-predicate-func-post.js 2`] = `
|
||||
"// @flow
|
||||
|
||||
// Feature check:
|
||||
// The predicate function is defined after the conditional check
|
||||
|
||||
function foo(x: string | Array<string>): string {
|
||||
if (is_string(x)) {
|
||||
// The use of \`is_string\` as a conditional check
|
||||
// should guarantee the narrowing of the type of \`x\`
|
||||
// to string.
|
||||
return x;
|
||||
} else {
|
||||
// Accordingly the negation of the above check
|
||||
// guarantees that \`x\` here is an Array<string>
|
||||
return x.join();
|
||||
}
|
||||
}
|
||||
|
||||
function is_string(x): %checks {
|
||||
return typeof x === \\"string\\";
|
||||
}
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// @flow
|
||||
|
||||
// Feature check:
|
||||
// The predicate function is defined after the conditional check
|
||||
|
||||
function foo(x: string | Array<string>): string {
|
||||
if (is_string(x)) {
|
||||
// The use of \`is_string\` as a conditional check
|
||||
// should guarantee the narrowing of the type of \`x\`
|
||||
// to string.
|
||||
return x;
|
||||
} else {
|
||||
// Accordingly the negation of the above check
|
||||
// guarantees that \`x\` here is an Array<string>
|
||||
return x.join();
|
||||
}
|
||||
}
|
||||
|
||||
function is_string(x): %checks {
|
||||
return typeof x === \\"string\\";
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
run_spec(__dirname);
|
||||
run_spec(__dirname, { parser: "babylon" });
|
||||
|
|
|
@ -15,6 +15,21 @@ declare function f2(x: mixed): boolean %checks;
|
|||
"
|
||||
`;
|
||||
|
||||
exports[`fail-0.js 2`] = `
|
||||
"// @flow
|
||||
|
||||
// Error: 'declare', 'checks' but missing predicate
|
||||
|
||||
declare function f2(x: mixed): boolean %checks;
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// @flow
|
||||
|
||||
// Error: 'declare', 'checks' but missing predicate
|
||||
|
||||
declare function f2(x: mixed): boolean %checks;
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`fail-1.js 1`] = `
|
||||
"// @flow
|
||||
|
||||
|
@ -30,6 +45,21 @@ function f6(x: mixed): %checks(x !== null) {}
|
|||
"
|
||||
`;
|
||||
|
||||
exports[`fail-1.js 2`] = `
|
||||
"// @flow
|
||||
|
||||
// Error: no return statement
|
||||
|
||||
function f6(x: mixed): %checks (x !== null) { }
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// @flow
|
||||
|
||||
// Error: no return statement
|
||||
|
||||
function f6(x: mixed): %checks(x !== null) {}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`fail-2.js 1`] = `
|
||||
"// @flow
|
||||
|
||||
|
@ -47,6 +77,23 @@ var a2 = (x: mixed): %checks(x !== null) => {
|
|||
"
|
||||
`;
|
||||
|
||||
exports[`fail-2.js 2`] = `
|
||||
"// @flow
|
||||
|
||||
var a2 = (x: mixed): %checks (x !== null) => { // Error: body form
|
||||
var x = 1; return x;
|
||||
}
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// @flow
|
||||
|
||||
var a2 = (x: mixed): %checks(x !== null) => {
|
||||
// Error: body form
|
||||
var x = 1;
|
||||
return x;
|
||||
};
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`fail-3.js 1`] = `
|
||||
"// @flow
|
||||
|
||||
|
@ -68,6 +115,27 @@ var a2 = (x: mixed): %checks(x !== null) => x !== null;
|
|||
"
|
||||
`;
|
||||
|
||||
exports[`fail-3.js 2`] = `
|
||||
"// @flow
|
||||
|
||||
// Cannot declare predicate with a function body is present.
|
||||
|
||||
function f5(x: mixed): %checks (x !== null) { return x !== null }
|
||||
|
||||
var a2 = (x: mixed): %checks (x !== null) => x !== null;
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// @flow
|
||||
|
||||
// Cannot declare predicate with a function body is present.
|
||||
|
||||
function f5(x: mixed): %checks(x !== null) {
|
||||
return x !== null;
|
||||
}
|
||||
|
||||
var a2 = (x: mixed): %checks(x !== null) => x !== null;
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`pass.js 1`] = `
|
||||
"// @flow
|
||||
|
||||
|
@ -128,3 +196,64 @@ declare function f(x: mixed): checks;
|
|||
typeof x === null;
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`pass.js 2`] = `
|
||||
"// @flow
|
||||
|
||||
declare function f1(x: mixed): boolean;
|
||||
|
||||
declare function f3(x: mixed): boolean %checks (x !== null);
|
||||
|
||||
declare function f4(x: mixed): boolean %checks (x !== null);
|
||||
|
||||
function f7(x: mixed): %checks { return x !== null }
|
||||
|
||||
var a0 = (x: mixed) => x !== null;
|
||||
|
||||
var a1 = (x: mixed): %checks => x !== null;
|
||||
|
||||
(x): %checks => x !== null;
|
||||
|
||||
const insert_a_really_big_predicated_arrow_function_name_here = (x)
|
||||
: %checks => x !== null;
|
||||
|
||||
declare var x;
|
||||
(x)
|
||||
checks => 123;
|
||||
|
||||
type checks = any;
|
||||
|
||||
declare function f(x: mixed): checks
|
||||
(typeof x === null);
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// @flow
|
||||
|
||||
declare function f1(x: mixed): boolean;
|
||||
|
||||
declare function f3(x: mixed): boolean %checks(x !== null);
|
||||
|
||||
declare function f4(x: mixed): boolean %checks(x !== null);
|
||||
|
||||
function f7(x: mixed): %checks {
|
||||
return x !== null;
|
||||
}
|
||||
|
||||
var a0 = (x: mixed) => x !== null;
|
||||
|
||||
var a1 = (x: mixed): %checks => x !== null;
|
||||
|
||||
(x): %checks => x !== null;
|
||||
|
||||
const insert_a_really_big_predicated_arrow_function_name_here = (x): %checks =>
|
||||
x !== null;
|
||||
|
||||
declare var x;
|
||||
x;
|
||||
checks => 123;
|
||||
|
||||
type checks = any;
|
||||
|
||||
declare function f(x: mixed): checks;
|
||||
typeof x === null;
|
||||
"
|
||||
`;
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
run_spec(__dirname);
|
||||
run_spec(__dirname, { parser: "babylon" });
|
||||
|
|
|
@ -274,14 +274,14 @@ babel-types@^6.16.0, babel-types@^6.18.0, babel-types@^6.21.0:
|
|||
lodash "^4.2.0"
|
||||
to-fast-properties "^1.0.1"
|
||||
|
||||
babylon@7.0.0-beta.8:
|
||||
version "7.0.0-beta.8"
|
||||
resolved "https://registry.yarnpkg.com/babylon/-/babylon-7.0.0-beta.8.tgz#2bdc5ae366041442c27e068cce6f0d7c06ea9949"
|
||||
|
||||
babylon@^6.11.0, babylon@^6.13.0:
|
||||
version "6.15.0"
|
||||
resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.15.0.tgz#ba65cfa1a80e1759b0e89fb562e27dccae70348e"
|
||||
|
||||
babylon@babylon@7.0.0-beta.4:
|
||||
version "7.0.0-beta.4"
|
||||
resolved "https://registry.yarnpkg.com/babylon/-/babylon-7.0.0-beta.4.tgz#82db799d2667f61bbaf34456dbfa91c37613459d"
|
||||
|
||||
balanced-match@^0.4.1:
|
||||
version "0.4.2"
|
||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838"
|
||||
|
|
Loading…
Reference in New Issue