Preserve empty line after comment (#493)

The logic was already working, it was just special-cased to the first comment of the file! Presumably because the new line detection logic used to be broken ;)

I manually checked the first 10 snapshots and they are all legit, so I assume that all of them are.

Fixes #356
master
Christopher Chedeau 2017-01-27 11:05:41 -08:00 committed by James Long
parent 8f26568bc8
commit 956779ec17
51 changed files with 175 additions and 8 deletions

View File

@ -372,7 +372,6 @@ function printComments(path, print, options) {
var parent = path.getParentNode(); var parent = path.getParentNode();
var printed = print(path); var printed = print(path);
var comments = n.Node.check(value) && types.getFieldValue(value, "comments"); var comments = n.Node.check(value) && types.getFieldValue(value, "comments");
var isFirstInProgram = n.Program.check(parent) && parent.body[0] === value;
if (!comments || comments.length === 0) { if (!comments || comments.length === 0) {
return printed; return printed;
@ -392,14 +391,8 @@ function printComments(path, print, options) {
) { ) {
leadingParts.push(printLeadingComment(commentPath, print, options)); leadingParts.push(printLeadingComment(commentPath, print, options));
// Support a special case where a comment exists at the very top
// of the file. Allow the user to add spacing between that file
// and any code beneath it.
const text = options.originalText; const text = options.originalText;
if ( if (util.hasNewline(text, util.skipNewline(text, util.locEnd(comment)))) {
isFirstInProgram &&
util.hasNewline(text, util.skipNewline(text, util.locEnd(comment)))
) {
leadingParts.push(hardline); leadingParts.push(hardline);
} }
} else if (trailing) { } else if (trailing) {

View File

@ -27,6 +27,7 @@ import a from \"a\";
a(); a();
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */ /* @flow */
\"use strict\"; \"use strict\";
import a from \"a\"; import a from \"a\";

View File

@ -107,6 +107,7 @@ function param_anno2(
// error below, since we\'re assigning elements to batchRequests // error below, since we\'re assigning elements to batchRequests
// which lack a path property. // which lack a path property.
// just assign result to new var instead of reassigning to param. // just assign result to new var instead of reassigning to param.
// Transform the requests to the format the Graph API expects. // Transform the requests to the format the Graph API expects.
batchRequests = batchRequests.map(request => { batchRequests = batchRequests.map(request => {
return { return {
@ -149,6 +150,7 @@ function foo() {
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
let myClassInstance: MyClass = null; let myClassInstance: MyClass = null;
// forward ref ok, null ~> class error // forward ref ok, null ~> class error
function bar(): MyClass { function bar(): MyClass {
return null; // forward ref ok, null ~> class error return null; // forward ref ok, null ~> class error
} }

View File

@ -107,6 +107,7 @@ function reduce_test() {
}); });
/* Added later, because the above is insufficient */ /* Added later, because the above is insufficient */
// acc is element type of array when no init is provided // acc is element type of array when no init is provided
[\"\"].reduce((acc, str) => acc * str.length); // error, string ~> number [\"\"].reduce((acc, str) => acc * str.length); // error, string ~> number
[\"\"].reduceRight((acc, str) => acc * str.length); // error, string ~> number [\"\"].reduceRight((acc, str) => acc * str.length); // error, string ~> number

View File

@ -68,6 +68,7 @@ async function f1(): Promise<boolean> {
// await: (p: Promise<T> | T) => T // await: (p: Promise<T> | T) => T
// //
async function f2(p: Promise<number>): Promise<number> { async function f2(p: Promise<number>): Promise<number> {
var x: number = await p; var x: number = await p;
var y: number = await 1; var y: number = await 1;
@ -86,10 +87,12 @@ async function f4(p: Promise<number>): Promise<boolean> {
// async arrow functions // async arrow functions
// //
var f5: () => Promise<number> = async () => await 1; var f5: () => Promise<number> = async () => await 1;
// async methods // async methods
// //
class C { class C {
async m() { async m() {
return 1; return 1;
@ -106,6 +109,7 @@ class C {
} }
// async function props // async function props
var obj = { f: async () => await 1 }; var obj = { f: async () => await 1 };
var objf: () => Promise<number> = obj.f; var objf: () => Promise<number> = obj.f;
" "
@ -322,9 +326,11 @@ function test1() {
// //
// void returns: // void returns:
// //
// inference should produce return type Promise<void> // inference should produce return type Promise<void>
// in the absence of an explicit return // in the absence of an explicit return
// //
function test2() { function test2() {
async function voidoid1() { async function voidoid1() {
console.log(\"HEY\"); console.log(\"HEY\");
@ -336,6 +342,7 @@ function test2() {
// annotated return type of Promise<void> should work // annotated return type of Promise<void> should work
// //
function test3() { function test3() {
async function voidoid4(): Promise<void> { // ok async function voidoid4(): Promise<void> { // ok
console.log(\"HEY\"); console.log(\"HEY\");
@ -346,6 +353,7 @@ function test3() {
// (note: misannotated return types with explicit // (note: misannotated return types with explicit
// return statements are covered in async.js) // return statements are covered in async.js)
// //
function test4() { function test4() {
async function voidoid5(): void { // error, void != Promise<void> async function voidoid5(): void { // error, void != Promise<void>
console.log(\"HEY\"); console.log(\"HEY\");

View File

@ -44,6 +44,7 @@ x ^= 0;
x &= 0; x &= 0;
// regression tests -- OK to assign consts like this: // regression tests -- OK to assign consts like this:
const { foo } = { foo: \"foo\" }; const { foo } = { foo: \"foo\" };
const [bar] = [\"bar\"]; const [bar] = [\"bar\"];
(foo: number); // error: string ~> number (foo: number); // error: string ~> number
@ -298,6 +299,7 @@ function type_reassign() {
} }
// class x * // class x *
function class_type() { function class_type() {
class A {} class A {}
type A = number; // error: name already bound type A = number; // error: name already bound
@ -324,6 +326,7 @@ function class_var() {
} }
// let x * // let x *
function let_type() { function let_type() {
let A = 0; let A = 0;
type A = number; // error: name already bound type A = number; // error: name already bound
@ -350,6 +353,7 @@ function let_var() {
} }
// const x * // const x *
function const_type() { function const_type() {
const A = 0; const A = 0;
type A = number; // error: name already bound type A = number; // error: name already bound
@ -381,6 +385,7 @@ function const_reassign() {
} }
// var x * // var x *
function var_type() { function var_type() {
var A = 0; var A = 0;
type A = number; // error: name already bound type A = number; // error: name already bound
@ -407,6 +412,7 @@ function var_var() {
} }
// function x * // function x *
function function_toplevel() { function function_toplevel() {
function a() {} function a() {}
function a() {} function a() {}
@ -420,6 +426,7 @@ function function_block() {
} }
// corner cases // corner cases
function var_shadow_nested_scope() { function var_shadow_nested_scope() {
{ {
let x = 0; let x = 0;
@ -439,6 +446,7 @@ function type_shadow_nested_scope() {
} }
// fn params name clash // fn params name clash
function fn_params_name_clash(x, x /* error: x already bound */) {} function fn_params_name_clash(x, x /* error: x already bound */) {}
function fn_params_clash_fn_binding(x, y) { function fn_params_clash_fn_binding(x, y) {
let x = 0; // error: x already bound let x = 0; // error: x already bound
@ -788,6 +796,7 @@ type T1 = T2; // ok
type T2 = number; type T2 = number;
// --- lets --- // --- lets ---
// to be correct, we would // to be correct, we would
// - not allow forward refs to lets from value positions, // - not allow forward refs to lets from value positions,
// while let is in TDZ. // while let is in TDZ.
@ -799,6 +808,7 @@ type T2 = number;
// a lambda runs. But a simple conservative approach would prohibit // a lambda runs. But a simple conservative approach would prohibit
// forward references to let/consts from within lambdas entirely, // forward references to let/consts from within lambdas entirely,
// which would be annoying. TODO // which would be annoying. TODO
function f0() { function f0() {
var v = x * c; // errors, let + const referenced before decl var v = x * c; // errors, let + const referenced before decl
let x = 0; let x = 0;
@ -860,15 +870,18 @@ function f5() {
// value (i.e., class or function). this is a basic flaw in our // value (i.e., class or function). this is a basic flaw in our
// phasing of AST traversal, and will be fixed. // phasing of AST traversal, and will be fixed.
// //
var x: C; // ok var x: C; // ok
var y = new C(); // error: let ref before decl from value position var y = new C(); // error: let ref before decl from value position
class C {} class C {}
var z: C = new C(); // ok var z: C = new C(); // ok
// --- vars --- // --- vars ---
// it\'s possible to annotate a var with a non-maybe type, // it\'s possible to annotate a var with a non-maybe type,
// but leave it uninitialized until later (as long as it\'s // but leave it uninitialized until later (as long as it\'s
// initialized before use) // initialized before use)
var a: number; // not an error per se - only if used before init var a: number; // not an error per se - only if used before init
function f(n: number) { function f(n: number) {
return n; return n;

View File

@ -183,6 +183,7 @@ var bar1: Bar = new Bar(); // OK
var bar2: Bar = Bar.factory(); // OK var bar2: Bar = Bar.factory(); // OK
// NB: Don\'t write expected errors using Foo to avoid error collapse hiding an // NB: Don\'t write expected errors using Foo to avoid error collapse hiding an
// unexpected failure in the above code. // unexpected failure in the above code.
var B = class Baz {}; var B = class Baz {};
var b = new Baz(); // error: Baz is not a runtime binding in this scope var b = new Baz(); // error: Baz is not a runtime binding in this scope
var C = class Qux {}; var C = class Qux {};

View File

@ -89,6 +89,7 @@ function takes_string(_: string) {}
// global write from function // global write from function
// //
var global_x = \"hello\"; var global_x = \"hello\";
function global_f() {} function global_f() {}
@ -103,6 +104,7 @@ takes_string(global_x); // error
global_x = 42; // shouldn\'t pollute linear refinement global_x = 42; // shouldn\'t pollute linear refinement
// local write from function // local write from function
// //
function local_func() { function local_func() {
var local_x = \"hello\"; var local_x = \"hello\";
@ -120,6 +122,7 @@ function local_func() {
// global write from method // global write from method
// //
var global_y = \"hello\"; var global_y = \"hello\";
var global_o = { var global_o = {
@ -136,6 +139,7 @@ takes_string(global_y); // error
global_y = 42; // shouldn\'t pollute linear refinement global_y = 42; // shouldn\'t pollute linear refinement
// local write from method // local write from method
// //
function local_meth() { function local_meth() {
var local_y = \"hello\"; var local_y = \"hello\";

View File

@ -17,6 +17,7 @@ declare module foo {
// This file triggers a violation of the \"disjoint-or-nested ranges invariant\" // This file triggers a violation of the \"disjoint-or-nested ranges invariant\"
// that we implicitly assume in type-at-pos and coverage implementations. In // that we implicitly assume in type-at-pos and coverage implementations. In
// particular, when unchecked it causes a crash with coverage --color. // particular, when unchecked it causes a crash with coverage --color.
declare module bar { declare module bar {
} }
" "
@ -65,9 +66,11 @@ declare module foo {
// This file triggers a violation of the \"disjoint-or-nested ranges invariant\" // This file triggers a violation of the \"disjoint-or-nested ranges invariant\"
// that we implicitly assume in type-at-pos and coverage implementations. In // that we implicitly assume in type-at-pos and coverage implementations. In
// particular, when unchecked it causes non-termination with coverage --color. // particular, when unchecked it causes non-termination with coverage --color.
declare module bar { declare module bar {
} }
// TODO // TODO
declare class qux {} declare class qux {}
" "
`; `;

View File

@ -23,6 +23,7 @@ module.exports = B;
var A = require(\"./A\"); var A = require(\"./A\");
//class B extends A { } //class B extends A { }
module.exports = B; module.exports = B;
" "
`; `;

View File

@ -900,6 +900,7 @@ import DefaultD from \"./D\"; // Error: No such module
// ================================================ // // ================================================ //
// == CommonJS Clobbering Literal Exports -> ES6 == // // == CommonJS Clobbering Literal Exports -> ES6 == //
// ================================================ // // ================================================ //
import { doesntExist1 } from \"CommonJS_Clobbering_Lit\"; // Error: Not an exported binding import { doesntExist1 } from \"CommonJS_Clobbering_Lit\"; // Error: Not an exported binding
import { numberValue1 } from \"CommonJS_Clobbering_Lit\"; import { numberValue1 } from \"CommonJS_Clobbering_Lit\";
var c1: number = numberValue1; var c1: number = numberValue1;
@ -920,6 +921,7 @@ var f4: string = CJS_Clobb_Lit_NS.default.numberValue5; // Error: number ~> stri
// ============================================== // // ============================================== //
// == CommonJS Clobbering Class Exports -> ES6 == // // == CommonJS Clobbering Class Exports -> ES6 == //
// ============================================== // // ============================================== //
import { doesntExist2 } from \"CommonJS_Clobbering_Class\"; // Error: Not an exported binding import { doesntExist2 } from \"CommonJS_Clobbering_Class\"; // Error: Not an exported binding
// The following import should error because class statics are not turned into // The following import should error because class statics are not turned into
// named exports for now. This avoids complexities with polymorphic static // named exports for now. This avoids complexities with polymorphic static
@ -941,6 +943,7 @@ var i3: string = new CJS_Clobb_Class_NS.default().instNumber2(); // Error: numbe
// =================================== // // =================================== //
// == CommonJS Named Exports -> ES6 == // // == CommonJS Named Exports -> ES6 == //
// =================================== // // =================================== //
import { doesntExist3 } from \"CommonJS_Named\"; // Error: Not an exported binding import { doesntExist3 } from \"CommonJS_Named\"; // Error: Not an exported binding
import { numberValue2 } from \"CommonJS_Named\"; import { numberValue2 } from \"CommonJS_Named\";
var j1: number = numberValue2; var j1: number = numberValue2;
@ -959,6 +962,7 @@ var m3: string = CJS_Named_NS.numberValue4; // Error: number ~> string
////////////////////////////// //////////////////////////////
// == ES6 Default -> ES6 == // // == ES6 Default -> ES6 == //
////////////////////////////// //////////////////////////////
import { doesntExist4 } from \"ES6_Default_AnonFunction1\"; // Error: Not an exported binding import { doesntExist4 } from \"ES6_Default_AnonFunction1\"; // Error: Not an exported binding
import ES6_Def_AnonFunc1 from \"ES6_Default_AnonFunction1\"; import ES6_Def_AnonFunc1 from \"ES6_Default_AnonFunction1\";
var n1: number = ES6_Def_AnonFunc1(); var n1: number = ES6_Def_AnonFunc1();
@ -972,6 +976,7 @@ var q2: string = new ES6_Def_NamedClass1().givesANum(); // Error: number ~> stri
//////////////////////////// ////////////////////////////
// == ES6 Named -> ES6 == // // == ES6 Named -> ES6 == //
//////////////////////////// ////////////////////////////
import doesntExist5 from \"ES6_Named1\"; // Error: Not an exported binding import doesntExist5 from \"ES6_Named1\"; // Error: Not an exported binding
import { specifierNumber1 as specifierNumber1_1 } from \"ES6_Named1\"; import { specifierNumber1 as specifierNumber1_1 } from \"ES6_Named1\";
var r1: number = specifierNumber1_1; var r1: number = specifierNumber1_1;
@ -1010,6 +1015,7 @@ var ac2: string = numberValue5; // Error: number ~> string
/////////////////////////////////// ///////////////////////////////////
// == ES6 Default -> CommonJS == // // == ES6 Default -> CommonJS == //
/////////////////////////////////// ///////////////////////////////////
require(\"ES6_Default_AnonFunction2\").doesntExist; // Error: \'doesntExist\' isn\'t an export require(\"ES6_Default_AnonFunction2\").doesntExist; // Error: \'doesntExist\' isn\'t an export
var ES6_Def_AnonFunc2 = require(\"ES6_Default_AnonFunction2\").default; var ES6_Def_AnonFunc2 = require(\"ES6_Default_AnonFunction2\").default;
var ad1: number = ES6_Def_AnonFunc2(); var ad1: number = ES6_Def_AnonFunc2();
@ -1023,6 +1029,7 @@ var ag2: string = new ES6_Def_NamedClass2().givesANum(); // Error: number ~> str
///////////////////////////////// /////////////////////////////////
// == ES6 Named -> CommonJS == // // == ES6 Named -> CommonJS == //
///////////////////////////////// /////////////////////////////////
var specifierNumber4 = require(\"ES6_Named2\").specifierNumber4; var specifierNumber4 = require(\"ES6_Named2\").specifierNumber4;
var ah1: number = specifierNumber4; var ah1: number = specifierNumber4;
var ah2: string = specifierNumber4; // Error: number ~> string var ah2: string = specifierNumber4; // Error: number ~> string
@ -1061,6 +1068,7 @@ var ar2: string = numberValue7; // Error: number ~> string
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
// == ES6 Default+Named -> ES6 import Default+Named== // // == ES6 Default+Named -> ES6 import Default+Named== //
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
import defaultNum, { str as namedStr } from \"./ES6_DefaultAndNamed\"; import defaultNum, { str as namedStr } from \"./ES6_DefaultAndNamed\";
var as1: number = defaultNum; var as1: number = defaultNum;
@ -1070,6 +1078,7 @@ var as4: number = namedStr; // Error: string ~> number
//////////////////////////////////////// ////////////////////////////////////////
// == Side-effect only ES6 imports == // // == Side-effect only ES6 imports == //
//////////////////////////////////////// ////////////////////////////////////////
import \"./SideEffects\"; import \"./SideEffects\";
////////////////////////////////////////////// //////////////////////////////////////////////

View File

@ -40,6 +40,7 @@ import type { str2 } from \"declare_m_e_with_other_type_declares\";
* \`declare var exports\` is deprecated, so we have a grace period where both * \`declare var exports\` is deprecated, so we have a grace period where both
* syntaxes will work. * syntaxes will work.
*/ */
import DEPRECATED__declare_var_exports from \"DEPRECATED__declare_var_exports\"; import DEPRECATED__declare_var_exports from \"DEPRECATED__declare_var_exports\";
(DEPRECATED__declare_var_exports: number); (DEPRECATED__declare_var_exports: number);
(DEPRECATED__declare_var_exports: string); // Error: number ~> string (DEPRECATED__declare_var_exports: string); // Error: number ~> string

View File

@ -45,6 +45,7 @@ declare module \"declare_m_e_with_other_type_declares\" {
* \`declare var exports\` is deprecated, so we have a grace period where both * \`declare var exports\` is deprecated, so we have a grace period where both
* syntaxes will work. * syntaxes will work.
*/ */
declare module \"DEPRECATED__declare_var_exports\" { declare module \"DEPRECATED__declare_var_exports\" {
declare var exports: number; declare var exports: number;
/** /**

View File

@ -47,6 +47,7 @@ var k4: toz = foo(k1); // works
////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////
// == Declared Module with exports prop (issue 880) == // // == Declared Module with exports prop (issue 880) == //
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
import blah from \"foo\"; import blah from \"foo\";
import type { Foo, Bar, Id } from \"foo\"; import type { Foo, Bar, Id } from \"foo\";

View File

@ -16,6 +16,7 @@ function f(x) {
var x = null; var x = null;
//... //...
f(x); f(x);
" "
`; `;

View File

@ -505,6 +505,7 @@ foo = (i: number) => {
}; };
// Also make sure that the following doesn\'t loop // Also make sure that the following doesn\'t loop
declare var o; declare var o;
var { x: o } = o; var { x: o } = o;
" "

View File

@ -75,6 +75,7 @@ exports[`test use_strict_with_flow.js 1`] = `
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\"use strict\"; \"use strict\";
/* @flow */ /* @flow */
(\"\": void); // error (\"\": void); // error
" "
`; `;

View File

@ -1003,6 +1003,7 @@ import DefaultD from \"./D\"; // Error: No such module
// ================================================ // // ================================================ //
// == CommonJS Clobbering Literal Exports -> ES6 == // // == CommonJS Clobbering Literal Exports -> ES6 == //
// ================================================ // // ================================================ //
import { doesntExist1 } from \"CommonJS_Clobbering_Lit\"; // Error: Not an exported binding import { doesntExist1 } from \"CommonJS_Clobbering_Lit\"; // Error: Not an exported binding
import { numberValue1 } from \"CommonJS_Clobbering_Lit\"; import { numberValue1 } from \"CommonJS_Clobbering_Lit\";
var c1: number = numberValue1; var c1: number = numberValue1;
@ -1023,6 +1024,7 @@ var f4: string = CJS_Clobb_Lit_NS.default.numberValue5; // Error: number ~> stri
// ============================================== // // ============================================== //
// == CommonJS Clobbering Class Exports -> ES6 == // // == CommonJS Clobbering Class Exports -> ES6 == //
// ============================================== // // ============================================== //
import { doesntExist2 } from \"CommonJS_Clobbering_Class\"; // Error: Not an exported binding import { doesntExist2 } from \"CommonJS_Clobbering_Class\"; // Error: Not an exported binding
// The following import should error because class statics are not turned into // The following import should error because class statics are not turned into
// named exports for now. This avoids complexities with polymorphic static // named exports for now. This avoids complexities with polymorphic static
@ -1044,6 +1046,7 @@ var i3: string = new CJS_Clobb_Class_NS.default().instNumber2(); // Error: numbe
// =================================== // // =================================== //
// == CommonJS Named Exports -> ES6 == // // == CommonJS Named Exports -> ES6 == //
// =================================== // // =================================== //
import { doesntExist3 } from \"CommonJS_Named\"; // Error: Not an exported binding import { doesntExist3 } from \"CommonJS_Named\"; // Error: Not an exported binding
import { numberValue2 } from \"CommonJS_Named\"; import { numberValue2 } from \"CommonJS_Named\";
var j1: number = numberValue2; var j1: number = numberValue2;
@ -1062,6 +1065,7 @@ var m3: string = CJS_Named_NS.numberValue4; // Error: number ~> string
////////////////////////////// //////////////////////////////
// == ES6 Default -> ES6 == // // == ES6 Default -> ES6 == //
////////////////////////////// //////////////////////////////
import { doesntExist4 } from \"ES6_Default_AnonFunction1\"; // Error: Not an exported binding import { doesntExist4 } from \"ES6_Default_AnonFunction1\"; // Error: Not an exported binding
import ES6_Def_AnonFunc1 from \"ES6_Default_AnonFunction1\"; import ES6_Def_AnonFunc1 from \"ES6_Default_AnonFunction1\";
var n1: number = ES6_Def_AnonFunc1(); var n1: number = ES6_Def_AnonFunc1();
@ -1078,6 +1082,7 @@ var q2: string = new ES6_Def_NamedClass1().givesANum(); // Error: number ~> stri
//////////////////////////// ////////////////////////////
// == ES6 Named -> ES6 == // // == ES6 Named -> ES6 == //
//////////////////////////// ////////////////////////////
import doesntExist5 from \"ES6_Named1\"; // Error: Not an exported binding import doesntExist5 from \"ES6_Named1\"; // Error: Not an exported binding
import { specifierNumber1 as specifierNumber1_1 } from \"ES6_Named1\"; import { specifierNumber1 as specifierNumber1_1 } from \"ES6_Named1\";
var r1: number = specifierNumber1_1; var r1: number = specifierNumber1_1;
@ -1122,6 +1127,7 @@ var ac2: string = numberValue5; // Error: number ~> string
/////////////////////////////////// ///////////////////////////////////
// == ES6 Default -> CommonJS == // // == ES6 Default -> CommonJS == //
/////////////////////////////////// ///////////////////////////////////
require(\"ES6_Default_AnonFunction2\").doesntExist; // Error: \'doesntExist\' isn\'t an export require(\"ES6_Default_AnonFunction2\").doesntExist; // Error: \'doesntExist\' isn\'t an export
var ES6_Def_AnonFunc2 = require(\"ES6_Default_AnonFunction2\").default; var ES6_Def_AnonFunc2 = require(\"ES6_Default_AnonFunction2\").default;
var ad1: number = ES6_Def_AnonFunc2(); var ad1: number = ES6_Def_AnonFunc2();
@ -1138,6 +1144,7 @@ var ag2: string = new ES6_Def_NamedClass2().givesANum(); // Error: number ~> str
///////////////////////////////// /////////////////////////////////
// == ES6 Named -> CommonJS == // // == ES6 Named -> CommonJS == //
///////////////////////////////// /////////////////////////////////
var specifierNumber4 = require(\"ES6_Named2\").specifierNumber4; var specifierNumber4 = require(\"ES6_Named2\").specifierNumber4;
var ah1: number = specifierNumber4; var ah1: number = specifierNumber4;
var ah2: string = specifierNumber4; // Error: number ~> string var ah2: string = specifierNumber4; // Error: number ~> string
@ -1182,6 +1189,7 @@ var ar2: string = numberValue7; // Error: number ~> string
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
// == ES6 Default+Named -> ES6 import Default+Named== // // == ES6 Default+Named -> ES6 import Default+Named== //
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
import defaultNum, { str as namedStr } from \"./ES6_DefaultAndNamed\"; import defaultNum, { str as namedStr } from \"./ES6_DefaultAndNamed\";
var as1: number = defaultNum; var as1: number = defaultNum;
@ -1191,6 +1199,7 @@ var as4: number = namedStr; // Error: string ~> number
//////////////////////////////////////// ////////////////////////////////////////
// == Side-effect only ES6 imports == // // == Side-effect only ES6 imports == //
//////////////////////////////////////// ////////////////////////////////////////
import \"./SideEffects\"; import \"./SideEffects\";
////////////////////////////////////////////// //////////////////////////////////////////////
@ -1298,6 +1307,7 @@ CommonJS_Clobbering_Frozen.numberValue1 = 123; // Error: exports are frozen
// //
// Requires // Requires
// //
function testRequires() { function testRequires() {
// CommonJS module // CommonJS module
var DefaultA = require(\"A\"); var DefaultA = require(\"A\");

View File

@ -275,6 +275,7 @@ new ClassFoo1(); // Error: ClassFoo1 is not a value-identifier
/////////////////////////////////////////////// ///////////////////////////////////////////////
// == Importing Class Type (Named Export) == // // == Importing Class Type (Named Export) == //
/////////////////////////////////////////////// ///////////////////////////////////////////////
import type { ClassFoo2 } from \"./ExportNamed_Class\"; import type { ClassFoo2 } from \"./ExportNamed_Class\";
import { foo2Inst } from \"./ExportNamed_Class\"; import { foo2Inst } from \"./ExportNamed_Class\";
@ -284,6 +285,7 @@ new ClassFoo2(); // Error: ClassFoo2 is not a value-identifier
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
// == Importing Class Type (CJS Default Export) == // // == Importing Class Type (CJS Default Export) == //
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
import type ClassFoo3T from \"./ExportCJSDefault_Class\"; import type ClassFoo3T from \"./ExportCJSDefault_Class\";
import ClassFoo3 from \"./ExportCJSDefault_Class\"; import ClassFoo3 from \"./ExportCJSDefault_Class\";
var c1: ClassFoo3T = new ClassFoo3(); var c1: ClassFoo3T = new ClassFoo3();
@ -291,6 +293,7 @@ new ClassFoo3T(); // Error: ClassFoo3 is not a value-identifier
/////////////////////////////////////////////////// ///////////////////////////////////////////////////
// == Importing Class Type (CJS Named Export) == // // == Importing Class Type (CJS Named Export) == //
/////////////////////////////////////////////////// ///////////////////////////////////////////////////
import type { ClassFoo4, ClassFoo5 } from \"./ExportCJSNamed_Class\"; import type { ClassFoo4, ClassFoo5 } from \"./ExportCJSNamed_Class\";
import { foo4Inst, foo5Inst } from \"./ExportCJSNamed_Class\"; import { foo4Inst, foo5Inst } from \"./ExportCJSNamed_Class\";
@ -302,6 +305,7 @@ var d3: typeof ClassFoo5 = foo5Inst; // Error: Can\'t typeof a type alias
//////////////////////////////////////////// ////////////////////////////////////////////
// == Import Type Alias (Named Export) == // // == Import Type Alias (Named Export) == //
//////////////////////////////////////////// ////////////////////////////////////////////
import type { AliasFoo3 } from \"./ExportNamed_Alias\"; import type { AliasFoo3 } from \"./ExportNamed_Alias\";
import { givesAFoo3Obj } from \"./ExportNamed_Alias\"; import { givesAFoo3Obj } from \"./ExportNamed_Alias\";
var e1: AliasFoo3 = givesAFoo3Obj(); var e1: AliasFoo3 = givesAFoo3Obj();
@ -310,18 +314,22 @@ var e3: typeof AliasFoo3 = givesAFoo3Obj(); // Error: Can\'t typeof a type alias
////////////////////////////////////////////// //////////////////////////////////////////////
// == Import Type Alias (Default Export) == // // == Import Type Alias (Default Export) == //
////////////////////////////////////////////// //////////////////////////////////////////////
// TODO: No support for this right now. It\'s most likely possible, but it\'s // TODO: No support for this right now. It\'s most likely possible, but it\'s
// unclear how useful it is at the moment and it entails a little // unclear how useful it is at the moment and it entails a little
// more work than named type exports, so I\'m punting on it for now. // more work than named type exports, so I\'m punting on it for now.
/////////////////////////////////////////////////////// ///////////////////////////////////////////////////////
// == Import Type With Non-Alias Compatible Value == // // == Import Type With Non-Alias Compatible Value == //
/////////////////////////////////////////////////////// ///////////////////////////////////////////////////////
import type { numValue } from \"./ExportsANumber\"; // Error: Cannot import-type a number value import type { numValue } from \"./ExportsANumber\"; // Error: Cannot import-type a number value
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// == Regression Test: https://github.com/facebook/flow/issues/359 == // // == Regression Test: https://github.com/facebook/flow/issues/359 == //
// Ensure that type bindings stay type bindings across function body // // Ensure that type bindings stay type bindings across function body //
// env contexts. // // env contexts. //
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
import type ClassFoo6 from \"./issue-359\"; import type ClassFoo6 from \"./issue-359\";
function foo() { function foo() {
ClassFoo6; // Error: Not a value binding ClassFoo6; // Error: Not a value binding

View File

@ -306,6 +306,7 @@ new ClassFoo1T(); // Error: ClassFoo1T is not bound to a value
///////////////////////////////////////////////// /////////////////////////////////////////////////
// == Importing Class Typeof (Named Export) == // // == Importing Class Typeof (Named Export) == //
///////////////////////////////////////////////// /////////////////////////////////////////////////
import typeof { ClassFoo2 as ClassFoo2T } from \"./ExportNamed_Class\"; import typeof { ClassFoo2 as ClassFoo2T } from \"./ExportNamed_Class\";
import { ClassFoo2 } from \"./ExportNamed_Class\"; import { ClassFoo2 } from \"./ExportNamed_Class\";
@ -315,6 +316,7 @@ new ClassFoo2T(); // Error: ClassFoo2T is not bound to a value
/////////////////////////////////////////////////////// ///////////////////////////////////////////////////////
// == Importing Class Typeof (CJS Default Export) == // // == Importing Class Typeof (CJS Default Export) == //
/////////////////////////////////////////////////////// ///////////////////////////////////////////////////////
import typeof ClassFoo3T from \"./ExportCJSDefault_Class\"; import typeof ClassFoo3T from \"./ExportCJSDefault_Class\";
import ClassFoo3 from \"./ExportCJSDefault_Class\"; import ClassFoo3 from \"./ExportCJSDefault_Class\";
@ -323,6 +325,7 @@ var c2: ClassFoo3T = new ClassFoo3(); // Error: ClassFoo3 (inst) ~> ClassFoo3 (c
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
// == Importing Class Typeof (CJS Named Export) == // // == Importing Class Typeof (CJS Named Export) == //
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
import typeof { ClassFoo4 as ClassFoo4T } from \"./ExportCJSNamed_Class\"; import typeof { ClassFoo4 as ClassFoo4T } from \"./ExportCJSNamed_Class\";
import { ClassFoo4 } from \"./ExportCJSNamed_Class\"; import { ClassFoo4 } from \"./ExportCJSNamed_Class\";
@ -331,16 +334,20 @@ var d2: ClassFoo4T = new ClassFoo4(); // Error: ClassFoo4 (inst) ~> ClassFoo4 (c
////////////////////////////////////////////// //////////////////////////////////////////////
// == Import Typeof Alias (Named Export) == // // == Import Typeof Alias (Named Export) == //
////////////////////////////////////////////// //////////////////////////////////////////////
import typeof { AliasFoo3 } from \"./ExportNamed_Alias\"; // Error: Can\'t \`import typeof\` type aliases! import typeof { AliasFoo3 } from \"./ExportNamed_Alias\"; // Error: Can\'t \`import typeof\` type aliases!
//////////////////////////////////////////////// ////////////////////////////////////////////////
// == Import Typeof Alias (Default Export) == // // == Import Typeof Alias (Default Export) == //
//////////////////////////////////////////////// ////////////////////////////////////////////////
// TODO: No support for this right now. It\'s most likely possible, but it\'s // TODO: No support for this right now. It\'s most likely possible, but it\'s
// unclear how useful it is at the moment and it entails a little // unclear how useful it is at the moment and it entails a little
// more work than named type exports, so I\'m punting on it for now. // more work than named type exports, so I\'m punting on it for now.
/////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////
// == Import Typeof With Non-Class Value (Default Export) == // // == Import Typeof With Non-Class Value (Default Export) == //
/////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////
import typeof num_default from \"./ExportDefault_Number\"; import typeof num_default from \"./ExportDefault_Number\";
var f1: num_default = 42; var f1: num_default = 42;
@ -348,6 +355,7 @@ var f2: num_default = \"asdf\"; // Error: string ~> number
///////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////
// == Import Typeof With Non-Class Value (Named Export) == // // == Import Typeof With Non-Class Value (Named Export) == //
///////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////
import typeof { num as num_named } from \"./ExportNamed_Number\"; import typeof { num as num_named } from \"./ExportNamed_Number\";
var g1: num_named = 42; var g1: num_named = 42;
@ -355,6 +363,7 @@ var g2: num_named = \"asdf\"; // Error: string ~> number
/////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////
// == Import Typeof With Non-Class Value (CJS Default Export) == // // == Import Typeof With Non-Class Value (CJS Default Export) == //
/////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////
import typeof num_cjs_default from \"./ExportCJSDefault_Number\"; import typeof num_cjs_default from \"./ExportCJSDefault_Number\";
var h1: num_cjs_default = 42; var h1: num_cjs_default = 42;
@ -362,6 +371,7 @@ var h2: num_cjs_default = \"asdf\"; // Error: string ~> number
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
// == Import Typeof With Non-Class Value (CJS Named Export) == // // == Import Typeof With Non-Class Value (CJS Named Export) == //
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
import typeof { num as num_cjs_named } from \"./ExportCJSNamed_Number\"; import typeof { num as num_cjs_named } from \"./ExportCJSNamed_Number\";
var i1: num_cjs_named = 42; var i1: num_cjs_named = 42;
@ -369,6 +379,7 @@ var i2: num_cjs_named = \"asdf\"; // Error: string ~> number
/////////////////////////////////////////////// ///////////////////////////////////////////////
// == Import Typeof ModuleNamespaceObject == // // == Import Typeof ModuleNamespaceObject == //
/////////////////////////////////////////////// ///////////////////////////////////////////////
import typeof * as ModuleNSObjT from \"./ExportNamed_Multi\"; import typeof * as ModuleNSObjT from \"./ExportNamed_Multi\";
var j1: ModuleNSObjT = { num: 42, str: \"asdf\" }; var j1: ModuleNSObjT = { num: 42, str: \"asdf\" };
var j2: ModuleNSObjT = { num: 42, str: 42 }; // Error: number ~> string var j2: ModuleNSObjT = { num: 42, str: 42 }; // Error: number ~> string

View File

@ -8,6 +8,7 @@ export type B = string;
// @flow // @flow
var A = require(\"./A\"); var A = require(\"./A\");
//import type C from \'./C\'; //import type C from \'./C\';
export type B = string; export type B = string;
" "
`; `;

View File

@ -94,6 +94,7 @@ var k: K = { x: \"\", y: \"\" }; // error: x should be number
declare class C { x: number } declare class C { x: number }
declare class D extends C, Other {} // error: multiple extends declare class D extends C, Other {} // error: multiple extends
//declare class E implements I { } // parse error //declare class E implements I { } // parse error
interface A<Y> { y: Y } interface A<Y> { y: Y }
interface A_<X> { x: X } interface A_<X> { x: X }
interface B<Z> extends A<string>, A_<Z> { z: Z } interface B<Z> extends A<string>, A_<Z> { z: Z }

View File

@ -69,6 +69,7 @@ React.createElement(\'bad\', {}); // This is fine
var React = require(\"react\"); var React = require(\"react\");
// The builtin $JSXIntrinsics should allow any string // The builtin $JSXIntrinsics should allow any string
var Div = \"div\"; var Div = \"div\";
var Bad = \"bad\"; var Bad = \"bad\";
var Str: string = \"str\"; var Str: string = \"str\";

View File

@ -65,11 +65,13 @@ class C {
} }
// check // check
(new C().foo(): boolean); // last wins (new C().foo(): boolean); // last wins
(new C().x: boolean); // last wins (new C().x: boolean); // last wins
(new C().bar: boolean); // last wins (new C().bar: boolean); // last wins
(new C().qux: boolean); // weird outlier where last doesn\'t win in classes (new C().qux: boolean); // weird outlier where last doesn\'t win in classes
// Objects // Objects
const o = { const o = {
foo(): number { foo(): number {
return 0; return 0;
@ -90,6 +92,7 @@ const o = {
}; };
// check // check
(o.foo(): boolean); // last wins (o.foo(): boolean); // last wins
(o.x: boolean); // last wins (o.x: boolean); // last wins
(o.bar: boolean); // last wins (o.bar: boolean); // last wins

View File

@ -37,6 +37,7 @@ var red:string = tuple[indices.red]; // error: tuple[0] is a number
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
var APIKeys = require(\"./enum\"); var APIKeys = require(\"./enum\");
// object that maps \"AGE\" to \"age\", \"NAME\" to \"name\" // object that maps \"AGE\" to \"age\", \"NAME\" to \"name\"
function foo(x: $Keys<typeof APIKeys>) {} function foo(x: $Keys<typeof APIKeys>) {}
foo(\"AGE\"); foo(\"AGE\");
foo(\"LOCATION\"); // error foo(\"LOCATION\"); // error

View File

@ -152,6 +152,7 @@ var x: string = 0;
var x: number = 1; var x: number = 1;
//declare var T: $Type<number | Array<T>>; //declare var T: $Type<number | Array<T>>;
function foo(p: boolean) {} function foo(p: boolean) {}
function sorry(really: boolean) { function sorry(really: boolean) {

View File

@ -27,6 +27,7 @@ var o3 = {};
o3.w = o2; o3.w = o2;
//declare var exports: { w: any }; //declare var exports: { w: any };
module.exports = o3; module.exports = o3;
" "
`; `;

View File

@ -55,6 +55,7 @@ function foo5<T>(): Array<T> {
var b = foo5(); var b = foo5();
var y: string = b[0]; var y: string = b[0];
*/ */
var foo6 = function<R>(x: R): R { var foo6 = function<R>(x: R): R {
return foo1(x); return foo1(x);
}; };

View File

@ -80,6 +80,7 @@ if (y instanceof A) {
y = 0; y = 0;
} }
//f(y); //f(y);
function bar() { function bar() {
return true; return true;
} }

View File

@ -90,6 +90,7 @@ var App = React.createClass({
var z = this.state.z; var z = this.state.z;
//this.state; //this.state;
return ( return (
<div> <div>
{foo(x, y)} {foo(x, y)}

View File

@ -392,6 +392,7 @@ import React from \"react\";
//import React from \"React\"; //import React from \"React\";
//var React = require(\"react\"); //var React = require(\"react\");
//var React = require(\"React\"); //var React = require(\"React\");
class HelloMessage extends React.Component { class HelloMessage extends React.Component {
props: { name: string }; props: { name: string };
} }

View File

@ -36,6 +36,7 @@ fs.readFile(\"file.exp\", {}, (_, data) => {
var fs = require(\"fs\"); var fs = require(\"fs\");
/* readFile */ /* readFile */
fs.readFile(\"file.exp\", (_, data) => { fs.readFile(\"file.exp\", (_, data) => {
(data: Buffer); (data: Buffer);
}); });
@ -53,6 +54,7 @@ fs.readFile(\"file.exp\", {}, (_, data) => {
}); });
/* readFileSync */ /* readFileSync */
(fs.readFileSync(\"file.exp\"): Buffer); (fs.readFileSync(\"file.exp\"): Buffer);
(fs.readFileSync(\"file.exp\"): string); // error (fs.readFileSync(\"file.exp\"): string); // error
(fs.readFileSync(\"file.exp\", \"blah\"): string); (fs.readFileSync(\"file.exp\", \"blah\"): string);

View File

@ -412,6 +412,7 @@ var y = new Foo();
// //
// toString // toString
// //
// call // call
takesAString(a.toString()); takesAString(a.toString());
d.toString(); // ok, even though dict specifies strings, this is a function d.toString(); // ok, even though dict specifies strings, this is a function
@ -450,6 +451,7 @@ takesAString(y.toString());
// //
// hasOwnProperty // hasOwnProperty
// //
// call // call
takesABool(a.hasOwnProperty(\"foo\")); takesABool(a.hasOwnProperty(\"foo\"));
@ -475,6 +477,7 @@ takesABool(y.hasOwnProperty(\"foo\"));
// //
// propertyIsEnumerable // propertyIsEnumerable
// //
// call // call
takesABool(a.propertyIsEnumerable(\"foo\")); takesABool(a.propertyIsEnumerable(\"foo\"));
@ -500,6 +503,7 @@ takesABool(y.propertyIsEnumerable(\"foo\"));
// //
// valueOf // valueOf
// //
// call // call
takesAnObject(a.valueOf()); takesAnObject(a.valueOf());
@ -529,6 +533,7 @@ var boolValueOf: boolean = true.valueOf();
// //
// toLocaleString // toLocaleString
// //
// call // call
takesAString(a.toLocaleString()); takesAString(a.toLocaleString());
@ -554,6 +559,7 @@ takesAString(y.toLocaleString());
// //
// constructor // constructor
// //
var k: Object = a.constructor; var k: Object = a.constructor;
(123).constructor; (123).constructor;
" "

View File

@ -136,6 +136,7 @@ function is_string_and_number(x, y): %checks {
declare function refine<T, P: $Pred<1>>(v: T, cb: P): $Refine<T, P, 1>; declare function refine<T, P: $Pred<1>>(v: T, cb: P): $Refine<T, P, 1>;
// function refine(v, cb) // function refine(v, cb)
// { if (cb(v)) { return v; } else { throw new Error(); } } // { if (cb(v)) { return v; } else { throw new Error(); } }
/* /*
Use case Use case
*/ */
@ -150,6 +151,7 @@ declare function refine_fst<T, P: $Pred<2>>(
): $Refine<T, P, 1>; ): $Refine<T, P, 1>;
// function refine_fst(v, w, cb) // function refine_fst(v, w, cb)
// { if (cb(v, w)) { return v; } else { throw new Error(); } } // { if (cb(v, w)) { return v; } else { throw new Error(); } }
declare var c: mixed; declare var c: mixed;
declare var d: mixed; declare var d: mixed;
@ -160,6 +162,7 @@ declare function refine2<T, P: $Pred<2>>(v: T, w: T, cb: P): $Refine<T, P, 1>;
// function refine_fst(v, w, cb) // function refine_fst(v, w, cb)
// { if (cb(v, w)) { return w; } else { throw new Error(); } } // { if (cb(v, w)) { return w; } else { throw new Error(); } }
function is_string(x): boolean %checks { function is_string(x): boolean %checks {
return typeof x === \"string\"; return typeof x === \"string\";
} }
@ -343,6 +346,7 @@ var e = refine(a, is_string_regular); // ERROR: is_string_regular is not a
(e: number); (e: number);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
function is_string(x): %checks { function is_string(x): %checks {
return typeof x === \"string\"; return typeof x === \"string\";
} }

View File

@ -388,6 +388,7 @@ declare function is_number(x: mixed): boolean %checks(typeof x === \"number\");
// Sanity check: // Sanity check:
// - Erroneous logic // - Erroneous logic
function bar(x: string | Array<string>): string { function bar(x: string | Array<string>): string {
if (is_number(x)) { if (is_number(x)) {
return x; return x;

View File

@ -412,6 +412,7 @@ new Promise(function(resolve, reject) {
///////////////////////////////////////////////// /////////////////////////////////////////////////
// == Promise constructor reject() function == // // == Promise constructor reject() function == //
///////////////////////////////////////////////// /////////////////////////////////////////////////
// TODO: Promise constructor reject(T) -> catch(T) // TODO: Promise constructor reject(T) -> catch(T)
new Promise(function(resolve, reject) { new Promise(function(resolve, reject) {
reject(0); reject(0);
@ -455,6 +456,7 @@ new Promise(function(resolve, reject) {
///////////////////////////// /////////////////////////////
// == Promise.resolve() == // // == Promise.resolve() == //
///////////////////////////// /////////////////////////////
// Promise.resolve(T) -> then(T) // Promise.resolve(T) -> then(T)
Promise.resolve(0).then(function(num) { Promise.resolve(0).then(function(num) {
var a: number = num; var a: number = num;
@ -476,6 +478,7 @@ Promise.resolve(Promise.resolve(Promise.resolve(0))).then(function(num) {
//////////////////////////// ////////////////////////////
// == Promise.reject() == // // == Promise.reject() == //
//////////////////////////// ////////////////////////////
// TODO: Promise.reject(T) -> catch(T) // TODO: Promise.reject(T) -> catch(T)
Promise.reject(0).catch(function(num) { Promise.reject(0).catch(function(num) {
var a: number = num; var a: number = num;
@ -495,6 +498,7 @@ Promise.reject(Promise.resolve(0)).then(function(num) {
////////////////////////////////// //////////////////////////////////
// == Promise.prototype.then == // // == Promise.prototype.then == //
////////////////////////////////// //////////////////////////////////
// resolvedPromise.then():T -> then(T) // resolvedPromise.then():T -> then(T)
Promise Promise
.resolve(0) .resolve(0)
@ -544,6 +548,7 @@ Promise
/////////////////////////////////// ///////////////////////////////////
// == Promise.prototype.catch == // // == Promise.prototype.catch == //
/////////////////////////////////// ///////////////////////////////////
// rejectedPromise.catch():U -> then(U) // rejectedPromise.catch():U -> then(U)
Promise Promise
.reject(0) .reject(0)

View File

@ -93,12 +93,14 @@ class P<X> {
x: X; x: X;
} }
// this is like Promise // this is like Promise
type Pstar<X> = X | Pstar<P<X>>; // this is like Promise* type Pstar<X> = X | Pstar<P<X>>; // this is like Promise*
var p: P<number> = new P(); var p: P<number> = new P();
(p.x: string); // error (p.x: string); // error
var pstar: Pstar<number> = 0; // OK var pstar: Pstar<number> = 0; // OK
(pstar: number); // error, but limit potentially unbounded number of errors! (pstar: number); // error, but limit potentially unbounded number of errors!
// e.g., P<number> ~/~ number, P<P<number>> ~/~ number, ... // e.g., P<number> ~/~ number, P<P<number>> ~/~ number, ...
pstar = p; // OK pstar = p; // OK
(pstar.x: string); // error (pstar.x: string); // error
pstar = (new P(): P<P<number>>); // OK pstar = (new P(): P<P<number>>); // OK

View File

@ -543,6 +543,7 @@ var tests = [
// the scope that gets merged after the if statement is the correct // the scope that gets merged after the if statement is the correct
// post-condition scope, not the one that was saved at the beginning of the // post-condition scope, not the one that was saved at the beginning of the
// if statement. // if statement.
function() { function() {
let x: { foo: ?string } = { foo: null }; let x: { foo: ?string } = { foo: null };
if (!x.foo) { if (!x.foo) {
@ -1193,6 +1194,7 @@ function foo(a, b, c) {
} }
// test refis out of switches that are exhaustive without default case // test refis out of switches that are exhaustive without default case
function exhaustion1(x): number { function exhaustion1(x): number {
var foo; var foo;
switch (x) { switch (x) {
@ -1574,6 +1576,7 @@ class A {
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
var undef_tests = [ var undef_tests = [
// NOTE: not (yet?) supporting non-strict eq test for undefined // NOTE: not (yet?) supporting non-strict eq test for undefined
// expr !== undefined // expr !== undefined
function() { function() {
var x: ?string = \"xxx\"; var x: ?string = \"xxx\";
@ -1718,6 +1721,7 @@ class A {
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
var void_tests = [ var void_tests = [
// NOTE: not (yet?) supporting non-strict eq test for undefined // NOTE: not (yet?) supporting non-strict eq test for undefined
// expr !== void(...) // expr !== void(...)
function() { function() {
var x: ?string = \"xxx\"; var x: ?string = \"xxx\";

View File

@ -668,6 +668,7 @@ function def_assign_within_for(b: boolean, obj: Obj) {
} }
// --- name-sensitive havoc --- // --- name-sensitive havoc ---
type Obj2 = { q: number | string }; type Obj2 = { q: number | string };
function def_assign_setprop_nohavoc(obj: Obj, obj2: Obj2) { function def_assign_setprop_nohavoc(obj: Obj, obj2: Obj2) {
@ -1582,6 +1583,7 @@ function e_array(x: Array<?string>): string {
} }
// --- name-sensitive havoc --- // --- name-sensitive havoc ---
function c2(x: { [key: string]: ?string }, y: { z: string }): string { function c2(x: { [key: string]: ?string }, y: { z: string }): string {
if (x[y.z]) { if (x[y.z]) {
y.z = \"HEY\"; y.z = \"HEY\";

View File

@ -51,6 +51,7 @@ function f(x: number) {
return x; return x;
} }
//function f(x:number):string { return x; } //function f(x:number):string { return x; }
var x: string = f(0); var x: string = f(0);
module.exports = f; module.exports = f;
@ -79,6 +80,7 @@ module.exports = o;
var o = { x: 0 }; var o = { x: 0 };
//var o: {x: number;} = { x: 0 } //var o: {x: number;} = { x: 0 }
var x: string = o.x; var x: string = o.x;
module.exports = o; module.exports = o;

View File

@ -35,6 +35,7 @@ function getNum() {
// $FlowFixMe This was the second loc in the error // $FlowFixMe This was the second loc in the error
var test3: string = getNum(); // This error should be suppressed var test3: string = getNum(); // This error should be suppressed
// $FlowFixMe Error unused suppression // $FlowFixMe Error unused suppression
var test4: string = 123; // This error is NOT suppressed var test4: string = 123; // This error is NOT suppressed
// $FlowFixMe Indentation shouldn\'t matter // $FlowFixMe Indentation shouldn\'t matter
var test5: string = 123; // This error should be suppressed var test5: string = 123; // This error should be suppressed

View File

@ -86,6 +86,7 @@ foo(o2.y); // setting o3.y to 0 has no effect on o2.y
/* /*
* this bindings: * this bindings:
*/ */
/* standard functions may rebind this */ /* standard functions may rebind this */
function f1(): number { function f1(): number {
return this.x; return this.x;

View File

@ -96,6 +96,7 @@ class B extends A {
} }
// covariance checks on this type in invariant positions // covariance checks on this type in invariant positions
class Invariant { class Invariant {
out_object(): { _: this } { out_object(): { _: this } {
return { _: this }; return { _: this };
@ -111,6 +112,7 @@ class Invariant {
} }
// covariance checks on this type as type args // covariance checks on this type as type args
class Misc { class Misc {
// Set<X> has invariant X // Set<X> has invariant X
out_set(): Set<this> { out_set(): Set<this> {
@ -483,7 +485,9 @@ class InheritOverride extends Override {}
(new InheritOverride().bar_caller(): InheritOverride); // error (new InheritOverride().bar_caller(): InheritOverride); // error
// blame flips below // blame flips below
// Examples with \`this\` types (compare with examples above) // Examples with \`this\` types (compare with examples above)
class Base2 { class Base2 {
foo(): this { foo(): this {
return this; return this;
@ -516,6 +520,7 @@ class Override2 extends Base2 {
return new Override2(); return new Override2();
} // error (cf. OK above) } // error (cf. OK above)
// see exploit below // see exploit below
corge(that: this) {} // error corge(that: this) {} // error
// see exploit below // see exploit below
grault(that: this) {} // error, too grault(that: this) {} // error, too

View File

@ -22,6 +22,7 @@ function foo(x: ?string): $NonMaybeType<?string> {
} }
//(foo(): string); // should not be necessary to expose the error above //(foo(): string); // should not be necessary to expose the error above
(0: $NonMaybeType<null>); // error (0: $NonMaybeType<null>); // error
(0: $NonMaybeType<?number>); // ok (0: $NonMaybeType<?number>); // ok
(0: $NonMaybeType<number | null>); // ok (0: $NonMaybeType<number | null>); // ok

View File

@ -22,6 +22,7 @@ module.exports = printBinaryExpression;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\"use babel\"; \"use babel\";
/* @flow */ /* @flow */
/* /*
* Copyright (c) 2015-present, Facebook, Inc. * Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved. * All rights reserved.
@ -29,6 +30,7 @@ module.exports = printBinaryExpression;
* This source code is licensed under the license found in the LICENSE file in * This source code is licensed under the license found in the LICENSE file in
* the root directory of this source tree. * the root directory of this source tree.
*/ */
import type { BinaryExpression } from \"./types\"; import type { BinaryExpression } from \"./types\";
function printBinaryExpression(node: BinaryExpression) { function printBinaryExpression(node: BinaryExpression) {
@ -5095,7 +5097,9 @@ export type JSXSpreadAttribute = {
/* /*
* Flow types for the Babylon AST. * Flow types for the Babylon AST.
*/ */
// Abstract types. Something must extend these. // Abstract types. Something must extend these.
export type Comment = export type Comment =
| { | {
type: \"CommentLine\", type: \"CommentLine\",
@ -8277,6 +8281,7 @@ export type Type =
}; };
// Concrete Types. Nothing can extend these. // Concrete Types. Nothing can extend these.
export type CommentLine = { export type CommentLine = {
type: \"CommentLine\", type: \"CommentLine\",
_CommentLine: void, _CommentLine: void,
@ -8302,6 +8307,7 @@ export type CommentBlock = {
}; };
// Babel concrete types. // Babel concrete types.
export type ArrayExpression = { export type ArrayExpression = {
type: \"ArrayExpression\", type: \"ArrayExpression\",
_ArrayExpression: void, _ArrayExpression: void,

View File

@ -95,6 +95,7 @@ class MyClass<T> {
var c: MyClass = new MyClass(0); // no error var c: MyClass = new MyClass(0); // no error
// no arity error in type annotation using polymorphic class with defaulting // no arity error in type annotation using polymorphic class with defaulting
class MyClass2<T, U=string> { class MyClass2<T, U=string> {
x: T; x: T;
y: U; y: U;
@ -106,17 +107,21 @@ class MyClass2<T, U=string> {
var c2: MyClass2 = new MyClass2(0, \"\"); // no error var c2: MyClass2 = new MyClass2(0, \"\"); // no error
// no arity error in type annotation using polymorphic type alias // no arity error in type annotation using polymorphic type alias
type MyObject<T> = { x: T }; type MyObject<T> = { x: T };
var o: MyObject = { x: 0 }; // no error var o: MyObject = { x: 0 }; // no error
// arity error in type alias rhs // arity error in type alias rhs
type MySubobject = { y: number } & MyObject; // no error type MySubobject = { y: number } & MyObject; // no error
// arity error in interface extends // arity error in interface extends
interface MyInterface<T> { x: T } interface MyInterface<T> { x: T }
interface MySubinterface extends MyInterface { y: number } // no error interface MySubinterface extends MyInterface { y: number } // no error
// no arity error in extends of polymorphic class // no arity error in extends of polymorphic class
class MySubclass class MySubclass
extends MyClass { // ok, type arg inferred extends MyClass { // ok, type arg inferred
y: number; y: number;
@ -126,6 +131,7 @@ class MySubclass
} }
// no arity error in call of polymorphic function // no arity error in call of polymorphic function
function singleton<T>(x: T): Array<T> { function singleton<T>(x: T): Array<T> {
return [x]; return [x];
} }

View File

@ -93,6 +93,7 @@ class MyClass<T> {
var c: MyClass = new MyClass(0); // error, missing argument list (1) var c: MyClass = new MyClass(0); // error, missing argument list (1)
// arity error in type annotation using polymorphic class with defaulting // arity error in type annotation using polymorphic class with defaulting
class MyClass2<T, U=string> { class MyClass2<T, U=string> {
x: T; x: T;
y: U; y: U;
@ -104,17 +105,21 @@ class MyClass2<T, U=string> {
var c2: MyClass2 = new MyClass2(0, \"\"); // error, missing argument list (1-2) var c2: MyClass2 = new MyClass2(0, \"\"); // error, missing argument list (1-2)
// arity error in type annotation using polymorphic type alias // arity error in type annotation using polymorphic type alias
type MyObject<T> = { x: T }; type MyObject<T> = { x: T };
var o: MyObject = { x: 0 }; // error, missing argument list var o: MyObject = { x: 0 }; // error, missing argument list
// arity error in type alias rhs // arity error in type alias rhs
type MySubobject = { y: number } & MyObject; // error, missing argument list type MySubobject = { y: number } & MyObject; // error, missing argument list
// arity error in interface extends // arity error in interface extends
interface MyInterface<T> { x: T } interface MyInterface<T> { x: T }
interface MySubinterface extends MyInterface { y: number } // error, missing argument list interface MySubinterface extends MyInterface { y: number } // error, missing argument list
// *no* arity error in extends of polymorphic class // *no* arity error in extends of polymorphic class
class MySubclass class MySubclass
extends MyClass { // ok, type arg inferred extends MyClass { // ok, type arg inferred
y: number; y: number;
@ -124,6 +129,7 @@ class MySubclass
} }
// *no* arity error in call of polymorphic function // *no* arity error in call of polymorphic function
function singleton<T>(x: T): Array<T> { function singleton<T>(x: T): Array<T> {
return [x]; return [x];
} }

View File

@ -132,6 +132,7 @@ declare class E<T> { m<T>(x: T): E<T> }
declare class F<T> extends E<T> { m<T>(x: T): F<T> } declare class F<T> extends E<T> { m<T>(x: T): F<T> }
// Bounds can refer to parent type params (until they are shadowed). // Bounds can refer to parent type params (until they are shadowed).
class G<T> { class G<T> {
x: T; x: T;
constructor(x: T) { constructor(x: T) {
@ -147,6 +148,7 @@ g.m(0); // ok
g.m(true); // err, bool ~> number|string g.m(true); // err, bool ~> number|string
(g.m(\"\"): G<number>); // err, string ~> number (g.m(\"\"): G<number>); // err, string ~> number
// Shadow bounds incompatible with parent // Shadow bounds incompatible with parent
class H<T> { class H<T> {
x: T; x: T;
m<T>(x: T) { m<T>(x: T) {

View File

@ -107,6 +107,7 @@ var a: MyClass1 = new MyClass1();
// Following tests are errors which conflate the type // Following tests are errors which conflate the type
// of the class value itself with the type of its // of the class value itself with the type of its
// instances. // instances.
// Aside: it\'s worth staring at the following (correct) // Aside: it\'s worth staring at the following (correct)
// type annotations until they make sense: // type annotations until they make sense:
// //
@ -121,6 +122,7 @@ var a: MyClass1 = new MyClass1();
// The second says that objects produced by the MyClass1 // The second says that objects produced by the MyClass1
// constructor function have type MyClass1 - the type of // constructor function have type MyClass1 - the type of
// instances of MyClass1. // instances of MyClass1.
// Error: assign the actual MyClass1 value to a variable // Error: assign the actual MyClass1 value to a variable
// whose annotated type is of instances of MyClass1. // whose annotated type is of instances of MyClass1.
// //
@ -141,12 +143,14 @@ var c: typeof MyClass2 = new MyClass2();
////////////////////////////////////// //////////////////////////////////////
// == typeof <<non-class value>> == // // == typeof <<non-class value>> == //
////////////////////////////////////// //////////////////////////////////////
var numValue: number = 42; var numValue: number = 42;
var d: typeof numValue = 100; var d: typeof numValue = 100;
var e: typeof numValue = \"asdf\"; // Error: string ~> number var e: typeof numValue = \"asdf\"; // Error: string ~> number
///////////////////////////////// /////////////////////////////////
// == typeof <<type-alias>> == // // == typeof <<type-alias>> == //
///////////////////////////////// /////////////////////////////////
type numberAlias = number; type numberAlias = number;
// This is an error because typeof takes a value, not // This is an error because typeof takes a value, not
@ -159,6 +163,7 @@ var f: typeof numberAlias = 42; // Error: \'typeof <<type-alias>>\' makes no sen
* These provoke a specific error, not just the generic * These provoke a specific error, not just the generic
* \"type is incompatible\" * \"type is incompatible\"
*/ */
var Map = { A: \"this is A\", B: \"this is B\", C: \"this is C\" }; var Map = { A: \"this is A\", B: \"this is B\", C: \"this is C\" };
var keys: $Keys<Map> = \"A\"; // Error: ineligible value used in type anno var keys: $Keys<Map> = \"A\"; // Error: ineligible value used in type anno
" "

View File

@ -327,6 +327,7 @@ function hello(x:X): string {
type X = ({ a: true } & { b: string }) | ({ a: false } & { c: string }); type X = ({ a: true } & { b: string }) | ({ a: false } & { c: string });
//type X = {a:true, b:string} | {a:false, c:string}; // this works. //type X = {a:true, b:string} | {a:false, c:string}; // this works.
function hello(x: X): string { function hello(x: X): string {
if (x.a === true) return x.b; if (x.a === true) return x.b;
else return x.c; else return x.c;
@ -459,6 +460,7 @@ const obj_result = obj({ x: \"\" }); // currently an error! (expect it to be OK)
// blocks until A1 is partially resolved. Since the argument partially matches // blocks until A1 is partially resolved. Since the argument partially matches
// A1, that branch is selected. Later, that branch errors, but other branches // A1, that branch is selected. Later, that branch errors, but other branches
// have been lost by then. // have been lost by then.
type A1 = { x: B1 }; type A1 = { x: B1 };
type A2 = { x: B2 }; type A2 = { x: B2 };
@ -470,6 +472,7 @@ type B2 = string;
/////////////////////////////////////// ///////////////////////////////////////
// similar example with function types // similar example with function types
/////////////////////////////////////// ///////////////////////////////////////
function fun(a: A3 | A4) { function fun(a: A3 | A4) {
return a(); return a();
} }
@ -487,6 +490,7 @@ type B4 = string;
///////////////////////////////////////////// /////////////////////////////////////////////
// similar example with class instance types // similar example with class instance types
///////////////////////////////////////////// /////////////////////////////////////////////
function inst(a: A5 | A6) {} function inst(a: A5 | A6) {}
class B5 {} class B5 {}
@ -598,6 +602,7 @@ type B1 = string;
/////////////////////////////////////// ///////////////////////////////////////
// similar example with function types // similar example with function types
/////////////////////////////////////// ///////////////////////////////////////
function fun(a: (() => number) | (() => string)) {} function fun(a: (() => number) | (() => string)) {}
fun((() => \"\": A2)); fun((() => \"\": A2));
@ -609,6 +614,7 @@ type B2 = string;
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
// similar example with generic class instance types // similar example with generic class instance types
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
class C<X> {} class C<X> {}
function inst(a: C<number> | C<string>) {} function inst(a: C<number> | C<string>) {}
@ -622,6 +628,7 @@ type B3 = string;
///////////////////////////////////////////// /////////////////////////////////////////////
// similar example with generic type aliases // similar example with generic type aliases
///////////////////////////////////////////// /////////////////////////////////////////////
function alias(a: T<number> | T<string>) {} function alias(a: T<number> | T<string>) {}
alias({ x: (x: V<B4>) => {} }); alias({ x: (x: V<B4>) => {} });
@ -632,6 +639,7 @@ type V<X> = X;
type B4 = string; type B4 = string;
// class statics // class statics
function stat(a: { x: number } | { x: string }) {} function stat(a: { x: number } | { x: string }) {}
class D { class D {
@ -643,6 +651,7 @@ stat(D);
type B5 = string; type B5 = string;
// tuples // tuples
function tup(a: [number, boolean] | [string, boolean]) {} function tup(a: [number, boolean] | [string, boolean]) {}
tup(([\"\", false]: A6)); tup(([\"\", false]: A6));
@ -704,6 +713,7 @@ type B1 = string;
//////////////////////////// ////////////////////////////
// example with array types // example with array types
//////////////////////////// ////////////////////////////
function arr(a: number[] | string[]) {} function arr(a: number[] | string[]) {}
arr(([]: A2)); arr(([]: A2));
@ -778,6 +788,7 @@ type B1 = string;
//////////////////////////// ////////////////////////////
// example with array types // example with array types
//////////////////////////// ////////////////////////////
function arr(a: number[] | string[]) {} function arr(a: number[] | string[]) {}
const a2 = ([]: A2); const a2 = ([]: A2);
@ -849,6 +860,7 @@ function fun_call(x: string): string {
///////////////////////////// /////////////////////////////
// example with array types // example with array types
///////////////////////////// /////////////////////////////
function arr(a: number[] | string[]) {} function arr(a: number[] | string[]) {}
var a2 = []; var a2 = [];
@ -971,6 +983,7 @@ type H2 = number;
/////////////////////////////// ///////////////////////////////
// polymorphic recursive types // polymorphic recursive types
/////////////////////////////// ///////////////////////////////
function polyrec(x: PF<number> | PF<string>) {} function polyrec(x: PF<number> | PF<string>) {}
rec({ x: 0 }); rec({ x: 0 });
@ -1150,6 +1163,7 @@ function id<X>(x: X): X {
///////////////////////// /////////////////////////
// primitive annotations // primitive annotations
///////////////////////// /////////////////////////
function check_prim(_: number | string) {} function check_prim(_: number | string) {}
// ok // ok
@ -1161,6 +1175,7 @@ check_prim(id(\"\"));
////////////////////////////// //////////////////////////////
// class instance annotations // class instance annotations
////////////////////////////// //////////////////////////////
class C {} class C {}
class D {} class D {}
function check_inst(_: C | D) {} function check_inst(_: C | D) {}
@ -1174,6 +1189,7 @@ check_inst(id(new C()));
//////////////////////// ////////////////////////
// function annotations // function annotations
//////////////////////// ////////////////////////
function check_fun(_: ((_: number) => number) | ((_: string) => string)) {} function check_fun(_: ((_: number) => number) | ((_: string) => string)) {}
// help! // help!
@ -1182,6 +1198,7 @@ check_fun(x => x);
////////////////////// //////////////////////
// object annotations // object annotations
////////////////////// //////////////////////
function check_obj(_: { x: number } | { x: string }) {} function check_obj(_: { x: number } | { x: string }) {}
// ok // ok
@ -1193,6 +1210,7 @@ check_obj({ x: id(\"\") });
///////////////////// /////////////////////
// array annotations // array annotations
///////////////////// /////////////////////
function check_arr(_: number[] | string[]) {} function check_arr(_: number[] | string[]) {}
// ok // ok
@ -1204,6 +1222,7 @@ check_arr([id(\"\")]);
////////////////////////////////////// //////////////////////////////////////
// generic class instance annotations // generic class instance annotations
////////////////////////////////////// //////////////////////////////////////
class P<X> {} class P<X> {}
function check_poly_inst(_: P<number> | P<string>) {} function check_poly_inst(_: P<number> | P<string>) {}
@ -1374,6 +1393,7 @@ type EventHandler = (event: Event) => mixed;
type KeyboardEventHandler = (event: KeyboardEvent) => mixed; type KeyboardEventHandler = (event: KeyboardEvent) => mixed;
// example where globals are not yet resolved // example where globals are not yet resolved
function bar(x: (() => void) | { x: number }) {} function bar(x: (() => void) | { x: number }) {}
bar(() => {}); bar(() => {});
@ -1814,6 +1834,7 @@ function hello4(x:X): string {
type X = ({ a: true } & { b: string }) | ({ a: false } & { c: string }); type X = ({ a: true } & { b: string }) | ({ a: false } & { c: string });
//type X = {a:true, b:string} | {a:false, c:string}; // this works. //type X = {a:true, b:string} | {a:false, c:string}; // this works.
function hello1(x: X): string { function hello1(x: X): string {
if (x.a === true) return x.b; if (x.a === true) return x.b;
else return x.c; else return x.c;

View File

@ -35,6 +35,7 @@ function test1(): string {
// regression test for analysis after abnormal control flow: // regression test for analysis after abnormal control flow:
// consts must not become bot (EmptyT). // consts must not become bot (EmptyT).
function test2() { function test2() {
const n = 0; const n = 0;