From a4643f1baed67c5ef70f2ef43c5f09d5246bf6e5 Mon Sep 17 00:00:00 2001 From: James Long Date: Mon, 9 Jan 2017 21:49:06 -0500 Subject: [PATCH] Add special case for comment at top of file; regenerate snapshots --- src/comments.js | 17 +- src/printer.js | 11 +- .../abnormal/__snapshots__/jsfmt.spec.js.snap | 7 +- tests/annot/__snapshots__/jsfmt.spec.js.snap | 81 +- .../any/__snapshots__/jsfmt.spec.js.snap | 12 +- tests/annot2/__snapshots__/jsfmt.spec.js.snap | 18 +- tests/any/__snapshots__/jsfmt.spec.js.snap | 46 +- tests/arith/__snapshots__/jsfmt.spec.js.snap | 153 +-- .../__snapshots__/jsfmt.spec.js.snap | 11 +- .../__snapshots__/jsfmt.spec.js.snap | 4 +- .../arraylib/__snapshots__/jsfmt.spec.js.snap | 30 +- tests/arrays/__snapshots__/jsfmt.spec.js.snap | 22 +- tests/arrows/__snapshots__/jsfmt.spec.js.snap | 13 +- tests/async/__snapshots__/jsfmt.spec.js.snap | 148 +-- .../__snapshots__/jsfmt.spec.js.snap | 53 +- .../__snapshots__/jsfmt.spec.js.snap | 8 +- .../__snapshots__/jsfmt.spec.js.snap | 3 +- .../lib/__snapshots__/jsfmt.spec.js.snap | 3 +- tests/binary/__snapshots__/jsfmt.spec.js.snap | 47 +- .../binding/__snapshots__/jsfmt.spec.js.snap | 322 ++++--- tests/bom/__snapshots__/jsfmt.spec.js.snap | 136 ++- .../__snapshots__/jsfmt.spec.js.snap | 31 +- tests/break/__snapshots__/jsfmt.spec.js.snap | 42 +- .../__snapshots__/jsfmt.spec.js.snap | 6 +- .../builtins/__snapshots__/jsfmt.spec.js.snap | 15 +- .../__snapshots__/jsfmt.spec.js.snap | 113 ++- .../callable/__snapshots__/jsfmt.spec.js.snap | 19 +- .../__snapshots__/jsfmt.spec.js.snap | 3 +- .../__snapshots__/jsfmt.spec.js.snap | 16 +- .../__snapshots__/jsfmt.spec.js.snap | 38 +- .../__snapshots__/jsfmt.spec.js.snap | 24 +- .../__snapshots__/jsfmt.spec.js.snap | 15 +- .../classes/__snapshots__/jsfmt.spec.js.snap | 112 +-- .../closure/__snapshots__/jsfmt.spec.js.snap | 97 +- .../commonjs/__snapshots__/jsfmt.spec.js.snap | 8 +- .../__snapshots__/jsfmt.spec.js.snap | 37 +- .../__snapshots__/jsfmt.spec.js.snap | 13 +- .../__snapshots__/jsfmt.spec.js.snap | 4 +- .../__snapshots__/jsfmt.spec.js.snap | 4 +- .../__snapshots__/jsfmt.spec.js.snap | 4 +- .../__snapshots__/jsfmt.spec.js.snap | 7 +- .../__snapshots__/jsfmt.spec.js.snap | 4 +- .../dir/__snapshots__/jsfmt.spec.js.snap | 5 +- .../__snapshots__/jsfmt.spec.js.snap | 6 +- .../src/__snapshots__/jsfmt.spec.js.snap | 4 +- .../__snapshots__/jsfmt.spec.js.snap | 5 +- .../__snapshots__/jsfmt.spec.js.snap | 20 +- .../__snapshots__/jsfmt.spec.js.snap | 25 +- .../__snapshots__/jsfmt.spec.js.snap | 6 +- .../testproj/__snapshots__/jsfmt.spec.js.snap | 4 +- .../__snapshots__/jsfmt.spec.js.snap | 4 +- .../subdir/__snapshots__/jsfmt.spec.js.snap | 7 +- .../__snapshots__/jsfmt.spec.js.snap | 4 +- .../__snapshots__/jsfmt.spec.js.snap | 16 +- .../__snapshots__/jsfmt.spec.js.snap | 7 +- .../__snapshots__/jsfmt.spec.js.snap | 14 +- .../__snapshots__/jsfmt.spec.js.snap | 5 +- .../__snapshots__/jsfmt.spec.js.snap | 33 +- .../ignore/__snapshots__/jsfmt.spec.js.snap | 4 +- .../no_flow/__snapshots__/jsfmt.spec.js.snap | 4 +- .../__snapshots__/jsfmt.spec.js.snap | 72 +- .../__snapshots__/jsfmt.spec.js.snap | 33 +- .../coverage/__snapshots__/jsfmt.spec.js.snap | 21 +- tests/cycle/__snapshots__/jsfmt.spec.js.snap | 11 +- tests/date/__snapshots__/jsfmt.spec.js.snap | 13 +- .../__snapshots__/jsfmt.spec.js.snap | 20 +- .../_d3/__snapshots__/jsfmt.spec.js.snap | 3 +- .../foo/bar/__snapshots__/jsfmt.spec.js.snap | 10 +- .../ws/__snapshots__/jsfmt.spec.js.snap | 1 - .../ws/test/__snapshots__/jsfmt.spec.js.snap | 3 +- .../__snapshots__/jsfmt.spec.js.snap | 26 +- .../_d3/__snapshots__/jsfmt.spec.js.snap | 3 +- .../foo/bar/__snapshots__/jsfmt.spec.js.snap | 10 +- .../ws/__snapshots__/jsfmt.spec.js.snap | 1 - .../ws/test/__snapshots__/jsfmt.spec.js.snap | 3 +- .../__snapshots__/jsfmt.spec.js.snap | 41 +- .../__snapshots__/jsfmt.spec.js.snap | 35 +- .../__snapshots__/jsfmt.spec.js.snap | 6 +- .../lib/__snapshots__/jsfmt.spec.js.snap | 3 +- .../__snapshots__/jsfmt.spec.js.snap | 364 ++++--- .../__snapshots__/jsfmt.spec.js.snap | 9 +- .../__snapshots__/jsfmt.spec.js.snap | 22 +- .../__snapshots__/jsfmt.spec.js.snap | 17 +- .../__snapshots__/jsfmt.spec.js.snap | 23 +- .../lib/__snapshots__/jsfmt.spec.js.snap | 11 +- .../__snapshots__/jsfmt.spec.js.snap | 36 +- tests/demo/1/__snapshots__/jsfmt.spec.js.snap | 7 +- tests/demo/2/__snapshots__/jsfmt.spec.js.snap | 15 +- tests/deps/__snapshots__/jsfmt.spec.js.snap | 25 +- .../__snapshots__/jsfmt.spec.js.snap | 225 +++-- .../__snapshots__/jsfmt.spec.js.snap | 455 ++++----- .../__snapshots__/jsfmt.spec.js.snap | 81 +- .../__snapshots__/jsfmt.spec.js.snap | 52 +- tests/dom/__snapshots__/jsfmt.spec.js.snap | 183 ++-- .../__snapshots__/jsfmt.spec.js.snap | 12 +- .../__snapshots__/jsfmt.spec.js.snap | 12 +- tests/encaps/__snapshots__/jsfmt.spec.js.snap | 13 +- .../__snapshots__/jsfmt.spec.js.snap | 12 +- tests/equals/__snapshots__/jsfmt.spec.js.snap | 8 +- .../__snapshots__/jsfmt.spec.js.snap | 3 +- .../__snapshots__/jsfmt.spec.js.snap | 454 ++++----- .../__snapshots__/jsfmt.spec.js.snap | 31 +- .../__snapshots__/jsfmt.spec.js.snap | 3 +- .../__snapshots__/jsfmt.spec.js.snap | 12 +- .../__snapshots__/jsfmt.spec.js.snap | 12 +- .../__snapshots__/jsfmt.spec.js.snap | 10 +- .../lib/__snapshots__/jsfmt.spec.js.snap | 3 +- .../__snapshots__/jsfmt.spec.js.snap | 32 +- .../__snapshots__/jsfmt.spec.js.snap | 3 +- .../__snapshots__/jsfmt.spec.js.snap | 6 +- .../__snapshots__/jsfmt.spec.js.snap | 7 +- .../__snapshots__/jsfmt.spec.js.snap | 3 +- .../__snapshots__/jsfmt.spec.js.snap | 54 +- tests/fetch/__snapshots__/jsfmt.spec.js.snap | 157 ++- .../__snapshots__/jsfmt.spec.js.snap | 7 +- .../fixpoint/__snapshots__/jsfmt.spec.js.snap | 16 +- .../__snapshots__/jsfmt.spec.js.snap | 3 +- tests/for/__snapshots__/jsfmt.spec.js.snap | 22 +- tests/forof/__snapshots__/jsfmt.spec.js.snap | 34 +- .../function/__snapshots__/jsfmt.spec.js.snap | 151 +-- tests/funrec/__snapshots__/jsfmt.spec.js.snap | 3 +- .../__snapshots__/jsfmt.spec.js.snap | 201 ++-- .../generics/__snapshots__/jsfmt.spec.js.snap | 25 +- .../__snapshots__/jsfmt.spec.js.snap | 4 +- .../get-def/__snapshots__/jsfmt.spec.js.snap | 22 +- .../helpers/__snapshots__/jsfmt.spec.js.snap | 9 +- .../get-def2/__snapshots__/jsfmt.spec.js.snap | 42 +- .../lib/__snapshots__/jsfmt.spec.js.snap | 6 +- .../__snapshots__/jsfmt.spec.js.snap | 8 +- .../__snapshots__/jsfmt.spec.js.snap | 4 +- .../__snapshots__/jsfmt.spec.js.snap | 123 ++- .../__snapshots__/jsfmt.spec.js.snap | 4 +- .../models/__snapshots__/jsfmt.spec.js.snap | 12 +- .../__snapshots__/jsfmt.spec.js.snap | 9 +- .../__snapshots__/jsfmt.spec.js.snap | 5 +- .../__snapshots__/jsfmt.spec.js.snap | 3 +- .../__snapshots__/jsfmt.spec.js.snap | 96 +- .../__snapshots__/jsfmt.spec.js.snap | 117 ++- .../batman/__snapshots__/jsfmt.spec.js.snap | 5 +- .../included/__snapshots__/jsfmt.spec.js.snap | 3 +- .../__snapshots__/jsfmt.spec.js.snap | 10 +- .../__snapshots__/jsfmt.spec.js.snap | 9 +- .../tmp1/__snapshots__/jsfmt.spec.js.snap | 3 +- .../tmp2/__snapshots__/jsfmt.spec.js.snap | 3 +- .../tmp3/__snapshots__/jsfmt.spec.js.snap | 3 +- .../__snapshots__/jsfmt.spec.js.snap | 15 +- .../tmp1/__snapshots__/jsfmt.spec.js.snap | 9 +- .../tmp2/__snapshots__/jsfmt.spec.js.snap | 5 +- .../tmp3/__snapshots__/jsfmt.spec.js.snap | 4 +- .../__snapshots__/jsfmt.spec.js.snap | 24 +- .../__snapshots__/jsfmt.spec.js.snap | 5 - .../__snapshots__/jsfmt.spec.js.snap | 3 +- .../__snapshots__/jsfmt.spec.js.snap | 24 +- .../tmp1/__snapshots__/jsfmt.spec.js.snap | 4 +- .../__snapshots__/jsfmt.spec.js.snap | 8 +- .../dir/__snapshots__/jsfmt.spec.js.snap | 3 +- .../indexer/__snapshots__/jsfmt.spec.js.snap | 34 +- tests/init/__snapshots__/jsfmt.spec.js.snap | 260 ++--- .../__snapshots__/jsfmt.spec.js.snap | 43 +- .../__snapshots__/jsfmt.spec.js.snap | 5 +- .../__snapshots__/jsfmt.spec.js.snap | 72 +- .../__snapshots__/jsfmt.spec.js.snap | 43 +- .../lib/__snapshots__/jsfmt.spec.js.snap | 20 +- .../__snapshots__/jsfmt.spec.js.snap | 6 +- tests/iter/__snapshots__/jsfmt.spec.js.snap | 24 +- .../iterable/__snapshots__/jsfmt.spec.js.snap | 62 +- .../__snapshots__/jsfmt.spec.js.snap | 51 +- .../__snapshots__/jsfmt.spec.js.snap | 50 +- .../lib/__snapshots__/jsfmt.spec.js.snap | 6 +- tests/keys/__snapshots__/jsfmt.spec.js.snap | 49 +- .../keyvalue/__snapshots__/jsfmt.spec.js.snap | 4 +- .../__snapshots__/jsfmt.spec.js.snap | 45 +- tests/lib/__snapshots__/jsfmt.spec.js.snap | 5 +- .../__snapshots__/jsfmt.spec.js.snap | 3 +- .../__snapshots__/jsfmt.spec.js.snap | 9 +- .../__snapshots__/jsfmt.spec.js.snap | 6 +- .../lib/__snapshots__/jsfmt.spec.js.snap | 3 +- tests/liberr/__snapshots__/jsfmt.spec.js.snap | 3 +- .../libs/__snapshots__/jsfmt.spec.js.snap | 3 +- .../__snapshots__/jsfmt.spec.js.snap | 3 +- .../__snapshots__/jsfmt.spec.js.snap | 3 +- tests/librec/__snapshots__/jsfmt.spec.js.snap | 3 +- .../lib/A/__snapshots__/jsfmt.spec.js.snap | 3 +- .../lib/B/__snapshots__/jsfmt.spec.js.snap | 3 +- .../literal/__snapshots__/jsfmt.spec.js.snap | 31 +- tests/locals/__snapshots__/jsfmt.spec.js.snap | 47 +- .../logical/__snapshots__/jsfmt.spec.js.snap | 505 +++++----- tests/loners/__snapshots__/jsfmt.spec.js.snap | 7 +- .../__snapshots__/jsfmt.spec.js.snap | 14 +- tests/misc/__snapshots__/jsfmt.spec.js.snap | 44 +- .../__snapshots__/jsfmt.spec.js.snap | 44 +- .../__snapshots__/jsfmt.spec.js.snap | 5 +- .../lib/__snapshots__/jsfmt.spec.js.snap | 3 +- .../src/__snapshots__/jsfmt.spec.js.snap | 7 +- .../__snapshots__/jsfmt.spec.js.snap | 15 +- .../__snapshots__/jsfmt.spec.js.snap | 4 +- .../modules/__snapshots__/jsfmt.spec.js.snap | 18 +- .../__snapshots__/jsfmt.spec.js.snap | 20 +- .../__snapshots__/jsfmt.spec.js.snap | 22 +- .../__snapshots__/jsfmt.spec.js.snap | 45 +- .../__snapshots__/jsfmt.spec.js.snap | 55 +- .../__snapshots__/jsfmt.spec.js.snap | 5 +- .../__snapshots__/jsfmt.spec.js.snap | 16 +- .../__snapshots__/jsfmt.spec.js.snap | 12 +- .../__snapshots__/jsfmt.spec.js.snap | 5 +- .../_d3/__snapshots__/jsfmt.spec.js.snap | 1 - .../foo/bar/__snapshots__/jsfmt.spec.js.snap | 8 +- .../ws/__snapshots__/jsfmt.spec.js.snap | 1 - .../ws/test/__snapshots__/jsfmt.spec.js.snap | 3 +- .../root/__snapshots__/jsfmt.spec.js.snap | 3 +- .../__snapshots__/jsfmt.spec.js.snap | 3 +- .../__snapshots__/jsfmt.spec.js.snap | 3 +- .../__snapshots__/jsfmt.spec.js.snap | 4 +- .../assert/__snapshots__/jsfmt.spec.js.snap | 7 +- .../basic/__snapshots__/jsfmt.spec.js.snap | 6 +- .../__snapshots__/jsfmt.spec.js.snap | 8 +- .../__snapshots__/jsfmt.spec.js.snap | 3 +- .../__snapshots__/jsfmt.spec.js.snap | 3 +- .../__snapshots__/jsfmt.spec.js.snap | 5 +- .../bar_lib/__snapshots__/jsfmt.spec.js.snap | 3 +- .../buffer/__snapshots__/jsfmt.spec.js.snap | 35 +- .../__snapshots__/jsfmt.spec.js.snap | 66 +- .../crypto/__snapshots__/jsfmt.spec.js.snap | 29 +- .../fs/__snapshots__/jsfmt.spec.js.snap | 19 +- .../__snapshots__/jsfmt.spec.js.snap | 27 +- .../package2/__snapshots__/jsfmt.spec.js.snap | 4 +- .../os/__snapshots__/jsfmt.spec.js.snap | 11 +- .../__snapshots__/jsfmt.spec.js.snap | 8 +- .../bar_lib/__snapshots__/jsfmt.spec.js.snap | 3 +- .../foo/__snapshots__/jsfmt.spec.js.snap | 5 +- .../__snapshots__/jsfmt.spec.js.snap | 3 +- .../__snapshots__/jsfmt.spec.js.snap | 3 +- .../__snapshots__/jsfmt.spec.js.snap | 3 +- .../__snapshots__/jsfmt.spec.js.snap | 3 +- .../stream/__snapshots__/jsfmt.spec.js.snap | 10 +- .../timers/__snapshots__/jsfmt.spec.js.snap | 5 +- .../url/__snapshots__/jsfmt.spec.js.snap | 3 +- .../nullable/__snapshots__/jsfmt.spec.js.snap | 25 +- .../__snapshots__/jsfmt.spec.js.snap | 3 +- .../__snapshots__/jsfmt.spec.js.snap | 42 +- .../__snapshots__/jsfmt.spec.js.snap | 6 +- .../__snapshots__/jsfmt.spec.js.snap | 231 +++-- .../__snapshots__/jsfmt.spec.js.snap | 54 +- .../__snapshots__/jsfmt.spec.js.snap | 20 +- .../__snapshots__/jsfmt.spec.js.snap | 6 +- .../objects/__snapshots__/jsfmt.spec.js.snap | 49 +- tests/objmap/__snapshots__/jsfmt.spec.js.snap | 14 +- .../optional/__snapshots__/jsfmt.spec.js.snap | 88 +- .../__snapshots__/jsfmt.spec.js.snap | 63 +- .../overload/__snapshots__/jsfmt.spec.js.snap | 76 +- .../lib/__snapshots__/jsfmt.spec.js.snap | 3 +- tests/parse/__snapshots__/jsfmt.spec.js.snap | 5 +- .../__snapshots__/jsfmt.spec.js.snap | 9 +- .../__snapshots__/jsfmt.spec.js.snap | 7 +- tests/path/__snapshots__/jsfmt.spec.js.snap | 3 +- .../plsummit/__snapshots__/jsfmt.spec.js.snap | 27 +- tests/poly/__snapshots__/jsfmt.spec.js.snap | 53 +- .../__snapshots__/jsfmt.spec.js.snap | 17 +- .../decls/__snapshots__/jsfmt.spec.js.snap | 3 +- .../__snapshots__/jsfmt.spec.js.snap | 87 +- .../__snapshots__/jsfmt.spec.js.snap | 109 ++- .../__snapshots__/jsfmt.spec.js.snap | 77 +- .../__snapshots__/jsfmt.spec.js.snap | 36 +- .../private/__snapshots__/jsfmt.spec.js.snap | 4 +- .../promises/__snapshots__/jsfmt.spec.js.snap | 265 +++--- .../__snapshots__/jsfmt.spec.js.snap | 5 +- .../__snapshots__/jsfmt.spec.js.snap | 8 +- tests/react/__snapshots__/jsfmt.spec.js.snap | 107 ++- .../__snapshots__/jsfmt.spec.js.snap | 19 +- .../__snapshots__/jsfmt.spec.js.snap | 34 +- tests/rec/__snapshots__/jsfmt.spec.js.snap | 93 +- .../__snapshots__/jsfmt.spec.js.snap | 9 +- .../tmp1A/__snapshots__/jsfmt.spec.js.snap | 5 - .../tmp2A/__snapshots__/jsfmt.spec.js.snap | 4 +- .../recheck/__snapshots__/jsfmt.spec.js.snap | 101 +- .../tmp1a/__snapshots__/jsfmt.spec.js.snap | 6 +- .../tmp1b/__snapshots__/jsfmt.spec.js.snap | 4 +- .../tmp1c/__snapshots__/jsfmt.spec.js.snap | 5 +- .../tmp1d/__snapshots__/jsfmt.spec.js.snap | 4 +- .../tmp1e/__snapshots__/jsfmt.spec.js.snap | 7 +- .../tmp1f/__snapshots__/jsfmt.spec.js.snap | 6 +- .../tmp1g/__snapshots__/jsfmt.spec.js.snap | 4 +- .../tmp1h/__snapshots__/jsfmt.spec.js.snap | 4 +- .../tmp2a/__snapshots__/jsfmt.spec.js.snap | 6 +- .../tmp2b/__snapshots__/jsfmt.spec.js.snap | 5 +- .../tmp2c/__snapshots__/jsfmt.spec.js.snap | 4 +- .../tmp2e/__snapshots__/jsfmt.spec.js.snap | 5 +- .../tmp2f/__snapshots__/jsfmt.spec.js.snap | 6 +- .../tmp3e/__snapshots__/jsfmt.spec.js.snap | 12 +- .../tmp3f/__snapshots__/jsfmt.spec.js.snap | 6 +- .../tmp4f/__snapshots__/jsfmt.spec.js.snap | 6 +- tests/record/__snapshots__/jsfmt.spec.js.snap | 33 +- tests/refi/__snapshots__/jsfmt.spec.js.snap | 517 +++++----- .../__snapshots__/jsfmt.spec.js.snap | 890 +++++++++--------- .../__snapshots__/jsfmt.spec.js.snap | 4 +- tests/regexp/__snapshots__/jsfmt.spec.js.snap | 3 +- .../replace/__snapshots__/jsfmt.spec.js.snap | 5 +- .../require/__snapshots__/jsfmt.spec.js.snap | 61 +- .../__snapshots__/jsfmt.spec.js.snap | 28 +- tests/return/__snapshots__/jsfmt.spec.js.snap | 15 +- .../__snapshots__/jsfmt.spec.js.snap | 25 +- tests/seal/__snapshots__/jsfmt.spec.js.snap | 10 +- tests/sealed/__snapshots__/jsfmt.spec.js.snap | 21 +- .../__snapshots__/jsfmt.spec.js.snap | 16 +- tests/shape/__snapshots__/jsfmt.spec.js.snap | 4 +- .../__snapshots__/jsfmt.spec.js.snap | 26 +- .../__snapshots__/jsfmt.spec.js.snap | 36 +- tests/spread/__snapshots__/jsfmt.spec.js.snap | 50 +- .../__snapshots__/jsfmt.spec.js.snap | 3 +- .../lib/__snapshots__/jsfmt.spec.js.snap | 3 +- .../statics/__snapshots__/jsfmt.spec.js.snap | 9 +- tests/strict/__snapshots__/jsfmt.spec.js.snap | 21 +- .../__snapshots__/jsfmt.spec.js.snap | 12 +- .../strings/__snapshots__/jsfmt.spec.js.snap | 9 +- .../__snapshots__/jsfmt.spec.js.snap | 45 +- .../suggest/__snapshots__/jsfmt.spec.js.snap | 12 +- tests/super/__snapshots__/jsfmt.spec.js.snap | 95 +- .../suppress/__snapshots__/jsfmt.spec.js.snap | 36 +- .../__snapshots__/jsfmt.spec.js.snap | 5 +- .../__snapshots__/jsfmt.spec.js.snap | 7 +- tests/switch/__snapshots__/jsfmt.spec.js.snap | 74 +- tests/symbol/__snapshots__/jsfmt.spec.js.snap | 6 +- .../symlink/__snapshots__/jsfmt.spec.js.snap | 9 +- .../__snapshots__/jsfmt.spec.js.snap | 45 +- tests/taint/__snapshots__/jsfmt.spec.js.snap | 124 ++- .../template/__snapshots__/jsfmt.spec.js.snap | 42 +- tests/this/__snapshots__/jsfmt.spec.js.snap | 80 +- .../__snapshots__/jsfmt.spec.js.snap | 7 +- .../__snapshots__/jsfmt.spec.js.snap | 178 ++-- .../lib/__snapshots__/jsfmt.spec.js.snap | 11 +- tests/throw/__snapshots__/jsfmt.spec.js.snap | 12 +- tests/traces/__snapshots__/jsfmt.spec.js.snap | 23 +- tests/traits/__snapshots__/jsfmt.spec.js.snap | 33 +- tests/try/__snapshots__/jsfmt.spec.js.snap | 117 +-- tests/tuples/__snapshots__/jsfmt.spec.js.snap | 33 +- .../__snapshots__/jsfmt.spec.js.snap | 55 +- .../__snapshots__/jsfmt.spec.js.snap | 32 +- .../__snapshots__/jsfmt.spec.js.snap | 188 +++- .../__snapshots__/jsfmt.spec.js.snap | 41 +- .../__snapshots__/jsfmt.spec.js.snap | 41 +- .../__snapshots__/jsfmt.spec.js.snap | 49 +- .../__snapshots__/jsfmt.spec.js.snap | 55 +- .../__snapshots__/jsfmt.spec.js.snap | 54 +- .../__snapshots__/jsfmt.spec.js.snap | 9 +- .../__snapshots__/jsfmt.spec.js.snap | 9 +- .../libs/__snapshots__/jsfmt.spec.js.snap | 8 +- .../__snapshots__/jsfmt.spec.js.snap | 14 +- .../typecast/__snapshots__/jsfmt.spec.js.snap | 16 +- tests/typeof/__snapshots__/jsfmt.spec.js.snap | 48 +- tests/unary/__snapshots__/jsfmt.spec.js.snap | 49 +- .../__snapshots__/jsfmt.spec.js.snap | 9 +- .../__snapshots__/jsfmt.spec.js.snap | 15 +- .../__snapshots__/jsfmt.spec.js.snap | 31 +- .../unicode/__snapshots__/jsfmt.spec.js.snap | 11 +- .../__snapshots__/jsfmt.spec.js.snap | 10 +- tests/union/__snapshots__/jsfmt.spec.js.snap | 123 +-- .../__snapshots__/jsfmt.spec.js.snap | 517 ++++++---- .../lib/__snapshots__/jsfmt.spec.js.snap | 11 +- .../__snapshots__/jsfmt.spec.js.snap | 34 +- tests/value/__snapshots__/jsfmt.spec.js.snap | 4 +- .../__snapshots__/jsfmt.spec.js.snap | 4 +- .../weakmode/__snapshots__/jsfmt.spec.js.snap | 10 +- tests/while/__snapshots__/jsfmt.spec.js.snap | 12 +- tests/window/__snapshots__/jsfmt.spec.js.snap | 7 +- tests/x/__snapshots__/jsfmt.spec.js.snap | 11 +- 365 files changed, 7437 insertions(+), 6418 deletions(-) diff --git a/src/comments.js b/src/comments.js index 617b2969..22d2966f 100644 --- a/src/comments.js +++ b/src/comments.js @@ -79,7 +79,8 @@ function decorateComment(node, comment, text) { if (locStart(child) - locStart(comment) <= 0 && locEnd(comment) - locEnd(child) <= 0) { // The comment is completely contained by this child node. - decorateComment(comment.enclosingNode = child, comment, text); + comment.enclosingNode = child; + decorateComment(child, comment, text); return; // Abandon the binary search at this level. } @@ -163,7 +164,7 @@ exports.attach = function(comments, ast, text) { addDanglingComment(en, comment); } else { - throw new Error("AST contains no nodes at all?"); + // throw new Error("AST contains no nodes at all?"); } }); @@ -271,9 +272,12 @@ function printTrailingComment(commentPath, print, options) { exports.printComments = function(path, print, options) { var value = path.getValue(); + var parent = path.getParentNode(); var printed = print(path); 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) { return printed; @@ -291,6 +295,15 @@ exports.printComments = function(path, print, options) { comment.type === "Block" || comment.type === "CommentBlock"))) { leadingParts.push(printLeadingComment(commentPath, print)); + + + // 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. + if(isFirstInProgram && + util.newlineExistsAfter(options.originalText, util.locEnd(comment))) { + leadingParts.push(hardline); + } } else if (trailing) { trailingParts.push(printTrailingComment(commentPath, print, options)); } diff --git a/src/printer.js b/src/printer.js index bc745a7b..01abe057 100644 --- a/src/printer.js +++ b/src/printer.js @@ -1551,8 +1551,6 @@ function genericPrintNoParens(path, options, print) { } function printStatementSequence(path, options, print) { - let inClassBody = namedTypes.ClassBody && - namedTypes.ClassBody.check(path.getParentNode()); let printed = []; path.map(function(stmtPath, i) { @@ -1571,11 +1569,13 @@ function printStatementSequence(path, options, print) { } const stmtPrinted = print(stmtPath); + const text = options.originalText; const parts = []; parts.push(stmtPrinted); - if (shouldAddSpacing(stmt, options) && !isLastStatement(stmtPath)) { + if (util.newlineExistsAfter(text, util.locEnd(stmt)) && + !isLastStatement(stmtPath)) { parts.push(hardline); } @@ -2008,11 +2008,6 @@ function nodeStr(str, options) { } } -function shouldAddSpacing(node, options) { - const text = options.originalText; - return util.newlineExistsAfter(text, util.locEnd(node)); -} - function isFirstStatement(path) { const parent = path.getParentNode(); const node = path.getValue(); diff --git a/tests/abnormal/__snapshots__/jsfmt.spec.js.snap b/tests/abnormal/__snapshots__/jsfmt.spec.js.snap index 8b18630e..7dcd1fc7 100644 --- a/tests/abnormal/__snapshots__/jsfmt.spec.js.snap +++ b/tests/abnormal/__snapshots__/jsfmt.spec.js.snap @@ -12,13 +12,13 @@ function foo() { break; } } + function bar() { L: do { continue L; } while (false); -} -" +}" `; exports[`test return.js 1`] = ` @@ -35,6 +35,5 @@ function foo() { if (x == null) return; bar(x); -} -" +}" `; diff --git a/tests/annot/__snapshots__/jsfmt.spec.js.snap b/tests/annot/__snapshots__/jsfmt.spec.js.snap index f759c082..5095fdef 100644 --- a/tests/annot/__snapshots__/jsfmt.spec.js.snap +++ b/tests/annot/__snapshots__/jsfmt.spec.js.snap @@ -60,45 +60,54 @@ var zer : null = null; function foobar(n : ?number) : number | null | void { return n; } function barfoo(n : number | null | void) : ?number { return n; } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// array sugar -// param type annos are strict UBs like var type annos -// error -// another error on param UB, more typical of www (mis)use-cases -// this one cribbed from API.atlas.js -// error below, since we\'re assigning elements to batchRequests -// which lack a path property. -// just assign result to new var instead of reassigning to param. -// Transform the requests to the format the Graph API expects. -// ... function foo(str: string, i: number): string { return str; } var bar: (str: number, i: number) => string = foo; + var qux = function(str: string, i: number): number { return foo(str, i); }; + var obj: { str: string, i: number, j: boolean } = { str: \"...\", i: \"...\", k: false }; + var arr: Array = [ 1, 2, \"...\" ]; + +// array sugar var array: number[] = [ 1, 2, \"...\" ]; + var matrix: number[][] = [ [ 1, 2 ], [ 3, 4 ] ]; var matrix_parens: number[][] = matrix; + var nullable_array: ?(number[]) = null; var nullable_array_parens: ?(number[]) = nullable_array; + var array_of_nullable: (?number)[] = [ null, 3 ]; + var array_of_tuple: [number, string][] = [ [ 0, \"foo\" ], [ 1, \"bar\" ] ]; var array_of_tuple_parens: [number, string][] = array_of_tuple; + type ObjType = { \"bar-foo\": string, \"foo-bar\": number }; var test_obj: ObjType = { \"bar-foo\": \"23\" }; + +// param type annos are strict UBs like var type annos function param_anno(n: number): void { - n = \"hey\"; + n = \"hey\"; // error } + +// another error on param UB, more typical of www (mis)use-cases +// this one cribbed from API.atlas.js function param_anno2( batchRequests: Array<{ method: string, path: string, params: ?Object }> ): void { + // error below, since we\'re assigning elements to batchRequests + // which lack a path property. + // just assign result to new var instead of reassigning to param. + // Transform the requests to the format the Graph API expects. batchRequests = batchRequests.map(request => { return { method: request.method, @@ -106,16 +115,19 @@ function param_anno2( relative_url: request.path }; }); + // ... } + var toz: null = 3; + var zer: null = null; + function foobar(n: ?number): number | null | void { return n; } function barfoo(n: number | null | void): ?number { return n; -} -" +}" `; exports[`test forward_ref.js 1`] = ` @@ -134,24 +146,23 @@ function foo() { class MyClass { } // looked up above } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// forward ref ok, null ~> class error -// forward ref ok, null ~> class error -// looked up above -// ok (no confusion across scopes) -// looked up above let myClassInstance: MyClass = null; +// forward ref ok, null ~> class error function bar(): MyClass { - return null; + return null; // forward ref ok, null ~> class error } + class MyClass {} +// looked up above function foo() { let myClassInstance: MyClass = mk(); + // ok (no confusion across scopes) function mk() { return new MyClass(); } - class MyClass {} -} -" + + class MyClass {} // looked up above +}" `; exports[`test issue-530.js 1`] = ` @@ -160,8 +171,8 @@ exports[`test issue-530.js 1`] = ` module.exports = foo; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ function foo(...args: any) {} -module.exports = foo; -" + +module.exports = foo;" `; exports[`test leak.js 1`] = ` @@ -189,6 +200,7 @@ function bar(y: MyObj): string { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /** @flow */ + /* This test documents an example we ran into of a type annotation leaking. * * When foo() calls bar(), we should make sure the type of x matches the type @@ -199,14 +211,16 @@ function bar(y: MyObj): string { * and type checking the body of bar() using the stricter dictionary type, * leading to an error. */ + type MyObj = Object; + function foo(x: { [key: string]: mixed }) { bar(x); } + function bar(y: MyObj): string { return y.foo; -} -" +}" `; exports[`test other.js 1`] = ` @@ -214,8 +228,7 @@ exports[`test other.js 1`] = ` module.exports = (C: any); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class C {} -module.exports = (C: any); -" +module.exports = (C: any);" `; exports[`test scope.js 1`] = ` @@ -244,13 +257,16 @@ class Foo { } } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// hypothetical immutable map type Merge = (a: T, b: T) => T; + +// hypothetical immutable map declare class Map { (): Map, insertWith(fn: Merge, k: K, v: V): Map } + declare function foldr(fn: (a: A, b: B) => B, b: B, as: A[]): B; + function insertMany( merge: Merge, vs: [K, V][], @@ -261,14 +277,14 @@ function insertMany( } return foldr(f, m, vs); } + class Foo { bar() { return function(a: A, b: B, c: C): void { ([ a, b, c ]: [A, B, C]); }; } -} -" +}" `; exports[`test test.js 1`] = ` @@ -276,6 +292,5 @@ exports[`test test.js 1`] = ` ((0: C): string); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ var C = require(\"./other\"); -((0: C): string); -" +((0: C): string);" `; diff --git a/tests/annot/any/__snapshots__/jsfmt.spec.js.snap b/tests/annot/any/__snapshots__/jsfmt.spec.js.snap index f6070a87..79123e3b 100644 --- a/tests/annot/any/__snapshots__/jsfmt.spec.js.snap +++ b/tests/annot/any/__snapshots__/jsfmt.spec.js.snap @@ -10,13 +10,14 @@ export default class { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ type T = any; + export default class { p: T; + constructor() { this.p = 0; } -} -" +}" `; exports[`test B.js 1`] = ` @@ -26,10 +27,9 @@ class B extends A { p: string; // OK, string ~> any } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// OK, string ~> any import A from \"./A\"; + class B extends A { - p: string; -} -" + p: string; // OK, string ~> any +}" `; diff --git a/tests/annot2/__snapshots__/jsfmt.spec.js.snap b/tests/annot2/__snapshots__/jsfmt.spec.js.snap index ad5e53c3..29765fd7 100644 --- a/tests/annot2/__snapshots__/jsfmt.spec.js.snap +++ b/tests/annot2/__snapshots__/jsfmt.spec.js.snap @@ -18,14 +18,16 @@ export default class { * @providesModule A * @flow */ + import type T from \"T\"; + export default class { p: T; + constructor() { this.p = 0; } -} -" +}" `; exports[`test B.js 1`] = ` @@ -42,12 +44,12 @@ class B extends A { /** * @flow */ -// OK, string ~> any + import A from \"A\"; + class B extends A { - p: string; -} -" + p: string; // OK, string ~> any +}" `; exports[`test T.js 1`] = ` @@ -55,9 +57,5 @@ exports[`test T.js 1`] = ` * @providesModule T */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -/** - * @providesModule T - */ - " `; diff --git a/tests/any/__snapshots__/jsfmt.spec.js.snap b/tests/any/__snapshots__/jsfmt.spec.js.snap index 8c9272d1..00f33d26 100644 --- a/tests/any/__snapshots__/jsfmt.spec.js.snap +++ b/tests/any/__snapshots__/jsfmt.spec.js.snap @@ -10,6 +10,7 @@ var y:string = bar(0); var z:string = qux(0); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + function foo(x: any): any { return x; } @@ -19,10 +20,10 @@ function bar(x: any): mixed { function qux(x: mixed): any { return x; } + var x: string = foo(0); var y: string = bar(0); -var z: string = qux(0); -" +var z: string = qux(0);" `; exports[`test anyexportflowfile.js 1`] = ` @@ -31,8 +32,8 @@ exports[`test anyexportflowfile.js 1`] = ` module.exports = ((x: any) => x: any); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -module.exports = ((x: any) => x: any); -" + +module.exports = ((x: any) => x: any);" `; exports[`test flowfixme.js 1`] = ` @@ -62,26 +63,27 @@ var w:string = baz(0); @flow */ + // no param -// param (info only) -// ...params are still checked. unknown type function foo(x: $FlowFixMe): $FlowFixMe { return x; } function bar(x: $FlowFixMe): mixed { return x; } +// param (info only) function qux(x: $FlowFixMe): $FlowFixMe { return x; } +// ...params are still checked. unknown type function baz(x: $FlowFixMe): $FlowFixMe { return x; } + var x: string = foo(0); var y: string = bar(0); var z: string = qux(0); -var w: string = baz(0); -" +var w: string = baz(0);" `; exports[`test flowissue.js 1`] = ` @@ -111,26 +113,27 @@ var w:string = baz(0); @flow */ + // no param -// param (info only) -// ...params are still checked. unknown type function foo(x: $FlowIssue): $FlowIssue { return x; } function bar(x: $FlowIssue): mixed { return x; } +// param (info only) function qux(x: $FlowIssue): $FlowIssue { return x; } +// ...params are still checked. unknown type function baz(x: $FlowIssue): $FlowIssue { return x; } + var x: string = foo(0); var y: string = bar(0); var z: string = qux(0); -var w: string = baz(0); -" +var w: string = baz(0);" `; exports[`test nonflowfile.js 1`] = ` @@ -139,8 +142,8 @@ exports[`test nonflowfile.js 1`] = ` module.exports = (x) => x; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @noflow -module.exports = x => x; -" + +module.exports = x => x;" `; exports[`test propagate.js 1`] = ` @@ -171,28 +174,30 @@ function bar2(x: mixed) { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// should be able to select first case and error + declare class C { bar(n1: number, n2: number): number, bar(s1: string, s2: string): string } + function foo(c: C, x: any): string { let y = x.y; - return c.bar(0, y); + return c.bar(0, y); // should be able to select first case and error } + var any_fun1 = require(\"./nonflowfile\"); function bar1(x: mixed) { if (any_fun1(x)) { (x: boolean); } } + var any_fun2 = require(\"./anyexportflowfile\"); function bar2(x: mixed) { if (any_fun2(x)) { (x: boolean); } -} -" +}" `; exports[`test reach.js 1`] = ` @@ -215,11 +220,12 @@ function foo(o: ?AsyncRequest) { * type annotations. Here we test propagation of any through the * annotation - without it, the body of the if will be unreachable */ + type AsyncRequest = any; + function foo(o: ?AsyncRequest) { if (o) { var n: number = o; } -} -" +}" `; diff --git a/tests/arith/__snapshots__/jsfmt.spec.js.snap b/tests/arith/__snapshots__/jsfmt.spec.js.snap index c5a6a2e7..58c4f6b4 100644 --- a/tests/arith/__snapshots__/jsfmt.spec.js.snap +++ b/tests/arith/__snapshots__/jsfmt.spec.js.snap @@ -92,116 +92,118 @@ let tests = [ ]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @providesModule Arith */ -// error -// error -// error -// test MaybeT(NumT) -// test OptionalT(NumT) -// test OptionalT(MaybeT(NumT)) -// === 0 -// === NaN -// === 1 -// === 1 -// === NaN -// === NaN -// === 1 -// === 1 -// === NaN -// === NaN -// error -// error -// error -// error -// error -// error -// error -// error -// error -// error -// error -// error -// error -// when one side is a string or number and the other is invalid, we -// assume you are expecting a string or number (respectively), rather than -// erroring twice saying number !~> string and obj !~> string. -// error: object !~> number -// error: object !~> number -// error: object !~> string -// error: object !~> string -// ok -// ok -// error, string ~> empty -// error, string ~> empty + function num(x: number) {} + function str(x: string) {} + function foo() { var x = 0; var y = \"...\"; var z = {}; num(x + x); num(x + y); + // error str(x + y); str(x + x); - str(z + y); + // error + str(z + y); // error } + +// test MaybeT(NumT) function bar0(x: ?number, y: number) { num(x + y); } function bar1(x: number, y: ?number) { num(x + y); } + +// test OptionalT(NumT) function bar2(x?: number, y: number) { num(x + y); } function bar3(x: number, y?: number) { num(x + y); } + +// test OptionalT(MaybeT(NumT)) function bar4(x?: ?number, y: number) { num(x + y); } function bar5(x: number, y?: ?number) { num(x + y); } + num(null + null); +// === 0 num(undefined + undefined); +// === NaN num(null + 1); +// === 1 num(1 + null); +// === 1 num(undefined + 1); +// === NaN num(1 + undefined); +// === NaN num(null + true); +// === 1 num(true + null); +// === 1 num(undefined + true); +// === NaN num(true + undefined); +// === NaN str(\"foo\" + true); +// error str(true + \"foo\"); +// error str(\"foo\" + null); +// error str(null + \"foo\"); +// error str(\"foo\" + undefined); +// error str(undefined + \"foo\"); +// error let tests = [ function(x: mixed, y: mixed) { x + y; + // error x + 0; + // error 0 + x; + // error x + \"\"; + // error \"\" + x; + // error x + {}; - ({}) + x; + // error + ({}) + x; // error }, + // when one side is a string or number and the other is invalid, we + // assume you are expecting a string or number (respectively), rather than + // erroring twice saying number !~> string and obj !~> string. function() { (1 + {}: number); + // error: object !~> number ({} + 1: number); + // error: object !~> number (\"1\" + {}: string); - ({} + \"1\": string); + // error: object !~> string + ({} + \"1\": string); // error: object !~> string }, function(x: any, y: number, z: string) { (x + y: string); + // ok (y + x: string); + // ok (x + z: empty); - (z + x: empty); + // error, string ~> empty + (z + x: empty); // error, string ~> empty } -]; -" +];" `; exports[`test exponent.js 1`] = ` @@ -218,15 +220,16 @@ y **= 2; // error (-2) ** 2; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// error + let x: number = 2 ** 3; x **= 4; + let y: string = \"123\"; y **= 2; +// error 1 + 2 ** 3 + 4; 2 ** 2; -(-2) ** 2; -" +(-2) ** 2;" `; exports[`test generic.js 1`] = ` @@ -239,27 +242,26 @@ function f(a: A, b: B): B {return a + b; } // error function f(a: A, b: B): B {return b + a; } // error ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// error -// error -// error -// error -// error + function f(a: A): A { return a + a; } +// error function f(a: A, b: B): A { return a + b; } +// error function f(a: A, b: B): A { return b + a; } +// error function f(a: A, b: B): B { return a + b; } +// error function f(a: A, b: B): B { return b + a; -} -" +} // error" `; exports[`test mult.js 1`] = ` @@ -277,15 +279,17 @@ let y: string = \"123\"; y *= 2; // error ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// error + function num(x: number) {} + num(null * 1); num(1 * null); + let x: number = 2 * 3; x *= 4; + let y: string = \"123\"; -y *= 2; -" +y *= 2; // error" `; exports[`test relational.js 1`] = ` @@ -321,43 +325,44 @@ let tests = [ ]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// error -// error -// error -// error -// error -// error -// error -// 2 errors: null !~> number; undefined !~> number -// 2 errors: null !~> number; undefined !~> number -// error -// error -// error -// error + 1 < 2; 1 < \"foo\"; +// error \"foo\" < 1; +// error \"foo\" < \"bar\"; 1 < { foo: 1 }; +// error ({ foo: 1 }) < 1; +// error ({ foo: 1 }) < { foo: 1 }; +// error \"foo\" < { foo: 1 }; +// error ({ foo: 1 }) < \"foo\"; +// error var x = (null: ?number); 1 < x; +// 2 errors: null !~> number; undefined !~> number x < 1; +// 2 errors: null !~> number; undefined !~> number null < null; +// error undefined < null; +// error null < undefined; +// error undefined < undefined; +// error NaN < 1; 1 < NaN; NaN < NaN; + let tests = [ function(x: any, y: number, z: string) { x > y; x > z; } -]; -" +];" `; diff --git a/tests/array-filter/__snapshots__/jsfmt.spec.js.snap b/tests/array-filter/__snapshots__/jsfmt.spec.js.snap index 55c9ec1e..6d4b7c85 100644 --- a/tests/array-filter/__snapshots__/jsfmt.spec.js.snap +++ b/tests/array-filter/__snapshots__/jsfmt.spec.js.snap @@ -10,13 +10,14 @@ function filterOutSmall (arr: Array): Array { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + function filterOutVoids(arr: Array): Array { return arr.filter(Boolean); } + function filterOutSmall(arr: Array): Array { return arr.filter(num => num && num > 10); -} -" +}" `; exports[`test test2.js 1`] = ` @@ -37,6 +38,7 @@ const filteredItems = filterItems([\'foo\', \'b\', 1, 2]); console.log(filteredItems); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + function filterItems(items: Array): Array { return items.map(item => { if (typeof item === \"string\") { @@ -46,7 +48,8 @@ function filterItems(items: Array): Array { } }).filter(Boolean); } + const filteredItems = filterItems([ \"foo\", \"b\", 1, 2 ]); -console.log(filteredItems); -" + +console.log(filteredItems);" `; diff --git a/tests/array_spread/__snapshots__/jsfmt.spec.js.snap b/tests/array_spread/__snapshots__/jsfmt.spec.js.snap index c902ddba..492d4a0d 100644 --- a/tests/array_spread/__snapshots__/jsfmt.spec.js.snap +++ b/tests/array_spread/__snapshots__/jsfmt.spec.js.snap @@ -13,7 +13,7 @@ var B = [ ...A ]; var C = [ 1, 2, 3 ]; B.sort((a, b) => a - b); C.sort((a, b) => a - b); + var x: Array = [ \"1\", \"2\" ]; -var y: Array = [ \"3\", ...x ]; -" +var y: Array = [ \"3\", ...x ];" `; diff --git a/tests/arraylib/__snapshots__/jsfmt.spec.js.snap b/tests/arraylib/__snapshots__/jsfmt.spec.js.snap index d9048ff0..ab3f33f7 100644 --- a/tests/arraylib/__snapshots__/jsfmt.spec.js.snap +++ b/tests/arraylib/__snapshots__/jsfmt.spec.js.snap @@ -58,27 +58,24 @@ function from_test() { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// Error -/* Adapted from the following source: - * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce - */ -/* Added later, because the above is insufficient */ -// acc is element type of array when no init is provided -// error, string ~> number -// error, string ~> number function foo(x: string) {} + var a = [ 0 ]; var b = a.map(function(x) { foo(x); return \"\" + x; }); + var c: number = a[0]; var d: number = b[0]; + var e: Array = a.reverse(); + var f = [ \"\" ]; var g: number = f.map(function() { return 0; })[0]; + var h: Array = [ 1, 2, 3 ]; var i: Array = [ \"a\", \"b\", \"c\" ]; var j: Array = h.concat(i); @@ -86,25 +83,37 @@ var k: Array = h.concat(h); var l: Array = h.concat(1, 2, 3); var m: Array = h.concat(\"a\", \"b\", \"c\"); var n: Array = h.concat(\"a\", \"b\", \"c\"); +// Error function reduce_test() { + /* Adapted from the following source: + * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce + */ [ 0, 1, 2, 3, 4 ].reduce(function(previousValue, currentValue, index, array) { return previousValue + currentValue + array[index]; }); + [ 0, 1, 2, 3, 4 ].reduce( function(previousValue, currentValue, index, array) { return previousValue + currentValue + array[index]; }, 10 ); + var total = [ 0, 1, 2, 3 ].reduce(function(a, b) { return a + b; }); + var flattened = [ [ 0, 1 ], [ 2, 3 ], [ 4, 5 ] ].reduce(function(a, b) { return a.concat(b); }); + + /* Added later, because the above is insufficient */ + // acc is element type of array when no init is provided [ \"\" ].reduce((acc, str) => acc * str.length); - [ \"\" ].reduceRight((acc, str) => acc * str.length); + // error, string ~> number + [ \"\" ].reduceRight((acc, str) => acc * str.length); // error, string ~> number } + function from_test() { var a: Array = Array.from([ 1, 2, 3 ], function(val, index) { return index % 2 ? \"foo\" : String(val); @@ -112,6 +121,5 @@ function from_test() { var b: Array = Array.from([ 1, 2, 3 ], function(val) { return String(val); }); -} -" +}" `; diff --git a/tests/arrays/__snapshots__/jsfmt.spec.js.snap b/tests/arrays/__snapshots__/jsfmt.spec.js.snap index 8ca259f3..56b529b4 100644 --- a/tests/arrays/__snapshots__/jsfmt.spec.js.snap +++ b/tests/arrays/__snapshots__/jsfmt.spec.js.snap @@ -40,17 +40,22 @@ var abig2: Array<{x:number; y:number}> = [ module.exports = \"arrays\"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @providesModule Arrays */ -// for literals, composite element type is union of individuals -// note: test both tuple and non-tuple inferred literals + function foo(x: string) {} + var a = []; a[0] = 1; a[1] = \"...\"; + foo(a[1]); var y; a.forEach(x => y = x); + +// for literals, composite element type is union of individuals +// note: test both tuple and non-tuple inferred literals var alittle: Array = [ 0, 1, 2, 3, null ]; var abig: Array = [ 0, 1, 2, 3, 4, 5, 6, 8, null ]; + var abig2: Array<{ x: number, y: number }> = [ { x: 0, y: 0 }, { x: 0, y: 0 }, @@ -70,8 +75,8 @@ var abig2: Array<{ x: number, y: number }> = [ { x: 0, y: 0, c: 1 }, { x: 0, y: 0, c: \"hey\" } ]; -module.exports = \"arrays\"; -" + +module.exports = \"arrays\";" `; exports[`test numeric_elem.js 1`] = ` @@ -83,12 +88,11 @@ var day = new Date; arr[day] = 0; (arr[day]: string); // error: number ~> string ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Date instances are numeric (see Flow_js.numeric) and thus can index into -// arrays. -// error: number ~> string var arr = []; var day = new Date(); + +// Date instances are numeric (see Flow_js.numeric) and thus can index into +// arrays. arr[day] = 0; -(arr[day]: string); -" +(arr[day]: string); // error: number ~> string" `; diff --git a/tests/arrows/__snapshots__/jsfmt.spec.js.snap b/tests/arrows/__snapshots__/jsfmt.spec.js.snap index e584d2ee..656caa77 100644 --- a/tests/arrows/__snapshots__/jsfmt.spec.js.snap +++ b/tests/arrows/__snapshots__/jsfmt.spec.js.snap @@ -14,14 +14,14 @@ var ident = (x: T): T => x; /** * @flow */ -// Error! -// Error + var add = (x: number, y: number): number => x + y; + var bad = (x: number): string => x; +// Error! var ident = (x: T): T => x; (ident(1): number); -(ident(\"hi\"): number); -" +(ident(\"hi\"): number); // Error" `; exports[`test arrows.js 1`] = ` @@ -36,15 +36,14 @@ exports[`test arrows.js 1`] = ` images[images.length - 1]; } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -//images = images.sort(function (a, b) { return a.width - b.width }); function selectBestEffortImageForWidth( maxWidth: number, images: Array ): Image { var maxPixelWidth = maxWidth; + //images = images.sort(function (a, b) { return a.width - b.width }); images = images.sort((a, b) => a.width - b.width + \"\"); return images.find(image => image.width >= maxPixelWidth) || images[images.length - 1]; -} -" +}" `; diff --git a/tests/async/__snapshots__/jsfmt.spec.js.snap b/tests/async/__snapshots__/jsfmt.spec.js.snap index ff7d0b2e..564deaeb 100644 --- a/tests/async/__snapshots__/jsfmt.spec.js.snap +++ b/tests/async/__snapshots__/jsfmt.spec.js.snap @@ -53,39 +53,43 @@ var obj = { f: async () => await 1 }; var objf : () => Promise = obj.f; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + // \"For async functions, a Promise is returned, // and the type of return expressions must be T.\" // -// error, number != bool -// await: (p: Promise | T) => T -// -// TODO: this is one of those bad generic errors, currently: -// \"inconsistent use of library definitions\" with two core.js locs -// error, number != bool -// async arrow functions -// -// async methods -// -// error, void != Promise -// async function props + async function f0(): Promise { return 1; } + async function f1(): Promise { - return 1; + return 1; // error, number != bool } + +// await: (p: Promise | T) => T +// async function f2(p: Promise): Promise { var x: number = await p; var y: number = await 1; return x + y; } + async function f3(p: Promise): Promise { return await p; } + +// TODO: this is one of those bad generic errors, currently: +// \"inconsistent use of library definitions\" with two core.js locs async function f4(p: Promise): Promise { - return await p; + return await p; // error, number != bool } + +// async arrow functions +// var f5: () => Promise = async () => await 1; + +// async methods +// class C { async m() { return 1; @@ -96,13 +100,15 @@ class C { static async m(a): void { await a; } + // error, void != Promise static async mt(a: T): Promise { return a; } } + +// async function props var obj = { f: async () => await 1 }; -var objf: () => Promise = obj.f; -" +var objf: () => Promise = obj.f;" `; exports[`test async_base_class.js 1`] = ` @@ -126,14 +132,15 @@ async function foo() { // am not clear on whether it should. In any case it\'s a strange corner case // that is probably not important to support. class C {} + var P: Promise> = new Promise(function(resolve, reject) { resolve(C); }); + async function foo() { class Bar extends (await P) {} return Bar; -} -" +}" `; exports[`test async_parse.js 1`] = ` @@ -164,23 +171,28 @@ var y = { async }; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ async function f() {} async function ft(a: T) {} + class C { async m() {} async mt(a: T) {} static async m(a) {} static async mt(a: T) {} } + var e = async function() {}; var et = async function(a: T) {}; + var n = new async function() {}(); + var o = { async m() {} }; var ot = { async m(a: T) {} }; var oz = { async async() {} }; + var x = { async: 5 }; console.log(x.async); + var async = 3; -var y = { async }; -" +var y = { async };" `; exports[`test async_promise.js 1`] = ` @@ -190,8 +202,7 @@ exports[`test async_promise.js 1`] = ` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ async function f(): Promise { return Promise.resolve(1); -} -" +}" `; exports[`test async_return_void.js 1`] = ` @@ -211,17 +222,19 @@ async function foo3(): Promise { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + async function foo1(): Promise { return; } + async function foo2(): Promise { return undefined; } + async function foo3(): Promise { function bar() {} return bar(); -} -" +}" `; exports[`test async2.js 1`] = ` @@ -287,59 +300,64 @@ function test5() { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + // misc basic -// valid -// Error: number ~> string + +function test1() { + async function foo() { + return 42; + } + + async function bar() { + var a = await foo(); + var b: number = a; + // valid + var c: string = a; // Error: number ~> string + } +} + // // void returns: // // inference should produce return type Promise // in the absence of an explicit return // -// ok -// error, void != Promise -// annotated return type of Promise should work -// -// ok -// other annotated return types should fail -// (note: misannotated return types with explicit -// return statements are covered in async.js) -// -// error, void != Promise -// error, number != void -function test1() { - async function foo() { - return 42; - } - async function bar() { - var a = await foo(); - var b: number = a; - var c: string = a; - } -} function test2() { async function voidoid1() { console.log(\"HEY\"); } + var voidoid2: () => Promise = voidoid1; - var voidoid3: () => void = voidoid1; + // ok + var voidoid3: () => void = voidoid1; // error, void != Promise } + +// annotated return type of Promise should work +// function test3() { async function voidoid4(): Promise { + // ok console.log(\"HEY\"); } } + +// other annotated return types should fail +// (note: misannotated return types with explicit +// return statements are covered in async.js) +// function test4() { async function voidoid5(): void { + // error, void != Promise console.log(\"HEY\"); } } + function test5() { async function voidoid6(): Promise { + // error, number != void console.log(\"HEY\"); } -} -" +}" `; exports[`test async3.js 1`] = ` @@ -377,6 +395,7 @@ async function baz() { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + /** * test nested-promise unwrapping. * Note: currently we don\'t do this properly in the underlying @@ -384,24 +403,28 @@ async function baz() { * be raised here. Once that\'s fixed, the errors here will go * away. */ -// a should now be typed as number, but is in fact -// Promise until nested-promise unwrap is fixed -// TODO this is valid code, but currently gives Promise ~> number error -// due to lack of transitive Promise unwrap. -// should be number ~> string error, but currently gives -// Promise ~> string error for the same reason + async function foo() { return 42; } + async function bar() { return foo(); } + async function baz() { + // a should now be typed as number, but is in fact + // Promise until nested-promise unwrap is fixed var a = await bar(); + + // TODO this is valid code, but currently gives Promise ~> number error + // due to lack of transitive Promise unwrap. var b: number = a; + + // should be number ~> string error, but currently gives + // Promise ~> string error for the same reason var c: string = a; -} -" +}" `; exports[`test await_parse.js 1`] = ` @@ -436,6 +459,7 @@ async function f() { async function ft(a: T) { await 1; } + class C { async m() { await 1; @@ -450,15 +474,18 @@ class C { await 1; } } + var e = async function() { await 1; }; var et = async function(a: T) { await 1; }; + var n = new async function() { await 1; }(); + var o = { async m() { await 1; @@ -474,9 +501,10 @@ var oz = { await async; } }; + var x = { await: 5 }; console.log(x.await); + var await = 3; -var y = { await }; -" +var y = { await };" `; diff --git a/tests/async_iteration/__snapshots__/jsfmt.spec.js.snap b/tests/async_iteration/__snapshots__/jsfmt.spec.js.snap index 92ce089a..68491e43 100644 --- a/tests/async_iteration/__snapshots__/jsfmt.spec.js.snap +++ b/tests/async_iteration/__snapshots__/jsfmt.spec.js.snap @@ -26,16 +26,14 @@ async function *delegate_return() { var x: void = yield *inner(); // error: number ~> void } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// error: number ~> void -// error: number ~> void -// error: number ~> void async function* delegate_next() { async function* inner() { - var x: void = yield; + var x: void = yield; // error: number ~> void } yield* inner(); } delegate_next().next(0); + async function* delegate_yield() { async function* inner() { yield 0; @@ -44,16 +42,16 @@ async function* delegate_yield() { } async () => { for await (const x of delegate_yield()) { - (x: void); + (x: void); // error: number ~> void } }; + async function* delegate_return() { async function* inner() { return 0; } - var x: void = yield* inner(); -} -" + var x: void = yield* inner(); // error: number ~> void +}" `; exports[`test generator.js 1`] = ` @@ -83,11 +81,13 @@ async function f() { } } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// error: string ~> void interface File { readLine(): Promise, close(): void, EOF: boolean } + declare function fileOpen(path: string): Promise; + async function* readLines(path) { let file: File = await fileOpen(path); + try { while (!file.EOF) { yield await file.readLine(); @@ -96,12 +96,12 @@ async function* readLines(path) { file.close(); } } + async function f() { for await (const line of readLines(\"/path/to/file\")) { - (line: void); + (line: void); // error: string ~> void } -} -" +}" `; exports[`test return.js 1`] = ` @@ -128,16 +128,16 @@ refuse_return().return(\"string\").then(result => { } }); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +declare var gen: AsyncGenerator; + // You can pass whatever you like to return, it doesn\'t need to be related to // the AsyncGenerator\'s return type -// error: string | number ~> void +gen.return(0).then(result => { + (result.value: void); // error: string | number ~> void +}); + // However, a generator can \"refuse\" the return by catching an exception and // yielding or returning internally. -// error: number | void ~> string -declare var gen: AsyncGenerator; -gen.return(0).then(result => { - (result.value: void); -}); async function* refuse_return() { try { yield 1; @@ -147,10 +147,9 @@ async function* refuse_return() { } refuse_return().return(\"string\").then(result => { if (result.done) { - (result.value: string); + (result.value: string); // error: number | void ~> string } -}); -" +});" `; exports[`test throw.js 1`] = ` @@ -187,8 +186,6 @@ async function *yield_return() { }); }); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// error: number ~> void -// error: number ~> void async function* catch_return() { try { yield 0; @@ -196,13 +193,15 @@ async function* catch_return() { return e; } } + async () => { catch_return().throw(\"\").then(({ value }) => { if (value !== undefined) { - (value: void); + (value: void); // error: number ~> void } }); }; + async function* yield_return() { try { yield 0; @@ -211,12 +210,12 @@ async function* yield_return() { yield e; } } + async () => { yield_return().throw(\"\").then(({ value }) => { if (value !== undefined) { - (value: void); + (value: void); // error: number ~> void } }); -}; -" +};" `; diff --git a/tests/autocomplete/__snapshots__/jsfmt.spec.js.snap b/tests/autocomplete/__snapshots__/jsfmt.spec.js.snap index c39735c8..a9d50a3a 100644 --- a/tests/autocomplete/__snapshots__/jsfmt.spec.js.snap +++ b/tests/autocomplete/__snapshots__/jsfmt.spec.js.snap @@ -12,6 +12,7 @@ declare var objectAssign: Object$Assign m ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + declare var idx: $Facebookism$Idx; declare var merge: $Facebookism$Merge; declare var mergeDeepInto: $Facebookism$MergeDeepInto; @@ -19,8 +20,8 @@ declare var mergeInto: $Facebookism$MergeInto; declare var mixin: $Facebookism$Mixin; declare var objectGetPrototypeOf: Object$GetPrototypeOf; declare var objectAssign: Object$Assign; -m; -" + +m;" `; exports[`test unknown.js 1`] = ` @@ -28,6 +29,5 @@ exports[`test unknown.js 1`] = ` module.exports = { x: { y: \"\" } }; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @noflow -module.exports = { x: { y: \"\" } }; -" +module.exports = { x: { y: \"\" } };" `; diff --git a/tests/auxiliary/__snapshots__/jsfmt.spec.js.snap b/tests/auxiliary/__snapshots__/jsfmt.spec.js.snap index 37d954bc..312f6bf6 100644 --- a/tests/auxiliary/__snapshots__/jsfmt.spec.js.snap +++ b/tests/auxiliary/__snapshots__/jsfmt.spec.js.snap @@ -1,6 +1,5 @@ exports[`test client.js 1`] = ` "var y:number = x; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -var y: number = x; -" +var y: number = x;" `; diff --git a/tests/auxiliary/lib/__snapshots__/jsfmt.spec.js.snap b/tests/auxiliary/lib/__snapshots__/jsfmt.spec.js.snap index 0f050a1f..17775692 100644 --- a/tests/auxiliary/lib/__snapshots__/jsfmt.spec.js.snap +++ b/tests/auxiliary/lib/__snapshots__/jsfmt.spec.js.snap @@ -1,6 +1,5 @@ exports[`test lib.js 1`] = ` "declare var x: string; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -declare var x: string; -" +declare var x: string;" `; diff --git a/tests/binary/__snapshots__/jsfmt.spec.js.snap b/tests/binary/__snapshots__/jsfmt.spec.js.snap index 5b8ba242..088fe984 100644 --- a/tests/binary/__snapshots__/jsfmt.spec.js.snap +++ b/tests/binary/__snapshots__/jsfmt.spec.js.snap @@ -55,64 +55,61 @@ let tests = [ ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// objects on RHS -// arrays on RHS -// primitive classes on RHS -// primitives on RHS -// error -// error -// error -// error -// bogus stuff on LHS -// error -// error -// error -// error -// error -// in predicates -// error -// error, !\'foo\' is a boolean -// annotations on RHS -// ok -// error + let tests = [ + // objects on RHS function() { \"foo\" in {}; \"foo\" in { foo: null }; 0 in {}; 0 in { \"0\": null }; }, + // arrays on RHS function() { \"foo\" in []; 0 in []; \"length\" in []; }, + // primitive classes on RHS function() { \"foo\" in new String(\"bar\"); \"foo\" in new Number(123); }, + // primitives on RHS function() { \"foo\" in 123; + // error \"foo\" in \"bar\"; + // error \"foo\" in void 0; - \"foo\" in null; + // error + \"foo\" in null; // error }, + // bogus stuff on LHS function() { null in {}; + // error void 0 in {}; + // error ({}) in {}; + // error [] in {}; - false in []; + // error + false in []; // error }, + // in predicates function() { if (\"foo\" in 123) {} + // error if (!\"foo\" in {}) {} + // error, !\'foo\' is a boolean if (!(\"foo\" in {})) {} }, + // annotations on RHS function(x: Object, y: mixed) { \"foo\" in x; - \"foo\" in y; + // ok + \"foo\" in y; // error } -]; -" +];" `; diff --git a/tests/binding/__snapshots__/jsfmt.spec.js.snap b/tests/binding/__snapshots__/jsfmt.spec.js.snap index fb51cf02..05c304cd 100644 --- a/tests/binding/__snapshots__/jsfmt.spec.js.snap +++ b/tests/binding/__snapshots__/jsfmt.spec.js.snap @@ -27,12 +27,9 @@ for (const { baz } of bazzes) { (baz: number); // error: string ~> number } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// errors: const cannot be reassigned -// regression tests -- OK to assign consts like this: -// error: string ~> number -// error: string ~> number -// error: string ~> number const x = 0; + +// errors: const cannot be reassigned x++; x--; x += 0; @@ -45,15 +42,18 @@ x >>>= 0; x |= 0; x ^= 0; x &= 0; + +// regression tests -- OK to assign consts like this: const { foo } = { foo: \"foo\" }; const [ bar ] = [ \"bar\" ]; (foo: number); +// error: string ~> number (bar: number); +// error: string ~> number declare var bazzes: { baz: string }[]; for (const { baz } of bazzes) { - (baz: number); -} -" + (baz: number); // error: string ~> number +}" `; exports[`test rebinding.js 1`] = ` @@ -265,188 +265,189 @@ function fn_params_clash_fn_binding(x,y) { * const x x x x x x * var x x x x */ + // type x * -// error: name already bound -// error: name already bound -// error: name already bound -// error: name already bound -// error: name already bound -// error: type alias ref\'d from value pos -// class x * -// error: name already bound -// error: name already bound -// error: name already bound -// error: name already bound -// error: name already bound -// let x * -// error: name already bound -// error: name already bound -// error: name already bound -// error: name already bound -// error: name already bound -// const x * -// error: name already bound -// error: name already bound -// error: name already bound -// error: name already bound -// error: name already bound -// error: cannot be reassigned -// var x * -// error: name already bound -// error: name already bound -// error: name already bound -// error: name already bound -// OK -// function x * -// OK -// error: name already bound -// corner cases -// error: name already bound -// error: name already bound -// fn params name clash -/* error: x already bound */ -// error: x already bound -// OK + function type_type() { type A = number; - type A = number; + type A = number; // error: name already bound } + function type_class() { type A = number; - class A {} + class A {} // error: name already bound } + function type_let() { type A = number; - let A = 0; + let A = 0; // error: name already bound } + function type_const() { type A = number; - const A = 0; + const A = 0; // error: name already bound } + function type_var() { type A = number; - var A = 0; + var A = 0; // error: name already bound } + function type_reassign() { type A = number; - A = 42; + A = 42; // error: type alias ref\'d from value pos } + +// class x * function class_type() { class A {} - type A = number; + type A = number; // error: name already bound } + function class_class() { class A {} - class A {} + class A {} // error: name already bound } + function class_let() { class A {} - let A = 0; + let A = 0; // error: name already bound } + function class_const() { class A {} - const A = 0; + const A = 0; // error: name already bound } + function class_var() { class A {} - var A = 0; + var A = 0; // error: name already bound } + +// let x * function let_type() { let A = 0; - type A = number; + type A = number; // error: name already bound } + function let_class() { let A = 0; - class A {} + class A {} // error: name already bound } + function let_let() { let A = 0; - let A = 0; + let A = 0; // error: name already bound } + function let_const() { let A = 0; - const A = 0; + const A = 0; // error: name already bound } + function let_var() { let A = 0; - var A = 0; + var A = 0; // error: name already bound } + +// const x * function const_type() { const A = 0; - type A = number; + type A = number; // error: name already bound } + function const_class() { const A = 0; - class A {} + class A {} // error: name already bound } + function const_let() { const A = 0; - let A = 0; + let A = 0; // error: name already bound } + function const_const() { const A = 0; - const A = 0; + const A = 0; // error: name already bound } + function const_var() { const A = 0; - var A = 0; + var A = 0; // error: name already bound } + function const_reassign() { const A = 0; - A = 42; + A = 42; // error: cannot be reassigned } + +// var x * function var_type() { var A = 0; - type A = number; + type A = number; // error: name already bound } + function var_class() { var A = 0; - class A {} + class A {} // error: name already bound } + function var_let() { var A = 0; - let A = 0; + let A = 0; // error: name already bound } + function var_const() { var A = 0; - const A = 0; + const A = 0; // error: name already bound } + function var_var() { var A = 0; - var A = 0; + var A = 0; // OK } + +// function x * function function_toplevel() { function a() {} + function a() {} } + function function_block() { { function a() {} + function a() {} } } + +// corner cases function var_shadow_nested_scope() { { let x = 0; { - var x = 0; + var x = 0; // error: name already bound } } } + function type_shadow_nested_scope() { { let x = 0; { - type x = string; + type x = string; // error: name already bound } } } -function fn_params_name_clash(x, x) {} + +// fn params name clash +function fn_params_name_clash(x, x /* error: x already bound */) {} function fn_params_clash_fn_binding(x, y) { let x = 0; - var y = 0; -} -" + // error: x already bound + var y = 0; // OK +}" `; exports[`test scope.js 1`] = ` @@ -560,125 +561,124 @@ function default_param_2() { } } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// ok: local to block -// error: string ~> number -// ok: local to switch -// error: string ~> number -// error: a already bound in switch -// a switch is a single lexical scope, so lets and non-disjoint -// cases can mix in odd ways. our support for edge cases is not -// yet perfect. -// error: assign before declaration -// error: use before declaration -// error: skipped initializer -// error: skipped initializer -// error: a no longer in scope -// ok -// ok -// ok -/* ok: local to init */ -/* error: string ~> number */ -/* ok: local to init */ -/* error: string ~> number */ -/* ok: local to init */ -/* error: string ~> number */ -// function binding in scope in default expr -// error: number ~> string -// fn body bindings not visible from param scope -// error: string ~> number -/* error: cannot resolve b */ function block_scope() { let a: number = 0; var b: number = 0; { let a = \"\"; - var b = \"\"; + // ok: local to block + var b = \"\"; // error: string ~> number } } + function switch_scope(x: string) { let a: number = 0; var b: number = 0; switch (x) { case \"foo\": let a = \"\"; + // ok: local to switch var b = \"\"; + // error: string ~> number break; case \"bar\": let a = \"\"; + // error: a already bound in switch break; } } + +// a switch is a single lexical scope, so lets and non-disjoint +// cases can mix in odd ways. our support for edge cases is not +// yet perfect. function switch_scope2(x: number) { switch (x) { case 0: a = \"\"; + // error: assign before declaration break; case 1: var b = a; + // error: use before declaration break; case 2: let a = \"\"; break; case 3: a = \"\"; + // error: skipped initializer break; case 4: var c: string = a; + // error: skipped initializer break; } - a = \"\"; + a = \"\"; // error: a no longer in scope } + function try_scope() { let a: number = 0; try { - let a = \"\"; + let a = \"\"; // ok } catch (e) { - let a = \"\"; + let a = \"\"; // ok } finally { - let a = \"\"; + let a = \"\"; // ok } } + function for_scope_let() { let a: number = 0; - for (let a = \"\"; ; ) {} + for (let a = \"\" /* ok: local to init */; ; ) {} } + function for_scope_var() { var a: number = 0; - for (var a = \"\"; ; ) {} + for (var a = \"\" /* error: string ~> number */; ; ) {} } + function for_in_scope_let(o: Object) { let a: number = 0; - for (let a in o) {} + for (let a /* ok: local to init */ in o) {} } + function for_in_scope_var(o: Object) { var a: number = 0; - for (var a in o) {} + for (var a /* error: string ~> number */ in o) {} } + function for_of_scope_let(xs: string[]) { let a: number = 0; - for (let a of xs) {} + for (let a /* ok: local to init */ of xs) {} } + function for_of_scope_var(xs: string[]) { var a: number = 0; - for (var a of xs) {} + for (var a /* error: string ~> number */ of xs) {} } + function default_param_1() { - function f(x: () => string = f): number { + // function binding in scope in default expr + function f( + // error: number ~> string + x: () => string = f + ): number { return 0; } } + function default_param_2() { + // fn body bindings not visible from param scope let a = \"\"; function f0(x = () => a): number { let a = 0; - return x(); + return x(); // error: string ~> number } - function f1(x = b): number { + function f1(x = b /* error: cannot resolve b */): number { let b = 0; return x; } -} -" +}" `; exports[`test tdz.js 1`] = ` @@ -784,9 +784,15 @@ a = 10; f(a); // ok, a: number (not ?number) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /** @flow */ + // -- types --- + // type aliases are hoisted and always available + +type T1 = T2; // ok +type T2 = number; + // --- lets --- // to be correct, we would // - not allow forward refs to lets from value positions, @@ -799,92 +805,96 @@ f(a); // ok, a: number (not ?number) // a lambda runs. But a simple conservative approach would prohibit // forward references to let/consts from within lambdas entirely, // which would be annoying. TODO -// errors, let + const referenced before decl -// error, attempt to write to let before decl -// error, attempt to write to let before decl -// errors, let + const referenced before decl -// functions are let-scoped and hoisted -// ok, finds hoisted outer -// ok, finds hoisted inner -// ok, hoisted outer not clobbered -// out-of-scope TDZ not enforced. sometimes right... -// ok, g doesn\'t run in TDZ -// ...sometimes wrong -// should error, but doesn\'t currently -// - from type positions, we currently error on forward refs to any -// value (i.e., class or function). this is a basic flaw in our -// phasing of AST traversal, and will be fixed. -// -// ok -// error: let ref before decl from value position -// ok -// --- vars --- -// it\'s possible to annotate a var with a non-maybe type, -// but leave it uninitialized until later (as long as it\'s -// initialized before use) -// not an error per se - only if used before init -// error: undefined ~/> number -// ok, a: number (not ?number) -type T1 = T2; -type T2 = number; function f0() { var v = x * c; + // errors, let + const referenced before decl let x = 0; const c = 0; } + function f1(b) { x = 10; + // error, attempt to write to let before decl let x = 0; if (b) { y = 10; + // error, attempt to write to let before decl let y = 0; } } + function f2() { { - var v = x * c; + var v = x * c; // errors, let + const referenced before decl } let x = 0; const c = 0; } + +// functions are let-scoped and hoisted function f3() { var s: string = foo(); + // ok, finds hoisted outer { var n: number = foo(); + // ok, finds hoisted inner function foo() { return 0; } } var s2: string = foo(); + // ok, hoisted outer not clobbered function foo() { return \"\"; } } + +// out-of-scope TDZ not enforced. sometimes right... function f4() { function g() { return x + c; } + // ok, g doesn\'t run in TDZ let x = 0; const c = 0; } + +// ...sometimes wrong function f5() { function g() { return x; } g(); + // should error, but doesn\'t currently let x = 0; const c = 0; } + +// - from type positions, we currently error on forward refs to any +// value (i.e., class or function). this is a basic flaw in our +// phasing of AST traversal, and will be fixed. +// var x: C; +// ok var y = new C(); +// error: let ref before decl from value position class C {} + var z: C = new C(); +// ok +// --- vars --- +// it\'s possible to annotate a var with a non-maybe type, +// but leave it uninitialized until later (as long as it\'s +// initialized before use) var a: number; +// not an error per se - only if used before init function f(n: number) { return n; } + f(a); +// error: undefined ~/> number a = 10; -f(a); -" + +f(a); // ok, a: number (not ?number)" `; diff --git a/tests/bom/__snapshots__/jsfmt.spec.js.snap b/tests/bom/__snapshots__/jsfmt.spec.js.snap index 47e0dd90..7250be84 100644 --- a/tests/bom/__snapshots__/jsfmt.spec.js.snap +++ b/tests/bom/__snapshots__/jsfmt.spec.js.snap @@ -68,109 +68,108 @@ for (let [x, y]: [string, number] of a.entries()) {} // incorrect for (let [x, y]: [number, number] of a.entries()) {} // incorrect ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + // constructor +const a: FormData = new FormData(); // correct +new FormData(\"\"); // incorrect +new FormData(document.createElement(\"input\")); // incorrect +new FormData(document.createElement(\"form\")); // correct // has +const b: boolean = a.has(\"foo\"); // correct // get +const c: ?(string | File) = a.get(\"foo\"); // correct +const d: string = a.get(\"foo\"); // incorrect +const e: Blob = a.get(\"foo\"); // incorrect +const f: ?(string | File | Blob) = a.get(\"foo\"); // incorrect +a.get(2); // incorrect // getAll +const a1: Array = a.getAll(\"foo\"); // correct +const a2: Array = a.getAll(\"foo\"); // incorrect +const a3: Array = a.getAll(\"foo\"); // incorrect +a.getAll(23); // incorrect // set +a.set(\"foo\", \"bar\"); // correct +a.set(\"foo\", {}); // incorrect +a.set(2, \"bar\"); // incorrect +a.set(\"foo\", \"bar\", \"baz\"); // incorrect +a.set(\"bar\", new File([], \"q\")); // correct +a.set(\"bar\", new File([], \"q\"), \"x\"); // correct +a.set(\"bar\", new File([], \"q\"), 2); // incorrect +a.set(\"bar\", new Blob()); // correct +a.set(\"bar\", new Blob(), \"x\"); // correct +a.set(\"bar\", new Blob(), 2); // incorrect // append +a.append(\"foo\", \"bar\"); // correct +a.append(\"foo\", {}); // incorrect +a.append(2, \"bar\"); // incorrect +a.append(\"foo\", \"bar\", \"baz\"); // incorrect +a.append(\"foo\", \"bar\"); // incorrect +a.append(\"bar\", new File([], \"q\")); // correct +a.append(\"bar\", new File([], \"q\"), \"x\"); // correct +a.append(\"bar\", new File([], \"q\"), 2); // incorrect +a.append(\"bar\", new Blob()); // correct +a.append(\"bar\", new Blob(), \"x\"); // correct +a.append(\"bar\", new Blob(), 2); // incorrect // delete +a.delete(\"xx\"); // correct +a.delete(3); // incorrect // keys +for (let x: string of a.keys()) {} // correct +for (let x: number of a.keys()) {} // incorrect // values +for (let x: string | File of a.values()) {} // correct +for (let x: string | File | Blob of a.values()) {} // incorrect // entries -// correct -// incorrect -// incorrect -// incorrect -// incorrect -const a: FormData = new FormData(); -new FormData(\"\"); -new FormData(document.createElement(\"input\")); -new FormData(document.createElement(\"form\")); -const b: boolean = a.has(\"foo\"); -const c: ?(string | File) = a.get(\"foo\"); -const d: string = a.get(\"foo\"); -const e: Blob = a.get(\"foo\"); -const f: ?(string | File | Blob) = a.get(\"foo\"); -a.get(2); -const a1: Array = a.getAll(\"foo\"); -const a2: Array = a.getAll(\"foo\"); -const a3: Array = a.getAll(\"foo\"); -a.getAll(23); -a.set(\"foo\", \"bar\"); -a.set(\"foo\", {}); -a.set(2, \"bar\"); -a.set(\"foo\", \"bar\", \"baz\"); -a.set(\"bar\", new File([], \"q\")); -a.set(\"bar\", new File([], \"q\"), \"x\"); -a.set(\"bar\", new File([], \"q\"), 2); -a.set(\"bar\", new Blob()); -a.set(\"bar\", new Blob(), \"x\"); -a.set(\"bar\", new Blob(), 2); -a.append(\"foo\", \"bar\"); -a.append(\"foo\", {}); -a.append(2, \"bar\"); -a.append(\"foo\", \"bar\", \"baz\"); -a.append(\"foo\", \"bar\"); -a.append(\"bar\", new File([], \"q\")); -a.append(\"bar\", new File([], \"q\"), \"x\"); -a.append(\"bar\", new File([], \"q\"), 2); -a.append(\"bar\", new Blob()); -a.append(\"bar\", new Blob(), \"x\"); -a.append(\"bar\", new Blob(), 2); -a.delete(\"xx\"); -a.delete(3); -for (let x: string of a.keys()) {} -for (let x: number of a.keys()) {} -for (let x: string | File of a.values()) {} -for (let x: string | File | Blob of a.values()) {} for (let [ x, y ]: [string, string | File] of a.entries()) {} +// correct for (let [ x, y ]: [string, string | File | Blob] of a.entries()) {} +// incorrect for (let [ x, y ]: [number, string] of a.entries()) {} +// incorrect for (let [ x, y ]: [string, number] of a.entries()) {} -for (let [ x, y ]: [number, number] of a.entries()) {} -" +// incorrect +for (let [ x, y ]: [number, number] of a.entries()) {} // incorrect" `; exports[`test MutationObserver.js 1`] = ` @@ -205,26 +204,8 @@ o.takeRecords(); // correct o.disconnect(); // correct ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + // constructor -// correct -// correct -// correct -// incorrect -// incorrect -// incorrect -// observe -// correct -// correct -// incorrect -// incorrect -// incorrect -// incorrect -// incorrect -// incorrect -// takeRecords -// correct -// disconnect -// correct function callback( arr: Array, observer: MutationObserver @@ -232,21 +213,38 @@ function callback( return; } const o: MutationObserver = new MutationObserver(callback); +// correct new MutationObserver((arr: Array) => true); +// correct new MutationObserver(() => {}); +// correct new MutationObserver(); +// incorrect new MutationObserver(42); +// incorrect new MutationObserver((n: number) => {}); +// incorrect +// observe const div = document.createElement(\"div\"); o.observe(div, { attributes: true, attributeFilter: [ \"style\" ] }); +// correct o.observe(div, { characterData: true, invalid: true }); +// correct o.observe(); +// incorrect o.observe(\"invalid\"); +// incorrect o.observe(div); +// incorrect o.observe(div, {}); +// incorrect o.observe(div, { subtree: true }); +// incorrect o.observe(div, { attributes: true, attributeFilter: true }); +// incorrect +// takeRecords o.takeRecords(); -o.disconnect(); -" +// correct +// disconnect +o.disconnect(); // correct" `; diff --git a/tests/bounded_poly/__snapshots__/jsfmt.spec.js.snap b/tests/bounded_poly/__snapshots__/jsfmt.spec.js.snap index 47e63d98..851d2f9e 100644 --- a/tests/bounded_poly/__snapshots__/jsfmt.spec.js.snap +++ b/tests/bounded_poly/__snapshots__/jsfmt.spec.js.snap @@ -6,10 +6,10 @@ function bar(x:X, y:Y): number { return y*0; } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ function foo(x: X, y: Y): void {} foo(0, \"\"); + function bar(x: X, y: Y): number { return y * 0; -} -" +}" `; exports[`test test.js 1`] = ` @@ -39,38 +39,37 @@ var q: number = c.qux(0); /* 2 more errors, since argument U = number is incompatible with T = string, and * result T = string is incompatible with number */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// OK -// error -// OK -// error, since T: number and U: number does not imply U: T -// OK, since T: number and U: T implies U: number -// error -// OK, since U: T -// error, since T = string is incompatible with number -/* 2 more errors, since argument U = number is incompatible with T = string, and - * result T = string is incompatible with number */ function foo(x: T): T { var _ = x * 1; + // OK var y: string = x; - return x; + // error + return x; // OK } + class C { bar(x: U): T { - return x; + return x; // error, since T: number and U: number does not imply U: T } qux(x: U): T { var _ = x * 1; + // OK, since T: number and U: T implies U: number var y: string = x; - return x; + // error + return x; // OK, since U: T } } + function example(o: T): T { o.x = 0; return o; } var obj1: { x: number, y: string } = example({ x: 0, y: \"\" }); var obj2: { x: number } = example({ x: 0 }); + var c: C = new C(); +// error, since T = string is incompatible with number var q: number = c.qux(0); -" +/* 2 more errors, since argument U = number is incompatible with T = string, and + * result T = string is incompatible with number */" `; diff --git a/tests/break/__snapshots__/jsfmt.spec.js.snap b/tests/break/__snapshots__/jsfmt.spec.js.snap index e2c0f7e5..e402a732 100644 --- a/tests/break/__snapshots__/jsfmt.spec.js.snap +++ b/tests/break/__snapshots__/jsfmt.spec.js.snap @@ -68,19 +68,6 @@ function test_const() { return st; } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// error: boolean !~> number -// 2 errors: ?string !~> number -// error: boolean !~> number -// 2 errors: (boolean | string) !~> number -// 2 errors: (boolean | string) !~> number -// error: boolean !~> number -// 2 errors: (boolean | string) !~> number -// 2 errors: (boolean | string) !~> number -// error: string !~> number -// error: string !~> number -// same basic test as foo(), but with const. probes the -// logic that still uses havoc to do env resets. -// no error function foo(b) { var x = b ? null : false; var z; @@ -89,10 +76,11 @@ function foo(b) { z = \"\"; break; } - var y: number = x; + var y: number = x; // error: boolean !~> number } - var w: number = z; + var w: number = z; // 2 errors: ?string !~> number } + function bar(b) { var x = b ? null : false; if (x == null) @@ -100,14 +88,17 @@ function bar(b) { switch (\"\") { case 0: var y: number = x; + // error: boolean !~> number x = \"\"; case 1: var z: number = x; + // 2 errors: (boolean | string) !~> number break; case 2: } - var w: number = x; + var w: number = x; // 2 errors: (boolean | string) !~> number } + function bar2(b) { var x = b ? null : false; if (x == null) @@ -115,16 +106,19 @@ function bar2(b) { switch (\"\") { case 0: { let y: number = x; + // error: boolean !~> number x = \"\"; } case 1: { let z: number = x; + // 2 errors: (boolean | string) !~> number break; } case 2: } - var w: number = x; + var w: number = x; // 2 errors: (boolean | string) !~> number } + function qux(b) { var z = 0; while (b) { @@ -133,20 +127,26 @@ function qux(b) { z = \"\"; continue; } + // error: string !~> number z = 0; } - var w: number = z; + var w: number = z; // error: string !~> number } + +// same basic test as foo(), but with const. probes the +// logic that still uses havoc to do env resets. function test_const() { let st: string = \"abc\"; + for (let i = 1; i < 100; i++) { const fooRes: ?string = \"HEY\"; if (!fooRes) { break; } - st = fooRes; + + st = fooRes; // no error } + return st; -} -" +}" `; diff --git a/tests/builtin_uses/__snapshots__/jsfmt.spec.js.snap b/tests/builtin_uses/__snapshots__/jsfmt.spec.js.snap index fead4428..3d92a994 100644 --- a/tests/builtin_uses/__snapshots__/jsfmt.spec.js.snap +++ b/tests/builtin_uses/__snapshots__/jsfmt.spec.js.snap @@ -5,8 +5,7 @@ module.exports = o; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ var o = Object.freeze({ foo: 0 }); (o.foo: string); -module.exports = o; -" +module.exports = o;" `; exports[`test test2.js 1`] = ` @@ -14,6 +13,5 @@ exports[`test test2.js 1`] = ` (o.foo: string); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ var o = require(\"./test\"); -(o.foo: string); -" +(o.foo: string);" `; diff --git a/tests/builtins/__snapshots__/jsfmt.spec.js.snap b/tests/builtins/__snapshots__/jsfmt.spec.js.snap index 520a4943..c2a155cf 100644 --- a/tests/builtins/__snapshots__/jsfmt.spec.js.snap +++ b/tests/builtins/__snapshots__/jsfmt.spec.js.snap @@ -17,21 +17,20 @@ function g() { foo = foo1; } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// error: number !~> string -// error: string !~> number -// error: string !~> number var a = [ \"...\" ]; var b = a.map(function(x) { return 0; }); var c: string = b[0]; +// error: number !~> string var array = []; function f() { array = array.map(function() { return \"...\"; }); - var x: number = array[0]; + var x: number = array[0]; // error: string !~> number } + var Foo = require(\"./genericfoo\"); var foo = new Foo(); function g() { @@ -39,9 +38,9 @@ function g() { return \"...\"; }); var x: number = foo1.get(); + // error: string !~> number foo = foo1; -} -" +}" `; exports[`test genericfoo.js 1`] = ` @@ -68,6 +67,6 @@ class Foo { return this.x; } } -module.exports = Foo; -" + +module.exports = Foo;" `; diff --git a/tests/call_properties/__snapshots__/jsfmt.spec.js.snap b/tests/call_properties/__snapshots__/jsfmt.spec.js.snap index 935c0342..a648256b 100644 --- a/tests/call_properties/__snapshots__/jsfmt.spec.js.snap +++ b/tests/call_properties/__snapshots__/jsfmt.spec.js.snap @@ -31,31 +31,35 @@ function f(): number { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // You should be able to call objects with call properties -// ...and get an error if the return type is wrong -// ...or if the param type is wrong -// ...or if the arity is wrong -// ...or if there is no call property -// Make sure we complain even if the object literal is unsealed. function a(f: { (): string }, g: { (x: number): string }): string { return f() + g(123); } + +// ...and get an error if the return type is wrong function b(f: { (): string }): number { return f(); } + +// ...or if the param type is wrong function c(f: { (x: number): number }): number { return f(\"hello\"); } + +// ...or if the arity is wrong function d(f: { (x: number): number }): number { return f(); } + +// ...or if there is no call property function e(f: {}): number { return f(); } + +// Make sure we complain even if the object literal is unsealed. function f(): number { var x = {}; return x(); -} -" +}" `; exports[`test B.js 1`] = ` @@ -81,38 +85,41 @@ var y : {} = function (x: number): string { return \"hi\"; }; var z : Object = function (x: number): string { return \"hi\"; }; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // You should be able to use a function as an object with a call property -// ...and it should notice when the return type is wrong -// ...or if the param type is wrong -// ...or if the arity is wrong -// ...but subtyping rules still apply -// arity -// return type -// param type -// A function can be an object var a: { (x: number): string } = function(x: number): string { return \"hi\"; }; + +// ...and it should notice when the return type is wrong var b: { (x: number): number } = function(x: number): string { return \"hi\"; }; + +// ...or if the param type is wrong var c: { (x: string): string } = function(x: number): string { return \"hi\"; }; + +// ...or if the arity is wrong var d: { (): string } = function(x: number): string { return \"hi\"; }; + +// ...but subtyping rules still apply var e: { (x: any): void } = function() {}; +// arity var f: { (): mixed } = function(): string { return \"hi\"; }; +// return type var g: { (x: string): void } = function(x: mixed) {}; +// param type +// A function can be an object var y: {} = function(x: number): string { return \"hi\"; }; var z: Object = function(x: number): string { return \"hi\"; -}; -" +};" `; exports[`test C.js 1`] = ` @@ -152,35 +159,39 @@ function g(x: {}): Function { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // You should be able to use an object as a function -// ...and it should notice when the return type is wrong -// ...or if the param type is wrong -// ...or if the arity is wrong -// ...or if it doesn\'t have a call property -// AnyFunT should also be allowed -// ... but only if the object is callable -// error function a(x: { (z: number): string }): (z: number) => string { return x; } + +// ...and it should notice when the return type is wrong function b(x: { (z: number): string }): (z: number) => number { return x; } + +// ...or if the param type is wrong function c(x: { (z: number): string }): (z: string) => string { return x; } + +// ...or if the arity is wrong function d(x: { (z: number): string }): () => string { return x; } + +// ...or if it doesn\'t have a call property function e(x: {}): () => string { return x; } + +// AnyFunT should also be allowed function f(x: { (z: number): string }): Function { return x; } + +// ... but only if the object is callable function g(x: {}): Function { - return x; -} -" + return x; // error +}" `; exports[`test D.js 1`] = ` @@ -208,26 +219,29 @@ function e(x: { (): string; (x: number): string }): () => number { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Multiple call properties should also be supported -// It should be fine when a function satisfies them all -// ...but should notice when a function doesn\'t satisfy them all -// Only one call property needs to match the function -// ...but you need at least one function a(f: { (): string, (x: number): string }): string { return f() + f(123); } + +// It should be fine when a function satisfies them all var b: { (): string, (x: number): string } = function(x?: number): string { return \"hi\"; }; + +// ...but should notice when a function doesn\'t satisfy them all var c: { (): string, (x: number): string } = function(x: number): string { return \"hi\"; }; + +// Only one call property needs to match the function function d(x: { (): string, (x: number): string }): () => string { return x; } + +// ...but you need at least one function e(x: { (): string, (x: number): string }): () => number { return x; -} -" +}" `; exports[`test E.js 1`] = ` @@ -243,14 +257,15 @@ f.myProp = 123; var c : { myProp: number } = f; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Expecting properties that don\'t exist should be an error -// Expecting properties that do exist should be fine -// Expecting properties in the functions statics should be fine var a: { someProp: number } = function() {}; + +// Expecting properties that do exist should be fine var b: { apply: Function } = function() {}; + +// Expecting properties in the functions statics should be fine var f = function() {}; f.myProp = 123; -var c: { myProp: number } = f; -" +var c: { myProp: number } = f;" `; exports[`test F.js 1`] = ` @@ -277,24 +292,28 @@ var y : {} = (x) => \"hi\" var z : Object = (x) => \"hi\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // You should be able to use an arrow function as an object with a call property -// ...and it should notice when the return type is wrong -// ...or if the param type is wrong -// ...or if the arity is wrong -// ...but subtyping rules still apply -// arity -// return type -// param type (date < number) -// A function can be an object + var a: { (x: number): string } = x => x.toString(); + +// ...and it should notice when the return type is wrong var b: { (x: number): number } = x => \"hi\"; + +// ...or if the param type is wrong var c: { (x: string): string } = x => x.toFixed(); + +// ...or if the arity is wrong var d: { (): string } = x => \"hi\"; + +// ...but subtyping rules still apply var e: { (x: any): void } = () => {}; +// arity var f: { (): mixed } = () => \"hi\"; +// return type var g: { (x: Date): void } = x => { x * 2; }; +// param type (date < number) +// A function can be an object var y: {} = x => \"hi\"; -var z: Object = x => \"hi\"; -" +var z: Object = x => \"hi\";" `; diff --git a/tests/callable/__snapshots__/jsfmt.spec.js.snap b/tests/callable/__snapshots__/jsfmt.spec.js.snap index 8a12d5db..87f45784 100644 --- a/tests/callable/__snapshots__/jsfmt.spec.js.snap +++ b/tests/callable/__snapshots__/jsfmt.spec.js.snap @@ -11,11 +11,12 @@ function f(x) { (f: F); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ type F = { (x: string): number, p?: string }; + function f(x) { return x.length; } -(f: F); -" + +(f: F);" `; exports[`test primitives.js 1`] = ` @@ -41,23 +42,23 @@ declare var callable: Callable; callable(0); // error, number ~> string callable.call(null, 0); // error, number ~> string ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// error, callable signature not found -// error, number ~> string -// error, number ~> string -// error, number ~> string -// error, number ~> string var x = Boolean(4); function foo(fn: (value: any) => boolean) {} foo(Boolean); + var dict: { [k: string]: any } = {}; dict(); +// error, callable signature not found interface ICall { (x: string): void } declare var icall: ICall; icall(0); +// error, number ~> string icall.call(null, 0); +// error, number ~> string type Callable = { (x: string): void }; + declare var callable: Callable; callable(0); -callable.call(null, 0); -" +// error, number ~> string +callable.call(null, 0); // error, number ~> string" `; diff --git a/tests/check-contents/__snapshots__/jsfmt.spec.js.snap b/tests/check-contents/__snapshots__/jsfmt.spec.js.snap index 0ad05acd..691a99c2 100644 --- a/tests/check-contents/__snapshots__/jsfmt.spec.js.snap +++ b/tests/check-contents/__snapshots__/jsfmt.spec.js.snap @@ -1,6 +1,5 @@ exports[`test not_flow.js 1`] = ` "1 * \'foo\'; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -1 * \"foo\"; -" +1 * \"foo\";" `; diff --git a/tests/class_munging/__snapshots__/jsfmt.spec.js.snap b/tests/class_munging/__snapshots__/jsfmt.spec.js.snap index 78a33130..6a3b1c46 100644 --- a/tests/class_munging/__snapshots__/jsfmt.spec.js.snap +++ b/tests/class_munging/__snapshots__/jsfmt.spec.js.snap @@ -18,18 +18,18 @@ class Bar extends Foo { /** * @flow */ -// error + class Foo { _method(): string { return \"this is private\"; } } + class Bar extends Foo { test() { - (this._method(): string); + (this._method(): string); // error } -} -" +}" `; exports[`test without_munging.js 1`] = ` @@ -54,16 +54,16 @@ class Bar extends Foo { * @flow * @preventMunge */ -// ok + class Foo { _method(): string { return \"this is not private\"; } } + class Bar extends Foo { test() { - (this._method(): string); + (this._method(): string); // ok } -} -" +}" `; diff --git a/tests/class_statics/__snapshots__/jsfmt.spec.js.snap b/tests/class_statics/__snapshots__/jsfmt.spec.js.snap index bdb7351e..9e4285bd 100644 --- a/tests/class_statics/__snapshots__/jsfmt.spec.js.snap +++ b/tests/class_statics/__snapshots__/jsfmt.spec.js.snap @@ -61,19 +61,6 @@ module.exports = { A: A, B: B, C: C, D: D, E: E } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// error? -// error? -// error? -// error -// error -// error -// error -// error -// error B ~> number -// error? -// error -// error -// note: above classdefs are sufficiently annotated to export class A { static x: number; static y: string; @@ -81,25 +68,34 @@ class A { static bar(y: string) {} } A.qux = function(x: string) {}; +// error? class B extends A { static x: string; + // error? static foo(x: string) {} + // error? static main() { B.x = 0; + // error B.x = \"\"; B.foo(0); + // error B.foo(\"\"); B.y = 0; + // error B.bar(0); - B.qux(0); + // error + B.qux(0); // error } static create(): A { return new this(); } + static badCreate(): number { - return new this(); + return new this(); // error B ~> number } } + class C { static x: X; static bar(x: X) {} @@ -107,22 +103,28 @@ class C { return new this(); } } + class D extends C { static main() { D.foo(0); + // error? D.bar(0); } } + var d: C<*> = D.create(); (new A(): typeof A); (B: typeof A); + class E { static x: number; static foo(): string { this.bar(); - return this.x; + // error + return this.x; // error } } -module.exports = { A: A, B: B, C: C, D: D, E: E }; -" + +// note: above classdefs are sufficiently annotated to export +module.exports = { A: A, B: B, C: C, D: D, E: E };" `; diff --git a/tests/class_subtyping/__snapshots__/jsfmt.spec.js.snap b/tests/class_subtyping/__snapshots__/jsfmt.spec.js.snap index 180e09de..0842f2b6 100644 --- a/tests/class_subtyping/__snapshots__/jsfmt.spec.js.snap +++ b/tests/class_subtyping/__snapshots__/jsfmt.spec.js.snap @@ -8,8 +8,8 @@ module.exports = { A, B }; /* @flow */ class A {} class B {} -module.exports = { A, B }; -" + +module.exports = { A, B };" `; exports[`test test2.js 1`] = ` @@ -23,10 +23,11 @@ var y: I.B = new C(); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ var I = require(\"./test.js\"); + class C extends I.A {} + var x: I.A = new C(); -var y: I.B = new C(); -" +var y: I.B = new C();" `; exports[`test test3.js 1`] = ` @@ -37,14 +38,13 @@ class C extends B {} var c: C> = new C; // none of the type args matter var a: A> = c; // the third type arg is incorrect ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// none of the type args matter -// the third type arg is incorrect class A {} class B extends A {} class C extends B {} + var c: C> = new C(); -var a: A> = c; -" +// none of the type args matter +var a: A> = c; // the third type arg is incorrect" `; exports[`test test4.js 1`] = ` @@ -65,14 +65,18 @@ foo(new D, { f_: 0 }); class C { x: X; } + function foo(c: C, x: X) {} + type O = { f: number }; + foo((new C(): C), { f_: 0 }); + class D extends C { bar() { this.x; } } -foo(new D(), { f_: 0 }); -" + +foo(new D(), { f_: 0 });" `; diff --git a/tests/class_type/__snapshots__/jsfmt.spec.js.snap b/tests/class_type/__snapshots__/jsfmt.spec.js.snap index 341b3c27..9a2e53fc 100644 --- a/tests/class_type/__snapshots__/jsfmt.spec.js.snap +++ b/tests/class_type/__snapshots__/jsfmt.spec.js.snap @@ -11,19 +11,17 @@ function bar(x: Class): B { return new x(); // error (too few args) } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// OK -// error (too few args) class A {} function foo(x: Class): A { - return new x(); + return new x(); // OK } + class B { constructor(_: any) {} } function bar(x: Class): B { - return new x(); -} -" + return new x(); // error (too few args) +}" `; exports[`test test2.js 1`] = ` @@ -46,13 +44,14 @@ check(B, new C); // makes it useless in such a function (when limited to classes and instances), // since everything can be trivially satisfied by going to \`mixed\`. declare function check(cls: $Type, inst: X): void; + class A {} class B extends A {} class C {} + check(B, new A()); check(A, new B()); check(C, new A()); check(C, new B()); -check(B, new C()); -" +check(B, new C());" `; diff --git a/tests/classes/__snapshots__/jsfmt.spec.js.snap b/tests/classes/__snapshots__/jsfmt.spec.js.snap index 1c99c586..cbf6ec21 100644 --- a/tests/classes/__snapshots__/jsfmt.spec.js.snap +++ b/tests/classes/__snapshots__/jsfmt.spec.js.snap @@ -8,8 +8,8 @@ module.exports = A; class A { foo(x: number): void {} } -module.exports = A; -" + +module.exports = A;" `; exports[`test B.js 1`] = ` @@ -22,13 +22,14 @@ let b = new B(); module.exports = B; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// error, number !~> function var A = require(\"./A\"); + class B extends A {} + let b = new B(); (b.foo: number); -module.exports = B; -" +// error, number !~> function +module.exports = B;" `; exports[`test C.js 1`] = ` @@ -43,15 +44,16 @@ let c = new C(); module.exports = C; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// error, number !~> function var B = require(\"./B\"); + class C extends B { foo(x: string): void {} } + let c = new C(); (c.foo: number); -module.exports = C; -" +// error, number !~> function +module.exports = C;" `; exports[`test D.js 1`] = ` @@ -61,8 +63,7 @@ new E().x ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class D {} class E {} -new E().x; -" +new E().x;" `; exports[`test class_shapes.js 1`] = ` @@ -103,42 +104,48 @@ var z = new Test2Class(); var w : Foo = z; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// exists in TestClass -// doesn\'t exist -// exists in TestClass, optional -/* doesn\'t exist*/ -// ok -// error, TestClass has no b -// ok -// error, TestClass has no d -// error, doesn\'t exist in TestClass -// ok, it\'s optional -// conflicts with cast to Foo -// conflicts with cast to Foo -// conflicts with cast to Foo -type Foo = { a: string, b: string, c?: ?string, d?: number }; + +type Foo = { + a: string, + // exists in TestClass + b: string, + // doesn\'t exist + c?: ?string, + // exists in TestClass, optional + d?: number /* doesn\'t exist*/ +}; + class TestClass { a: string; c: ?string; } + var x = new TestClass(); + x.a; +// ok x.b; +// error, TestClass has no b x.c; +// ok x.d; +// error, TestClass has no d var y: Foo = x; y.b; +// error, doesn\'t exist in TestClass y.d; +// ok, it\'s optional class Test2Superclass { a: number; - c: ?number; + // conflicts with cast to Foo + c: ?number; // conflicts with cast to Foo } class Test2Class extends Test2Superclass { - b: number; + b: number; // conflicts with cast to Foo } + var z = new Test2Class(); -var w: Foo = z; -" +var w: Foo = z;" `; exports[`test expr.js 1`] = ` @@ -173,30 +180,29 @@ var _Alias = class Alias { var alias1: Alias = new _Alias(); // error: bad pun var alias2: Alias = _Alias.factory(); // error: bad pun ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// OK: Foo is a type in this scope -// OK: Foo is a runtime binding in this scope +var Bar = class Foo { + static factory(): Foo { + // OK: Foo is a type in this scope + return new Foo(); // OK: Foo is a runtime binding in this scope + } +}; + +var bar1: Bar = new Bar(); // OK +var bar2: Bar = Bar.factory(); // OK // NB: Don\'t write expected errors using Foo to avoid error collapse hiding an // unexpected failure in the above code. -// error: Baz is not a runtime binding in this scope -// error: Qux is not a type in this scope -// OK: anon classes create no binding, but can be bound manually -// error: bad pun -// error: bad pun -var Bar = class Foo { - static factory(): Foo { - return new Foo(); - } -}; -var bar1: Bar = new Bar(); -var bar2: Bar = Bar.factory(); var B = class Baz {}; var b = new Baz(); +// error: Baz is not a runtime binding in this scope var C = class Qux {}; var c: Qux = new C(); +// error: Qux is not a type in this scope +// OK: anon classes create no binding, but can be bound manually var Anon = class {}; var anon: Anon = new Anon(); + class Alias {} var _Alias = class Alias { static factory(): Alias { @@ -204,8 +210,8 @@ var _Alias = class Alias { } }; var alias1: Alias = new _Alias(); -var alias2: Alias = _Alias.factory(); -" +// error: bad pun +var alias2: Alias = _Alias.factory(); // error: bad pun" `; exports[`test loc.js 1`] = ` @@ -216,10 +222,10 @@ type Foo = number class Foo {} // error, shadows type Foo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// error, shadows type Foo + type Foo = number; -class Foo {} -" + +class Foo {} // error, shadows type Foo" `; exports[`test statics.js 1`] = ` @@ -238,17 +244,17 @@ declare var o: {p:number}; (o: Class); // error, object type incompatible with class type ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// Class static fields are compatible with object types -// ok -// errors, string ~> number & vice versa (unify) -// error, object type incompatible with class type + class C { static p: string; } C.p = \"hi\"; + +// Class static fields are compatible with object types (C: { p: string }); +// ok (C: { p: number }); +// errors, string ~> number & vice versa (unify) declare var o: { p: number }; -(o: Class); -" +(o: Class); // error, object type incompatible with class type" `; diff --git a/tests/closure/__snapshots__/jsfmt.spec.js.snap b/tests/closure/__snapshots__/jsfmt.spec.js.snap index 2dfec3fe..8a46a08c 100644 --- a/tests/closure/__snapshots__/jsfmt.spec.js.snap +++ b/tests/closure/__snapshots__/jsfmt.spec.js.snap @@ -84,76 +84,84 @@ function local_meth() { * Test tracking of variable types across closure calls. * @flow */ + +function takes_string(_: string) {} + // global write from function // -// ok -// error -// shouldn\'t pollute linear refinement -// local write from function -// -// ok -// error -// shouldn\'t pollute linear refinement -// global write from method -// -// ok -// error -// shouldn\'t pollute linear refinement -// local write from method -// -// ok -// error -// shouldn\'t pollute linear refinement -function takes_string(_: string) {} var global_x = \"hello\"; + function global_f() {} function global_g() { global_x = 42; } + global_f(); takes_string(global_x); +// ok global_g(); takes_string(global_x); +// error global_x = 42; +// shouldn\'t pollute linear refinement +// local write from function +// function local_func() { var local_x = \"hello\"; + function local_f() {} function local_g() { local_x = 42; } + local_f(); takes_string(local_x); + // ok local_g(); takes_string(local_x); - local_x = 42; + // error + local_x = 42; // shouldn\'t pollute linear refinement } + +// global write from method +// var global_y = \"hello\"; + var global_o = { f: function() {}, g: function() { global_y = 42; } }; + global_o.f(); takes_string(global_y); +// ok global_o.g(); takes_string(global_y); +// error global_y = 42; +// shouldn\'t pollute linear refinement +// local write from method +// function local_meth() { var local_y = \"hello\"; + var local_o = { f: function() {}, g: function() { local_y = 42; } }; + local_o.f(); takes_string(local_y); + // ok local_o.g(); takes_string(local_y); - local_y = 42; -} -" + // error + local_y = 42; // shouldn\'t pollute linear refinement +}" `; exports[`test cond_havoc.js 1`] = ` @@ -172,10 +180,10 @@ function example(b: bool): number { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + // from sam, https://github.com/facebook/flow/issues/780 // call to f() within if should properly havoc x. // -// error, string ~/~> number (return type anno) TODO function example(b: boolean): number { var x = 0; function f() { @@ -184,9 +192,8 @@ function example(b: boolean): number { if (b) { f(); } - return x; -} -" + return x; // error, string ~/~> number (return type anno) TODO +}" `; exports[`test const.js 1`] = ` @@ -242,63 +249,61 @@ call_me(); * consts retain refinements * @flow */ + // global, anybody can call it at any time -// ok: if const_x is truthy here, it\'s truthy everywhere -// error: var_x might no longer be truthy when call_me is called -// error -// ok -// ok -// ok -// error -// error -// error -// in a galaxy far far away var call_me: () => void = () => {}; + function g(x: ?number) { const const_x = x; if (const_x) { + // ok: if const_x is truthy here, it\'s truthy everywhere call_me = () => { var y: number = const_x; }; } + var var_x = x; if (var_x) { + // error: var_x might no longer be truthy when call_me is called call_me = () => { var y: number = var_x; - }; + }; // error } var_x = null; } + function h(x: number | string | boolean) { const const_x = x; if (typeof const_x == \"number\") { call_me = () => { var y: number = const_x; - }; + }; // ok } else if (typeof const_x == \"string\") { call_me = () => { var y: string = const_x; - }; + }; // ok } else if (typeof const_x == \"boolean\") { call_me = () => { var y: boolean = const_x; - }; + }; // ok } + var var_x = x; if (typeof var_x == \"number\") { call_me = () => { var y: number = var_x; - }; + }; // error } else if (typeof var_x == \"string\") { call_me = () => { var y: string = var_x; - }; + }; // error } else if (typeof var_x == \"boolean\") { call_me = () => { var y: boolean = var_x; - }; + }; // error } } -call_me(); -" + +// in a galaxy far far away +call_me();" `; diff --git a/tests/commonjs/__snapshots__/jsfmt.spec.js.snap b/tests/commonjs/__snapshots__/jsfmt.spec.js.snap index 3fa8065b..8aed7821 100644 --- a/tests/commonjs/__snapshots__/jsfmt.spec.js.snap +++ b/tests/commonjs/__snapshots__/jsfmt.spec.js.snap @@ -5,8 +5,8 @@ function f(x:string) { } module.exports = f; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ function f(x: string) {} -module.exports = f; -" + +module.exports = f;" `; exports[`test Rel.js 1`] = ` @@ -16,6 +16,6 @@ var f = require(\'./Abs\'); f(0); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ var f = require(\"./Abs\"); -f(0); -" + +f(0);" `; diff --git a/tests/computed_props/__snapshots__/jsfmt.spec.js.snap b/tests/computed_props/__snapshots__/jsfmt.spec.js.snap index ce1cfa12..e815bba5 100644 --- a/tests/computed_props/__snapshots__/jsfmt.spec.js.snap +++ b/tests/computed_props/__snapshots__/jsfmt.spec.js.snap @@ -23,19 +23,21 @@ ColorIdToNumber.XXX; // oops module.exports = { ColorId, ColorNumber }; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// oops -// oops var ColorId = { RED: \"R\", GREEN: \"G\", BLUE: \"B\" }; + var ColorNumber = { RED: \"ff0000\", GREEN: \"00ff00\", BLUE: \"0000ff\" }; + var ColorIdToNumber = { [ColorId.RED]: ColorNumber.RED, [ColorId.GREEN]: ColorNumber.GREEN, [ColorId.BLUE]: ColorNumber.BLUE }; + (ColorIdToNumber[ColorId.RED]: \"ffffff\"); +// oops ColorIdToNumber.XXX; -module.exports = { ColorId, ColorNumber }; -" +// oops +module.exports = { ColorId, ColorNumber };" `; exports[`test test2.js 1`] = ` @@ -50,16 +52,16 @@ var ColorIdToNumber = { module.exports = ColorIdToNumber; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// oops var { ColorId, ColorNumber } = require(\"./test\"); var ColorIdToNumber = { [ColorId.RED]: ColorNumber.RED, [ColorId.GREEN]: ColorNumber.GREEN, [ColorId.BLUE]: ColorNumber.BLUE }; + (ColorIdToNumber[ColorId.GREEN]: \"ffffff\"); -module.exports = ColorIdToNumber; -" +// oops +module.exports = ColorIdToNumber;" `; exports[`test test3.js 1`] = ` @@ -68,18 +70,16 @@ var ColorIdToNumber = require(\'./test2\'); (ColorIdToNumber[ColorId.BLUE]: \'ffffff\'); // oops ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// oops var { ColorId } = require(\"./test\"); var ColorIdToNumber = require(\"./test2\"); -(ColorIdToNumber[ColorId.BLUE]: \"ffffff\"); -" + +(ColorIdToNumber[ColorId.BLUE]: \"ffffff\"); // oops" `; exports[`test test4.js 1`] = ` "module.exports = \'hello\'; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -module.exports = \"hello\"; -" +module.exports = \"hello\";" `; exports[`test test5.js 1`] = ` @@ -93,18 +93,15 @@ module.exports = { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ var hello = require(\"./test4\"); var dummy = require(\"./test\"); -module.exports = { ...dummy, [hello]: \"world\", ...dummy }; -" +module.exports = { ...dummy, [hello]: \"world\", ...dummy };" `; exports[`test test6.js 1`] = ` "var o = require(\'./test5\'); (o.hello: \'nothing\'); // oops ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// oops var o = require(\"./test5\"); -(o.hello: \"nothing\"); -" +(o.hello: \"nothing\"); // oops" `; exports[`test test7.js 1`] = ` @@ -114,8 +111,6 @@ var x: string = obj[\'m\'](); // error, number ~> string var arr = [function() { return this.length }]; var y: string = arr[0](); // error: number ~> string ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// error, number ~> string -// error: number ~> string var obj = { x: 0, m() { @@ -123,11 +118,11 @@ var obj = { } }; var x: string = obj[\"m\"](); +// error, number ~> string var arr = [ function() { return this.length; } ]; -var y: string = arr[0](); -" +var y: string = arr[0](); // error: number ~> string" `; diff --git a/tests/conditional/__snapshots__/jsfmt.spec.js.snap b/tests/conditional/__snapshots__/jsfmt.spec.js.snap index a9955eca..d274011b 100644 --- a/tests/conditional/__snapshots__/jsfmt.spec.js.snap +++ b/tests/conditional/__snapshots__/jsfmt.spec.js.snap @@ -25,25 +25,28 @@ function d(): string { // expected \`: number | boolean\` } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// equivalent to \`return (x && 1) || 0\` -// expected \`: number | boolean\` -// equivalent to \`return x != null && x\` + function a(): number { var x: ?string = null; return x ? 1 : 0; } + function b(): number { var x: ?number = null; return x != null ? x : 0; } + function c(): number { + // equivalent to \`return (x && 1) || 0\` var x = false; var temp = x ? 1 : x; return temp ? temp : 0; } + function d(): string { + // expected \`: number | boolean\` + // equivalent to \`return x != null && x\` var x: ?number = null; return x != null ? x : x != null; -} -" +}" `; diff --git a/tests/config_all/__snapshots__/jsfmt.spec.js.snap b/tests/config_all/__snapshots__/jsfmt.spec.js.snap index 7439bd43..21f64e04 100644 --- a/tests/config_all/__snapshots__/jsfmt.spec.js.snap +++ b/tests/config_all/__snapshots__/jsfmt.spec.js.snap @@ -1,7 +1,5 @@ exports[`test no_at_flow.js 1`] = ` "var x: number = \"not a number\"; // Error: string ~> number ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Error: string ~> number -var x: number = \"not a number\"; -" +var x: number = \"not a number\"; // Error: string ~> number" `; diff --git a/tests/config_all_false/__snapshots__/jsfmt.spec.js.snap b/tests/config_all_false/__snapshots__/jsfmt.spec.js.snap index 9c3f9553..c6a7fecd 100644 --- a/tests/config_all_false/__snapshots__/jsfmt.spec.js.snap +++ b/tests/config_all_false/__snapshots__/jsfmt.spec.js.snap @@ -1,7 +1,5 @@ exports[`test no_at_flow.js 1`] = ` "var x: number = \"not a number\"; // No error ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// No error -var x: number = \"not a number\"; -" +var x: number = \"not a number\"; // No error" `; diff --git a/tests/config_all_weak/__snapshots__/jsfmt.spec.js.snap b/tests/config_all_weak/__snapshots__/jsfmt.spec.js.snap index 67a13971..7d241981 100644 --- a/tests/config_all_weak/__snapshots__/jsfmt.spec.js.snap +++ b/tests/config_all_weak/__snapshots__/jsfmt.spec.js.snap @@ -4,6 +4,6 @@ exports[`test no_at_flow.js 1`] = ` x.length; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ var x; -x.length; -" + +x.length;" `; diff --git a/tests/config_file_extensions/__snapshots__/jsfmt.spec.js.snap b/tests/config_file_extensions/__snapshots__/jsfmt.spec.js.snap index f0084118..1fb0adac 100644 --- a/tests/config_file_extensions/__snapshots__/jsfmt.spec.js.snap +++ b/tests/config_file_extensions/__snapshots__/jsfmt.spec.js.snap @@ -14,11 +14,12 @@ foo(\'Hello, world!\'); /* * @flow */ -// This file should be ignored, so this should not result in an error + function foo(x) { var a: number = \"asdf\"; return x * 10; } -foo(\"Hello, world!\"); -" + +// This file should be ignored, so this should not result in an error +foo(\"Hello, world!\");" `; diff --git a/tests/config_ignore/__snapshots__/jsfmt.spec.js.snap b/tests/config_ignore/__snapshots__/jsfmt.spec.js.snap index 3dded236..2d9735b5 100644 --- a/tests/config_ignore/__snapshots__/jsfmt.spec.js.snap +++ b/tests/config_ignore/__snapshots__/jsfmt.spec.js.snap @@ -5,7 +5,7 @@ exports[`test foo.js 1`] = ` var x: number = \"string\"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + // No error, this file is ignored -var x: number = \"string\"; -" +var x: number = \"string\";" `; diff --git a/tests/config_ignore/dir/__snapshots__/jsfmt.spec.js.snap b/tests/config_ignore/dir/__snapshots__/jsfmt.spec.js.snap index 33fdb611..792ebbf2 100644 --- a/tests/config_ignore/dir/__snapshots__/jsfmt.spec.js.snap +++ b/tests/config_ignore/dir/__snapshots__/jsfmt.spec.js.snap @@ -4,7 +4,6 @@ exports[`test foo.js 1`] = ` var x: number = \"string\"; // Error string ~> number ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// Error string ~> number -var x: number = \"string\"; -" + +var x: number = \"string\"; // Error string ~> number" `; diff --git a/tests/config_module_name_mapper_PROJECT_ROOT-1.0/__snapshots__/jsfmt.spec.js.snap b/tests/config_module_name_mapper_PROJECT_ROOT-1.0/__snapshots__/jsfmt.spec.js.snap index 24d88ab7..31e87ba5 100644 --- a/tests/config_module_name_mapper_PROJECT_ROOT-1.0/__snapshots__/jsfmt.spec.js.snap +++ b/tests/config_module_name_mapper_PROJECT_ROOT-1.0/__snapshots__/jsfmt.spec.js.snap @@ -7,9 +7,9 @@ var a: number = test; var b: string = test; // Error: number ~> string ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// Error: number ~> string + import {test} from \"testmodule\"; + var a: number = test; -var b: string = test; -" +var b: string = test; // Error: number ~> string" `; diff --git a/tests/config_module_name_mapper_PROJECT_ROOT-1.0/src/__snapshots__/jsfmt.spec.js.snap b/tests/config_module_name_mapper_PROJECT_ROOT-1.0/src/__snapshots__/jsfmt.spec.js.snap index 3f334f90..4a594c4e 100644 --- a/tests/config_module_name_mapper_PROJECT_ROOT-1.0/src/__snapshots__/jsfmt.spec.js.snap +++ b/tests/config_module_name_mapper_PROJECT_ROOT-1.0/src/__snapshots__/jsfmt.spec.js.snap @@ -4,6 +4,6 @@ exports[`test testmodule.js 1`] = ` export let test = 42; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -export let test = 42; -" + +export let test = 42;" `; diff --git a/tests/config_module_name_mapper_filetype/__snapshots__/jsfmt.spec.js.snap b/tests/config_module_name_mapper_filetype/__snapshots__/jsfmt.spec.js.snap index 48930403..5f6bd248 100644 --- a/tests/config_module_name_mapper_filetype/__snapshots__/jsfmt.spec.js.snap +++ b/tests/config_module_name_mapper_filetype/__snapshots__/jsfmt.spec.js.snap @@ -5,8 +5,7 @@ import {className} from \"./SomeCSSFile.css\"; import {doesntExist} from \"./SomeCSSFile.css\"; // Error: \`doestExist\` isn\'t an export ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// Error: \`doestExist\` isn\'t an export + import {className} from \"./SomeCSSFile.css\"; -import {doesntExist} from \"./SomeCSSFile.css\"; -" +import {doesntExist} from \"./SomeCSSFile.css\"; // Error: \`doestExist\` isn\'t an export" `; diff --git a/tests/config_module_name_rewrite_haste/__snapshots__/jsfmt.spec.js.snap b/tests/config_module_name_rewrite_haste/__snapshots__/jsfmt.spec.js.snap index 74f4ff2e..ce0f9871 100644 --- a/tests/config_module_name_rewrite_haste/__snapshots__/jsfmt.spec.js.snap +++ b/tests/config_module_name_rewrite_haste/__snapshots__/jsfmt.spec.js.snap @@ -14,19 +14,19 @@ var m2 = require(\'2DoesntExist\'); // Error import {numVal as numVal2} from \'3DoesntExist\'; // Error ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// Error: \'Exists2\' is not a valid module name -// -// This tests that, for haste, the first name_mapper regexp that happens to -// match the given module name string is picked. -// Error -// Error + var m1 = require(\"1DoesntExist\"); import {numVal as numVal1} from \"1DoesntExist\"; var a_1: number = m1.numVal; var a_2: number = numVal1; + +// Error: \'Exists2\' is not a valid module name +// +// This tests that, for haste, the first name_mapper regexp that happens to +// match the given module name string is picked. var m2 = require(\"2DoesntExist\"); -import {numVal as numVal2} from \"3DoesntExist\"; -" +// Error +import {numVal as numVal2} from \"3DoesntExist\"; // Error" `; exports[`test Exists.js 1`] = ` @@ -43,6 +43,6 @@ module.exports = { * @providesModule Exists * @flow */ -module.exports = { numVal: 42 }; -" + +module.exports = { numVal: 42 };" `; diff --git a/tests/config_module_name_rewrite_node/__snapshots__/jsfmt.spec.js.snap b/tests/config_module_name_rewrite_node/__snapshots__/jsfmt.spec.js.snap index cdfbf29b..7b2cddb5 100644 --- a/tests/config_module_name_rewrite_node/__snapshots__/jsfmt.spec.js.snap +++ b/tests/config_module_name_rewrite_node/__snapshots__/jsfmt.spec.js.snap @@ -26,34 +26,33 @@ var c_3: number = numVal3; var c_4: string = numVal3; // Error: number ~> string ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// Error: number ~> string -// Error: number ~> string -// This tests that, for node, the first name mapping that both matches *and* -// results in a valid module filename is picked. -// Error: number ~> string -// Error: number ~> string -// node_modules/Exists/index.js -// Error: number ~> string -// Error: number ~> string + var m1 = require(\"./1DoesntExist\"); var a_1: number = m1.numVal; var a_2: string = m1.numVal; +// Error: number ~> string import {numVal} from \"./1DoesntExist\"; var a_3: number = numVal; var a_4: string = numVal; +// Error: number ~> string +// This tests that, for node, the first name mapping that both matches *and* +// results in a valid module filename is picked. var m2 = require(\"./2DoesntExist\"); var b_1: number = m2.numVal; var b_2: string = m2.numVal; +// Error: number ~> string import {numVal as numVal2} from \"./3DoesntExist\"; var b_3: number = numVal2; var b_4: string = numVal2; +// Error: number ~> string +// node_modules/Exists/index.js var m3 = require(\"4DoesntExist\"); var c_1: number = m3.numVal; var c_2: string = m3.numVal; +// Error: number ~> string import {numVal as numVal3} from \"5DoesntExist\"; var c_3: number = numVal3; -var c_4: string = numVal3; -" +var c_4: string = numVal3; // Error: number ~> string" `; exports[`test Exists.js 1`] = ` @@ -64,6 +63,6 @@ module.exports = { }; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -module.exports = { numVal: 42 }; -" + +module.exports = { numVal: 42 };" `; diff --git a/tests/config_module_system_node_resolve_dirname/__snapshots__/jsfmt.spec.js.snap b/tests/config_module_system_node_resolve_dirname/__snapshots__/jsfmt.spec.js.snap index 6fa40e88..5da0d19e 100644 --- a/tests/config_module_system_node_resolve_dirname/__snapshots__/jsfmt.spec.js.snap +++ b/tests/config_module_system_node_resolve_dirname/__snapshots__/jsfmt.spec.js.snap @@ -7,9 +7,9 @@ import {name} from \"testproj\"; (name: \"custom_resolve_dir/testproj\"); // Error: Resolve from node_modules first! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// Error: Resolve from node_modules first! + import {name} from \"testproj\"; + (name: \"node_modules/testproj\"); -(name: \"custom_resolve_dir/testproj\"); -" +(name: \"custom_resolve_dir/testproj\"); // Error: Resolve from node_modules first!" `; diff --git a/tests/config_module_system_node_resolve_dirname/custom_resolve_dir/testproj/__snapshots__/jsfmt.spec.js.snap b/tests/config_module_system_node_resolve_dirname/custom_resolve_dir/testproj/__snapshots__/jsfmt.spec.js.snap index bbf8400e..064d8dbd 100644 --- a/tests/config_module_system_node_resolve_dirname/custom_resolve_dir/testproj/__snapshots__/jsfmt.spec.js.snap +++ b/tests/config_module_system_node_resolve_dirname/custom_resolve_dir/testproj/__snapshots__/jsfmt.spec.js.snap @@ -4,6 +4,6 @@ exports[`test index.js 1`] = ` export var name: \"otherdir/testproj\" = \"otherdir/testproj\"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -export var name: \"otherdir/testproj\" = \"otherdir/testproj\"; -" + +export var name: \"otherdir/testproj\" = \"otherdir/testproj\";" `; diff --git a/tests/config_module_system_node_resolve_dirname/custom_resolve_dir/testproj2/__snapshots__/jsfmt.spec.js.snap b/tests/config_module_system_node_resolve_dirname/custom_resolve_dir/testproj2/__snapshots__/jsfmt.spec.js.snap index 24500e9d..a39e15e2 100644 --- a/tests/config_module_system_node_resolve_dirname/custom_resolve_dir/testproj2/__snapshots__/jsfmt.spec.js.snap +++ b/tests/config_module_system_node_resolve_dirname/custom_resolve_dir/testproj2/__snapshots__/jsfmt.spec.js.snap @@ -4,6 +4,6 @@ exports[`test index.js 1`] = ` export var name: \"otherdir/testproj2\" = \"otherdir/testproj2\"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -export var name: \"otherdir/testproj2\" = \"otherdir/testproj2\"; -" + +export var name: \"otherdir/testproj2\" = \"otherdir/testproj2\";" `; diff --git a/tests/config_module_system_node_resolve_dirname/subdir/__snapshots__/jsfmt.spec.js.snap b/tests/config_module_system_node_resolve_dirname/subdir/__snapshots__/jsfmt.spec.js.snap index 86ce5276..89260f69 100644 --- a/tests/config_module_system_node_resolve_dirname/subdir/__snapshots__/jsfmt.spec.js.snap +++ b/tests/config_module_system_node_resolve_dirname/subdir/__snapshots__/jsfmt.spec.js.snap @@ -7,9 +7,10 @@ import {name} from \"testproj2\"; (name: \"subdir/custom_resolve_dir/testproj2\"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// Error: Resolve from sibling \'custom_resolve_dir\' first! + import {name} from \"testproj2\"; + (name: \"node_modules/testproj2\"); -(name: \"subdir/custom_resolve_dir/testproj2\"); -" +// Error: Resolve from sibling \'custom_resolve_dir\' first! +(name: \"subdir/custom_resolve_dir/testproj2\");" `; diff --git a/tests/config_module_system_node_resolve_dirname/subdir/custom_resolve_dir/testproj2/__snapshots__/jsfmt.spec.js.snap b/tests/config_module_system_node_resolve_dirname/subdir/custom_resolve_dir/testproj2/__snapshots__/jsfmt.spec.js.snap index 9507811c..84e7dcf6 100644 --- a/tests/config_module_system_node_resolve_dirname/subdir/custom_resolve_dir/testproj2/__snapshots__/jsfmt.spec.js.snap +++ b/tests/config_module_system_node_resolve_dirname/subdir/custom_resolve_dir/testproj2/__snapshots__/jsfmt.spec.js.snap @@ -4,6 +4,6 @@ exports[`test index.js 1`] = ` export var name: \"subdir/custom_resolve_dir/testproj2\" = \"subdir/custom_resolve_dir/testproj2\"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -export var name: \"subdir/custom_resolve_dir/testproj2\" = \"subdir/custom_resolve_dir/testproj2\"; -" + +export var name: \"subdir/custom_resolve_dir/testproj2\" = \"subdir/custom_resolve_dir/testproj2\";" `; diff --git a/tests/config_munging_underscores/__snapshots__/jsfmt.spec.js.snap b/tests/config_munging_underscores/__snapshots__/jsfmt.spec.js.snap index 5eeef88d..d42ede62 100644 --- a/tests/config_munging_underscores/__snapshots__/jsfmt.spec.js.snap +++ b/tests/config_munging_underscores/__snapshots__/jsfmt.spec.js.snap @@ -35,9 +35,11 @@ class B extends A { B._sProperty = \"B._sProperty string\"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + class A { _property1: number; static _sProperty: number; + constructor() { this._property1 = 5; } @@ -49,9 +51,11 @@ class A { } } A._sProperty = 48; + class B extends A { _property1: string; static _sProperty: string; + constructor() { super(); this._property1 = \"another string\"; @@ -63,8 +67,7 @@ class B extends A { return 23; } } -B._sProperty = \"B._sProperty string\"; -" +B._sProperty = \"B._sProperty string\";" `; exports[`test commonjs_export.js 1`] = ` @@ -77,11 +80,12 @@ class C { module.exports = new C; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + class C { _p: string; } -module.exports = new C(); -" + +module.exports = new C();" `; exports[`test commonjs_import.js 1`] = ` @@ -90,6 +94,6 @@ exports[`test commonjs_import.js 1`] = ` import {_p} from \"./commonjs_export\"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -import {_p} from \"./commonjs_export\"; -" + +import {_p} from \"./commonjs_export\";" `; diff --git a/tests/config_munging_underscores2/__snapshots__/jsfmt.spec.js.snap b/tests/config_munging_underscores2/__snapshots__/jsfmt.spec.js.snap index 69d00c9c..c2784abc 100644 --- a/tests/config_munging_underscores2/__snapshots__/jsfmt.spec.js.snap +++ b/tests/config_munging_underscores2/__snapshots__/jsfmt.spec.js.snap @@ -35,9 +35,11 @@ class B extends A { B._sProperty = \"B._sProperty string\"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + class A { _property1: number; static _sProperty: number; + constructor() { this._property1 = 5; } @@ -49,9 +51,11 @@ class A { } } A._sProperty = 48; + class B extends A { _property1: string; static _sProperty: string; + constructor() { super(); this._property1 = \"another string\"; @@ -63,6 +67,5 @@ class B extends A { return 23; } } -B._sProperty = \"B._sProperty string\"; -" +B._sProperty = \"B._sProperty string\";" `; diff --git a/tests/const_params/__snapshots__/jsfmt.spec.js.snap b/tests/const_params/__snapshots__/jsfmt.spec.js.snap index 24fef60f..3ad7783d 100644 --- a/tests/const_params/__snapshots__/jsfmt.spec.js.snap +++ b/tests/const_params/__snapshots__/jsfmt.spec.js.snap @@ -43,21 +43,21 @@ function durable_refi(x: ?number) { * * @flow */ -// error, const param cannot be reassigned + +function cannot_reassign(x: string) { + x = \"hey\"; // error, const param cannot be reassigned +} + // Note: const params use the same machinery as explicit // const bindings, which are tested more extensively elsewhere. // Here we\'re just making sure the machinery is hooked up. // -// ok: if x is truthy here, it\'s truthy everywhere -function cannot_reassign(x: string) { - x = \"hey\"; -} function durable_refi(x: ?number) { if (x) { + // ok: if x is truthy here, it\'s truthy everywhere return () => { var y: number = x; }; } -} -" +}" `; diff --git a/tests/constructor/__snapshots__/jsfmt.spec.js.snap b/tests/constructor/__snapshots__/jsfmt.spec.js.snap index 666897f0..91658226 100644 --- a/tests/constructor/__snapshots__/jsfmt.spec.js.snap +++ b/tests/constructor/__snapshots__/jsfmt.spec.js.snap @@ -12,9 +12,10 @@ module.exports = C; class C { constructor() {} } + class D { constructor(): number {} } -module.exports = C; -" + +module.exports = C;" `; diff --git a/tests/constructor_annots/__snapshots__/jsfmt.spec.js.snap b/tests/constructor_annots/__snapshots__/jsfmt.spec.js.snap index 7033255d..87424304 100644 --- a/tests/constructor_annots/__snapshots__/jsfmt.spec.js.snap +++ b/tests/constructor_annots/__snapshots__/jsfmt.spec.js.snap @@ -22,31 +22,30 @@ interface IFoo extends IFooPrototype { exports.Foo2 = (Foo: Class); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Foo is a class-like function -// constructs objects with property x -// has static property y -// exporting Foo directly doesn\'t work -// Foo\'s instance and static props are not picked up -// so you want to type Foo, by declaring it as a class -/* error, should have declared x: number instead*/ -/* error, should have declared static y: number instead*/ function Foo() { - this.x = 0; + this.x = 0; // constructs objects with property x } Foo.y = 0; +// has static property y Foo.prototype = { m() { return 0; } }; + +// exporting Foo directly doesn\'t work +// Foo\'s instance and static props are not picked up exports.Foo = Foo; + +// so you want to type Foo, by declaring it as a class interface IFooPrototype { m(): number } interface IFoo extends IFooPrototype { + /* error, should have declared x: number instead*/ static (): void, x: boolean, - static y: boolean + static y: boolean /* error, should have declared static y: number instead*/ } -exports.Foo2 = (Foo: Class); -" +exports.Foo2 = (Foo: Class);" `; exports[`test test.js 1`] = ` @@ -60,17 +59,17 @@ var x2: string = new Foo2().x; // error, found boolean instead of string var y2: string = Foo2.y; // error, found boolean instead of string var z2: string = new Foo2().m(); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// error, found number instead of string -// error, found number instead of string -// error, found boolean instead of string -// error, found boolean instead of string var Foo = require(\"./constructors\").Foo; var x: string = new Foo().x; +// error, found number instead of string var y: string = Foo.y; +// error, found number instead of string var z: string = new Foo().m(); + var Foo2 = require(\"./constructors\").Foo2; var x2: string = new Foo2().x; +// error, found boolean instead of string var y2: string = Foo2.y; -var z2: string = new Foo2().m(); -" +// error, found boolean instead of string +var z2: string = new Foo2().m();" `; diff --git a/tests/contents/ignore/__snapshots__/jsfmt.spec.js.snap b/tests/contents/ignore/__snapshots__/jsfmt.spec.js.snap index 19942181..202203ff 100644 --- a/tests/contents/ignore/__snapshots__/jsfmt.spec.js.snap +++ b/tests/contents/ignore/__snapshots__/jsfmt.spec.js.snap @@ -1,6 +1,5 @@ exports[`test dummy.js 1`] = ` "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - " `; @@ -11,6 +10,5 @@ xxx ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ require(\"./dummy\"); var xxx = 0; -xxx; -" +xxx;" `; diff --git a/tests/contents/no_flow/__snapshots__/jsfmt.spec.js.snap b/tests/contents/no_flow/__snapshots__/jsfmt.spec.js.snap index 19942181..202203ff 100644 --- a/tests/contents/no_flow/__snapshots__/jsfmt.spec.js.snap +++ b/tests/contents/no_flow/__snapshots__/jsfmt.spec.js.snap @@ -1,6 +1,5 @@ exports[`test dummy.js 1`] = ` "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - " `; @@ -11,6 +10,5 @@ xxx ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ require(\"./dummy\"); var xxx = 0; -xxx; -" +xxx;" `; diff --git a/tests/core_tests/__snapshots__/jsfmt.spec.js.snap b/tests/core_tests/__snapshots__/jsfmt.spec.js.snap index 7b43343f..1d739301 100644 --- a/tests/core_tests/__snapshots__/jsfmt.spec.js.snap +++ b/tests/core_tests/__snapshots__/jsfmt.spec.js.snap @@ -43,12 +43,11 @@ let tests = [ ]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + // Boolean (the class) tests. booleans (the literals) are not part of core.js -// constructor -// toString -// valueOf -// casting + let tests = [ + // constructor function() { new Boolean(); new Boolean(0); @@ -59,15 +58,18 @@ let tests = [ new Boolean(undefined); new Boolean(\"\"); }, + // toString function() { true.toString(); let x: boolean = false; x.toString(); new Boolean(true).toString(); }, + // valueOf function() { (new Boolean(0).valueOf(): boolean); }, + // casting function() { Boolean(); Boolean(0); @@ -78,8 +80,7 @@ let tests = [ Boolean(undefined); Boolean(\"\"); } -]; -" +];" `; exports[`test map.js 1`] = ` @@ -117,19 +118,15 @@ let tests = [ ]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// good constructors -// bad constructors -// error -// error -// get() -// error, string | void -// error, wrong key type + function* generator(): Iterable<[string, number]> { while (true) { yield [ \"foo\", 123 ]; } } + let tests = [ + // good constructors function() { let w = new Map(); let x = new Map(null); @@ -139,16 +136,19 @@ let tests = [ let b: Map = new Map([ [ \"foo\", 123 ] ]); let c: Map = new Map(generator()); }, + // bad constructors function() { let x = new Map([ \"foo\", 123 ]); - let y: Map = new Map([ [ \"foo\", 123 ] ]); + // error + let y: Map = new Map([ [ \"foo\", 123 ] ]); // error }, + // get() function(x: Map) { (x.get(\"foo\"): boolean); - x.get(123); + // error, string | void + x.get(123); // error, wrong key type } -]; -" +];" `; exports[`test regexp.js 1`] = ` @@ -183,38 +183,35 @@ let tests = [ ]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// constructor -// invalid in ES5, valid in ES6 -// invalid in ES5, valid in ES6 -// called as a function (equivalent to the constructor per ES6 21.2.3) -// invalid in ES5, valid in ES6 -// invalid in ES5, valid in ES6 -// invalid flags -// error -// error + let tests = [ + // constructor function() { new RegExp(\"foo\"); new RegExp(/foo/); new RegExp(\"foo\", \"i\"); new RegExp(\"foo\", \"ig\"); new RegExp(/foo/, \"i\"); - new RegExp(/foo/g, \"i\"); + // invalid in ES5, valid in ES6 + new RegExp(/foo/g, \"i\"); // invalid in ES5, valid in ES6 }, + // called as a function (equivalent to the constructor per ES6 21.2.3) function() { RegExp(\"foo\"); RegExp(/foo/); RegExp(\"foo\", \"i\"); RegExp(\"foo\", \"ig\"); RegExp(/foo/, \"i\"); - RegExp(/foo/g, \"i\"); + // invalid in ES5, valid in ES6 + RegExp(/foo/g, \"i\"); // invalid in ES5, valid in ES6 }, + // invalid flags function() { RegExp(\"foo\", \"z\"); - new RegExp(\"foo\", \"z\"); + // error + new RegExp(\"foo\", \"z\"); // error } -]; -" +];" `; exports[`test weakset.js 1`] = ` @@ -256,11 +253,11 @@ function* numbers(): Iterable { let ws5 = new WeakSet(numbers()); // error, must be objects ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// error, must be objects -// error, must be objects + let ws = new WeakSet(); let obj: Object = {}; let dict: { foo: string } = { foo: \"bar\" }; + ws.add(window); ws.add(obj); ws.add(dict); @@ -270,20 +267,25 @@ ws.has(dict); ws.delete(window); ws.delete(obj); ws.delete(dict); + let ws2 = new WeakSet([ obj, dict ]); + let ws3 = new WeakSet([ 1, 2, 3 ]); +// error, must be objects function* generator(): Iterable<{ foo: string }> { while (true) { yield { foo: \"bar\" }; } } + let ws4 = new WeakSet(generator()); + function* numbers(): Iterable { let i = 0; while (true) { yield i++; } } -let ws5 = new WeakSet(numbers()); -" + +let ws5 = new WeakSet(numbers()); // error, must be objects" `; diff --git a/tests/covariance/__snapshots__/jsfmt.spec.js.snap b/tests/covariance/__snapshots__/jsfmt.spec.js.snap index 6ee94bc9..a3cf7b2c 100644 --- a/tests/covariance/__snapshots__/jsfmt.spec.js.snap +++ b/tests/covariance/__snapshots__/jsfmt.spec.js.snap @@ -49,9 +49,23 @@ n.x = [0]; */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +type CovArrayVerbose = Array; +var b: CovArrayVerbose = []; +var y: CovArrayVerbose = b; +y[0] = \"\"; // error +class NVerbose { + x: CovArrayVerbose; + foo(): CovArrayVerbose { + return this.x; + } +} + +var nv: NVerbose = new NVerbose(); +nv.x = [ 0 ]; +(nv.x[0]: string); // error -// error +(nv.foo()[0]: string); // error /* TODO: use existentials for non-verbose covariance? type CovArray = Array<*:X>; @@ -85,20 +99,5 @@ n.x = [0]; (n.x[0]: string); // error (n.foo()[0]: string); // not an error! -*/ -type CovArrayVerbose = Array; -var b: CovArrayVerbose = []; -var y: CovArrayVerbose = b; -y[0] = \"\"; -class NVerbose { - x: CovArrayVerbose; - foo(): CovArrayVerbose { - return this.x; - } -} -var nv: NVerbose = new NVerbose(); -nv.x = [ 0 ]; -(nv.x[0]: string); -(nv.foo()[0]: string); -" +*/" `; diff --git a/tests/coverage/__snapshots__/jsfmt.spec.js.snap b/tests/coverage/__snapshots__/jsfmt.spec.js.snap index f9dfe473..5e77587c 100644 --- a/tests/coverage/__snapshots__/jsfmt.spec.js.snap +++ b/tests/coverage/__snapshots__/jsfmt.spec.js.snap @@ -11,13 +11,12 @@ declare module bar { // TODO ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +declare module foo {} +// TODO // This file triggers a violation of the \"disjoint-or-nested ranges invariant\" // that we implicitly assume in type-at-pos and coverage implementations. In // particular, when unchecked it causes a crash with coverage --color. -// TODO -declare module foo {} -declare module bar {} -" +declare module bar {}" `; exports[`test declare_module.js 1`] = ` @@ -27,8 +26,8 @@ declare module foo { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // check coverage of declare module -declare module foo {} -" + +declare module foo {}" `; exports[`test no_pragma.js 1`] = ` @@ -36,8 +35,7 @@ exports[`test no_pragma.js 1`] = ` (x: string); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ let x = 0; -(x: string); -" +(x: string);" `; exports[`test non-termination.js 1`] = ` @@ -56,12 +54,11 @@ declare module bar { declare class qux { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +declare module foo {} // This file triggers a violation of the \"disjoint-or-nested ranges invariant\" // that we implicitly assume in type-at-pos and coverage implementations. In // particular, when unchecked it causes non-termination with coverage --color. -// TODO -declare module foo {} declare module bar {} -declare class qux {} -" +// TODO +declare class qux {}" `; diff --git a/tests/cycle/__snapshots__/jsfmt.spec.js.snap b/tests/cycle/__snapshots__/jsfmt.spec.js.snap index f652eb51..6d507481 100644 --- a/tests/cycle/__snapshots__/jsfmt.spec.js.snap +++ b/tests/cycle/__snapshots__/jsfmt.spec.js.snap @@ -6,9 +6,10 @@ class A extends B { } module.exports = A; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ var B = require(\"./B\"); + class A extends B {} -module.exports = A; -" + +module.exports = A;" `; exports[`test B.js 1`] = ` @@ -18,8 +19,8 @@ exports[`test B.js 1`] = ` module.exports = B; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -//class B extends A { } var A = require(\"./A\"); -module.exports = B; -" + +//class B extends A { } +module.exports = B;" `; diff --git a/tests/date/__snapshots__/jsfmt.spec.js.snap b/tests/date/__snapshots__/jsfmt.spec.js.snap index e4ac978b..5960075e 100644 --- a/tests/date/__snapshots__/jsfmt.spec.js.snap +++ b/tests/date/__snapshots__/jsfmt.spec.js.snap @@ -28,12 +28,12 @@ new Date(2015, 6, 18, 11, 55, 42, \'999\'); new Date(\'2015\', 6); new Date(2015, 6, 18, 11, 55, 42, 999, \'hahaha\'); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// valid constructors -// invalid constructors -// invalid constructors that we incorrectly consider valid var d = new Date(0); var x: string = d.getTime(); + var y: number = d; + +// valid constructors new Date(); new Date(1234567890); new Date(\"2015/06/18\"); @@ -43,6 +43,8 @@ new Date(2015, 6, 18, 11); new Date(2015, 6, 18, 11, 55); new Date(2015, 6, 18, 11, 55, 42); new Date(2015, 6, 18, 11, 55, 42, 999); + +// invalid constructors new Date({}); new Date(2015, \"6\"); new Date(2015, 6, \"18\"); @@ -50,7 +52,8 @@ new Date(2015, 6, 18, \"11\"); new Date(2015, 6, 18, 11, \"55\"); new Date(2015, 6, 18, 11, 55, \"42\"); new Date(2015, 6, 18, 11, 55, 42, \"999\"); + +// invalid constructors that we incorrectly consider valid new Date(\"2015\", 6); -new Date(2015, 6, 18, 11, 55, 42, 999, \"hahaha\"); -" +new Date(2015, 6, 18, 11, 55, 42, 999, \"hahaha\");" `; diff --git a/tests/declaration_files_haste/__snapshots__/jsfmt.spec.js.snap b/tests/declaration_files_haste/__snapshots__/jsfmt.spec.js.snap index 284cf97a..96e5c12e 100644 --- a/tests/declaration_files_haste/__snapshots__/jsfmt.spec.js.snap +++ b/tests/declaration_files_haste/__snapshots__/jsfmt.spec.js.snap @@ -10,8 +10,8 @@ module.exports.fun = (): string => \"hello there\"; * @providesModule ExplicitProvidesModuleDifferentName * @flow */ -module.exports.fun = (): string => \"hello there\"; -" + +module.exports.fun = (): string => \"hello there\";" `; exports[`test ExplicitProvidesModuleSameName.js 1`] = ` @@ -26,8 +26,8 @@ module.exports.fun = (): string => \"hello there\"; * @providesModule ExplicitProvidesModuleSameName * @flow */ -module.exports.fun = (): string => \"hello there\"; -" + +module.exports.fun = (): string => \"hello there\";" `; exports[`test ImplicitProvidesModule.js 1`] = ` @@ -42,15 +42,13 @@ module.exports.fun = (): string => \"hello there\"; * @providesModule ImplicitProvidesModule * @flow */ -module.exports.fun = (): string => \"hello there\"; -" + +module.exports.fun = (): string => \"hello there\";" `; exports[`test md5.js 1`] = ` "/* @providesModule md5 */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -/* @providesModule md5 */ - " `; @@ -67,11 +65,13 @@ var ExplicitDifferentName = require(\'ExplicitProvidesModuleDifferentName\'); (ExplicitDifferentName.fun(): string); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + var Implicit = require(\"ImplicitProvidesModule\"); (Implicit.fun(): string); + var ExplicitSameName = require(\"ExplicitProvidesModuleSameName\"); (ExplicitSameName.fun(): string); + var ExplicitDifferentName = require(\"ExplicitProvidesModuleDifferentName\"); -(ExplicitDifferentName.fun(): string); -" +(ExplicitDifferentName.fun(): string);" `; diff --git a/tests/declaration_files_haste/external/_d3/__snapshots__/jsfmt.spec.js.snap b/tests/declaration_files_haste/external/_d3/__snapshots__/jsfmt.spec.js.snap index 15ba9644..cc5be09e 100644 --- a/tests/declaration_files_haste/external/_d3/__snapshots__/jsfmt.spec.js.snap +++ b/tests/declaration_files_haste/external/_d3/__snapshots__/jsfmt.spec.js.snap @@ -1,6 +1,5 @@ exports[`test min.js 1`] = ` "module.exports.fun = (): string => \"hello there\"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -module.exports.fun = (): string => \"hello there\"; -" +module.exports.fun = (): string => \"hello there\";" `; diff --git a/tests/declaration_files_haste/foo/bar/__snapshots__/jsfmt.spec.js.snap b/tests/declaration_files_haste/foo/bar/__snapshots__/jsfmt.spec.js.snap index 43a7dfa3..33332b40 100644 --- a/tests/declaration_files_haste/foo/bar/__snapshots__/jsfmt.spec.js.snap +++ b/tests/declaration_files_haste/foo/bar/__snapshots__/jsfmt.spec.js.snap @@ -14,14 +14,16 @@ var unreachable = require(\'annotation\'); (corge.fun(): string); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// make sure we don\'t pick up non-header @providesModule -// annotations - see node_modules/qux/docblock.js + var docblock = require(\"qux/docblock\"); var min = require(\"d3/min.js\"); var corge = require(\"qux/corge\"); + +// make sure we don\'t pick up non-header @providesModule +// annotations - see node_modules/qux/docblock.js var unreachable = require(\"annotation\"); + (docblock.fun(): string); (min.fun(): string); -(corge.fun(): string); -" +(corge.fun(): string);" `; diff --git a/tests/declaration_files_haste/ws/__snapshots__/jsfmt.spec.js.snap b/tests/declaration_files_haste/ws/__snapshots__/jsfmt.spec.js.snap index c0fb13f9..b5388480 100644 --- a/tests/declaration_files_haste/ws/__snapshots__/jsfmt.spec.js.snap +++ b/tests/declaration_files_haste/ws/__snapshots__/jsfmt.spec.js.snap @@ -1,5 +1,4 @@ exports[`test index.js 1`] = ` "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - " `; diff --git a/tests/declaration_files_haste/ws/test/__snapshots__/jsfmt.spec.js.snap b/tests/declaration_files_haste/ws/test/__snapshots__/jsfmt.spec.js.snap index 188da262..428ec8fd 100644 --- a/tests/declaration_files_haste/ws/test/__snapshots__/jsfmt.spec.js.snap +++ b/tests/declaration_files_haste/ws/test/__snapshots__/jsfmt.spec.js.snap @@ -1,6 +1,5 @@ exports[`test client.js 1`] = ` "var ws = require(\'../\'); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -var ws = require(\"../\"); -" +var ws = require(\"../\");" `; diff --git a/tests/declaration_files_incremental_haste/__snapshots__/jsfmt.spec.js.snap b/tests/declaration_files_incremental_haste/__snapshots__/jsfmt.spec.js.snap index 0a3ea919..3e4f0f33 100644 --- a/tests/declaration_files_incremental_haste/__snapshots__/jsfmt.spec.js.snap +++ b/tests/declaration_files_incremental_haste/__snapshots__/jsfmt.spec.js.snap @@ -7,8 +7,7 @@ export function foo(): Implementation { return new Implementation; } class Implementation {} export function foo(): Implementation { return new Implementation(); -} -" +}" `; exports[`test ExplicitProvidesModuleDifferentName.js 1`] = ` @@ -24,9 +23,9 @@ module.exports.fun = (): Implementation => new Implementation; * @providesModule ExplicitProvidesModuleDifferentName * @flow */ + class Implementation {} -module.exports.fun = (): Implementation => new Implementation(); -" +module.exports.fun = (): Implementation => new Implementation();" `; exports[`test ExplicitProvidesModuleSameName.js 1`] = ` @@ -42,9 +41,9 @@ module.exports.fun = (): Implementation => new Implementation; * @providesModule ExplicitProvidesModuleSameName * @flow */ + class Implementation {} -module.exports.fun = (): Implementation => new Implementation(); -" +module.exports.fun = (): Implementation => new Implementation();" `; exports[`test ImplicitProvidesModule.js 1`] = ` @@ -60,16 +59,14 @@ module.exports.fun = (): Implementation => new Implementation; * @providesModule ImplicitProvidesModule * @flow */ + class Implementation {} -module.exports.fun = (): Implementation => new Implementation(); -" +module.exports.fun = (): Implementation => new Implementation();" `; exports[`test md5.js 1`] = ` "/* @providesModule md5 */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -/* @providesModule md5 */ - " `; @@ -86,14 +83,13 @@ var ExplicitDifferentName = require(\'ExplicitProvidesModuleDifferentName\'); (ExplicitDifferentName.fun(): boolean); // Error: Either Implementation ~> boolean or Declaration ~> boolean ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// Error: Either Implementation ~> boolean or Declaration ~> boolean -// Error: Either Implementation ~> boolean or Declaration ~> boolean -// Error: Either Implementation ~> boolean or Declaration ~> boolean + var Implicit = require(\"ImplicitProvidesModule\"); (Implicit.fun(): boolean); +// Error: Either Implementation ~> boolean or Declaration ~> boolean var ExplicitSameName = require(\"ExplicitProvidesModuleSameName\"); (ExplicitSameName.fun(): boolean); +// Error: Either Implementation ~> boolean or Declaration ~> boolean var ExplicitDifferentName = require(\"ExplicitProvidesModuleDifferentName\"); -(ExplicitDifferentName.fun(): boolean); -" +(ExplicitDifferentName.fun(): boolean); // Error: Either Implementation ~> boolean or Declaration ~> boolean" `; diff --git a/tests/declaration_files_incremental_haste/external/_d3/__snapshots__/jsfmt.spec.js.snap b/tests/declaration_files_incremental_haste/external/_d3/__snapshots__/jsfmt.spec.js.snap index 02bbf30a..ce8fdd85 100644 --- a/tests/declaration_files_incremental_haste/external/_d3/__snapshots__/jsfmt.spec.js.snap +++ b/tests/declaration_files_incremental_haste/external/_d3/__snapshots__/jsfmt.spec.js.snap @@ -3,6 +3,5 @@ exports[`test min.js 1`] = ` module.exports.fun = (): Implementation => new Implementation; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class Implementation {} -module.exports.fun = (): Implementation => new Implementation(); -" +module.exports.fun = (): Implementation => new Implementation();" `; diff --git a/tests/declaration_files_incremental_haste/foo/bar/__snapshots__/jsfmt.spec.js.snap b/tests/declaration_files_incremental_haste/foo/bar/__snapshots__/jsfmt.spec.js.snap index 1642bb7e..56c382fc 100644 --- a/tests/declaration_files_incremental_haste/foo/bar/__snapshots__/jsfmt.spec.js.snap +++ b/tests/declaration_files_incremental_haste/foo/bar/__snapshots__/jsfmt.spec.js.snap @@ -10,14 +10,14 @@ var corge = require(\'qux/corge\'); (corge.fun(): boolean); // Error: Either Implementation ~> boolean or Declaration ~> boolean ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// Error: Either Implementation ~> boolean or Declaration ~> boolean -// Error: Either Implementation ~> boolean or Declaration ~> boolean -// Error: Either Implementation ~> boolean or Declaration ~> boolean + var docblock = require(\"qux/docblock\"); var min = require(\"d3/min.js\"); var corge = require(\"qux/corge\"); + (docblock.fun(): boolean); +// Error: Either Implementation ~> boolean or Declaration ~> boolean (min.fun(): boolean); -(corge.fun(): boolean); -" +// Error: Either Implementation ~> boolean or Declaration ~> boolean +(corge.fun(): boolean); // Error: Either Implementation ~> boolean or Declaration ~> boolean" `; diff --git a/tests/declaration_files_incremental_haste/ws/__snapshots__/jsfmt.spec.js.snap b/tests/declaration_files_incremental_haste/ws/__snapshots__/jsfmt.spec.js.snap index c0fb13f9..b5388480 100644 --- a/tests/declaration_files_incremental_haste/ws/__snapshots__/jsfmt.spec.js.snap +++ b/tests/declaration_files_incremental_haste/ws/__snapshots__/jsfmt.spec.js.snap @@ -1,5 +1,4 @@ exports[`test index.js 1`] = ` "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - " `; diff --git a/tests/declaration_files_incremental_haste/ws/test/__snapshots__/jsfmt.spec.js.snap b/tests/declaration_files_incremental_haste/ws/test/__snapshots__/jsfmt.spec.js.snap index 188da262..428ec8fd 100644 --- a/tests/declaration_files_incremental_haste/ws/test/__snapshots__/jsfmt.spec.js.snap +++ b/tests/declaration_files_incremental_haste/ws/test/__snapshots__/jsfmt.spec.js.snap @@ -1,6 +1,5 @@ exports[`test client.js 1`] = ` "var ws = require(\'../\'); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -var ws = require(\"../\"); -" +var ws = require(\"../\");" `; diff --git a/tests/declaration_files_incremental_node/__snapshots__/jsfmt.spec.js.snap b/tests/declaration_files_incremental_node/__snapshots__/jsfmt.spec.js.snap index 1e0dbe29..f3cbb366 100644 --- a/tests/declaration_files_incremental_node/__snapshots__/jsfmt.spec.js.snap +++ b/tests/declaration_files_incremental_node/__snapshots__/jsfmt.spec.js.snap @@ -5,8 +5,7 @@ export function foo(): Implementation { return new Implementation; } class Implementation {} export function foo(): Implementation { return new Implementation(); -} -" +}" `; exports[`test test_absolute.js 1`] = ` @@ -53,47 +52,46 @@ var F = require(\'package_with_dir_main\'); (F.fun(): boolean); // Error either Implementation ~> boolean or Declaration ~> boolean ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + // This will require ./node_modules/B.js.flow -// Error either Implementation ~> boolean or Declaration ~> boolean -// This will require ./node_modules/B.js.flow -// Error either Implementation ~> boolean or Declaration ~> boolean -// Error either Implementation ~> boolean or Declaration ~> boolean -// Error either Implementation ~> boolean or Declaration ~> boolean -// Error either Implementation ~> boolean or Declaration ~> boolean -// Error either Implementation ~> boolean or Declaration ~> boolean -// This will require ./node_modules/B.js.flow -// Error either Implementation ~> boolean or Declaration ~> boolean -// This will require ./node_modules/B.js.flow -// Error either Implementation ~> boolean or Declaration ~> boolean -// Error either Implementation ~> boolean or Declaration ~> boolean -// Error either Implementation ~> boolean or Declaration ~> boolean -// Error either Implementation ~> boolean or Declaration ~> boolean -// Error either Implementation ~> boolean or Declaration ~> boolean var B1 = require(\"B\"); (B1.fun(): boolean); +// Error either Implementation ~> boolean or Declaration ~> boolean +// This will require ./node_modules/B.js.flow var B2 = require(\"B.js\"); (B2.fun(): boolean); +// Error either Implementation ~> boolean or Declaration ~> boolean var C = require(\"package_with_full_main\"); (C.fun(): boolean); +// Error either Implementation ~> boolean or Declaration ~> boolean var D = require(\"package_with_partial_main\"); (D.fun(): boolean); +// Error either Implementation ~> boolean or Declaration ~> boolean var E = require(\"package_with_no_package_json\"); (E.fun(): boolean); +// Error either Implementation ~> boolean or Declaration ~> boolean var F = require(\"package_with_dir_main\"); (F.fun(): boolean); +// Error either Implementation ~> boolean or Declaration ~> boolean +// This will require ./node_modules/B.js.flow var B1 = require(\"B\"); (B1.fun(): boolean); +// Error either Implementation ~> boolean or Declaration ~> boolean +// This will require ./node_modules/B.js.flow var B2 = require(\"B.js\"); (B2.fun(): boolean); +// Error either Implementation ~> boolean or Declaration ~> boolean var C = require(\"package_with_full_main\"); (C.fun(): boolean); +// Error either Implementation ~> boolean or Declaration ~> boolean var D = require(\"package_with_partial_main\"); (D.fun(): boolean); +// Error either Implementation ~> boolean or Declaration ~> boolean var E = require(\"package_with_no_package_json\"); (E.fun(): boolean); +// Error either Implementation ~> boolean or Declaration ~> boolean var F = require(\"package_with_dir_main\"); -(F.fun(): boolean); -" +(F.fun(): boolean); // Error either Implementation ~> boolean or Declaration ~> boolean" `; exports[`test test_relative.js 1`] = ` @@ -101,8 +99,7 @@ exports[`test test_relative.js 1`] = ` (foo(): boolean); // Error: either Implementation ~> boolean or Definition ~> boolean ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Error: either Implementation ~> boolean or Definition ~> boolean import {foo} from \"./A\"; -(foo(): boolean); -" + +(foo(): boolean); // Error: either Implementation ~> boolean or Definition ~> boolean" `; diff --git a/tests/declaration_files_node/__snapshots__/jsfmt.spec.js.snap b/tests/declaration_files_node/__snapshots__/jsfmt.spec.js.snap index 777cf1f1..2763bc7e 100644 --- a/tests/declaration_files_node/__snapshots__/jsfmt.spec.js.snap +++ b/tests/declaration_files_node/__snapshots__/jsfmt.spec.js.snap @@ -4,8 +4,8 @@ exports[`test A.js 1`] = ` module.exports.fun = (): string => \'hello there!\'; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -module.exports.fun = (): string => \"hello there!\"; -" + +module.exports.fun = (): string => \"hello there!\";" `; exports[`test CJS.js 1`] = ` @@ -13,8 +13,7 @@ exports[`test CJS.js 1`] = ` module.exports = 42; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -module.exports = 42; -" +module.exports = 42;" `; exports[`test test_absolute.js 1`] = ` @@ -41,27 +40,26 @@ var F = require(\'package_with_dir_main\'); (F.fun(): string); // Error number ~> string ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + // This will require ./node_modules/B.js.flow -// Error number ~> string -// This will require ./node_modules/B.js.flow -// Error number ~> string -// Error number ~> string -// Error number ~> string -// Error number ~> string -// Error number ~> string var B1 = require(\"B\"); (B1.fun(): string); +// Error number ~> string +// This will require ./node_modules/B.js.flow var B2 = require(\"B.js\"); (B2.fun(): string); +// Error number ~> string var C = require(\"package_with_full_main\"); (C.fun(): string); +// Error number ~> string var D = require(\"package_with_partial_main\"); (D.fun(): string); +// Error number ~> string var E = require(\"package_with_no_package_json\"); (E.fun(): string); +// Error number ~> string var F = require(\"package_with_dir_main\"); -(F.fun(): string); -" +(F.fun(): string); // Error number ~> string" `; exports[`test test_relative.js 1`] = ` @@ -80,17 +78,16 @@ var CJS = require(\'./CJS.js\'); (CJS: number); // Error: string ~> number ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + // This will require ./A.js.flow -// Error number ~> string -// This will require ./A.js.flow -// Error number ~> string -// Error: string ~> number var A1 = require(\"./A\"); (A1.fun(): string); +// Error number ~> string +// This will require ./A.js.flow var A2 = require(\"./A.js\"); (A2.fun(): string); +// Error number ~> string var CJS = require(\"./CJS.js\"); (CJS: string); -(CJS: number); -" +(CJS: number); // Error: string ~> number" `; diff --git a/tests/declare_class/__snapshots__/jsfmt.spec.js.snap b/tests/declare_class/__snapshots__/jsfmt.spec.js.snap index 254d373a..4da8927d 100644 --- a/tests/declare_class/__snapshots__/jsfmt.spec.js.snap +++ b/tests/declare_class/__snapshots__/jsfmt.spec.js.snap @@ -10,11 +10,11 @@ C.foo(\"\"); (C.name: string); (C.name: number); // error, it\'s a string ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// error, it\'s a string declare class C { static x: number, static foo(x: number): void } + C.x = \"\"; C.foo(\"\"); + (C.name: string); -(C.name: number); -" +(C.name: number); // error, it\'s a string" `; diff --git a/tests/declare_class/lib/__snapshots__/jsfmt.spec.js.snap b/tests/declare_class/lib/__snapshots__/jsfmt.spec.js.snap index 912318f3..e9edd496 100644 --- a/tests/declare_class/lib/__snapshots__/jsfmt.spec.js.snap +++ b/tests/declare_class/lib/__snapshots__/jsfmt.spec.js.snap @@ -11,6 +11,5 @@ declare class D extends _module.C { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ declare class _C { foo(): number } declare var _module: { C: Class<_C> }; -declare class D extends _module.C { foo(): string } -" +declare class D extends _module.C { foo(): string }" `; diff --git a/tests/declare_export/__snapshots__/jsfmt.spec.js.snap b/tests/declare_export/__snapshots__/jsfmt.spec.js.snap index c83406e6..67666fab 100644 --- a/tests/declare_export/__snapshots__/jsfmt.spec.js.snap +++ b/tests/declare_export/__snapshots__/jsfmt.spec.js.snap @@ -4,15 +4,13 @@ exports[`test B.js 1`] = ` exports.numberValue = 42; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -exports.numberValue = 42; -" + +exports.numberValue = 42;" `; exports[`test C.js 1`] = ` "/* @flow */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -/* @flow */ - " `; @@ -43,11 +41,14 @@ module.exports = Test; * @providesModule CommonJS_Clobbering_Class * @flow */ + class Base { static baseProp: number; } + class Test extends Base { static childProp: number; + static staticNumber1(): number { return 1; } @@ -57,6 +58,7 @@ class Test extends Base { static staticNumber3(): number { return 3; } + instNumber1(): number { return 1; } @@ -64,8 +66,8 @@ class Test extends Base { return 2; } } -module.exports = Test; -" + +module.exports = Test;" `; exports[`test CommonJS_Clobbering_Lit.js 1`] = ` @@ -86,14 +88,14 @@ module.exports = { * @providesModule CommonJS_Clobbering_Lit * @flow */ + module.exports = { numberValue1: 1, numberValue2: 2, numberValue3: 3, numberValue4: 4, numberValue5: 5 -}; -" +};" `; exports[`test CommonJS_Named.js 1`] = ` @@ -112,12 +114,12 @@ exports.numberValue5 = 5; * @providesModule CommonJS_Named * @flow */ + exports.numberValue1 = 1; exports.numberValue2 = 2; exports.numberValue3 = 3; exports.numberValue4 = 4; -exports.numberValue5 = 5; -" +exports.numberValue5 = 5;" `; exports[`test ES6_Default_AnonFunction1.js 1`] = ` @@ -132,8 +134,8 @@ declare export default () => number; * @providesModule ES6_Default_AnonFunction1 * @flow */ -declare export default () => number -" + +declare export default () => number" `; exports[`test ES6_Default_AnonFunction2.js 1`] = ` @@ -148,8 +150,8 @@ declare export default () =>number; * @providesModule ES6_Default_AnonFunction2 * @flow */ -declare export default () => number -" + +declare export default () => number" `; exports[`test ES6_Default_NamedClass1.js 1`] = ` @@ -170,13 +172,14 @@ declare export function getAFoo(): FooImpl; * @providesModule ES6_Default_NamedClass1 * @flow */ + +declare export default class FooImpl { givesANum(): number } + // Regression test for https://github.com/facebook/flow/issues/511 // // Default-exported class should also be available in local scope -declare export default class FooImpl { givesANum(): number } declare export {FooImpl as Foo} -declare export function getAFoo(): FooImpl; -" +declare export function getAFoo(): FooImpl;" `; exports[`test ES6_Default_NamedClass2.js 1`] = ` @@ -191,6 +194,7 @@ declare export default class Foo { givesANum(): number; }; * @providesModule ES6_Default_NamedClass2 * @flow */ + declare export default class Foo { givesANum(): number } " `; @@ -207,8 +211,8 @@ declare export default function foo():number; * @providesModule ES6_Default_NamedFunction1 * @flow */ -declare export default function foo(): number; -" + +declare export default function foo(): number;" `; exports[`test ES6_Default_NamedFunction2.js 1`] = ` @@ -223,8 +227,8 @@ declare export default function foo():number; * @providesModule ES6_Default_NamedFunction2 * @flow */ -declare export default function foo(): number; -" + +declare export default function foo(): number;" `; exports[`test ES6_DefaultAndNamed.js 1`] = ` @@ -234,9 +238,9 @@ declare export default number; declare export var str: string; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + declare export default number -declare export var str: string; -" +declare export var str: string;" `; exports[`test ES6_ExportAllFrom_Intermediary1.js 1`] = ` @@ -251,8 +255,8 @@ declare export * from \"ES6_ExportAllFrom_Source1\"; * @providesModule ES6_ExportAllFrom_Intermediary1 * @flow */ -declare export * from \"ES6_ExportAllFrom_Source1\" -" + +declare export * from \"ES6_ExportAllFrom_Source1\"" `; exports[`test ES6_ExportAllFrom_Intermediary2.js 1`] = ` @@ -267,8 +271,8 @@ declare export * from \"ES6_ExportAllFrom_Source2\"; * @providesModule ES6_ExportAllFrom_Intermediary2 * @flow */ -declare export * from \"ES6_ExportAllFrom_Source2\" -" + +declare export * from \"ES6_ExportAllFrom_Source2\"" `; exports[`test ES6_ExportAllFrom_Source1.js 1`] = ` @@ -283,8 +287,8 @@ declare export var numberValue1: number; * @providesModule ES6_ExportAllFrom_Source1 * @flow */ -declare export var numberValue1: number; -" + +declare export var numberValue1: number;" `; exports[`test ES6_ExportAllFrom_Source2.js 1`] = ` @@ -299,8 +303,8 @@ declare export var numberValue2: number; * @providesModule ES6_ExportAllFrom_Source2 * @flow */ -declare export var numberValue2: number; -" + +declare export var numberValue2: number;" `; exports[`test ES6_ExportAllFromMulti.js 1`] = ` @@ -310,9 +314,9 @@ declare export * from \"./ES6_ExportAllFrom_Source1\"; declare export * from \"./ES6_ExportAllFrom_Source2\"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + declare export * from \"./ES6_ExportAllFrom_Source1\" -declare export * from \"./ES6_ExportAllFrom_Source2\" -" +declare export * from \"./ES6_ExportAllFrom_Source2\"" `; exports[`test ES6_ExportFrom_Intermediary1.js 1`] = ` @@ -330,8 +334,8 @@ declare export { * @providesModule ES6_ExportFrom_Intermediary1 * @flow */ -declare export {numberValue1, numberValue2 as numberValue2_renamed} from \"ES6_ExportFrom_Source1\" -" + +declare export {numberValue1, numberValue2 as numberValue2_renamed} from \"ES6_ExportFrom_Source1\"" `; exports[`test ES6_ExportFrom_Intermediary2.js 1`] = ` @@ -349,8 +353,8 @@ declare export { * @providesModule ES6_ExportFrom_Intermediary2 * @flow */ -declare export {numberValue1, numberValue2 as numberValue2_renamed2} from \"ES6_ExportFrom_Source2\" -" + +declare export {numberValue1, numberValue2 as numberValue2_renamed2} from \"ES6_ExportFrom_Source2\"" `; exports[`test ES6_ExportFrom_Source1.js 1`] = ` @@ -366,9 +370,9 @@ declare export var numberValue2: number; * @providesModule ES6_ExportFrom_Source1 * @flow */ + declare export var numberValue1: number; -declare export var numberValue2: number; -" +declare export var numberValue2: number;" `; exports[`test ES6_ExportFrom_Source2.js 1`] = ` @@ -384,9 +388,9 @@ declare export var numberValue2: number; * @providesModule ES6_ExportFrom_Source2 * @flow */ + declare export var numberValue1: number; -declare export var numberValue2: number; -" +declare export var numberValue2: number;" `; exports[`test ES6_Named1.js 1`] = ` @@ -416,20 +420,23 @@ declare export var varDeclNumber2: number; * @providesModule ES6_Named1 * @flow */ + var specifierNumber1 = 1; var specifierNumber2 = 2; var specifierNumber3 = 3; var groupedSpecifierNumber1 = 1; var groupedSpecifierNumber2 = 2; + declare export {specifierNumber1} declare export {specifierNumber2 as specifierNumber2Renamed} declare export {specifierNumber3} declare export {groupedSpecifierNumber1, groupedSpecifierNumber2} + declare export function givesANumber(): number; declare export class NumberGenerator { givesANumber(): number } + declare export var varDeclNumber1: number; -declare export var varDeclNumber2: number; -" +declare export var varDeclNumber2: number;" `; exports[`test ES6_Named2.js 1`] = ` @@ -457,18 +464,21 @@ declare export var varDeclNumber4: number; * @providesModule ES6_Named2 * @flow */ + var specifierNumber4 = 1; var specifierNumber5 = 2; var groupedSpecifierNumber3 = 1; var groupedSpecifierNumber4 = 2; + declare export {specifierNumber4} declare export {specifierNumber5 as specifierNumber5Renamed} declare export {groupedSpecifierNumber3, groupedSpecifierNumber4} + declare export function givesANumber2(): number; declare export class NumberGenerator2 { givesANumber(): number } + declare export var varDeclNumber3: number; -declare export var varDeclNumber4: number; -" +declare export var varDeclNumber4: number;" `; exports[`test ProvidesModuleA.js 1`] = ` @@ -487,12 +497,12 @@ exports.stringValue = \"str\"; * @providesModule A * @flow */ + exports.numberValue1 = 42; exports.numberValue2 = 42; exports.numberValue3 = 42; exports.numberValue4 = 42; -exports.stringValue = \"str\"; -" +exports.stringValue = \"str\";" `; exports[`test ProvidesModuleCJSDefault.js 1`] = ` @@ -509,8 +519,8 @@ module.exports = { * @providesModule CJSDefault * @flow */ -module.exports = { numberValue: 42 }; -" + +module.exports = { numberValue: 42 };" `; exports[`test ProvidesModuleD.js 1`] = ` @@ -519,11 +529,6 @@ exports[`test ProvidesModuleD.js 1`] = ` * @flow */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -/** - * @providesModule D - * @flow - */ - " `; @@ -539,24 +544,12 @@ export default { }; */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -/** - * @providesModule ES6Default - * @flow - */ -/* -export default { - numberValue: 42, -}; -*/ - " `; exports[`test SideEffects.js 1`] = ` "/* @flow */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -/* @flow */ - " `; @@ -854,271 +847,274 @@ var at3: number = numberValue9; var at4: string = numberValue9; // Error: number ~> string ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + // ===================== // // == Path Resolution == // // ===================== // + // @providesModule +import * as DefaultA from \"A\"; +var a1: number = DefaultA.numberValue1; +var a2: string = DefaultA.numberValue1; // Error: number ~> string // File path +import * as DefaultB from \"./B\"; +var b1: number = DefaultB.numberValue; +var b2: string = DefaultB.numberValue; // Error: number ~> string // C.js exists, but not as a providesModule +import DefaultC from \"C\"; // Error: No such module // @providesModule D exists, but not as a filename +import DefaultD from \"./D\"; // Error: No such module // ================================================ // // == CommonJS Clobbering Literal Exports -> ES6 == // // ================================================ // +import {doesntExist1} from \"CommonJS_Clobbering_Lit\"; // Error: Not an exported binding +import {numberValue1} from \"CommonJS_Clobbering_Lit\"; +var c1: number = numberValue1; +var c2: string = numberValue1; // Error: number ~> string +import {numberValue2 as numVal1} from \"CommonJS_Clobbering_Lit\"; +var d1: number = numVal1; +var d2: string = numVal1; // Error: number ~> string +import CJS_Clobb_Lit from \"CommonJS_Clobbering_Lit\"; +var e1: number = CJS_Clobb_Lit.numberValue3; +var e2: string = CJS_Clobb_Lit.numberValue3; // Error: number ~> string +CJS_Clobb_Lit.doesntExist; // Error: doesntExist isn\'t a property +import * as CJS_Clobb_Lit_NS from \"CommonJS_Clobbering_Lit\"; +var f1: number = CJS_Clobb_Lit_NS.numberValue4; +var f2: number = CJS_Clobb_Lit_NS.default.numberValue4; +CJS_Clobb_Lit_NS.default.default; // Error: No \'default\' property on the exported obj +var f3: string = CJS_Clobb_Lit_NS.numberValue4; // Error: number ~> string +var f4: string = CJS_Clobb_Lit_NS.default.numberValue5; // Error: number ~> string // ============================================== // // == CommonJS Clobbering Class Exports -> ES6 == // // ============================================== // +import {doesntExist2} from \"CommonJS_Clobbering_Class\"; // Error: Not an exported binding // The following import should error because class statics are not turned into // named exports for now. This avoids complexities with polymorphic static // members (where the polymophism is defined on the class itself rather than the // method). +import {staticNumber1, baseProp, childProp} from \"CommonJS_Clobbering_Class\"; // Error +import CJS_Clobb_Class from \"CommonJS_Clobbering_Class\"; +new CJS_Clobb_Class(); +new CJS_Clobb_Class().doesntExist; // Error: Class has no \`doesntExist\` property +var h1: number = CJS_Clobb_Class.staticNumber2(); +var h2: string = CJS_Clobb_Class.staticNumber2(); // Error: number ~> string +var h3: number = new CJS_Clobb_Class().instNumber1(); +var h4: string = new CJS_Clobb_Class().instNumber1(); // Error: number ~> string +import * as CJS_Clobb_Class_NS from \"CommonJS_Clobbering_Class\"; +new CJS_Clobb_Class_NS(); // Error: Namespace object isn\'t constructable +var i1: number = CJS_Clobb_Class_NS.staticNumber3(); // Error: Class statics not copied to Namespace object +var i2: number = new CJS_Clobb_Class_NS.default().instNumber2(); +var i3: string = new CJS_Clobb_Class_NS.default().instNumber2(); // Error: number ~> string // =================================== // // == CommonJS Named Exports -> ES6 == // // =================================== // +import {doesntExist3} from \"CommonJS_Named\"; // Error: Not an exported binding +import {numberValue2} from \"CommonJS_Named\"; +var j1: number = numberValue2; +var j2: string = numberValue2; // Error: number ~> string +import {numberValue3 as numVal3} from \"CommonJS_Named\"; +var k1: number = numVal3; +var k2: string = numVal3; // Error: number ~> string +import * as CJS_Named from \"CommonJS_Named\"; +var l1: number = CJS_Named.numberValue1; +var l2: string = CJS_Named.numberValue1; // Error: number ~> string +CJS_Named.doesntExist; // Error: doesntExist isn\'t a property +import * as CJS_Named_NS from \"CommonJS_Named\"; +var m1: number = CJS_Named_NS.numberValue4; +var m2: string = CJS_Named_NS.default.numberValue4; // Error: CommonJS_Named has no default export +var m3: string = CJS_Named_NS.numberValue4; // Error: number ~> string ////////////////////////////// // == ES6 Default -> ES6 == // ////////////////////////////// +import {doesntExist4} from \"ES6_Default_AnonFunction1\"; // Error: Not an exported binding +import ES6_Def_AnonFunc1 from \"ES6_Default_AnonFunction1\"; +var n1: number = ES6_Def_AnonFunc1(); +var n2: string = ES6_Def_AnonFunc1(); // Error: number ~> string +import ES6_Def_NamedFunc1 from \"ES6_Default_NamedFunction1\"; +var o1: number = ES6_Def_NamedFunc1(); +var o2: string = ES6_Def_NamedFunc1(); // Error: number ~> string +import ES6_Def_NamedClass1 from \"ES6_Default_NamedClass1\"; +var q1: number = new ES6_Def_NamedClass1().givesANum(); +var q2: string = new ES6_Def_NamedClass1().givesANum(); // Error: number ~> string //////////////////////////// // == ES6 Named -> ES6 == // //////////////////////////// -// Error: Not an exported binding -// Error: number ~> string -// Error: number ~> string -// Error: number ~> string -// Error: number ~> string -// Error: number ~> string -// Error: number ~> string -// Error: number ~> string -// Error: number ~> string -// Error: number ~> string -// Error: number ~> string -// Error: number ~> string -// Error: number ~> string -/////////////////////////////////// -// == ES6 Default -> CommonJS == // -/////////////////////////////////// -// Error: \'doesntExist\' isn\'t an export -// Error: number ~> string -// Error: number ~> string -// Error: number ~> string -///////////////////////////////// -// == ES6 Named -> CommonJS == // -///////////////////////////////// -// Error: number ~> string -// Error: number ~> string -// Error: number ~> string -// Error: number ~> string -// Error: number ~> string -// Error: number ~> string -// Error: number ~> string -// Error: number ~> string -// Error: number ~> string -// Error: number ~> string -// Error: number ~> string -//////////////////////////////////////////////////////// -// == ES6 Default+Named -> ES6 import Default+Named== // -//////////////////////////////////////////////////////// -// Error: number ~> string -// Error: string ~> number -//////////////////////////////////////// -// == Side-effect only ES6 imports == // -//////////////////////////////////////// -////////////////////////////////////////////// -// == Suggest export name on likely typo == // -////////////////////////////////////////////// -// Error: Did you mean \`import {specifierNumber1} from ...\`? -// Error: Did you mean \`specifierNumber1\`? -/////////////////////////////////////////////////// -// == Multi \`export *\` should combine exports == // -/////////////////////////////////////////////////// -// Error: number ~> string -// Error: number ~> string -import * as DefaultA from \"A\"; -var a1: number = DefaultA.numberValue1; -var a2: string = DefaultA.numberValue1; -import * as DefaultB from \"./B\"; -var b1: number = DefaultB.numberValue; -var b2: string = DefaultB.numberValue; -import DefaultC from \"C\"; -import DefaultD from \"./D\"; -import {doesntExist1} from \"CommonJS_Clobbering_Lit\"; -import {numberValue1} from \"CommonJS_Clobbering_Lit\"; -var c1: number = numberValue1; -var c2: string = numberValue1; -import {numberValue2 as numVal1} from \"CommonJS_Clobbering_Lit\"; -var d1: number = numVal1; -var d2: string = numVal1; -import CJS_Clobb_Lit from \"CommonJS_Clobbering_Lit\"; -var e1: number = CJS_Clobb_Lit.numberValue3; -var e2: string = CJS_Clobb_Lit.numberValue3; -CJS_Clobb_Lit.doesntExist; -import * as CJS_Clobb_Lit_NS from \"CommonJS_Clobbering_Lit\"; -var f1: number = CJS_Clobb_Lit_NS.numberValue4; -var f2: number = CJS_Clobb_Lit_NS.default.numberValue4; -CJS_Clobb_Lit_NS.default.default; -var f3: string = CJS_Clobb_Lit_NS.numberValue4; -var f4: string = CJS_Clobb_Lit_NS.default.numberValue5; -import {doesntExist2} from \"CommonJS_Clobbering_Class\"; -import {staticNumber1, baseProp, childProp} from \"CommonJS_Clobbering_Class\"; -import CJS_Clobb_Class from \"CommonJS_Clobbering_Class\"; -new CJS_Clobb_Class(); -new CJS_Clobb_Class().doesntExist; -var h1: number = CJS_Clobb_Class.staticNumber2(); -var h2: string = CJS_Clobb_Class.staticNumber2(); -var h3: number = new CJS_Clobb_Class().instNumber1(); -var h4: string = new CJS_Clobb_Class().instNumber1(); -import * as CJS_Clobb_Class_NS from \"CommonJS_Clobbering_Class\"; -new CJS_Clobb_Class_NS(); -var i1: number = CJS_Clobb_Class_NS.staticNumber3(); -var i2: number = new CJS_Clobb_Class_NS.default().instNumber2(); -var i3: string = new CJS_Clobb_Class_NS.default().instNumber2(); -import {doesntExist3} from \"CommonJS_Named\"; -import {numberValue2} from \"CommonJS_Named\"; -var j1: number = numberValue2; -var j2: string = numberValue2; -import {numberValue3 as numVal3} from \"CommonJS_Named\"; -var k1: number = numVal3; -var k2: string = numVal3; -import * as CJS_Named from \"CommonJS_Named\"; -var l1: number = CJS_Named.numberValue1; -var l2: string = CJS_Named.numberValue1; -CJS_Named.doesntExist; -import * as CJS_Named_NS from \"CommonJS_Named\"; -var m1: number = CJS_Named_NS.numberValue4; -var m2: string = CJS_Named_NS.default.numberValue4; -var m3: string = CJS_Named_NS.numberValue4; -import {doesntExist4} from \"ES6_Default_AnonFunction1\"; -import ES6_Def_AnonFunc1 from \"ES6_Default_AnonFunction1\"; -var n1: number = ES6_Def_AnonFunc1(); -var n2: string = ES6_Def_AnonFunc1(); -import ES6_Def_NamedFunc1 from \"ES6_Default_NamedFunction1\"; -var o1: number = ES6_Def_NamedFunc1(); -var o2: string = ES6_Def_NamedFunc1(); -import ES6_Def_NamedClass1 from \"ES6_Default_NamedClass1\"; -var q1: number = new ES6_Def_NamedClass1().givesANum(); -var q2: string = new ES6_Def_NamedClass1().givesANum(); import doesntExist5 from \"ES6_Named1\"; +// Error: Not an exported binding import {specifierNumber1 as specifierNumber1_1} from \"ES6_Named1\"; var r1: number = specifierNumber1_1; var r2: string = specifierNumber1_1; +// Error: number ~> string import {specifierNumber2Renamed} from \"ES6_Named1\"; var s1: number = specifierNumber2Renamed; var s2: string = specifierNumber2Renamed; +// Error: number ~> string import {specifierNumber3 as specifierNumber3Renamed} from \"ES6_Named1\"; var t1: number = specifierNumber3Renamed; var t2: string = specifierNumber3Renamed; +// Error: number ~> string import {groupedSpecifierNumber1, groupedSpecifierNumber2} from \"ES6_Named1\"; var u1: number = groupedSpecifierNumber1; var u2: number = groupedSpecifierNumber2; var u3: string = groupedSpecifierNumber1; +// Error: number ~> string var u4: string = groupedSpecifierNumber2; +// Error: number ~> string import {givesANumber} from \"ES6_Named1\"; var v1: number = givesANumber(); var v2: string = givesANumber(); +// Error: number ~> string import {NumberGenerator} from \"ES6_Named1\"; var w1: number = new NumberGenerator().givesANumber(); var w2: string = new NumberGenerator().givesANumber(); +// Error: number ~> string import {varDeclNumber1, varDeclNumber2} from \"ES6_Named1\"; var x1: number = varDeclNumber1; var x2: number = varDeclNumber2; var x3: string = varDeclNumber1; +// Error: number ~> string var x4: string = varDeclNumber2; +// Error: number ~> string import {numberValue1 as numberValue4} from \"ES6_ExportFrom_Intermediary1\"; var aa1: number = numberValue4; var aa2: string = numberValue4; +// Error: number ~> string import {numberValue2_renamed} from \"ES6_ExportFrom_Intermediary1\"; var ab1: number = numberValue2_renamed; var ab2: string = numberValue2_renamed; +// Error: number ~> string import {numberValue1 as numberValue5} from \"ES6_ExportAllFrom_Intermediary1\"; var ac1: number = numberValue5; var ac2: string = numberValue5; +// Error: number ~> string +/////////////////////////////////// +// == ES6 Default -> CommonJS == // +/////////////////////////////////// require(\"ES6_Default_AnonFunction2\").doesntExist; +// Error: \'doesntExist\' isn\'t an export var ES6_Def_AnonFunc2 = require(\"ES6_Default_AnonFunction2\").default; var ad1: number = ES6_Def_AnonFunc2(); var ad2: string = ES6_Def_AnonFunc2(); +// Error: number ~> string var ES6_Def_NamedFunc2 = require(\"ES6_Default_NamedFunction2\").default; var ae1: number = ES6_Def_NamedFunc2(); var ae2: string = ES6_Def_NamedFunc2(); +// Error: number ~> string var ES6_Def_NamedClass2 = require(\"ES6_Default_NamedClass2\").default; var ag1: number = new ES6_Def_NamedClass2().givesANum(); var ag2: string = new ES6_Def_NamedClass2().givesANum(); +// Error: number ~> string +///////////////////////////////// +// == ES6 Named -> CommonJS == // +///////////////////////////////// var specifierNumber4 = require(\"ES6_Named2\").specifierNumber4; var ah1: number = specifierNumber4; var ah2: string = specifierNumber4; +// Error: number ~> string var specifierNumber5Renamed = require(\"ES6_Named2\").specifierNumber5Renamed; var ai1: number = specifierNumber5Renamed; var ai2: string = specifierNumber5Renamed; +// Error: number ~> string var groupedSpecifierNumber3 = require(\"ES6_Named2\").groupedSpecifierNumber3; var groupedSpecifierNumber4 = require(\"ES6_Named2\").groupedSpecifierNumber4; var aj1: number = groupedSpecifierNumber3; var aj2: number = groupedSpecifierNumber4; var aj3: string = groupedSpecifierNumber3; +// Error: number ~> string var aj4: string = groupedSpecifierNumber4; +// Error: number ~> string var givesANumber2 = require(\"ES6_Named2\").givesANumber2; var ak1: number = givesANumber2(); var ak2: string = givesANumber2(); +// Error: number ~> string var NumberGenerator2 = require(\"ES6_Named2\").NumberGenerator2; var al1: number = new NumberGenerator2().givesANumber(); var al2: string = new NumberGenerator2().givesANumber(); +// Error: number ~> string var varDeclNumber3 = require(\"ES6_Named2\").varDeclNumber3; var varDeclNumber4 = require(\"ES6_Named2\").varDeclNumber4; var am1: number = varDeclNumber3; var am2: number = varDeclNumber4; var am3: string = varDeclNumber3; +// Error: number ~> string var am4: string = varDeclNumber4; +// Error: number ~> string var numberValue6 = require(\"ES6_ExportFrom_Intermediary2\").numberValue1; var ap1: number = numberValue6; var ap2: string = numberValue6; +// Error: number ~> string var numberValue2_renamed2 = require( \"ES6_ExportFrom_Intermediary2\" ).numberValue2_renamed2; var aq1: number = numberValue2_renamed2; var aq2: string = numberValue2_renamed2; +// Error: number ~> string var numberValue7 = require(\"ES6_ExportAllFrom_Intermediary2\").numberValue2; var ar1: number = numberValue7; var ar2: string = numberValue7; +// Error: number ~> string +//////////////////////////////////////////////////////// +// == ES6 Default+Named -> ES6 import Default+Named== // +//////////////////////////////////////////////////////// import defaultNum, {str as namedStr} from \"./ES6_DefaultAndNamed\"; + var as1: number = defaultNum; var as2: string = defaultNum; +// Error: number ~> string var as3: string = namedStr; var as4: number = namedStr; +// Error: string ~> number +//////////////////////////////////////// +// == Side-effect only ES6 imports == // +//////////////////////////////////////// import \"./SideEffects\"; + +////////////////////////////////////////////// +// == Suggest export name on likely typo == // +////////////////////////////////////////////// import specifierNumber1 from \"ES6_Named1\"; +// Error: Did you mean \`import {specifierNumber1} from ...\`? import {specifierNumber} from \"ES6_Named1\"; +// Error: Did you mean \`specifierNumber1\`? +/////////////////////////////////////////////////// +// == Multi \`export *\` should combine exports == // +/////////////////////////////////////////////////// import {numberValue1 as numberValue8, numberValue2 as numberValue9} from \"./ES6_ExportAllFromMulti\"; + var at1: number = numberValue8; var at2: string = numberValue8; +// Error: number ~> string var at3: number = numberValue9; -var at4: string = numberValue9; -" +var at4: string = numberValue9; // Error: number ~> string" `; diff --git a/tests/declare_fun/__snapshots__/jsfmt.spec.js.snap b/tests/declare_fun/__snapshots__/jsfmt.spec.js.snap index b43e39d7..a9b0d153 100644 --- a/tests/declare_fun/__snapshots__/jsfmt.spec.js.snap +++ b/tests/declare_fun/__snapshots__/jsfmt.spec.js.snap @@ -7,14 +7,13 @@ declare function foo(x: X): X; (foo(\"hello\"): number); // OK (foo(false): void); // error, boolean ~/~ undefined ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// OK -// OK -// error, boolean ~/~ undefined declare function foo(x: number): string; declare function foo(x: string): number; declare function foo(x: X): X; + (foo(0): string); +// OK (foo(\"hello\"): number); -(foo(false): void); -" +// OK +(foo(false): void); // error, boolean ~/~ undefined" `; diff --git a/tests/declare_module_exports/__snapshots__/jsfmt.spec.js.snap b/tests/declare_module_exports/__snapshots__/jsfmt.spec.js.snap index 1bcc4dda..63317532 100644 --- a/tests/declare_module_exports/__snapshots__/jsfmt.spec.js.snap +++ b/tests/declare_module_exports/__snapshots__/jsfmt.spec.js.snap @@ -26,27 +26,27 @@ import declare_m_e_with_declare_var_e from \"declare_m_e_with_declare_var_e\"; (declare_m_e_with_declare_var_e: string); // Error: number ~> string ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + +import declare_module_exports from \"declare_module_exports\"; +(declare_module_exports: number); +(declare_module_exports: string); // Error: number ~> string // Error: Has no named export \"str\"! +import {str} from \"declare_m_e_with_other_value_declares\"; + +import type {str2} from \"declare_m_e_with_other_type_declares\"; +(\"asdf\": str2); +(42: str2); // Error: number ~> string /** * \`declare var exports\` is deprecated, so we have a grace period where both * syntaxes will work. */ -// Error: number ~> string -// Error: number ~> string -import declare_module_exports from \"declare_module_exports\"; -(declare_module_exports: number); -(declare_module_exports: string); -import {str} from \"declare_m_e_with_other_value_declares\"; -import type {str2} from \"declare_m_e_with_other_type_declares\"; -(\"asdf\": str2); -(42: str2); import DEPRECATED__declare_var_exports from \"DEPRECATED__declare_var_exports\"; (DEPRECATED__declare_var_exports: number); (DEPRECATED__declare_var_exports: string); +// Error: number ~> string import declare_m_e_with_declare_var_e from \"declare_m_e_with_declare_var_e\"; (declare_m_e_with_declare_var_e: number); -(declare_m_e_with_declare_var_e: string); -" +(declare_m_e_with_declare_var_e: string); // Error: number ~> string" `; diff --git a/tests/declare_module_exports/flow-typed/__snapshots__/jsfmt.spec.js.snap b/tests/declare_module_exports/flow-typed/__snapshots__/jsfmt.spec.js.snap index 2ef52a3f..238f11c8 100644 --- a/tests/declare_module_exports/flow-typed/__snapshots__/jsfmt.spec.js.snap +++ b/tests/declare_module_exports/flow-typed/__snapshots__/jsfmt.spec.js.snap @@ -30,13 +30,6 @@ declare module \"declare_m_e_with_declare_var_e\" { declare var exports: string; } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -/** - * \`declare var exports\` is deprecated, so we have a grace period where both - * syntaxes will work. - */ -/** - * Ensure that, if both are present, \`declare module.exports\` wins - */ declare module \"declare_module_exports\" { declare module.exports: number; } @@ -48,12 +41,18 @@ declare module \"declare_m_e_with_other_type_declares\" { declare module.exports: number; declare type str2 = string; } +/** + * \`declare var exports\` is deprecated, so we have a grace period where both + * syntaxes will work. + */ declare module \"DEPRECATED__declare_var_exports\" { declare var exports: number; + /** + * Ensure that, if both are present, \`declare module.exports\` wins + */ } declare module \"declare_m_e_with_declare_var_e\" { declare module.exports: number; declare var exports: string; -} -" +}" `; diff --git a/tests/declare_type/__snapshots__/jsfmt.spec.js.snap b/tests/declare_type/__snapshots__/jsfmt.spec.js.snap index 509d3fd0..fc2b8b1f 100644 --- a/tests/declare_type/__snapshots__/jsfmt.spec.js.snap +++ b/tests/declare_type/__snapshots__/jsfmt.spec.js.snap @@ -33,30 +33,31 @@ blah(0, 0); /** * @flow */ + //////////////////////////////////////////////////////////// // == Import Declared Type Alias From Declared Module == // ////////////////////////////////////////////////////////// -// Error: string to int -// works -// works -////////////////////////////////////////////////////////// -// == Declared Module with exports prop (issue 880) == // -//////////////////////////////////////////////////////// -// error : {toz : number} ~> string -// error : number ~> A -// error : string ~> number import type {baz} from \"ModuleAliasFoo\"; import {foo} from \"ModuleAliasFoo\"; var k1: baz = 42; var k2: baz = \"shab\"; +// Error: string to int var k3: toz = foo(k1); +// works import type {toz} from \"ModuleAliasFoo\"; var k4: toz = foo(k1); +// works +////////////////////////////////////////////////////////// +// == Declared Module with exports prop (issue 880) == // +//////////////////////////////////////////////////////// import blah from \"foo\"; import type {Foo, Bar, Id} from \"foo\"; + blah(0, 0); + ({ toz: 3 }: Foo); +// error : {toz : number} ~> string (3: Bar); -(\"lol\": Id); -" +// error : number ~> A +(\"lol\": Id); // error : string ~> number" `; diff --git a/tests/declare_type/lib/__snapshots__/jsfmt.spec.js.snap b/tests/declare_type/lib/__snapshots__/jsfmt.spec.js.snap index 17504770..c68a0624 100644 --- a/tests/declare_type/lib/__snapshots__/jsfmt.spec.js.snap +++ b/tests/declare_type/lib/__snapshots__/jsfmt.spec.js.snap @@ -12,12 +12,12 @@ declare module ModuleAliasFoo { /** * @flow */ + declare module ModuleAliasFoo { declare type baz = number; declare type toz = string; declare function foo(bar: baz): toz; -} -" +}" `; exports[`test declare_type_exports.js 1`] = ` @@ -40,13 +40,16 @@ declare module \'foo\' { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + declare module \"foo\" { declare class A { toz: number } + declare var n: string; + declare type Foo = typeof n; declare type Bar = A; declare type Id = T; + declare var exports: { (a: number, b: number): number }; -} -" +}" `; diff --git a/tests/def_site_variance/__snapshots__/jsfmt.spec.js.snap b/tests/def_site_variance/__snapshots__/jsfmt.spec.js.snap index e2983148..af1bff4f 100644 --- a/tests/def_site_variance/__snapshots__/jsfmt.spec.js.snap +++ b/tests/def_site_variance/__snapshots__/jsfmt.spec.js.snap @@ -31,20 +31,6 @@ class PropVariance<+Out,-In> { con_dict2: {-[k:string]: In}; // ok } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// error on both targs (A ~/~> B) -// OK for both targs (B ~> A) -// error -// error -// error -// ok -// ok -// error -// error -// error -// ok -// error -// error -// ok class Variance<+Out, -In> { foo(x: Out): Out { return x; @@ -53,25 +39,39 @@ class Variance<+Out, -In> { return y; } } + class A {} class B extends A {} + function subtyping(v1: Variance, v2: Variance) { (v1: Variance); - (v2: Variance); + // error on both targs (A ~/~> B) + (v2: Variance); // OK for both targs (B ~> A) } + class PropVariance<+Out, -In> { inv1: Out; + // error inv2: In; + // error -co1: Out; + // error -co2: In; + // ok +con1: Out; + // ok +con2: In; + // error inv_dict1: { [k: string]: Out }; + // error inv_dict2: { [k: string]: In }; + // error co_dict1: { +[k: string]: Out }; + // ok co_dict2: { +[k: string]: In }; + // error con_dict1: { -[k: string]: Out }; - con_dict2: { -[k: string]: In }; -} -" + // error + con_dict2: { -[k: string]: In }; // ok +}" `; diff --git a/tests/demo/1/__snapshots__/jsfmt.spec.js.snap b/tests/demo/1/__snapshots__/jsfmt.spec.js.snap index eaf0b237..82c66b13 100644 --- a/tests/demo/1/__snapshots__/jsfmt.spec.js.snap +++ b/tests/demo/1/__snapshots__/jsfmt.spec.js.snap @@ -9,11 +9,12 @@ var x = null; f(x); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* demo */ -//... + function f(x) { return 42 / x; } + var x = null; -f(x); -" +//... +f(x);" `; diff --git a/tests/demo/2/__snapshots__/jsfmt.spec.js.snap b/tests/demo/2/__snapshots__/jsfmt.spec.js.snap index d62a8fbb..86b4da7f 100644 --- a/tests/demo/2/__snapshots__/jsfmt.spec.js.snap +++ b/tests/demo/2/__snapshots__/jsfmt.spec.js.snap @@ -20,26 +20,31 @@ a.onLoad(callback); module.exports = A; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @providesModule Demo */ -// instance field declaration + class A { x: number; + // instance field declaration constructor(x) { this.x = x; } + getX() { return this.x; } + onLoad(callback) { return callback(this.getX()); } } + function callback(x: string) { return x.length; } + var a = new A(42); a.onLoad(callback); -module.exports = A; -" + +module.exports = A;" `; exports[`test B.js 1`] = ` @@ -48,6 +53,6 @@ exports[`test B.js 1`] = ` var z = new A(\"42\").getX(); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ var A = require(\"Demo\"); -var z = new A(\"42\").getX(); -" + +var z = new A(\"42\").getX();" `; diff --git a/tests/deps/__snapshots__/jsfmt.spec.js.snap b/tests/deps/__snapshots__/jsfmt.spec.js.snap index 70f5644e..250e838c 100644 --- a/tests/deps/__snapshots__/jsfmt.spec.js.snap +++ b/tests/deps/__snapshots__/jsfmt.spec.js.snap @@ -1,15 +1,13 @@ exports[`test A.js 1`] = ` "require(\'./C\'); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -require(\"./C\"); -" +require(\"./C\");" `; exports[`test B.js 1`] = ` "require(\'./C\'); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -require(\"./C\"); -" +require(\"./C\");" `; exports[`test C.js 1`] = ` @@ -21,50 +19,41 @@ require(\'./G\'); require(\"./D\"); require(\"./E\"); require(\"./F\"); -require(\"./G\"); -" +require(\"./G\");" `; exports[`test D.js 1`] = ` "require(\'./I\'); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -require(\"./I\"); -" +require(\"./I\");" `; exports[`test E.js 1`] = ` "require(\'./I\'); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -require(\"./I\"); -" +require(\"./I\");" `; exports[`test F.js 1`] = ` "// empty ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// empty - " `; exports[`test G.js 1`] = ` "require(\'./H\'); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -require(\"./H\"); -" +require(\"./H\");" `; exports[`test H.js 1`] = ` "// empty ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// empty - " `; exports[`test I.js 1`] = ` "require(\'./A\'); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -require(\"./A\"); -" +require(\"./A\");" `; diff --git a/tests/destructuring/__snapshots__/jsfmt.spec.js.snap b/tests/destructuring/__snapshots__/jsfmt.spec.js.snap index 8d854f33..90fef426 100644 --- a/tests/destructuring/__snapshots__/jsfmt.spec.js.snap +++ b/tests/destructuring/__snapshots__/jsfmt.spec.js.snap @@ -12,23 +12,22 @@ let d = zs[1]; // run off the end let [...e] = 0; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// retain tuple info -// run off the end -// error: number ~> void -// error: string ~> void -// error: boolean ~> void -// error: number|string|boolean ~> void let xs = [ 0, \"\", true ]; let [ a, ...ys ] = xs; let [ b, ...zs ] = ys; let c = zs[0]; +// retain tuple info let d = zs[1]; +// run off the end (a: void); +// error: number ~> void (b: void); +// error: string ~> void (c: void); +// error: boolean ~> void (d: void); -let [ ...e ] = 0; -" +// error: number|string|boolean ~> void +let [ ...e ] = 0;" `; exports[`test computed.js 1`] = ` @@ -42,17 +41,15 @@ var { [key]: val2 } = { key: \"val\" }; var { [\"key\"]: val3, ...spread } = { key: \"val\" }; (spread.key: void); // error (gasp!) in general we don\'t know if a computed prop should be excluded from spread ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// error: string ~> void -// ok (gasp!) by existing StrT -> ElemT rule -// error (gasp!) in general we don\'t know if a computed prop should be excluded from spread var { [\"key\"]: val1 } = { key: \"val\" }; (val1: void); +// error: string ~> void var key: string = \"key\"; var { [key]: val2 } = { key: \"val\" }; (val2: void); +// ok (gasp!) by existing StrT -> ElemT rule var { [\"key\"]: val3, ...spread } = { key: \"val\" }; -(spread.key: void); -" +(spread.key: void); // error (gasp!) in general we don\'t know if a computed prop should be excluded from spread" `; exports[`test defaults.js 1`] = ` @@ -140,90 +137,104 @@ function obj_prop_union2({p}:{p:number}|{p:string}={p:true}) {} function default_expr_scope({a, b = a}) {} ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// errors: -// * number ~> void, from default on _.p.q -// * boolean ~> void, from default on _.p -// * string ~> void, from default on _ -// * null ~> void, from call below -// ok -// ok -// ok -// ok, provides add\'l lower bound -// errors: -// * number ~> void, from default on o.p.q -// * boolean ~> void, from default on o.p -// * string ~> void, from default on o -// * null ~> void, from call below -// ok -// ok -// ok -// ok, provides add\'l lower bound -// errors: -// * number ~> void, from default on _.p -// * string ~> void, from default on _ -// * null ~> void, from call below -// ok -// ok -// ok -// error: boolean ~> string -// error: number ~> string -// error: string ~> void -// error: boolean ~> string -// error: number ~> string -// error: string ~> void -// error: property \`x\` cannot be accessed on null -// error: expected object instead of number -// error: element 0 cannot be accessed on null -// error: expected array instead of null -// Default values in destructuring unwrap optional types -// ok -// ok -// union-like upper bounds preserved through destructuring -// TODO: union-of-objects upper bounds preserved through destructuring + function obj_prop_fun({ p: { q = 0 } = { q: true } } = { p: { q: \"\" } }) { + // errors: + // * number ~> void, from default on _.p.q + // * boolean ~> void, from default on _.p + // * string ~> void, from default on _ + // * null ~> void, from call below (q: void); } obj_prop_fun(); +// ok obj_prop_fun({}); +// ok obj_prop_fun({ p: {} }); +// ok obj_prop_fun({ p: { q: null } }); +// ok, provides add\'l lower bound function obj_prop_var(o = { p: { q: \"\" } }) { var { p: { q = 0 } = { q: true } } = o; + // errors: + // * number ~> void, from default on o.p.q + // * boolean ~> void, from default on o.p + // * string ~> void, from default on o + // * null ~> void, from call below (q: void); } obj_prop_var(); +// ok obj_prop_var({}); +// ok obj_prop_var({ p: {} }); +// ok obj_prop_var({ p: { q: null } }); +// ok, provides add\'l lower bound function obj_rest( { p: { q, ...o } = { q: 0, r: 0 } } = { p: { q: 0, r: \"\" } } ) { + // errors: + // * number ~> void, from default on _.p + // * string ~> void, from default on _ + // * null ~> void, from call below (o.r: void); } obj_rest(); +// ok obj_rest({}); +// ok obj_rest({ p: {} }); +// ok obj_rest({ p: { q: 0, r: null } }); -function obj_prop_annot({ p = true }: { p: string } = { p: 0 }) { - (p: void); + +function obj_prop_annot( + { + // error: boolean ~> string + p = true + }: { p: string } = { + // error: number ~> string + p: 0 + } +) { + (p: void); // error: string ~> void } -var { p = true }: { p: string } = { p: 0 }; + +var { + // error: boolean ~> string + p = true +}: { p: string } = { + // error: number ~> string + p: 0 +}; (p: void); +// error: string ~> void function obj_prop_err({ x: { y } } = null) {} +// error: property \`x\` cannot be accessed on null function obj_rest_err({ ...o } = 0) {} +// error: expected object instead of number function arr_elem_err([ x ] = null) {} +// error: element 0 cannot be accessed on null function arr_rest_err([ ...a ] = null) {} +// error: expected array instead of null function gen(x: T, { p = x }: { p: T }): T { return p; } + +// Default values in destructuring unwrap optional types obj_prop_fun(({}: { p?: { q?: null } })); +// ok obj_prop_var(({}: { p?: { q?: null } })); +// ok +// union-like upper bounds preserved through destructuring function obj_prop_opt({ p }: { p?: string } = { p: 0 }) {} function obj_prop_maybe({ p }: { p: ?string } = { p: 0 }) {} function obj_prop_union({ p }: { p: number | string } = { p: true }) {} + +// TODO: union-of-objects upper bounds preserved through destructuring function obj_prop_union2({ p }: { p: number } | { p: string } = { p: true }) {} -function default_expr_scope({ a, b = a }) {} -" + +function default_expr_scope({ a, b = a }) {}" `; exports[`test destructuring.js 1`] = ` @@ -299,70 +310,81 @@ var cp1_err: string = childprop1; // Error: number ~> string var cp2: number = others.childprop1; var cp2_err: string = others.childprop2; // Error: number ~> string ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// error on foo -// error on baz -// error, baz doesn\'t exist -// no error, rest is unsealed -// Error: number ~> string -// Error: number ~> string -// Error: number ~> string -// Error: number ~> string declare var a: string; declare var b: string; declare var c: string; [ { a1: a, b }, c ] = [ { a1: 0, b: 1 }, 2 ]; + var { m } = { m: 0 }; ({ m } = { m: m }); + var obj; ({ n: obj.x } = { n: 3 }); [ obj.x ] = [ \"foo\" ]; + function foo({ p, z: [ r ] }) { a = p; b = z; c = r; } foo({ p: 0, z: [ 1, 2 ] }); + [ a, , b, ...c ] = [ 0, 1, true, 3 ]; + function bar({ x, ...z }) { var o: { x: string, y: number } = z; } bar({ x: \"\", y: 0 }); + var spread = { y: \"\" }; var extend: { x: number, y: string, z: boolean } = { x: 0, ...spread }; + function qux(_: { a: number }) {} qux({ a: \"\" }); function corge({ b }: { b: string }) {} corge({ b: 0 }); + var { n }: { n: number } = { n: \"\" }; + function test() { var { foo } = { bar: 123 }; - var { bar, baz } = { bar: 123 }; + // error on foo + var { bar, baz } = { bar: 123 }; // error on baz } + function test() { var x = { foo: \"abc\", bar: 123 }; var { foo, ...rest } = x; (x.baz: string); - (rest.baz: string); + // error, baz doesn\'t exist + (rest.baz: string); // no error, rest is unsealed } + module.exports = corge; + class Base { baseprop1: number; baseprop2: number; } + class Child extends Base { childprop1: number; childprop2: number; } + var { baseprop1, childprop1, ...others } = new Child(); + var bp1: number = baseprop1; var bp1_err: string = baseprop1; +// Error: number ~> string var bp2: number = others.baseprop2; var bp2_err: string = others.baseprop2; +// Error: number ~> string var cp1: number = childprop1; var cp1_err: string = childprop1; +// Error: number ~> string var cp2: number = others.childprop1; -var cp2_err: string = others.childprop2; -" +var cp2_err: string = others.childprop2; // Error: number ~> string" `; exports[`test destructuring_param.js 1`] = ` @@ -379,27 +401,24 @@ exports[`test destructuring_param.js 1`] = ` // return a + b + c + d; // } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +function f(a, { b }) { + return a + b; +} // TODO: These throw errors when parsing. // function g(a, { a }) { // return a; // } // function h({ a, { b } }, { c }, { { d } }) { // return a + b + c + d; -// } -function f(a, { b }) { - return a + b; -} -" +// }" `; exports[`test eager.js 1`] = ` "var x; ({x} = null); // error, property \`x\` can not be accessed on \`null\` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// error, property \`x\` can not be accessed on \`null\` var x; -({ x } = null); -" +({ x } = null); // error, property \`x\` can not be accessed on \`null\`" `; exports[`test poly.js 1`] = ` @@ -437,44 +456,45 @@ function arr_rest_pattern([ _, ...a ] : ArrRest) { // a: [X] } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// prop: X -// prop: X -// elem: X -// elem: X -// proj: X -// proj: X -// nonsense -// r: X[] -// o: { x: X } -// o: { x: X } -// a: [X] -// a: [X] + function obj_pattern({ prop }: { prop: X }) {} +// prop: X type Prop = { prop: X }; function obj_pattern2({ prop }: Prop) {} +// prop: X function arr_pattern([ elem ]: X[]) {} +// elem: X type Elem = X[]; function arr_pattern2([ elem ]: Elem) {} +// elem: X function tup_pattern([ proj ]: [X]) {} +// proj: X type Proj = [X]; function tup_pattern2([ proj ]: Proj) {} +// proj: X function rest_antipattern(...t: T) {} +// nonsense function rest_pattern(...r: X[]) {} +// r: X[] function obj_rest_pattern({ _, ...o }: { _: any, x: X }) { + // o: { x: X } o.x; } type ObjRest = { _: any, x: X }; function obj_rest_pattern({ _, ...o }: ObjRest) { + // o: { x: X } o.x; } + function arr_rest_pattern([ _, ...a ]: [any, X]) { + // a: [X] a[0]; } type ArrRest = [any, X]; function arr_rest_pattern([ _, ...a ]: ArrRest) { + // a: [X] a[0]; -} -" +}" `; exports[`test rec.js 1`] = ` @@ -500,20 +520,24 @@ declare var o; var { x: o } = o; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + // Make sure that destructuring doesn\'t cause infinite loops when combined with // funny doses of repositioning -// Also make sure that the following doesn\'t loop + let foo = (i: number) => [ i ]; + const bar = (i: number) => { [ i ] = foo(i); return [ i ]; }; + foo = (i: number) => { return bar(i); }; + +// Also make sure that the following doesn\'t loop declare var o; -var { x: o } = o; -" +var { x: o } = o;" `; exports[`test string_lit.js 1`] = ` @@ -523,13 +547,11 @@ exports[`test string_lit.js 1`] = ` var { \"with-dash\": with_dash } = { \"with-dash\": \"motivating example\" }; (with_dash: \"motivating example\"); // ok ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// error: string ~> void -// ok var { \"key\": val } = { key: \"val\" }; (val: void); +// error: string ~> void var { \"with-dash\": with_dash } = { \"with-dash\": \"motivating example\" }; -(with_dash: \"motivating example\"); -" +(with_dash: \"motivating example\"); // ok" `; exports[`test unannotated.js 1`] = ` @@ -544,9 +566,10 @@ function bar() { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + var { x } = { x: { foo: \"foo\" } }; + function bar() { x.bar; -} -" +}" `; diff --git a/tests/dictionary/__snapshots__/jsfmt.spec.js.snap b/tests/dictionary/__snapshots__/jsfmt.spec.js.snap index 41fa7c36..97766912 100644 --- a/tests/dictionary/__snapshots__/jsfmt.spec.js.snap +++ b/tests/dictionary/__snapshots__/jsfmt.spec.js.snap @@ -6,11 +6,10 @@ const k: any = \'foo\' const val: string = dict[k] // error: number incompatible with string ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// error: number incompatible with string + const dict: { [key: string]: number } = {}; const k: any = \"foo\"; -const val: string = dict[k]; -" +const val: string = dict[k]; // error: number incompatible with string" `; exports[`test compatible.js 1`] = ` @@ -31,21 +30,22 @@ function foo2( } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// this adds a fooBar property to the param type, which should NOT cause -// an error in the return type because it is a dictionary. -// x\'s prototype has a toString method + function foo0( x: Array<{ [key: string]: mixed }> ): Array<{ [key: string]: mixed }> { + // this adds a fooBar property to the param type, which should NOT cause + // an error in the return type because it is a dictionary. x[0].fooBar = \"foobar\"; return x; } + function foo2( x: { [key: string]: number } ): { [key: string]: number, +toString: () => string } { + // x\'s prototype has a toString method return x; -} -" +}" `; exports[`test dictionary.js 1`] = ` @@ -385,288 +385,310 @@ function subtype_optional_c_to_dict( * * @flow */ + // Some logic is variance-sensitive. +class A {} +class B extends A {} +class C extends B {} + // Just a couple of short type names. Compare to string/number. +class X {} +class Y {} + // Any property can be set on a dict with string keys. +function set_prop_to_string_key(o: { [k: string]: any }) { + o.prop = \"ok\"; +} + // **UNSOUND** // This is allowed by design. We don\'t track get/set and we don\'t wrap the // return type in a maybe. -// ok -// ok +function unsound_dict_has_every_key(o: { [k: string]: X }) { + (o.p: X); + // ok + (o[\"p\"]: X); // ok +} + // As with any object type, we can assign subtypes to properties. -// error, A ~> B -// ok -// ok +function set_prop_covariant(o: { [k: string]: B }) { + o.p = new A(); + // error, A ~> B + o.p = new B(); + // ok + o.p = new C(); // ok +} + // This isn\'t specific behavior to dictionaries, but for completeness... -// ok -// ok -// error, C ~> B +function get_prop_contravariant(o: { [k: string]: B }) { + (o.p: A); + // ok + (o.p: B); + // ok + (o.p: C); // error, C ~> B +} + // Dot-notation can not be used to add properties to dictionaries with // non-string keys, because keys are strings. -// error: string ~> number +function add_prop_to_nonstring_key_dot(o: { [k: number]: any }) { + o.prop = \"err\"; // error: string ~> number +} + // Bracket notation can be used to add properties to dictionaries with // non-string keys, even though all keys are strings. This is a convenient // affordance. +function add_prop_to_nonstring_key_bracket(o: { [k: number]: any }) { + o[0] = \"ok\"; +} + // Objects can be part dict, part not by mixing an indexer with declared props. -// ok -// ok -// ok -// ok +function mix_with_declared_props(o: { [k: number]: X, p: Y }, x: X, y: Y) { + (o[0]: X); + // ok + (o.p: Y); + // ok + o[0] = x; + // ok + o.p = y; // ok +} + // Indeed, dict types are still Objects and have Object.prototype stuff -// error: string ~> boolean -// ok +function object_prototype( + o: { [k: string]: number } +): { [k: string]: number, +toString: () => string } { + (o.toString(): boolean); + // error: string ~> boolean + return o; // ok +} + // **UNSOUND** // Because we support non-string props w/ bracket notation, it\'s possible to // write into a declared prop unsoundly. -// a[\"0\"] no longer X -// error -// in[0].p no longer B -// ok -// error -// not true -// error -// x[0].p no longer B -// ok -// error -// not true -// ok, A == A -// ok, B <: A -// ok, C <: A -// error, A not <: B -// ok, B == B -// ok, C <: A -// error, A not <: C -// error, A not <: C -// ok, C == C +function unsound_string_conversion_alias_declared_prop( + o: { [k: number]: any, \"0\": X } +) { + o[0] = \"not-x\"; // a[\"0\"] no longer X +} + +function unification_dict_values_invariant(x: Array<{ [k: string]: B }>) { + let a: Array<{ [k: string]: A }> = x; + // error + a[0].p = new A(); + // in[0].p no longer B + let b: Array<{ [k: string]: B }> = x; + // ok + let c: Array<{ [k: string]: C }> = x; + // error + (x[0].p: C); // not true +} + +function subtype_dict_values_invariant(x: { [k: string]: B }) { + let a: { [k: string]: A } = x; + // error + a.p = new A(); + // x[0].p no longer B + let b: { [k: string]: B } = x; + // ok + let c: { [k: string]: C } = x; + // error + (x.p: C); // not true +} + +function subtype_dict_values_fresh_exception() { + let a: { [k: string]: A } = { + a: new A(), + // ok, A == A + b: new B(), + // ok, B <: A + // ok, C <: A + c: new C() + }; + + let b: { [k: string]: B } = { + a: new A(), + // error, A not <: B + b: new B(), + // ok, B == B + // ok, C <: A + c: new C() + }; + + let c: { [k: string]: C } = { + a: new A(), + // error, A not <: C + b: new B(), + // error, A not <: C + // ok, C == C + c: new C() + }; +} + // Actually, unsound_string_conversion_alias_declared_prop behavior makes an // argument that we shouldn\'t really care about this, since we ignore the fact // that coercing values to string keys can cause unintended aliasing in general. // Barring some compelling use case for that in this context, though, we choose // to be strict. -// error -// ok -// error -// error -// ok -// error -// error: A ~> B -// x[0].p no longer B -// ok -// error -// not true -// error -// xa[0].p no longer B -// ok -// error -// not true -// error: A ~> B -// x.p no longer B -// ok -// error -// not true -// error -// xa.p no longer B -// ok -// error -// not true -// error: if allowed, could write {p:X,q:Y} into \`x\` -// error: if allowed, could write {p:X,q:Y} into returned array -// error -// x.p no longer B -// ok -// error -// not true -// error -// x.p no longer B -// error -// not true -// Only props in l which are not in u must match indexer, but must do so -// exactly. -// error (as above), but exclusive of x -// ok, -// error (as above), but exclusive of x -// error -// ok -// error -// error -// ok -// error -// error -// ok -// error -// error: A ~> B -// ok -// error: C ~> B -class A {} -class B extends A {} -class C extends B {} -class X {} -class Y {} -function set_prop_to_string_key(o: { [k: string]: any }) { - o.prop = \"ok\"; -} -function unsound_dict_has_every_key(o: { [k: string]: X }) { - (o.p: X); - (o[\"p\"]: X); -} -function set_prop_covariant(o: { [k: string]: B }) { - o.p = new A(); - o.p = new B(); - o.p = new C(); -} -function get_prop_contravariant(o: { [k: string]: B }) { - (o.p: A); - (o.p: B); - (o.p: C); -} -function add_prop_to_nonstring_key_dot(o: { [k: number]: any }) { - o.prop = \"err\"; -} -function add_prop_to_nonstring_key_bracket(o: { [k: number]: any }) { - o[0] = \"ok\"; -} -function mix_with_declared_props(o: { [k: number]: X, p: Y }, x: X, y: Y) { - (o[0]: X); - (o.p: Y); - o[0] = x; - o.p = y; -} -function object_prototype( - o: { [k: string]: number } -): { [k: string]: number, +toString: () => string } { - (o.toString(): boolean); - return o; -} -function unsound_string_conversion_alias_declared_prop( - o: { [k: number]: any, \"0\": X } -) { - o[0] = \"not-x\"; -} -function unification_dict_values_invariant(x: Array<{ [k: string]: B }>) { - let a: Array<{ [k: string]: A }> = x; - a[0].p = new A(); - let b: Array<{ [k: string]: B }> = x; - let c: Array<{ [k: string]: C }> = x; - (x[0].p: C); -} -function subtype_dict_values_invariant(x: { [k: string]: B }) { - let a: { [k: string]: A } = x; - a.p = new A(); - let b: { [k: string]: B } = x; - let c: { [k: string]: C } = x; - (x.p: C); -} -function subtype_dict_values_fresh_exception() { - let a: { [k: string]: A } = { a: new A(), b: new B(), c: new C() }; - let b: { [k: string]: B } = { a: new A(), b: new B(), c: new C() }; - let c: { [k: string]: C } = { a: new A(), b: new B(), c: new C() }; -} function unification_dict_keys_invariant(x: Array<{ [k: B]: any }>) { let a: Array<{ [k: A]: any }> = x; + // error let b: Array<{ [k: B]: any }> = x; - let c: Array<{ [k: C]: any }> = x; + // ok + let c: Array<{ [k: C]: any }> = x; // error } + function subtype_dict_keys_invariant(x: { [k: B]: any }) { let a: { [k: A]: any } = x; + // error let b: { [k: B]: any } = x; - let c: { [k: C]: any } = x; + // ok + let c: { [k: C]: any } = x; // error } + function unification_mix_with_declared_props_invariant_l( x: Array<{ [k: string]: B }> ) { let a: Array<{ [k: string]: B, p: A }> = x; + // error: A ~> B a[0].p = new A(); + // x[0].p no longer B let b: Array<{ [k: string]: B, p: B }> = x; + // ok let c: Array<{ [k: string]: B, p: C }> = x; - (x[0].p: C); + // error + (x[0].p: C); // not true } + function unification_mix_with_declared_props_invariant_r( xa: Array<{ [k: string]: A, p: B }>, xb: Array<{ [k: string]: B, p: B }>, xc: Array<{ [k: string]: C, p: B }> ) { let a: Array<{ [k: string]: A }> = xa; + // error a[0].p = new A(); + // xa[0].p no longer B let b: Array<{ [k: string]: B }> = xb; + // ok let c: Array<{ [k: string]: C }> = xc; - (xc[0].p: C); + // error + (xc[0].p: C); // not true } + function subtype_mix_with_declared_props_invariant_l(x: { [k: string]: B }) { let a: { [k: string]: B, p: A } = x; + // error: A ~> B a.p = new A(); + // x.p no longer B let b: { [k: string]: B, p: B } = x; + // ok let c: { [k: string]: B, p: C } = x; - (x.p: C); + // error + (x.p: C); // not true } + function subtype_mix_with_declared_props_invariant_r( xa: { [k: string]: A, p: B }, xb: { [k: string]: B, p: B }, xc: { [k: string]: C, p: B } ) { let a: { [k: string]: A } = xa; + // error a.p = new A(); + // xa.p no longer B let b: { [k: string]: B } = xb; + // ok let c: { [k: string]: C } = xc; - (xc.p: C); + // error + (xc.p: C); // not true } + function unification_dict_to_obj( x: Array<{ [k: string]: X }> ): Array<{ p: X }> { - return x; + return x; // error: if allowed, could write {p:X,q:Y} into \`x\` } + function unification_obj_to_dict( x: Array<{ p: X }> ): Array<{ [k: string]: X }> { - return x; + return x; // error: if allowed, could write {p:X,q:Y} into returned array } + function subtype_dict_to_obj(x: { [k: string]: B }) { let a: { p: A } = x; + // error a.p = new A(); + // x.p no longer B let b: { p: B } = x; + // ok let c: { p: C } = x; - (x.p: C); + // error + (x.p: C); // not true } + function subtype_obj_to_dict(x: { p: B }) { let a: { [k: string]: A } = x; + // error a.p = new A(); + // x.p no longer B let b: { [k: string]: B } = x; + let c: { [k: string]: C } = x; - (x.p: C); + // error + (x.p: C); // not true } + +// Only props in l which are not in u must match indexer, but must do so +// exactly. function subtype_obj_to_mixed(x: { p: B, x: X }) { let a: { [k: string]: A, x: X } = x; + // error (as above), but exclusive of x let b: { [k: string]: B, x: X } = x; - let c: { [k: string]: C, x: X } = x; + // ok, + let c: { [k: string]: C, x: X } = x; // error (as above), but exclusive of x } + function unification_dict_to_mixed(x: Array<{ [k: string]: B }>) { let a: Array<{ [k: string]: B, p: A }> = x; + // error let b: Array<{ [k: string]: B, p: B }> = x; - let c: Array<{ [k: string]: B, p: C }> = x; + // ok + let c: Array<{ [k: string]: B, p: C }> = x; // error } + function subtype_dict_to_mixed(x: { [k: string]: B }) { let a: { [k: string]: B, p: A } = x; + // error let b: { [k: string]: B, p: B } = x; - let c: { [k: string]: B, p: C } = x; + // ok + let c: { [k: string]: B, p: C } = x; // error } + function subtype_dict_to_optional_a(x: { [k: string]: B }) { - let a: { p?: A } = x; + let a: { p?: A } = x; // error } + function subtype_dict_to_optional_b(x: { [k: string]: B }) { - let b: { p?: B } = x; + let b: { p?: B } = x; // ok } + function subtype_dict_to_optional_c(x: { [k: string]: B }) { - let c: { p?: C } = x; + let c: { p?: C } = x; // error } + function subtype_optional_a_to_dict(x: { p?: A }): { [k: string]: B } { + // error: A ~> B return x; } + function subtype_optional_b_to_dict(x: { p?: B }): { [k: string]: B } { + // ok return x; } + function subtype_optional_c_to_dict(x: { p?: C }): { [k: string]: B } { + // error: C ~> B return x; -} -" +}" `; exports[`test incompatible.js 1`] = ` @@ -729,63 +751,70 @@ function foo8(x: {[key: string]: number}) { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// 2 errors, number !~> string & vice versa -// 2 errors, string !~> number & vice versa -// 2 errors (null & undefined) -// 2 errors, since c[\'x\'] = null updates b -// 2 errors (number !~> string, string !~> number) -// error, fooBar:string !~> number (x\'s dictionary) -// OK, since number ~> mixed (x elem\'s dictionary) -// error: mixed ~> string -// OK, since we assume dictionaries have every key -// error: foo can\'t exist in x -// error, some prop in x could be incompatible (covariance) -// error, some prop in return could be incompatible -// error + var x: { [key: string]: string } = {}; var y: { [key: string]: number } = x; +// 2 errors, number !~> string & vice versa var z: { [key: number]: string } = x; +// 2 errors, string !~> number & vice versa var a: { [key: string]: ?string } = {}; var b: { [key: string]: string } = a; +// 2 errors (null & undefined) var c: { [key: string]: ?string } = b; +// 2 errors, since c[\'x\'] = null updates b +// 2 errors (number !~> string, string !~> number) function foo0( x: Array<{ [key: string]: number }> ): Array<{ [key: string]: string }> { return x; } + +// error, fooBar:string !~> number (x\'s dictionary) function foo1( x: Array<{ [key: string]: number }> ): Array<{ [key: string]: number, fooBar: string }> { return x; } + function foo2( x: Array<{ [key: string]: mixed }> ): Array<{ [key: string]: mixed, fooBar: string }> { x[0].fooBar = 123; - return x; + // OK, since number ~> mixed (x elem\'s dictionary) + return x; // error: mixed ~> string } + +// OK, since we assume dictionaries have every key function foo3(x: { [key: string]: number }): { foo: number } { return x; } + +// error: foo can\'t exist in x function foo4( x: { [key: string]: number } ): { [key: string]: number, foo: string } { return x; } + +// error, some prop in x could be incompatible (covariance) function foo5(x: Array<{ [key: string]: number }>): Array<{ foo: number }> { return x; } + +// error, some prop in return could be incompatible function foo6(x: Array<{ foo: number }>): Array<{ [key: string]: number }> { return x; } + function foo7(x: { [key: string]: number, bar: string }) { (x.bar: string); } + function foo8(x: { [key: string]: number }) { (x.foo: string); + // error (x.foo: number); -} -" +}" `; exports[`test issue-1745.js 1`] = ` @@ -816,29 +845,30 @@ class B { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// no error -// no error -// no error -// no error + class A { x: { [k: string]: number }; + m1() { - this.x = { bar: 0 }; + this.x = { bar: 0 }; // no error } + m2() { - this.x.foo = 0; + this.x.foo = 0; // no error } } + class B { x: { [k: string]: number }; + m2() { - this.x.foo = 0; + this.x.foo = 0; // no error } + m1() { - this.x = { bar: 0 }; + this.x = { bar: 0 }; // no error } -} -" +}" `; exports[`test test.js 1`] = ` @@ -853,16 +883,16 @@ var o: { foo: QueryFunction } = { module.exports = o; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// error, number ~/~ string type Params = { [name: string]: string, count: number }; type QueryFunction = (params: Params) => string; + var o: { foo: QueryFunction } = { foo(params) { - return params.count; + return params.count; // error, number ~/~ string } }; -module.exports = o; -" + +module.exports = o;" `; exports[`test test_client.js 1`] = ` @@ -872,10 +902,9 @@ o.foo = function (params) { return params.count; // error, number ~/~ string } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// error, number ~/~ string var o = require(\"./test\"); + o.foo = function(params) { - return params.count; -}; -" + return params.count; // error, number ~/~ string +};" `; diff --git a/tests/disjoint-union-perf/__snapshots__/jsfmt.spec.js.snap b/tests/disjoint-union-perf/__snapshots__/jsfmt.spec.js.snap index 44313304..8b7d63fe 100644 --- a/tests/disjoint-union-perf/__snapshots__/jsfmt.spec.js.snap +++ b/tests/disjoint-union-perf/__snapshots__/jsfmt.spec.js.snap @@ -83,6 +83,7 @@ export type TypedNode = /** * @flow */ + export type InferredType = \"unknown\" | \"gender\" | \"enum\" | @@ -90,12 +91,14 @@ export type InferredType = \"unknown\" | \"number\" | \"string\" | \"error\"; + export type Pos = { firstLine: number, firstColumn: number, lastLine: number, lastColumn: number }; + export type TypedBinaryOpNode = { exprNodeType: \"binary_op\", binaryOp: \"plus\" | \"multiply\" | \"divide\" | \"minus\", @@ -105,6 +108,7 @@ export type TypedBinaryOpNode = { exprType: InferredType, typed: true }; + export type TypedUnaryMinusNode = { exprNodeType: \"unary_minus\", op: TypedNode, @@ -112,6 +116,7 @@ export type TypedUnaryMinusNode = { exprType: InferredType, typed: true }; + export type TypedNumberNode = { exprNodeType: \"number\", value: number, @@ -119,6 +124,7 @@ export type TypedNumberNode = { exprType: \"number\", typed: true }; + export type TypedStringLiteralNode = { exprNodeType: \"string_literal\", value: string, @@ -126,6 +132,7 @@ export type TypedStringLiteralNode = { exprType: \"string\", typed: true }; + export type TypedVariableNode = { exprNodeType: \"variable\", name: string, @@ -133,6 +140,7 @@ export type TypedVariableNode = { exprType: InferredType, typed: true }; + export type TypedFunctionInvocationNode = { exprNodeType: \"function_invocation\", name: string, @@ -141,13 +149,13 @@ export type TypedFunctionInvocationNode = { exprType: \"error\" | \"string\", typed: true }; + export type TypedNode = TypedBinaryOpNode | TypedUnaryMinusNode | TypedNumberNode | TypedStringLiteralNode | TypedVariableNode | - TypedFunctionInvocationNode; -" + TypedFunctionInvocationNode;" `; exports[`test emit.js 1`] = ` @@ -220,10 +228,12 @@ export function emitExpression(node: TypedNode) : t.Expression { /** * @flow */ -// FALLTHROUGH import * as t from \"./jsAst\"; + const b = t.builders; + import type {TypedNode} from \"./ast\"; + function getBinaryOp( op: \"plus\" | \"minus\" | \"divide\" | \"multiply\" ): \"+\" | \"-\" | \"*\" | \"/\" { @@ -240,9 +250,11 @@ function getBinaryOp( throw new Error(\"Invalid binary operator: \" + op); } } + export function emitExpression(node: TypedNode): t.Expression { switch (node.exprNodeType) { case \"string_literal\": + // FALLTHROUGH case \"number\": return b.literal(node.value); case \"variable\": @@ -254,6 +266,7 @@ export function emitExpression(node: TypedNode): t.Expression { case \"binary_op\": { const lhs = emitExpression(node.lhs); const rhs = emitExpression(node.rhs); + const op = getBinaryOp(node.binaryOp); return b.binaryExpression(op, lhs, rhs); } @@ -267,14 +280,15 @@ export function emitExpression(node: TypedNode): t.Expression { b.identifier(node.name), false ); + const args = node.parameters.map(n => emitExpression(n)); + return b.callExpression(callee, args); } default: throw new Error(\"Unknown expression type: \" + node.type); } -} -" +}" `; exports[`test jsAst.js 1`] = ` @@ -918,21 +932,21 @@ export const builders : { /** * @flow */ -/* TODO Missing from the Parser API.*/ -// ast-types exports all expressions as patterns. -// That seems not like it was intended. export type Comment = { loc: ?SourceLocation, value: string, leading: boolean, trailing: boolean }; + export type SourceLocation = { start: SourcePosition, end: SourcePosition, source: ?string }; + export type SourcePosition = { line: number, column: number }; + export type File = { source: ?string, start: SourcePosition, @@ -941,6 +955,7 @@ export type File = { type: \"File\", program: Program }; + export type Program = { source: ?string, start: SourcePosition, @@ -949,6 +964,7 @@ export type Program = { type: \"Program\", body: Statement[] }; + export type BinaryOperator = \"==\" | \"!=\" | \"===\" | @@ -965,12 +981,13 @@ export type BinaryOperator = \"==\" | \"*\" | \"/\" | \"%\" | - \"&\" | + \"&\" /* TODO Missing from the Parser API.*/ | \"|\" | \"^\" | \"in\" | \"instanceof\" | \"..\"; + export type UnaryOperator = \"-\" | \"+\" | \"!\" | @@ -978,6 +995,7 @@ export type UnaryOperator = \"-\" | \"typeof\" | \"void\" | \"delete\"; + export type AssignmentOperator = \"=\" | \"+=\" | \"-=\" | @@ -990,8 +1008,11 @@ export type AssignmentOperator = \"=\" | \"|=\" | \"^=\" | \"&=\"; + export type UpdateOperator = \"++\" | \"--\"; + export type LogicalOperator = \"&&\" | \"||\"; + export type Node = EmptyStatement | BlockStatement | ExpressionStatement | @@ -1024,6 +1045,7 @@ export type Node = EmptyStatement | VariableDeclaration | FunctionDeclaration | VariableDeclarator; + export type Statement = BlockStatement | EmptyStatement | ExpressionStatement | @@ -1037,6 +1059,7 @@ export type Statement = BlockStatement | ForInStatement | TryStatement | Declaration; + export type EmptyStatement = { source: ?string, start: SourcePosition, @@ -1044,6 +1067,7 @@ export type EmptyStatement = { comments: ?Array, type: \"EmptyStatement\" }; + export type BlockStatement = { source: ?string, start: SourcePosition, @@ -1052,6 +1076,7 @@ export type BlockStatement = { type: \"BlockStatement\", body: Statement[] }; + export type ExpressionStatement = { source: ?string, start: SourcePosition, @@ -1060,6 +1085,7 @@ export type ExpressionStatement = { type: \"ExpressionStatement\", expression: Expression }; + export type IfStatement = { source: ?string, start: SourcePosition, @@ -1070,6 +1096,7 @@ export type IfStatement = { consequent: Statement, alternate: ?Statement }; + export type BreakStatement = { source: ?string, start: SourcePosition, @@ -1078,6 +1105,7 @@ export type BreakStatement = { type: \"BreakStatement\", label: ?Identifier }; + export type ContinueStatement = { source: ?string, start: SourcePosition, @@ -1086,6 +1114,7 @@ export type ContinueStatement = { type: \"ContinueStatement\", label: ?Identifier }; + export type ReturnStatement = { source: ?string, start: SourcePosition, @@ -1094,6 +1123,7 @@ export type ReturnStatement = { type: \"ReturnStatement\", argument: ?Expression }; + export type ThrowStatement = { source: ?string, start: SourcePosition, @@ -1102,6 +1132,7 @@ export type ThrowStatement = { type: \"ThrowStatement\", argument: ?Expression }; + export type WhileStatement = { source: ?string, start: SourcePosition, @@ -1111,6 +1142,7 @@ export type WhileStatement = { test: Expression, body: Statement }; + export type ForStatement = { source: ?string, start: SourcePosition, @@ -1122,6 +1154,7 @@ export type ForStatement = { update: ?Expression, body: Statement }; + export type ForInStatement = { source: ?string, start: SourcePosition, @@ -1132,6 +1165,7 @@ export type ForInStatement = { right: Expression, body: Statement }; + export type TryStatement = { source: ?string, start: SourcePosition, @@ -1143,6 +1177,7 @@ export type TryStatement = { handlers: CatchClause[], finalizer: ?BlockStatement }; + export type CatchClause = { source: ?string, start: SourcePosition, @@ -1153,6 +1188,7 @@ export type CatchClause = { guard: ?Expression, body: BlockStatement }; + export type Expression = Identifier | ThisExpression | Literal | @@ -1168,6 +1204,7 @@ export type Expression = Identifier | MemberExpression | ArrayExpression | ObjectExpreession; + export type Identifier = { source: ?string, start: SourcePosition, @@ -1176,6 +1213,7 @@ export type Identifier = { type: \"Identifier\", name: string }; + export type Literal = { source: ?string, start: SourcePosition, @@ -1185,6 +1223,7 @@ export type Literal = { value: ?(string | boolean | number | RegExp), regex: ?{ pattern: string, flags: string } }; + export type ThisExpression = { source: ?string, start: SourcePosition, @@ -1192,6 +1231,7 @@ export type ThisExpression = { comments: ?Array, type: \"ThisExpression\" }; + export type ArrayExpression = { source: ?string, start: SourcePosition, @@ -1200,6 +1240,7 @@ export type ArrayExpression = { type: \"ArrayExpression\", elements: Expression[] }; + export type ObjectExpreession = { source: ?string, start: SourcePosition, @@ -1208,6 +1249,7 @@ export type ObjectExpreession = { type: \"ObjectExpression\", properties: Property[] }; + export type Property = { source: ?string, start: SourcePosition, @@ -1218,6 +1260,7 @@ export type Property = { key: Literal | Identifier, value: Expression }; + export type FunctionExpression = { source: ?string, start: SourcePosition, @@ -1228,6 +1271,7 @@ export type FunctionExpression = { params: Pattern[], body: BlockStatement }; + export type BinaryExpression = { source: ?string, start: SourcePosition, @@ -1238,6 +1282,7 @@ export type BinaryExpression = { left: Expression, right: Expression }; + export type UnaryExpression = { source: ?string, start: SourcePosition, @@ -1248,6 +1293,7 @@ export type UnaryExpression = { argument: Expression, prefix: boolean }; + export type AssignmentExpression = { source: ?string, start: SourcePosition, @@ -1258,6 +1304,7 @@ export type AssignmentExpression = { left: Pattern, right: Expression }; + export type UpdateExpression = { source: ?string, start: SourcePosition, @@ -1268,6 +1315,7 @@ export type UpdateExpression = { argument: Expression, prefix: boolean }; + export type LogicalExpression = { source: ?string, start: SourcePosition, @@ -1278,6 +1326,7 @@ export type LogicalExpression = { left: Expression, right: Expression }; + export type ConditionalExpression = { source: ?string, start: SourcePosition, @@ -1288,6 +1337,7 @@ export type ConditionalExpression = { consequent: Expression, alternate: Expression }; + export type NewExpression = { source: ?string, start: SourcePosition, @@ -1297,6 +1347,7 @@ export type NewExpression = { callee: Expression, arguments: Expression[] }; + export type CallExpression = { source: ?string, start: SourcePosition, @@ -1306,6 +1357,7 @@ export type CallExpression = { callee: Expression, arguments: Expression[] }; + export type MemberExpression = { source: ?string, start: SourcePosition, @@ -1316,8 +1368,12 @@ export type MemberExpression = { property: Identifier | Expression, computed: boolean }; +// ast-types exports all expressions as patterns. +// That seems not like it was intended. export type Pattern = Identifier; + export type Declaration = VariableDeclaration | FunctionDeclaration; + export type VariableDeclaration = { source: ?string, start: SourcePosition, @@ -1327,6 +1383,7 @@ export type VariableDeclaration = { kind: \"var\" | \"let\" | \"const\", declarations: VariableDeclarator[] }; + export type FunctionDeclaration = { source: ?string, start: SourcePosition, @@ -1337,6 +1394,7 @@ export type FunctionDeclaration = { body: BlockStatement, params: Pattern[] }; + export type VariableDeclarator = { source: ?string, start: SourcePosition, @@ -1346,7 +1404,9 @@ export type VariableDeclarator = { id: Pattern, init: ?Expression }; + const a: any = null; + export const builders: { emptyStatement(): EmptyStatement, blockStatement(body: Statement[]): BlockStatement, @@ -1448,6 +1508,5 @@ export const builders: { params: Pattern[] ): FunctionDeclaration, variableDeclarator(id: Pattern, init?: Expression): VariableDeclarator -} = a; -" +} = a;" `; diff --git a/tests/docblock_flow/__snapshots__/jsfmt.spec.js.snap b/tests/docblock_flow/__snapshots__/jsfmt.spec.js.snap index 205f3c27..b2afd74a 100644 --- a/tests/docblock_flow/__snapshots__/jsfmt.spec.js.snap +++ b/tests/docblock_flow/__snapshots__/jsfmt.spec.js.snap @@ -6,9 +6,8 @@ exports[`test license_with_flow.js 1`] = ` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* Copyright example */ /* @flow */ -// error -(\"\": void); -" + +(\"\": void); // error" `; exports[`test max_header_tokens.js 1`] = ` @@ -21,15 +20,6 @@ exports[`test max_header_tokens.js 1`] = ` * @flow */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -/* @flow */ -/* second token */ -/* third token */ -/** - * After max_header_tokens (in .flowconfig), we no longer care: - * - * @flow - */ - " `; @@ -37,9 +27,6 @@ exports[`test multiple_flows_1.js 1`] = ` "/* @flow */ /* @flow */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -/* @flow */ -/* @flow */ - " `; @@ -49,11 +36,6 @@ exports[`test multiple_flows_2.js 1`] = ` * @noflow */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -/** - * @flow - * @noflow - */ - " `; @@ -64,12 +46,6 @@ exports[`test multiple_providesModule_1.js 1`] = ` * @flow */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -/** - * @providesModule Foo - * @providesModule Bar - * @flow - */ - " `; @@ -82,14 +58,6 @@ exports[`test multiple_providesModule_2.js 1`] = ` * @providesModule Bar */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -/** - * @providesModule Foo - * @flow - */ -/** - * @providesModule Bar - */ - " `; @@ -99,11 +67,9 @@ exports[`test use_strict_with_flow.js 1`] = ` (\"\": void); // error ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -/* @flow */ -// error \"use strict\"; -(\"\": void); -" +/* @flow */ +(\"\": void); // error" `; exports[`test with_flow.js 1`] = ` @@ -112,9 +78,8 @@ exports[`test with_flow.js 1`] = ` (\"\": void); // error ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// error -(\"\": void); -" + +(\"\": void); // error" `; exports[`test without_flow.js 1`] = ` @@ -123,7 +88,6 @@ exports[`test without_flow.js 1`] = ` (\"\": void); // no error ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* some other comment */ -// no error -(\"\": void); -" + +(\"\": void); // no error" `; diff --git a/tests/dom/__snapshots__/jsfmt.spec.js.snap b/tests/dom/__snapshots__/jsfmt.spec.js.snap index 8a6c0d46..1da6f769 100644 --- a/tests/dom/__snapshots__/jsfmt.spec.js.snap +++ b/tests/dom/__snapshots__/jsfmt.spec.js.snap @@ -14,18 +14,17 @@ let tests = [ ]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// fillRect -// moveTo -// error: should be numbers + let tests = [ + // fillRect function(ctx: CanvasRenderingContext2D) { ctx.fillRect(0, 0, 200, 100); }, + // moveTo function(ctx: CanvasRenderingContext2D) { - ctx.moveTo(\"0\", \"1\"); + ctx.moveTo(\"0\", \"1\"); // error: should be numbers } -]; -" +];" `; exports[`test CustomEvent.js 1`] = ` @@ -40,14 +39,14 @@ let tests = [ ]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// CustomEvent + let tests = [ + // CustomEvent function(document: Document) { const event = document.createEvent(\"CustomEvent\"); event.initCustomEvent(\"butts\", true, false, { nice: 42 }); } -]; -" +];" `; exports[`test Document.js 1`] = ` @@ -64,16 +63,16 @@ let tests = [ ]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// createElement + let tests = [ + // createElement function(document: Document) { (document.createElement(\"canvas\"): HTMLCanvasElement); (document.createElement(\"link\"): HTMLLinkElement); (document.createElement(\"option\"): HTMLOptionElement); (document.createElement(\"select\"): HTMLSelectElement); } -]; -" +];" `; exports[`test Element.js 1`] = ` @@ -97,9 +96,9 @@ let tests = [ ]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// scrollIntoView -// fails + let tests = [ + // scrollIntoView function(element: Element) { element.scrollIntoView(); element.scrollIntoView(false); @@ -107,12 +106,13 @@ let tests = [ element.scrollIntoView({ behavior: \"smooth\", block: \"end\" }); element.scrollIntoView({ block: \"end\" }); element.scrollIntoView({ behavior: \"smooth\" }); + + // fails element.scrollIntoView({ behavior: \"invalid\" }); element.scrollIntoView({ block: \"invalid\" }); element.scrollIntoView(1); } -]; -" +];" `; exports[`test HTMLCanvasElement.js 1`] = ` @@ -126,13 +126,13 @@ let tests = [ ]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// getContext + let tests = [ + // getContext function(el: HTMLCanvasElement) { (el.getContext(\"2d\"): ?CanvasRenderingContext2D); } -]; -" +];" `; exports[`test HTMLElement.js 1`] = ` @@ -156,9 +156,9 @@ let tests = [ ]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// scrollIntoView -// fails + let tests = [ + // scrollIntoView function(element: HTMLElement) { element.scrollIntoView(); element.scrollIntoView(false); @@ -166,12 +166,13 @@ let tests = [ element.scrollIntoView({ behavior: \"smooth\", block: \"end\" }); element.scrollIntoView({ block: \"end\" }); element.scrollIntoView({ behavior: \"smooth\" }); + + // fails element.scrollIntoView({ behavior: \"invalid\" }); element.scrollIntoView({ block: \"invalid\" }); element.scrollIntoView(1); } -]; -" +];" `; exports[`test HTMLInputElement.js 1`] = ` @@ -189,19 +190,18 @@ let tests = [ ]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// setRangeText -// end is required -// invalid value + let tests = [ + // setRangeText function(el: HTMLInputElement) { el.setRangeText(\"foo\"); el.setRangeText(\"foo\", 123); + // end is required el.setRangeText(\"foo\", 123, 234); el.setRangeText(\"foo\", 123, 234, \"select\"); - el.setRangeText(\"foo\", 123, 234, \"bogus\"); + el.setRangeText(\"foo\", 123, 234, \"bogus\"); // invalid value } -]; -" +];" `; exports[`test URL.js 1`] = ` @@ -227,41 +227,40 @@ const q: string = c.search; // correct const r: string = c.username; // correct ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// correct -// correct -// correct -// correct -// not correct -// correct -// correct -// correct -// correct -// correct -// correct -// correct -// correct -// correct -// correct -// correct -// correct + const a = new URL(\"http://flowtype.org/\"); +// correct const b = new URL(\"/docs\", a); +// correct const c = new URL(\"/docs\", \"http://flowtype.org/\"); +// correct const d: URLSearchParams = c.searchParams; +// correct const e: string = c.path; +// not correct const f: string = c.pathname; +// correct const g: string = c.hash; +// correct const h: string = c.host; +// correct const i: string = c.hostname; +// correct const j: string = c.href; +// correct const l: string = c.origin; +// correct const m: string = c.password; +// correct const n: string = c.pathname; +// correct const o: string = c.port; +// correct const p: string = c.protocol; +// correct const q: string = c.search; -const r: string = c.username; -" +// correct +const r: string = c.username; // correct" `; exports[`test eventtarget.js 1`] = ` @@ -292,31 +291,30 @@ let tests = [ ]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// attachEvent -// invalid, may be undefined -// valid -// detachEvent -// invalid, may be undefined -// valid + let listener: EventListener = function(event: Event): void {}; + let tests = [ + // attachEvent function() { let target = new EventTarget(); (target.attachEvent(\"foo\", listener): void); - (target.attachEvent && target.attachEvent(\"foo\", listener): void); + // invalid, may be undefined + (target.attachEvent && target.attachEvent(\"foo\", listener): void); // valid }, + // detachEvent function() { let target = new EventTarget(); (target.detachEvent(\"foo\", listener): void); - (target.detachEvent && target.detachEvent(\"foo\", listener): void); + // invalid, may be undefined + (target.detachEvent && target.detachEvent(\"foo\", listener): void); // valid }, function() { window.onmessage = (event: MessageEvent) => { (event.target: window); }; } -]; -" +];" `; exports[`test path2d.js 1`] = ` @@ -333,19 +331,18 @@ let tests = [ ]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// arcTo -// valid -// valid -// invalid + let tests = [ + // arcTo function() { let path = new Path2D(); (path.arcTo(0, 0, 0, 0, 10): void); + // valid (path.arcTo(0, 0, 0, 0, 10, 20, 5): void); - (path.arcTo(0, 0, 0, 0, 10, \"20\", 5): void); + // valid + (path.arcTo(0, 0, 0, 0, 10, \"20\", 5): void); // invalid } -]; -" +];" `; exports[`test registerElement.js 1`] = ` @@ -409,12 +406,9 @@ let tests = [ ]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// should work with Object.create() -// or with Object.assign() -// should complain about invalid callback parameters -// Error: This might be null -// Error: This might be null + let tests = [ + // should work with Object.create() function() { document.registerElement(\"custom-element\", { prototype: Object.create(HTMLElement.prototype, { @@ -432,6 +426,7 @@ let tests = [ }) }); }, + // or with Object.assign() function() { document.registerElement(\"custom-element\", { prototype: Object.assign(Object.create(HTMLElement.prototype), { @@ -447,20 +442,22 @@ let tests = [ }) }); }, + // should complain about invalid callback parameters function() { document.registerElement(\"custom-element\", { prototype: { attributeChangedCallback( localName: string, oldVal: string, + // Error: This might be null newVal: string, + // Error: This might be null namespace: string ) {} } }); } -]; -" +];" `; exports[`test traversal.js 1`] = ` @@ -661,24 +658,9 @@ let tests = [ ]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// basic functionality -// rootNode must be a Node -// valid -// invalid -// invalid -// Type Parameters -// NodeFilterInterface -// valid -// invalid -// valid -// invalid -// invalid -// valid -// invalid -// valid -// invalid -// invalid + let tests = [ + // basic functionality function() { const i: NodeIterator<*, *> = document.createNodeIterator(document.body); const filter: NodeFilter = i.filter; @@ -693,14 +675,17 @@ let tests = [ typeof NodeFilter.FILTER_REJECT | typeof NodeFilter.FILTER_SKIP = filter.acceptNode(document.body); }, + // rootNode must be a Node function() { document.createNodeIterator(document.body); - document.createNodeIterator({}); + // valid + document.createNodeIterator({}); // invalid }, function() { document.createTreeWalker(document.body); - document.createTreeWalker({}); + document.createTreeWalker({}); // invalid }, + // Type Parameters function() { const _root = document.body; const i = document.createNodeIterator(_root, NodeFilter.SHOW_ELEMENT); @@ -854,20 +839,25 @@ let tests = [ const previousNode: Node | null = w.previousNode(); const nextNode: Node | null = w.nextNode(); }, + // NodeFilterInterface function() { document.createNodeIterator( document.body, -1, node => NodeFilter.FILTER_ACCEPT ); + // valid document.createNodeIterator(document.body, -1, node => \"accept\"); + // invalid document.createNodeIterator(document.body, -1, { accept: node => NodeFilter.FILTER_ACCEPT }); + // valid document.createNodeIterator(document.body, -1, { accept: node => \"accept\" }); - document.createNodeIterator(document.body, -1, {}); + // invalid + document.createNodeIterator(document.body, -1, {}); // invalid }, function() { document.createTreeWalker( @@ -875,13 +865,16 @@ let tests = [ -1, node => NodeFilter.FILTER_ACCEPT ); + // valid document.createTreeWalker(document.body, -1, node => \"accept\"); + // invalid document.createTreeWalker(document.body, -1, { accept: node => NodeFilter.FILTER_ACCEPT }); + // valid document.createTreeWalker(document.body, -1, { accept: node => \"accept\" }); - document.createTreeWalker(document.body, -1, {}); + // invalid + document.createTreeWalker(document.body, -1, {}); // invalid } -]; -" +];" `; diff --git a/tests/dump-types/__snapshots__/jsfmt.spec.js.snap b/tests/dump-types/__snapshots__/jsfmt.spec.js.snap index 21ac10bf..1a91de17 100644 --- a/tests/dump-types/__snapshots__/jsfmt.spec.js.snap +++ b/tests/dump-types/__snapshots__/jsfmt.spec.js.snap @@ -9,8 +9,7 @@ module.exports = num; var num = 42; function bar() {} bar(); -module.exports = num; -" +module.exports = num;" `; exports[`test test.js 1`] = ` @@ -37,15 +36,18 @@ declare var obj: {a?: {b: ?{c: null | {d: number}}}}; const idxResult = idx(obj, obj => obj.a.b.c.d); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// test deduping of inferred types var num = require(\"./import\"); function foo(x) {} foo(0); var a: string = num; + function unannotated(x) { return x; } + +// test deduping of inferred types const nullToUndefined = val => val === null ? undefined : val; + function f0(x: ?Object) { return nullToUndefined(x); } @@ -58,8 +60,8 @@ function f2(x: ?string) { function f3(x: ?string) { return nullToUndefined(x); } + declare var idx: $Facebookism$Idx; declare var obj: { a?: { b: ?{ c: null | { d: number } } } }; -const idxResult = idx(obj, obj => obj.a.b.c.d); -" +const idxResult = idx(obj, obj => obj.a.b.c.d);" `; diff --git a/tests/duplicate_methods/__snapshots__/jsfmt.spec.js.snap b/tests/duplicate_methods/__snapshots__/jsfmt.spec.js.snap index 05b08534..66511d1d 100644 --- a/tests/duplicate_methods/__snapshots__/jsfmt.spec.js.snap +++ b/tests/duplicate_methods/__snapshots__/jsfmt.spec.js.snap @@ -39,26 +39,34 @@ class C1 { m() {} m() {} } + new C1().m(); + class C2 { get m() { return 42; } m() {} } + new C2().m(); + class C3 { set m(x) {} m() {} } + new C3().m(); + class C4 { get m() { return 42; } set m(x: number) {} } + new C4().m = new C4().m - 42; + class C5 { m() {} get m() { @@ -66,6 +74,6 @@ class C5 { } set m(x: number) {} } -new C5().m = new C5().m - 42; -" + +new C5().m = new C5().m - 42;" `; diff --git a/tests/encaps/__snapshots__/jsfmt.spec.js.snap b/tests/encaps/__snapshots__/jsfmt.spec.js.snap index 425186a3..459e71ef 100644 --- a/tests/encaps/__snapshots__/jsfmt.spec.js.snap +++ b/tests/encaps/__snapshots__/jsfmt.spec.js.snap @@ -16,22 +16,21 @@ function tag2(strings,...values) { var s3 = tag2 \`la la la\`; (s3.foo: number); // error: string ~> number ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// error: no prop x in A -// error: string ~> number -// ok: tagged templates can return whatever -// error: string ~> number class A {} var a = new A(); var s1 = \`l\${a.x}r\`; +// error: no prop x in A function tag(strings, ...values) { var x: number = strings[0]; + // error: string ~> number return x; } var s2 = tag\`l\${42}r\`; + function tag2(strings, ...values) { - return { foo: \"\" }; + return { foo: \"\" }; // ok: tagged templates can return whatever } + var s3 = tag2\`la la la\`; -(s3.foo: number); -" +(s3.foo: number); // error: string ~> number" `; diff --git a/tests/enumerror/__snapshots__/jsfmt.spec.js.snap b/tests/enumerror/__snapshots__/jsfmt.spec.js.snap index 5c22163c..45188918 100644 --- a/tests/enumerror/__snapshots__/jsfmt.spec.js.snap +++ b/tests/enumerror/__snapshots__/jsfmt.spec.js.snap @@ -27,26 +27,30 @@ function keys2union(s: Keys): Union { return s; } // ok function union2keys(s: Union): Keys { return s; } // ok ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /** @flow */ -// ok -// ok + function isActive( ad: { state: $Keys<{ PAUSED: string, ACTIVE: string, DELETED: string }> } ): boolean { return ad.state === \"ACTIVE\"; } + isActive({ state: \"PAUSE\" }); + var MyStates = { PAUSED: \"PAUSED\", ACTIVE: \"ACTIVE\", DELETED: \"DELETED\" }; function isActive2(ad: { state: $Keys }): boolean { return ad.state === MyStates.ACTIVE; } + isActive2({ state: \"PAUSE\" }); + type Keys = $Keys<{ x: any, y: any }>; type Union = \"x\" | \"y\"; + function keys2union(s: Keys): Union { return s; } +// ok function union2keys(s: Union): Keys { return s; -} -" +} // ok" `; diff --git a/tests/equals/__snapshots__/jsfmt.spec.js.snap b/tests/equals/__snapshots__/jsfmt.spec.js.snap index 8830a42a..60ba6df1 100644 --- a/tests/equals/__snapshots__/jsfmt.spec.js.snap +++ b/tests/equals/__snapshots__/jsfmt.spec.js.snap @@ -13,16 +13,16 @@ var x = (null : ?number); (1 == x); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// error -// error + 1 == 1; \"foo\" == \"bar\"; 1 == null; null == 1; 1 == \"\"; +// error \"\" == 1; +// error var x = (null: ?number); x == 1; -1 == x; -" +1 == x;" `; diff --git a/tests/error_messages/__snapshots__/jsfmt.spec.js.snap b/tests/error_messages/__snapshots__/jsfmt.spec.js.snap index 23fd81f9..ad7a4e10 100644 --- a/tests/error_messages/__snapshots__/jsfmt.spec.js.snap +++ b/tests/error_messages/__snapshots__/jsfmt.spec.js.snap @@ -1,6 +1,5 @@ exports[`test errors.js 1`] = ` "if (typeof define === \'function\' && define.amd) { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -if (typeof define === \"function\" && define.amd) {} -" +if (typeof define === \"function\" && define.amd) {}" `; diff --git a/tests/es6modules/__snapshots__/jsfmt.spec.js.snap b/tests/es6modules/__snapshots__/jsfmt.spec.js.snap index 1e9ebc18..1a1634e9 100644 --- a/tests/es6modules/__snapshots__/jsfmt.spec.js.snap +++ b/tests/es6modules/__snapshots__/jsfmt.spec.js.snap @@ -4,15 +4,13 @@ exports[`test B.js 1`] = ` exports.numberValue = 42; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -exports.numberValue = 42; -" + +exports.numberValue = 42;" `; exports[`test C.js 1`] = ` "/* @flow */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -/* @flow */ - " `; @@ -43,11 +41,14 @@ module.exports = Test; * @providesModule CommonJS_Clobbering_Class * @flow */ + class Base { static baseProp: number; } + class Test extends Base { static childProp: number; + static staticNumber1(): number { return 1; } @@ -57,6 +58,7 @@ class Test extends Base { static staticNumber3(): number { return 3; } + instNumber1(): number { return 1; } @@ -64,8 +66,8 @@ class Test extends Base { return 2; } } -module.exports = Test; -" + +module.exports = Test;" `; exports[`test CommonJS_Clobbering_Frozen.js 1`] = ` @@ -82,8 +84,8 @@ module.exports = Object.freeze({ * @providesModule CommonJS_Clobbering_Frozen * @flow */ -module.exports = Object.freeze({ numberValue1: 1 }); -" + +module.exports = Object.freeze({ numberValue1: 1 });" `; exports[`test CommonJS_Clobbering_Lit.js 1`] = ` @@ -104,14 +106,14 @@ module.exports = { * @providesModule CommonJS_Clobbering_Lit * @flow */ + module.exports = { numberValue1: 1, numberValue2: 2, numberValue3: 3, numberValue4: 4, numberValue5: 5 -}; -" +};" `; exports[`test CommonJS_Named.js 1`] = ` @@ -130,12 +132,12 @@ exports.numberValue5 = 5; * @providesModule CommonJS_Named * @flow */ + exports.numberValue1 = 1; exports.numberValue2 = 2; exports.numberValue3 = 3; exports.numberValue4 = 4; -exports.numberValue5 = 5; -" +exports.numberValue5 = 5;" `; exports[`test ES6_Default_AnonClass1.js 1`] = ` @@ -150,6 +152,7 @@ export default class { givesANum(): number { return 42; }}; * @providesModule ES6_Default_AnonClass1 * @flow */ + export default class { givesANum(): number { return 42; @@ -170,6 +173,7 @@ export default class { givesANum(): number { return 42; }}; * @providesModule ES6_Default_AnonClass2 * @flow */ + export default class { givesANum(): number { return 42; @@ -190,10 +194,10 @@ export default function():number { return 42; } * @providesModule ES6_Default_AnonFunction1 * @flow */ + export default function(): number { return 42; -} -" +}" `; exports[`test ES6_Default_AnonFunction2.js 1`] = ` @@ -208,10 +212,10 @@ export default function():number { return 42; } * @providesModule ES6_Default_AnonFunction2 * @flow */ + export default function(): number { return 42; -} -" +}" `; exports[`test ES6_Default_NamedClass1.js 1`] = ` @@ -231,16 +235,17 @@ new Foo(); * @providesModule ES6_Default_NamedClass1 * @flow */ -// Regression test for https://github.com/facebook/flow/issues/511 -// -// Default-exported class should also be available in local scope + export default class Foo { givesANum(): number { return 42; } } -new Foo(); -" + +// Regression test for https://github.com/facebook/flow/issues/511 +// +// Default-exported class should also be available in local scope +new Foo();" `; exports[`test ES6_Default_NamedClass2.js 1`] = ` @@ -255,6 +260,7 @@ export default class Foo { givesANum(): number { return 42; }}; * @providesModule ES6_Default_NamedClass2 * @flow */ + export default class Foo { givesANum(): number { return 42; @@ -275,10 +281,10 @@ export default function foo():number { return 42; } * @providesModule ES6_Default_NamedFunction1 * @flow */ + export default function foo(): number { return 42; -} -" +}" `; exports[`test ES6_Default_NamedFunction2.js 1`] = ` @@ -293,10 +299,10 @@ export default function foo():number { return 42; } * @providesModule ES6_Default_NamedFunction2 * @flow */ + export default function foo(): number { return 42; -} -" +}" `; exports[`test ES6_DefaultAndNamed.js 1`] = ` @@ -306,9 +312,9 @@ export default 42; export var str = \'asdf\'; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + export default 42 -export var str = \"asdf\"; -" +export var str = \"asdf\";" `; exports[`test ES6_ExportAllFrom_Intermediary1.js 1`] = ` @@ -323,8 +329,8 @@ export * from \"ES6_ExportAllFrom_Source1\"; * @providesModule ES6_ExportAllFrom_Intermediary1 * @flow */ -export * from \"ES6_ExportAllFrom_Source1\" -" + +export * from \"ES6_ExportAllFrom_Source1\"" `; exports[`test ES6_ExportAllFrom_Intermediary2.js 1`] = ` @@ -339,8 +345,8 @@ export * from \"ES6_ExportAllFrom_Source2\"; * @providesModule ES6_ExportAllFrom_Intermediary2 * @flow */ -export * from \"ES6_ExportAllFrom_Source2\" -" + +export * from \"ES6_ExportAllFrom_Source2\"" `; exports[`test ES6_ExportAllFrom_Source1.js 1`] = ` @@ -355,8 +361,8 @@ export var numberValue1 = 1; * @providesModule ES6_ExportAllFrom_Source1 * @flow */ -export var numberValue1 = 1; -" + +export var numberValue1 = 1;" `; exports[`test ES6_ExportAllFrom_Source2.js 1`] = ` @@ -371,8 +377,8 @@ export var numberValue2 = 1; * @providesModule ES6_ExportAllFrom_Source2 * @flow */ -export var numberValue2 = 1; -" + +export var numberValue2 = 1;" `; exports[`test ES6_ExportAllFromMulti.js 1`] = ` @@ -382,9 +388,9 @@ export * from \"./ES6_ExportAllFrom_Source1\"; export * from \"./ES6_ExportAllFrom_Source2\"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + export * from \"./ES6_ExportAllFrom_Source1\" -export * from \"./ES6_ExportAllFrom_Source2\" -" +export * from \"./ES6_ExportAllFrom_Source2\"" `; exports[`test ES6_ExportFrom_Intermediary1.js 1`] = ` @@ -402,8 +408,8 @@ export { * @providesModule ES6_ExportFrom_Intermediary1 * @flow */ -export {numberValue1, numberValue2 as numberValue2_renamed} from \"ES6_ExportFrom_Source1\" -" + +export {numberValue1, numberValue2 as numberValue2_renamed} from \"ES6_ExportFrom_Source1\"" `; exports[`test ES6_ExportFrom_Intermediary2.js 1`] = ` @@ -421,8 +427,8 @@ export { * @providesModule ES6_ExportFrom_Intermediary2 * @flow */ -export {numberValue1, numberValue2 as numberValue2_renamed2} from \"ES6_ExportFrom_Source2\" -" + +export {numberValue1, numberValue2 as numberValue2_renamed2} from \"ES6_ExportFrom_Source2\"" `; exports[`test ES6_ExportFrom_Source1.js 1`] = ` @@ -437,8 +443,8 @@ export var numberValue1 = 1, numberValue2 = 2; * @providesModule ES6_ExportFrom_Source1 * @flow */ -export var numberValue1 = 1, numberValue2 = 2; -" + +export var numberValue1 = 1, numberValue2 = 2;" `; exports[`test ES6_ExportFrom_Source2.js 1`] = ` @@ -453,8 +459,8 @@ export var numberValue1 = 1, numberValue2 = 2; * @providesModule ES6_ExportFrom_Source2 * @flow */ -export var numberValue1 = 1, numberValue2 = 2; -" + +export var numberValue1 = 1, numberValue2 = 2;" `; exports[`test ES6_Named1.js 1`] = ` @@ -485,27 +491,31 @@ export var [destructuredArrNumber] = [1] * @providesModule ES6_Named1 * @flow */ + var specifierNumber1 = 1; var specifierNumber2 = 2; var specifierNumber3 = 3; var groupedSpecifierNumber1 = 1; var groupedSpecifierNumber2 = 2; + export {specifierNumber1} export {specifierNumber2 as specifierNumber2Renamed} export {specifierNumber3} export {groupedSpecifierNumber1, groupedSpecifierNumber2} + export function givesANumber(): number { return 42; } + export class NumberGenerator { givesANumber(): number { return 42; } } + export var varDeclNumber1 = 1, varDeclNumber2 = 2; export var { destructuredObjNumber } = { destructuredObjNumber: 1 }; -export var [ destructuredArrNumber ] = [ 1 ]; -" +export var [ destructuredArrNumber ] = [ 1 ];" `; exports[`test ES6_Named2.js 1`] = ` @@ -534,25 +544,29 @@ export var [destructuredArrNumber2] = [1] * @providesModule ES6_Named2 * @flow */ + var specifierNumber4 = 1; var specifierNumber5 = 2; var groupedSpecifierNumber3 = 1; var groupedSpecifierNumber4 = 2; + export {specifierNumber4} export {specifierNumber5 as specifierNumber5Renamed} export {groupedSpecifierNumber3, groupedSpecifierNumber4} + export function givesANumber2(): number { return 42; } + export class NumberGenerator2 { givesANumber(): number { return 42; } } + export var varDeclNumber3 = 1, varDeclNumber4 = 2; export var { destructuredObjNumber2 } = { destructuredObjNumber2: 1 }; -export var [ destructuredArrNumber2 ] = [ 1 ]; -" +export var [ destructuredArrNumber2 ] = [ 1 ];" `; exports[`test ExportType.js 1`] = ` @@ -561,8 +575,8 @@ exports[`test ExportType.js 1`] = ` export type typeAlias = number; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -export type typeAlias = number; -" + +export type typeAlias = number;" `; exports[`test ProvidesModuleA.js 1`] = ` @@ -581,12 +595,12 @@ exports.stringValue = \"str\"; * @providesModule A * @flow */ + exports.numberValue1 = 42; exports.numberValue2 = 42; exports.numberValue3 = 42; exports.numberValue4 = 42; -exports.stringValue = \"str\"; -" +exports.stringValue = \"str\";" `; exports[`test ProvidesModuleCJSDefault.js 1`] = ` @@ -603,8 +617,8 @@ module.exports = { * @providesModule CJSDefault * @flow */ -module.exports = { numberValue: 42 }; -" + +module.exports = { numberValue: 42 };" `; exports[`test ProvidesModuleD.js 1`] = ` @@ -613,11 +627,6 @@ exports[`test ProvidesModuleD.js 1`] = ` * @flow */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -/** - * @providesModule D - * @flow - */ - " `; @@ -633,24 +642,12 @@ export default { }; */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -/** - * @providesModule ES6Default - * @flow - */ -/* -export default { - numberValue: 42, -}; -*/ - " `; exports[`test SideEffects.js 1`] = ` "/* @flow */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -/* @flow */ - " `; @@ -953,302 +950,305 @@ var at4: string = numberValue9; // Error: number ~> string import {typeAlias} from \"./ExportType\"; // Error: Cannot vanilla-import a type alias! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + // ===================== // // == Path Resolution == // // ===================== // + // @providesModule +import * as DefaultA from \"A\"; +var a1: number = DefaultA.numberValue1; +var a2: string = DefaultA.numberValue1; // Error: number ~> string // File path +import * as DefaultB from \"./B\"; +var b1: number = DefaultB.numberValue; +var b2: string = DefaultB.numberValue; // Error: number ~> string // C.js exists, but not as a providesModule +import DefaultC from \"C\"; // Error: No such module // @providesModule D exists, but not as a filename +import DefaultD from \"./D\"; // Error: No such module // ================================================ // // == CommonJS Clobbering Literal Exports -> ES6 == // // ================================================ // +import {doesntExist1} from \"CommonJS_Clobbering_Lit\"; // Error: Not an exported binding +import {numberValue1} from \"CommonJS_Clobbering_Lit\"; +var c1: number = numberValue1; +var c2: string = numberValue1; // Error: number ~> string +import {numberValue2 as numVal1} from \"CommonJS_Clobbering_Lit\"; +var d1: number = numVal1; +var d2: string = numVal1; // Error: number ~> string +import CJS_Clobb_Lit from \"CommonJS_Clobbering_Lit\"; +var e1: number = CJS_Clobb_Lit.numberValue3; +var e2: string = CJS_Clobb_Lit.numberValue3; // Error: number ~> string +CJS_Clobb_Lit.doesntExist; // Error: doesntExist isn\'t a property +import * as CJS_Clobb_Lit_NS from \"CommonJS_Clobbering_Lit\"; +var f1: number = CJS_Clobb_Lit_NS.numberValue4; +var f2: number = CJS_Clobb_Lit_NS.default.numberValue4; +CJS_Clobb_Lit_NS.default.default; // Error: No \'default\' property on the exported obj +var f3: string = CJS_Clobb_Lit_NS.numberValue4; // Error: number ~> string +var f4: string = CJS_Clobb_Lit_NS.default.numberValue5; // Error: number ~> string // ============================================== // // == CommonJS Clobbering Class Exports -> ES6 == // // ============================================== // +import {doesntExist2} from \"CommonJS_Clobbering_Class\"; // Error: Not an exported binding // The following import should error because class statics are not turned into // named exports for now. This avoids complexities with polymorphic static // members (where the polymophism is defined on the class itself rather than the // method). +import {staticNumber1, baseProp, childProp} from \"CommonJS_Clobbering_Class\"; // Error +import CJS_Clobb_Class from \"CommonJS_Clobbering_Class\"; +new CJS_Clobb_Class(); +new CJS_Clobb_Class().doesntExist; // Error: Class has no \`doesntExist\` property +var h1: number = CJS_Clobb_Class.staticNumber2(); +var h2: string = CJS_Clobb_Class.staticNumber2(); // Error: number ~> string +var h3: number = new CJS_Clobb_Class().instNumber1(); +var h4: string = new CJS_Clobb_Class().instNumber1(); // Error: number ~> string +import * as CJS_Clobb_Class_NS from \"CommonJS_Clobbering_Class\"; +new CJS_Clobb_Class_NS(); // Error: Namespace object isn\'t constructable +var i1: number = CJS_Clobb_Class_NS.staticNumber3(); // Error: Class statics not copied to Namespace object +var i2: number = new CJS_Clobb_Class_NS.default().instNumber2(); +var i3: string = new CJS_Clobb_Class_NS.default().instNumber2(); // Error: number ~> string // =================================== // // == CommonJS Named Exports -> ES6 == // // =================================== // +import {doesntExist3} from \"CommonJS_Named\"; // Error: Not an exported binding +import {numberValue2} from \"CommonJS_Named\"; +var j1: number = numberValue2; +var j2: string = numberValue2; // Error: number ~> string +import {numberValue3 as numVal3} from \"CommonJS_Named\"; +var k1: number = numVal3; +var k2: string = numVal3; // Error: number ~> string +import * as CJS_Named from \"CommonJS_Named\"; +var l1: number = CJS_Named.numberValue1; +var l2: string = CJS_Named.numberValue1; // Error: number ~> string +CJS_Named.doesntExist; // Error: doesntExist isn\'t a property +import * as CJS_Named_NS from \"CommonJS_Named\"; +var m1: number = CJS_Named_NS.numberValue4; +var m2: string = CJS_Named_NS.default.numberValue4; // Error: CommonJS_Named has no default export +var m3: string = CJS_Named_NS.numberValue4; // Error: number ~> string ////////////////////////////// // == ES6 Default -> ES6 == // ////////////////////////////// +import {doesntExist4} from \"ES6_Default_AnonFunction1\"; // Error: Not an exported binding +import ES6_Def_AnonFunc1 from \"ES6_Default_AnonFunction1\"; +var n1: number = ES6_Def_AnonFunc1(); +var n2: string = ES6_Def_AnonFunc1(); // Error: number ~> string +import ES6_Def_NamedFunc1 from \"ES6_Default_NamedFunction1\"; +var o1: number = ES6_Def_NamedFunc1(); +var o2: string = ES6_Def_NamedFunc1(); // Error: number ~> string +import ES6_Def_AnonClass1 from \"ES6_Default_AnonClass1\"; +var p1: number = new ES6_Def_AnonClass1().givesANum(); +var p2: string = new ES6_Def_AnonClass1().givesANum(); // Error: number ~> string +import ES6_Def_NamedClass1 from \"ES6_Default_NamedClass1\"; +var q1: number = new ES6_Def_NamedClass1().givesANum(); +var q2: string = new ES6_Def_NamedClass1().givesANum(); // Error: number ~> string //////////////////////////// // == ES6 Named -> ES6 == // //////////////////////////// -// Error: Not an exported binding -// Error: number ~> string -// Error: number ~> string -// Error: number ~> string -// Error: number ~> string -// Error: number ~> string -// Error: number ~> string -// Error: number ~> string -// Error: number ~> string -// Error: number ~> string -// Error: number ~> string -// Error: number ~> string -// Error: number ~> string -// Error: number ~> string -// Error: number ~> string -/////////////////////////////////// -// == ES6 Default -> CommonJS == // -/////////////////////////////////// -// Error: \'doesntExist\' isn\'t an export -// Error: number ~> string -// Error: number ~> string -// Error: number ~> string -// Error: number ~> string -///////////////////////////////// -// == ES6 Named -> CommonJS == // -///////////////////////////////// -// Error: number ~> string -// Error: number ~> string -// Error: number ~> string -// Error: number ~> string -// Error: number ~> string -// Error: number ~> string -// Error: number ~> string -// Error: number ~> string -// Error: number ~> string -// Error: number ~> string -// Error: number ~> string -// Error: number ~> string -// Error: number ~> string -//////////////////////////////////////////////////////// -// == ES6 Default+Named -> ES6 import Default+Named== // -//////////////////////////////////////////////////////// -// Error: number ~> string -// Error: string ~> number -//////////////////////////////////////// -// == Side-effect only ES6 imports == // -//////////////////////////////////////// -////////////////////////////////////////////// -// == Suggest export name on likely typo == // -////////////////////////////////////////////// -// Error: Did you mean \`import {specifierNumber1} from ...\`? -// Error: Did you mean \`specifierNumber1\`? -/////////////////////////////////////////////////// -// == Multi \`export *\` should combine exports == // -/////////////////////////////////////////////////// -// Error: number ~> string -// Error: number ~> string -///////////////////////////////////////////////////////////// -// == Vanilla \`import\` cannot import a type-only export == // -///////////////////////////////////////////////////////////// -// Error: Cannot vanilla-import a type alias! -import * as DefaultA from \"A\"; -var a1: number = DefaultA.numberValue1; -var a2: string = DefaultA.numberValue1; -import * as DefaultB from \"./B\"; -var b1: number = DefaultB.numberValue; -var b2: string = DefaultB.numberValue; -import DefaultC from \"C\"; -import DefaultD from \"./D\"; -import {doesntExist1} from \"CommonJS_Clobbering_Lit\"; -import {numberValue1} from \"CommonJS_Clobbering_Lit\"; -var c1: number = numberValue1; -var c2: string = numberValue1; -import {numberValue2 as numVal1} from \"CommonJS_Clobbering_Lit\"; -var d1: number = numVal1; -var d2: string = numVal1; -import CJS_Clobb_Lit from \"CommonJS_Clobbering_Lit\"; -var e1: number = CJS_Clobb_Lit.numberValue3; -var e2: string = CJS_Clobb_Lit.numberValue3; -CJS_Clobb_Lit.doesntExist; -import * as CJS_Clobb_Lit_NS from \"CommonJS_Clobbering_Lit\"; -var f1: number = CJS_Clobb_Lit_NS.numberValue4; -var f2: number = CJS_Clobb_Lit_NS.default.numberValue4; -CJS_Clobb_Lit_NS.default.default; -var f3: string = CJS_Clobb_Lit_NS.numberValue4; -var f4: string = CJS_Clobb_Lit_NS.default.numberValue5; -import {doesntExist2} from \"CommonJS_Clobbering_Class\"; -import {staticNumber1, baseProp, childProp} from \"CommonJS_Clobbering_Class\"; -import CJS_Clobb_Class from \"CommonJS_Clobbering_Class\"; -new CJS_Clobb_Class(); -new CJS_Clobb_Class().doesntExist; -var h1: number = CJS_Clobb_Class.staticNumber2(); -var h2: string = CJS_Clobb_Class.staticNumber2(); -var h3: number = new CJS_Clobb_Class().instNumber1(); -var h4: string = new CJS_Clobb_Class().instNumber1(); -import * as CJS_Clobb_Class_NS from \"CommonJS_Clobbering_Class\"; -new CJS_Clobb_Class_NS(); -var i1: number = CJS_Clobb_Class_NS.staticNumber3(); -var i2: number = new CJS_Clobb_Class_NS.default().instNumber2(); -var i3: string = new CJS_Clobb_Class_NS.default().instNumber2(); -import {doesntExist3} from \"CommonJS_Named\"; -import {numberValue2} from \"CommonJS_Named\"; -var j1: number = numberValue2; -var j2: string = numberValue2; -import {numberValue3 as numVal3} from \"CommonJS_Named\"; -var k1: number = numVal3; -var k2: string = numVal3; -import * as CJS_Named from \"CommonJS_Named\"; -var l1: number = CJS_Named.numberValue1; -var l2: string = CJS_Named.numberValue1; -CJS_Named.doesntExist; -import * as CJS_Named_NS from \"CommonJS_Named\"; -var m1: number = CJS_Named_NS.numberValue4; -var m2: string = CJS_Named_NS.default.numberValue4; -var m3: string = CJS_Named_NS.numberValue4; -import {doesntExist4} from \"ES6_Default_AnonFunction1\"; -import ES6_Def_AnonFunc1 from \"ES6_Default_AnonFunction1\"; -var n1: number = ES6_Def_AnonFunc1(); -var n2: string = ES6_Def_AnonFunc1(); -import ES6_Def_NamedFunc1 from \"ES6_Default_NamedFunction1\"; -var o1: number = ES6_Def_NamedFunc1(); -var o2: string = ES6_Def_NamedFunc1(); -import ES6_Def_AnonClass1 from \"ES6_Default_AnonClass1\"; -var p1: number = new ES6_Def_AnonClass1().givesANum(); -var p2: string = new ES6_Def_AnonClass1().givesANum(); -import ES6_Def_NamedClass1 from \"ES6_Default_NamedClass1\"; -var q1: number = new ES6_Def_NamedClass1().givesANum(); -var q2: string = new ES6_Def_NamedClass1().givesANum(); import doesntExist5 from \"ES6_Named1\"; +// Error: Not an exported binding import {specifierNumber1 as specifierNumber1_1} from \"ES6_Named1\"; var r1: number = specifierNumber1_1; var r2: string = specifierNumber1_1; +// Error: number ~> string import {specifierNumber2Renamed} from \"ES6_Named1\"; var s1: number = specifierNumber2Renamed; var s2: string = specifierNumber2Renamed; +// Error: number ~> string import {specifierNumber3 as specifierNumber3Renamed} from \"ES6_Named1\"; var t1: number = specifierNumber3Renamed; var t2: string = specifierNumber3Renamed; +// Error: number ~> string import {groupedSpecifierNumber1, groupedSpecifierNumber2} from \"ES6_Named1\"; var u1: number = groupedSpecifierNumber1; var u2: number = groupedSpecifierNumber2; var u3: string = groupedSpecifierNumber1; +// Error: number ~> string var u4: string = groupedSpecifierNumber2; +// Error: number ~> string import {givesANumber} from \"ES6_Named1\"; var v1: number = givesANumber(); var v2: string = givesANumber(); +// Error: number ~> string import {NumberGenerator} from \"ES6_Named1\"; var w1: number = new NumberGenerator().givesANumber(); var w2: string = new NumberGenerator().givesANumber(); +// Error: number ~> string import {varDeclNumber1, varDeclNumber2} from \"ES6_Named1\"; var x1: number = varDeclNumber1; var x2: number = varDeclNumber2; var x3: string = varDeclNumber1; +// Error: number ~> string var x4: string = varDeclNumber2; +// Error: number ~> string import {destructuredObjNumber} from \"ES6_Named1\"; var y1: number = destructuredObjNumber; var y2: string = destructuredObjNumber; +// Error: number ~> string import {destructuredArrNumber} from \"ES6_Named1\"; var z1: number = destructuredArrNumber; var z2: string = destructuredArrNumber; +// Error: number ~> string import {numberValue1 as numberValue4} from \"ES6_ExportFrom_Intermediary1\"; var aa1: number = numberValue4; var aa2: string = numberValue4; +// Error: number ~> string import {numberValue2_renamed} from \"ES6_ExportFrom_Intermediary1\"; var ab1: number = numberValue2_renamed; var ab2: string = numberValue2_renamed; +// Error: number ~> string import {numberValue1 as numberValue5} from \"ES6_ExportAllFrom_Intermediary1\"; var ac1: number = numberValue5; var ac2: string = numberValue5; +// Error: number ~> string +/////////////////////////////////// +// == ES6 Default -> CommonJS == // +/////////////////////////////////// require(\"ES6_Default_AnonFunction2\").doesntExist; +// Error: \'doesntExist\' isn\'t an export var ES6_Def_AnonFunc2 = require(\"ES6_Default_AnonFunction2\").default; var ad1: number = ES6_Def_AnonFunc2(); var ad2: string = ES6_Def_AnonFunc2(); +// Error: number ~> string var ES6_Def_NamedFunc2 = require(\"ES6_Default_NamedFunction2\").default; var ae1: number = ES6_Def_NamedFunc2(); var ae2: string = ES6_Def_NamedFunc2(); +// Error: number ~> string var ES6_Def_AnonClass2 = require(\"ES6_Default_AnonClass2\").default; var af1: number = new ES6_Def_AnonClass2().givesANum(); var af2: string = new ES6_Def_AnonClass2().givesANum(); +// Error: number ~> string var ES6_Def_NamedClass2 = require(\"ES6_Default_NamedClass2\").default; var ag1: number = new ES6_Def_NamedClass2().givesANum(); var ag2: string = new ES6_Def_NamedClass2().givesANum(); +// Error: number ~> string +///////////////////////////////// +// == ES6 Named -> CommonJS == // +///////////////////////////////// var specifierNumber4 = require(\"ES6_Named2\").specifierNumber4; var ah1: number = specifierNumber4; var ah2: string = specifierNumber4; +// Error: number ~> string var specifierNumber5Renamed = require(\"ES6_Named2\").specifierNumber5Renamed; var ai1: number = specifierNumber5Renamed; var ai2: string = specifierNumber5Renamed; +// Error: number ~> string var groupedSpecifierNumber3 = require(\"ES6_Named2\").groupedSpecifierNumber3; var groupedSpecifierNumber4 = require(\"ES6_Named2\").groupedSpecifierNumber4; var aj1: number = groupedSpecifierNumber3; var aj2: number = groupedSpecifierNumber4; var aj3: string = groupedSpecifierNumber3; +// Error: number ~> string var aj4: string = groupedSpecifierNumber4; +// Error: number ~> string var givesANumber2 = require(\"ES6_Named2\").givesANumber2; var ak1: number = givesANumber2(); var ak2: string = givesANumber2(); +// Error: number ~> string var NumberGenerator2 = require(\"ES6_Named2\").NumberGenerator2; var al1: number = new NumberGenerator2().givesANumber(); var al2: string = new NumberGenerator2().givesANumber(); +// Error: number ~> string var varDeclNumber3 = require(\"ES6_Named2\").varDeclNumber3; var varDeclNumber4 = require(\"ES6_Named2\").varDeclNumber4; var am1: number = varDeclNumber3; var am2: number = varDeclNumber4; var am3: string = varDeclNumber3; +// Error: number ~> string var am4: string = varDeclNumber4; +// Error: number ~> string var destructuredObjNumber2 = require(\"ES6_Named2\").destructuredObjNumber2; var an1: number = destructuredObjNumber2; var an2: string = destructuredObjNumber2; +// Error: number ~> string var destructuredArrNumber2 = require(\"ES6_Named2\").destructuredArrNumber2; var ao1: number = destructuredArrNumber2; var ao2: string = destructuredArrNumber2; +// Error: number ~> string var numberValue6 = require(\"ES6_ExportFrom_Intermediary2\").numberValue1; var ap1: number = numberValue6; var ap2: string = numberValue6; +// Error: number ~> string var numberValue2_renamed2 = require( \"ES6_ExportFrom_Intermediary2\" ).numberValue2_renamed2; var aq1: number = numberValue2_renamed2; var aq2: string = numberValue2_renamed2; +// Error: number ~> string var numberValue7 = require(\"ES6_ExportAllFrom_Intermediary2\").numberValue2; var ar1: number = numberValue7; var ar2: string = numberValue7; +// Error: number ~> string +//////////////////////////////////////////////////////// +// == ES6 Default+Named -> ES6 import Default+Named== // +//////////////////////////////////////////////////////// import defaultNum, {str as namedStr} from \"./ES6_DefaultAndNamed\"; + var as1: number = defaultNum; var as2: string = defaultNum; +// Error: number ~> string var as3: string = namedStr; var as4: number = namedStr; +// Error: string ~> number +//////////////////////////////////////// +// == Side-effect only ES6 imports == // +//////////////////////////////////////// import \"./SideEffects\"; + +////////////////////////////////////////////// +// == Suggest export name on likely typo == // +////////////////////////////////////////////// import specifierNumber1 from \"ES6_Named1\"; +// Error: Did you mean \`import {specifierNumber1} from ...\`? import {specifierNumber} from \"ES6_Named1\"; +// Error: Did you mean \`specifierNumber1\`? +/////////////////////////////////////////////////// +// == Multi \`export *\` should combine exports == // +/////////////////////////////////////////////////// import {numberValue1 as numberValue8, numberValue2 as numberValue9} from \"./ES6_ExportAllFromMulti\"; + var at1: number = numberValue8; var at2: string = numberValue8; +// Error: number ~> string var at3: number = numberValue9; var at4: string = numberValue9; -import {typeAlias} from \"./ExportType\"; -" +// Error: number ~> string +///////////////////////////////////////////////////////////// +// == Vanilla \`import\` cannot import a type-only export == // +///////////////////////////////////////////////////////////// +import {typeAlias} from \"./ExportType\"; // Error: Cannot vanilla-import a type alias!" `; exports[`test test_imports_are_frozen.js 1`] = ` @@ -1306,55 +1306,55 @@ function testRequires() { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + // // Imports // + // CommonJS module +import * as DefaultA from \"A\"; +DefaultA.numberValue1 = 123; // Error: DefaultA is frozen // ES6 module +import * as ES6_Named1 from \"ES6_Named1\"; +ES6_Named1.varDeclNumber1 = 123; // Error: ES6_Named1 is frozen // CommonJS module that clobbers module.exports +import * as CommonJS_Star from \"CommonJS_Clobbering_Lit\"; +CommonJS_Star.numberValue1 = 123; // Error: frozen +CommonJS_Star.default.numberValue1 = 123; // ok +import CommonJS_Clobbering_Lit from \"CommonJS_Clobbering_Lit\"; +CommonJS_Clobbering_Lit.numberValue1 = 123; // ok // CommonJS module that clobbers module.exports with a frozen object +import * as CommonJS_Frozen_Star from \"CommonJS_Clobbering_Frozen\"; +CommonJS_Frozen_Star.numberValue1 = 123; // Error: frozen +CommonJS_Frozen_Star.default.numberValue1 = 123; // Error: frozen +import CommonJS_Clobbering_Frozen from \"CommonJS_Clobbering_Frozen\"; +CommonJS_Clobbering_Frozen.numberValue1 = 123; // Error: exports are frozen // // Requires // -// CommonJS module -// ok, not frozen by default -// ES6 module -// error, es6 exports are frozen -// CommonJS module that clobbers module.exports -// ok, not frozen by default -// CommonJS module that clobbers module.exports with a frozen object -// Error: frozen -import * as DefaultA from \"A\"; -DefaultA.numberValue1 = 123; -import * as ES6_Named1 from \"ES6_Named1\"; -ES6_Named1.varDeclNumber1 = 123; -import * as CommonJS_Star from \"CommonJS_Clobbering_Lit\"; -CommonJS_Star.numberValue1 = 123; -CommonJS_Star.default.numberValue1 = 123; -import CommonJS_Clobbering_Lit from \"CommonJS_Clobbering_Lit\"; -CommonJS_Clobbering_Lit.numberValue1 = 123; -import * as CommonJS_Frozen_Star from \"CommonJS_Clobbering_Frozen\"; -CommonJS_Frozen_Star.numberValue1 = 123; -CommonJS_Frozen_Star.default.numberValue1 = 123; -import CommonJS_Clobbering_Frozen from \"CommonJS_Clobbering_Frozen\"; -CommonJS_Clobbering_Frozen.numberValue1 = 123; function testRequires() { + // CommonJS module var DefaultA = require(\"A\"); DefaultA.numberValue1 = 123; + // ok, not frozen by default + // ES6 module var ES6_Named1 = require(\"ES6_Named1\"); ES6_Named1.numberValue = 123; + // error, es6 exports are frozen + // CommonJS module that clobbers module.exports var CommonJS_Star = require(\"CommonJS_Clobbering_Lit\"); CommonJS_Star.numberValue1 = 123; + // ok, not frozen by default + // CommonJS module that clobbers module.exports with a frozen object var CommonJS_Frozen_Star = require(\"CommonJS_Clobbering_Frozen\"); - CommonJS_Frozen_Star.numberValue1 = 123; -} -" + CommonJS_Frozen_Star.numberValue1 = 123; // Error: frozen +}" `; diff --git a/tests/es_declare_module/__snapshots__/jsfmt.spec.js.snap b/tests/es_declare_module/__snapshots__/jsfmt.spec.js.snap index 1b9d8aa8..b8fc7736 100644 --- a/tests/es_declare_module/__snapshots__/jsfmt.spec.js.snap +++ b/tests/es_declare_module/__snapshots__/jsfmt.spec.js.snap @@ -42,52 +42,51 @@ import type {T as T2} from \"ES\"; import {exports as nope} from \"ES\"; // Error: Not an export ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// Error: number ~> string -// Error: string ~> number -// Error: Module ~> number -// Error: No such export! -// Error: number ~> string -// Error: string ~> number -// Error: No such export! -// Error: string ~> number -// Error: number ~> string -// Error: number ~> C -// Error: number ~> CType -// Error: T is a type import, not a value -// Error: string ~> number -// Error: Not an export + import {num1, str1} from \"CJS_Named\"; import CJS_Named from \"CJS_Named\"; (num1: number); (num1: string); +// Error: number ~> string (str1: string); (str1: number); +// Error: string ~> number (CJS_Named: { num1: number, str1: string }); (CJS_Named: number); +// Error: Module ~> number import {num2} from \"CJS_Clobbered\"; +// Error: No such export! import {numExport} from \"CJS_Clobbered\"; (numExport: number); (numExport: string); +// Error: number ~> string import type {numType} from \"CJS_Clobbered\"; (42: numType); (\"asdf\": numType); +// Error: string ~> number import {strHidden} from \"ES\"; +// Error: No such export! import {str3} from \"ES\"; (str3: string); (str3: number); +// Error: string ~> number import {num3} from \"ES\"; (num3: number); (num3: string); +// Error: number ~> string import {C} from \"ES\"; import type {C as CType} from \"ES\"; (new C(): C); (42: C); +// Error: number ~> C (new C(): CType); (42: CType); +// Error: number ~> CType import {T} from \"ES\"; +// Error: T is a type import, not a value import type {T as T2} from \"ES\"; (42: T2); (\"asdf\": T2); -import {exports as nope} from \"ES\"; -" +// Error: string ~> number +import {exports as nope} from \"ES\"; // Error: Not an export" `; diff --git a/tests/es_declare_module/flow-typed/__snapshots__/jsfmt.spec.js.snap b/tests/es_declare_module/flow-typed/__snapshots__/jsfmt.spec.js.snap index f8c3d213..4b233fcf 100644 --- a/tests/es_declare_module/flow-typed/__snapshots__/jsfmt.spec.js.snap +++ b/tests/es_declare_module/flow-typed/__snapshots__/jsfmt.spec.js.snap @@ -37,6 +37,5 @@ declare module \"ES\" { declare export class C {} declare export type T = number; declare var exports: number; -} -" +}" `; diff --git a/tests/esproposal_export_star_as.enable/__snapshots__/jsfmt.spec.js.snap b/tests/esproposal_export_star_as.enable/__snapshots__/jsfmt.spec.js.snap index 57a0ee57..2e9765b6 100644 --- a/tests/esproposal_export_star_as.enable/__snapshots__/jsfmt.spec.js.snap +++ b/tests/esproposal_export_star_as.enable/__snapshots__/jsfmt.spec.js.snap @@ -10,14 +10,14 @@ var c: string = source.str; var d: number = source.str; // Error: num ~> string ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// Error: num ~> string -// Error: num ~> string + import {source} from \"./test\"; + var a: number = source.num; var b: string = source.num; +// Error: num ~> string var c: string = source.str; -var d: number = source.str; -" +var d: number = source.str; // Error: num ~> string" `; exports[`test source.js 1`] = ` @@ -27,7 +27,7 @@ export var str = \'asdf\'; export var num = 42; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + export var str = \"asdf\"; -export var num = 42; -" +export var num = 42;" `; diff --git a/tests/esproposal_export_star_as.ignore/__snapshots__/jsfmt.spec.js.snap b/tests/esproposal_export_star_as.ignore/__snapshots__/jsfmt.spec.js.snap index 2c454949..75873b36 100644 --- a/tests/esproposal_export_star_as.ignore/__snapshots__/jsfmt.spec.js.snap +++ b/tests/esproposal_export_star_as.ignore/__snapshots__/jsfmt.spec.js.snap @@ -10,14 +10,14 @@ var c: string = source.str; var d: number = source.str; // Ignored error: num ~> string ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// Error: num ~> string -// Ignored error: num ~> string + import {source} from \"./test\"; + var a: number = source.num; var b: string = source.num; +// Error: num ~> string var c: string = source.str; -var d: number = source.str; -" +var d: number = source.str; // Ignored error: num ~> string" `; exports[`test source.js 1`] = ` @@ -27,7 +27,7 @@ export var str = \'asdf\'; export var num = 42; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + export var str = \"asdf\"; -export var num = 42; -" +export var num = 42;" `; diff --git a/tests/export_default/__snapshots__/jsfmt.spec.js.snap b/tests/export_default/__snapshots__/jsfmt.spec.js.snap index 2ca98135..d047f6e2 100644 --- a/tests/export_default/__snapshots__/jsfmt.spec.js.snap +++ b/tests/export_default/__snapshots__/jsfmt.spec.js.snap @@ -1,8 +1,7 @@ exports[`test P.js 1`] = ` "module.exports = require(\'M\'); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -module.exports = require(\"M\"); -" +module.exports = require(\"M\");" `; exports[`test test.js 1`] = ` @@ -14,14 +13,13 @@ N.y = P(N.y); var Q = require(\'Q\'); // declaration of Q redirects to module M N.z = Q(N.z); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// implementation of P redirects to module M -// declaration of Q redirects to module M var M = require(\"M\"); var N = require(\"N\"); N.x = M(N.x); var P = require(\"./P\"); +// implementation of P redirects to module M N.y = P(N.y); var Q = require(\"Q\"); -N.z = Q(N.z); -" +// declaration of Q redirects to module M +N.z = Q(N.z);" `; diff --git a/tests/export_default/lib/__snapshots__/jsfmt.spec.js.snap b/tests/export_default/lib/__snapshots__/jsfmt.spec.js.snap index 6d1560fc..b309e5c5 100644 --- a/tests/export_default/lib/__snapshots__/jsfmt.spec.js.snap +++ b/tests/export_default/lib/__snapshots__/jsfmt.spec.js.snap @@ -21,6 +21,5 @@ declare module N { } declare module Q { declare var exports: $Exports<\"M\">; -} -" +}" `; diff --git a/tests/export_type/__snapshots__/jsfmt.spec.js.snap b/tests/export_type/__snapshots__/jsfmt.spec.js.snap index 839a4136..f4c40f2b 100644 --- a/tests/export_type/__snapshots__/jsfmt.spec.js.snap +++ b/tests/export_type/__snapshots__/jsfmt.spec.js.snap @@ -7,10 +7,11 @@ export interface IFoo { prop: number }; module.exports = {} ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + export type talias4 = number; export interface IFoo { prop: number } -module.exports = {}; -" + +module.exports = {};" `; exports[`test importer.js 1`] = ` @@ -48,31 +49,32 @@ var m: IFoo2 = {prop: \'asdf\'}; var n: IFoo2 = {prop: 42}; // Error: {prop:number} ~> {prop:string} ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// Error: string ~> number -// Error: string ~> number -// Error: string ~> number -// Error: string ~> number -// Error: string ~> number -// Error: {prop:string} ~> {prop:number} -// Error: {prop:number} ~> {prop:string} + import type {inlinedType1, standaloneType1, talias1, talias3} from \"./types_only\"; + var a: inlinedType1 = 42; var b: inlinedType1 = \"asdf\"; +// Error: string ~> number var c: standaloneType1 = 42; var d: standaloneType1 = \"asdf\"; +// Error: string ~> number var e: talias1 = 42; var f: talias1 = \"asdf\"; +// Error: string ~> number var g: talias3 = 42; var h: talias3 = \"asdf\"; +// Error: string ~> number import type {talias4} from \"./cjs_with_types\"; var i: talias4 = 42; var j: talias4 = \"asdf\"; +// Error: string ~> number import {IFoo, IFoo2} from \"./types_only\"; + var k: IFoo = { prop: 42 }; var l: IFoo = { prop: \"asdf\" }; +// Error: {prop:string} ~> {prop:number} var m: IFoo2 = { prop: \"asdf\" }; -var n: IFoo2 = { prop: 42 }; -" +var n: IFoo2 = { prop: 42 }; // Error: {prop:number} ~> {prop:string}" `; exports[`test types_only.js 1`] = ` @@ -93,16 +95,19 @@ export type {talias1, talias2 as talias3, IFoo2} from \"./types_only2\"; export interface IFoo { prop: number }; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// Error: string ~> number -// Error: Missing \`type\` keyword + export type inlinedType1 = number; var a: inlinedType1 = 42; var b: inlinedType1 = \"asdf\"; +// Error: string ~> number type standaloneType1 = number; export type {standaloneType1} + type standaloneType2 = number; export {standaloneType2} +// Error: Missing \`type\` keyword export type {talias1, talias2 as talias3, IFoo2} from \"./types_only2\" + export interface IFoo { prop: number } " `; @@ -115,6 +120,7 @@ export type talias2 = number; export interface IFoo2 { prop: string }; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + export type talias1 = number; export type talias2 = number; export interface IFoo2 { prop: string } diff --git a/tests/extensions/__snapshots__/jsfmt.spec.js.snap b/tests/extensions/__snapshots__/jsfmt.spec.js.snap index 524d171e..972a2680 100644 --- a/tests/extensions/__snapshots__/jsfmt.spec.js.snap +++ b/tests/extensions/__snapshots__/jsfmt.spec.js.snap @@ -3,6 +3,5 @@ exports[`test foo.js 1`] = ` imp(1337); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ var imp = require(\"./bar\"); -imp(1337); -" +imp(1337);" `; diff --git a/tests/facebook_fbt_none/__snapshots__/jsfmt.spec.js.snap b/tests/facebook_fbt_none/__snapshots__/jsfmt.spec.js.snap index 8b22529f..f3911907 100644 --- a/tests/facebook_fbt_none/__snapshots__/jsfmt.spec.js.snap +++ b/tests/facebook_fbt_none/__snapshots__/jsfmt.spec.js.snap @@ -5,9 +5,7 @@ var React = require(\'react\'); (: number); // Error: ReactElement ~> number ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// Error: ReactElement ~> number var React = require(\"react\"); -(: React.Element<*>); -(: number); -" +(: React.Element<*>); +(: number); // Error: ReactElement ~> number" `; diff --git a/tests/facebook_fbt_some/__snapshots__/jsfmt.spec.js.snap b/tests/facebook_fbt_some/__snapshots__/jsfmt.spec.js.snap index 01fa23f9..e438040a 100644 --- a/tests/facebook_fbt_some/__snapshots__/jsfmt.spec.js.snap +++ b/tests/facebook_fbt_some/__snapshots__/jsfmt.spec.js.snap @@ -5,8 +5,7 @@ exports[`test main.js 1`] = ` (: string); // Error (the libdef in this test marks fbt as number) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// Error (the libdef in this test marks fbt as number) -(: number); -(: string); -" + +(: number); +(: string); // Error (the libdef in this test marks fbt as number)" `; diff --git a/tests/facebook_fbt_some/flow-typed/__snapshots__/jsfmt.spec.js.snap b/tests/facebook_fbt_some/flow-typed/__snapshots__/jsfmt.spec.js.snap index cba08a2c..9447133d 100644 --- a/tests/facebook_fbt_some/flow-typed/__snapshots__/jsfmt.spec.js.snap +++ b/tests/facebook_fbt_some/flow-typed/__snapshots__/jsfmt.spec.js.snap @@ -1,6 +1,5 @@ exports[`test fbt.js 1`] = ` "type Fbt = number ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -type Fbt = number; -" +type Fbt = number;" `; diff --git a/tests/facebookisms/__snapshots__/jsfmt.spec.js.snap b/tests/facebookisms/__snapshots__/jsfmt.spec.js.snap index 02ea1f92..8e7373a7 100644 --- a/tests/facebookisms/__snapshots__/jsfmt.spec.js.snap +++ b/tests/facebookisms/__snapshots__/jsfmt.spec.js.snap @@ -3,8 +3,7 @@ exports[`test Bar.js 1`] = ` module.exports = Bar; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ var Bar = { x: 0 }; -module.exports = Bar; -" +module.exports = Bar;" `; exports[`test copyProperties.js 1`] = ` @@ -49,17 +48,13 @@ let tests = [ ]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// global -// error, unknown global -// annotation -// module from lib -// too few args -// err, num !~> string -// passed as a function + let tests = [ + // global function() { - copyProperties(); + copyProperties(); // error, unknown global }, + // annotation function(copyProperties: Object$Assign) { let result = {}; result.baz = false; @@ -69,22 +64,24 @@ let tests = [ baz: boolean }); }, + // module from lib function() { const copyProperties = require(\"copyProperties\"); let x = { foo: \"a\" }; let y = { bar: 123 }; (copyProperties({}, x, y): { foo: string, bar: number }); }, + // too few args function(copyProperties: Object$Assign) { copyProperties(); - (copyProperties({ foo: \"a\" }): { foo: number }); + (copyProperties({ foo: \"a\" }): { foo: number }); // err, num !~> string }, + // passed as a function function(copyProperties: Object$Assign) { function x(cb: Function) {} x(copyProperties); } -]; -" +];" `; exports[`test invariant.js 1`] = ` @@ -104,19 +101,18 @@ let tests = [ ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// error, forgot to require invariant + let tests = [ function() { let x: ?string = null; - invariant(x, \"truthy only\"); + invariant(x, \"truthy only\"); // error, forgot to require invariant }, function(invariant: Function) { let x: ?string = null; invariant(x); (x: string); } -]; -" +];" `; exports[`test lib.js 1`] = ` @@ -140,8 +136,7 @@ declare module \"mergeInto\" { } declare module \"mixin\" { declare var exports: $Facebookism$Mixin; -} -" +}" `; exports[`test mergeInto.js 1`] = ` @@ -181,36 +176,35 @@ let tests = [ ]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// global -// error, unknown global -// annotation -// module from lib -// too few args -// passed as a function + let tests = [ + // global function() { - mergeInto(); + mergeInto(); // error, unknown global }, + // annotation function(mergeInto: $Facebookism$MergeInto) { let result = {}; result.baz = false; (mergeInto(result, { foo: \"a\" }, { bar: 123 }): void); (result: { foo: string, bar: number, baz: boolean }); }, + // module from lib function() { const mergeInto = require(\"mergeInto\"); let result: { foo?: string, bar?: number, baz: boolean } = { baz: false }; (mergeInto(result, { foo: \"a\" }, { bar: 123 }): void); }, + // too few args function(mergeInto: $Facebookism$MergeInto) { mergeInto(); }, + // passed as a function function(mergeInto: $Facebookism$MergeInto) { function x(cb: Function) {} x(mergeInto); } -]; -" +];" `; exports[`test test.js 1`] = ` @@ -226,11 +220,11 @@ class Foo extends mixin(Bar) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ var Bar = require(\"./Bar\"); var mixin = require(\"mixin\"); + class Foo extends mixin(Bar) { m() { var x: string = this.x; this.y = \"\"; } -} -" +}" `; diff --git a/tests/fetch/__snapshots__/jsfmt.spec.js.snap b/tests/fetch/__snapshots__/jsfmt.spec.js.snap index 162ff450..f72dcd8d 100644 --- a/tests/fetch/__snapshots__/jsfmt.spec.js.snap +++ b/tests/fetch/__snapshots__/jsfmt.spec.js.snap @@ -26,23 +26,26 @@ const c: Promise = const d: Promise = fetch(\'image.png\'); // incorrect ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + // most of the details are tested in the separate file // here I test the basic usage -// incorrect -// correct -// incorrect + const myRequest = new Request(\"http://google.com\"); + const a: Promise = fetch(myRequest).then(response => response.text()); + const b: Promise = fetch(myRequest); +// incorrect var myInit = { method: \"GET\", headers: { \"Content-Type\": \"image/jpeg\" }, mode: \"cors\", cache: \"default\" }; + const c: Promise = fetch(\"image.png\").then(response => response.blob()); -const d: Promise = fetch(\"image.png\"); -" +// correct +const d: Promise = fetch(\"image.png\"); // incorrect" `; exports[`test headers.js 1`] = ` @@ -76,45 +79,44 @@ for (let v of e.entries()) { e.getAll(\'content-type\').forEach((v: string) => {}); // correct ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// not correct -// not correct -// correct -// correct -// correct -// correct -// not correct -// not correct -// correct -// not correct -// not correct -// not correct -// correct -// not correct -// correct -// correct -// correct + const a = new Headers(\"\'Content-Type\': \'image/jpeg\'\"); +// not correct const b = new Headers([ \"Content-Type\", \"image/jpeg\" ]); +// not correct const c = new Headers({ \"Content-Type\", \"image/jpeg\" }); +// correct const d = new Headers(c); +// correct const e: Headers = new Headers(); +// correct e.append(\"Content-Type\", \"image/jpeg\"); +// correct e.append(\"Content-Type\"); +// not correct e.append({ \"Content-Type\", \"image/jpeg\" }); +// not correct e.set(\"Content-Type\", \"image/jpeg\"); +// correct e.set(\"Content-Type\"); +// not correct e.set({ \"Content-Type\", \"image/jpeg\" }); +// not correct const f: Headers = e.append(\"Content-Type\", \"image/jpeg\"); +// not correct const g: string = e.get(\"Content-Type\"); +// correct const h: number = e.get(\"Content-Type\"); +// not correct for (let v of e) { - const [ i, j ]: [string, string] = v; + const [ i, j ]: [string, string] = v; // correct } + for (let v of e.entries()) { - const [ i, j ]: [string, string] = v; + const [ i, j ]: [string, string] = v; // correct } -e.getAll(\"content-type\").forEach((v: string) => {}); -" + +e.getAll(\"content-type\").forEach((v: string) => {}); // correct" `; exports[`test request.js 1`] = ` @@ -171,34 +173,27 @@ h.arrayBuffer().then((ab: ArrayBuffer) => ab); // correct h.arrayBuffer().then((ab: Buffer) => ab); // incorrect ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// incorrect -// correct -// correct -// correct (doesn\'t make much sense though) -// incorrect -// incorrect -// correct -// correct -// correct -// incorrect - headers is string -// incorrect - CONNECT is forbidden -// correct -// incorrect -// correct -// incorrect const a: Request = new Request(); +// incorrect const b: Request = new Request(\"http://example.org\"); +// correct const c: Request = new Request(b); +// correct const d: Request = new Request(c.clone()); +// correct (doesn\'t make much sense though) const e: Request = new Request(b, c); +// incorrect const f: Request = new Request({}); +// incorrect const g: Request = new Request(\"http://example.org\", {}); +// correct const h: Request = new Request(\"http://example.org\", { method: \"GET\", headers: { \"Content-Type\": \"image/jpeg\" }, mode: \"cors\", cache: \"default\" }); +// correct const i: Request = new Request(\"http://example.org\", { method: \"POST\", headers: { \"Content-Type\": \"image/jpeg\" }, @@ -206,24 +201,30 @@ const i: Request = new Request(\"http://example.org\", { mode: \"cors\", cache: \"default\" }); +// correct const j: Request = new Request(\"http://example.org\", { method: \"GET\", headers: \"Content-Type: image/jpeg\", mode: \"cors\", cache: \"default\" }); +// incorrect - headers is string const k: Request = new Request(\"http://example.org\", { method: \"CONNECT\", headers: { \"Content-Type\": \"image/jpeg\" }, mode: \"cors\", cache: \"default\" }); +// incorrect - CONNECT is forbidden var l: boolean = h.bodyUsed; + h.text().then((t: string) => t); +// correct h.text().then((t: Buffer) => t); +// incorrect h.arrayBuffer().then((ab: ArrayBuffer) => ab); -h.arrayBuffer().then((ab: Buffer) => ab); -" +// correct +h.arrayBuffer().then((ab: Buffer) => ab); // incorrect" `; exports[`test response.js 1`] = ` @@ -275,47 +276,46 @@ h.arrayBuffer().then((ab: ArrayBuffer) => ab); // correct h.arrayBuffer().then((ab: Buffer) => ab); // incorrect ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// correct -// correct -// correct -// correct -// incorrect -// incorrect -// correct -// correct, if verbose -// incorrect -// correct -// incorrect -// correct -// incorrect const a: Response = new Response(); +// correct const b: Response = new Response(new Blob()); +// correct const c: Response = new Response(new FormData()); +// correct const d: Response = new Response(new FormData(), { status: 404 }); +// correct const e: Response = new Response(\"responsebody\", { status: \"404\" }); +// incorrect const f: Response = new Response(\"responsebody\", { status: 404, headers: \"\'Content-Type\': \'image/jpeg\'\" }); +// incorrect const g: Response = new Response(\"responsebody\", { status: 404, headers: { \"Content-Type\": \"image/jpeg\" } }); +// correct const h: Response = new Response(\"responsebody\", { status: 404, headers: new Headers({ \"Content-Type\": \"image/jpeg\" }) }); +// correct, if verbose const i: Response = new Response({ status: 404, headers: new Headers({ \"Content-Type\": \"image/jpeg\" }) }); +// incorrect const ok: boolean = h.ok; const status: number = h.status; + h.text().then((t: string) => t); +// correct h.text().then((t: Buffer) => t); +// incorrect h.arrayBuffer().then((ab: ArrayBuffer) => ab); -h.arrayBuffer().then((ab: Buffer) => ab); -" +// correct +h.arrayBuffer().then((ab: Buffer) => ab); // incorrect" `; exports[`test urlsearchparams.js 1`] = ` @@ -349,43 +349,42 @@ for (let v of e.entries()) { e.getAll(\'key1\').forEach((v: string) => {}); // correct ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// correct -// not correct -// not correct -// correct -// correct -// correct -// not correct -// not correct -// correct -// not correct -// not correct -// not correct -// correct -// not correct -// correct -// correct -// correct + const a = new URLSearchParams(\"key1=value1\"); +// correct const b = new URLSearchParams([ \"key1\", \"value1\" ]); +// not correct const c = new URLSearchParams({ \"key1\", \"value1\" }); +// not correct const d = new URLSearchParams(c); +// correct const e: URLSearchParams = new URLSearchParams(); +// correct e.append(\"key1\", \"value1\"); +// correct e.append(\"key1\"); +// not correct e.append({ \"key1\", \"value1\" }); +// not correct e.set(\"key1\", \"value1\"); +// correct e.set(\"key1\"); +// not correct e.set({ \"key1\", \"value1\" }); +// not correct const f: URLSearchParams = e.append(\"key1\", \"value1\"); +// not correct const g: string = e.get(\"key1\"); +// correct const h: number = e.get(\"key1\"); +// not correct for (let v of e) { - const [ i, j ]: [string, string] = v; + const [ i, j ]: [string, string] = v; // correct } + for (let v of e.entries()) { - const [ i, j ]: [string, string] = v; + const [ i, j ]: [string, string] = v; // correct } -e.getAll(\"key1\").forEach((v: string) => {}); -" + +e.getAll(\"key1\").forEach((v: string) => {}); // correct" `; diff --git a/tests/find-module/__snapshots__/jsfmt.spec.js.snap b/tests/find-module/__snapshots__/jsfmt.spec.js.snap index 3a5cd026..56242dee 100644 --- a/tests/find-module/__snapshots__/jsfmt.spec.js.snap +++ b/tests/find-module/__snapshots__/jsfmt.spec.js.snap @@ -1,8 +1,7 @@ exports[`test req.js 1`] = ` "module.exports = 0; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -module.exports = 0; -" +module.exports = 0;" `; exports[`test test.js 1`] = ` @@ -13,6 +12,6 @@ import x from \'./req\'; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ var x = require(\"./req\"); (x: string); -import x from \"./req\"; -" + +import x from \"./req\";" `; diff --git a/tests/fixpoint/__snapshots__/jsfmt.spec.js.snap b/tests/fixpoint/__snapshots__/jsfmt.spec.js.snap index f04e7e95..752597a2 100644 --- a/tests/fixpoint/__snapshots__/jsfmt.spec.js.snap +++ b/tests/fixpoint/__snapshots__/jsfmt.spec.js.snap @@ -31,15 +31,18 @@ factorial(\"...\"); module.exports = {fn: fix}; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @providesModule Fun */ + function eq(x: number, y: number) { return true; } + function sub(x: number, y: number) { return 0; } function mul(x: number, y: number) { return 0; } + function fix(fold) { var delta = function(delta) { return fold(function(x) { @@ -49,6 +52,7 @@ function fix(fold) { }; return delta(delta); } + function mk_factorial() { return fix(function(factorial) { return function(n) { @@ -59,10 +63,11 @@ function mk_factorial() { }; }); } + var factorial = mk_factorial(); factorial(\"...\"); -module.exports = { fn: fix }; -" + +module.exports = { fn: fix };" `; exports[`test Ycombinator.js 1`] = ` @@ -89,12 +94,14 @@ Y(func2); module.exports = Y; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @providesModule Ycombinator */ + function Y(f) { function g(x) { return f(x(x)); } g(g); } + function func1(f) { function fix_f(x: number): number { return f(x); @@ -107,8 +114,9 @@ function func2(f) { } return fix_f; } + Y(func1); Y(func2); -module.exports = Y; -" + +module.exports = Y;" `; diff --git a/tests/flow_ast.template_strings/__snapshots__/jsfmt.spec.js.snap b/tests/flow_ast.template_strings/__snapshots__/jsfmt.spec.js.snap index c4ce4267..423da73c 100644 --- a/tests/flow_ast.template_strings/__snapshots__/jsfmt.spec.js.snap +++ b/tests/flow_ast.template_strings/__snapshots__/jsfmt.spec.js.snap @@ -1,6 +1,5 @@ exports[`test foo.js 1`] = ` "a\`foo \${bar} baz\` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -a\`foo \${bar} baz\`; -" +a\`foo \${bar} baz\`;" `; diff --git a/tests/for/__snapshots__/jsfmt.spec.js.snap b/tests/for/__snapshots__/jsfmt.spec.js.snap index 4fa368cb..f622c007 100644 --- a/tests/for/__snapshots__/jsfmt.spec.js.snap +++ b/tests/for/__snapshots__/jsfmt.spec.js.snap @@ -48,6 +48,7 @@ function corge(x: boolean) { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + function foo(x: boolean) { var max = 10; for (var ii = 0; ii < max; ii++) { @@ -58,6 +59,7 @@ function foo(x: boolean) { } console.log(\"this is still reachable\"); } + function bar(x: boolean) { var max = 0; for (var ii = 0; ii < max; ii++) { @@ -65,6 +67,7 @@ function bar(x: boolean) { } console.log(\"this is still reachable\"); } + function baz(x: boolean) { var max = 0; for (var ii = 0; ii < max; ii++) { @@ -72,6 +75,7 @@ function baz(x: boolean) { } console.log(\"this is still reachable\"); } + function bliffl(x: boolean) { var max = 10; loop1: @@ -84,14 +88,14 @@ function bliffl(x: boolean) { } console.log(\"this is still reachable\"); } + function corge(x: boolean) { var max = 0; for (var ii = 0; ii < max; ii++) { break; } console.log(\"this is still reachable\"); -} -" +}" `; exports[`test abnormal_for_in.js 1`] = ` @@ -148,18 +152,21 @@ function foo(x: boolean) { } console.log(\"this is still reachable\"); } + function bar(x: boolean) { for (var prop in {}) { return; } console.log(\"this is still reachable\"); } + function baz(x: boolean) { for (var prop in {}) { continue; } console.log(\"this is still reachable\"); } + function bliffl(x: boolean) { var obj = { a: 1, b: 2 }; loop1: @@ -172,13 +179,13 @@ function bliffl(x: boolean) { } console.log(\"this is still reachable\"); } + function corge(x: boolean) { for (var prop in {}) { break; } console.log(\"this is still reachable\"); -} -" +}" `; exports[`test abnormal_for_of.js 1`] = ` @@ -235,18 +242,21 @@ function foo(x: boolean) { } console.log(\"this is still reachable\"); } + function bar(x: boolean) { for (var elem of []) { return; } console.log(\"this is still reachable\"); } + function baz(x: boolean) { for (var elem of []) { continue; } console.log(\"this is still reachable\"); } + function bliffl(x: boolean) { var arr = [ 1, 2, 3 ]; loop1: @@ -259,11 +269,11 @@ function bliffl(x: boolean) { } console.log(\"this is still reachable\"); } + function corge(x: boolean) { for (var elem of []) { break; } console.log(\"this is still reachable\"); -} -" +}" `; diff --git a/tests/forof/__snapshots__/jsfmt.spec.js.snap b/tests/forof/__snapshots__/jsfmt.spec.js.snap index 0652bf64..57760407 100644 --- a/tests/forof/__snapshots__/jsfmt.spec.js.snap +++ b/tests/forof/__snapshots__/jsfmt.spec.js.snap @@ -56,55 +56,55 @@ function testSet2(set: Set<*>): void { /** * @flow */ -// Error - number ~> string -// Error - number ~> string -// Error - string ~> number -// Error - tuple ~> number -// Any tuple is fine -// Error - tuple ~> number -// Error - string ~> number -// Anything goes + function testArray(arr: Array): void { for (var x of arr) { - (x: string); + (x: string); // Error - number ~> string } } + function testIterable1(iterable: Iterable): void { for (var x of iterable) { - (x: string); + (x: string); // Error - number ~> string } } + function testIterable2(iterable: Iterable<*>): void { for (var x of iterable) { (x: string); } } + function testString(str: string): void { for (var x of str) { - (x: number); + (x: number); // Error - string ~> number } } + function testMap1(map: Map): void { for (var elem of map) { (elem: [string, number]); - (elem: number); + (elem: number); // Error - tuple ~> number } } + function testMap2(map: Map<*, *>): void { for (var elem of map) { (elem: [number, string]); - (elem: number); + // Any tuple is fine + (elem: number); // Error - tuple ~> number } } + function testSet1(set: Set): void { for (var x of set) { - (x: number); + (x: number); // Error - string ~> number } } + function testSet2(set: Set<*>): void { for (var x of set) { - (x: number); + (x: number); // Anything goes } -} -" +}" `; diff --git a/tests/function/__snapshots__/jsfmt.spec.js.snap b/tests/function/__snapshots__/jsfmt.spec.js.snap index 0b2326b9..c9dfcaab 100644 --- a/tests/function/__snapshots__/jsfmt.spec.js.snap +++ b/tests/function/__snapshots__/jsfmt.spec.js.snap @@ -42,53 +42,55 @@ function test2(): number { return 0; } (test2.apply(): number); (test2.apply(\"\"): number); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// expect []/\"\" this +function test(a: string, b: number): number { + return this.length; // expect []/\"\" this +} + // tuples flow correctly into params +test.apply(\"\", [ \"\", 0 ]); + // wrong this is an error +test.apply(0, [ \"\", 0 ]); // error: lookup \`length\` on Number // not enough arguments is an error (via incompatible RestT) +test.apply(\"\", [ \"\" ]); // error: string ~> number // mistyped arguments is an error +test.apply(\"\", [ \"\", \"\" ]); // error: string ~> number (2nd arg) +test.apply(\"\", [ 0, 0 ]); // error: number ~> string (1st arg) // resolve args array from tvar +function f(args) { + test.apply(\"\", args); +} +f([ \"\", 0 ]); // OK +f([ \"\", \"\" ]); // error: string ~> number (2nd arg) +f([ 0, 0 ]); // error: number ~> string (1st arg) // expect array +test.apply(\"\", \"not array\"); // error: expect array of args // expect 4 errors: // - lookup length on Number (because 0 is used as \`this\`) // - 123 is not a string // - \'foo\' is not a number // - return type (number) is not void +(test.call.apply(test, [ 0, 123, \"foo\" ]): void); + // expect 2 errors: // - lookup length on number (0 is used as \`this\`) // - 123 is not a string -// args are optional -function test(a: string, b: number): number { - return this.length; -} -test.apply(\"\", [ \"\", 0 ]); -test.apply(0, [ \"\", 0 ]); -test.apply(\"\", [ \"\" ]); -test.apply(\"\", [ \"\", \"\" ]); -test.apply(\"\", [ 0, 0 ]); -function f(args) { - test.apply(\"\", args); -} -f([ \"\", 0 ]); -f([ \"\", \"\" ]); -f([ 0, 0 ]); -test.apply(\"\", \"not array\"); -(test.call.apply(test, [ 0, 123, \"foo\" ]): void); (test.bind.apply(test, [ 0, 123 ]): (b: number) => number); + +// args are optional function test2(): number { return 0; } (test2.apply(): number); -(test2.apply(\"\"): number); -" +(test2.apply(\"\"): number);" `; exports[`test bind.js 1`] = ` @@ -103,16 +105,15 @@ let tests = [ ]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// ok -// error, number !~> string + let tests = [ function(x: (a: string, b: string) => void) { let y = x.bind(x, \"foo\"); y(\"bar\"); - y(123); + // ok + y(123); // error, number !~> string } -]; -" +];" `; exports[`test call.js 1`] = ` @@ -153,45 +154,47 @@ function test2(): number { return 0; } (test2.call(\"\"): number); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// expect []/\"\" this + +function test(a: string, b: number): number { + return this.length; // expect []/\"\" this +} + // args flow correctly into params +test.call(\"\", \"\", 0); + // wrong this is an error +test.call(0, \"\", 0); // error: lookup \`length\` on Number // not enough arguments is an error (via incompatible RestT) +test.call(\"\", \"\"); // error: string ~> number // mistyped arguments is an error +test.call(\"\", \"\", \"\"); // error: string ~> number (2nd arg) +test.call(\"\", 0, 0); // error: number ~> string (1st arg) // resolve args array from tvar +function f(args) { + test.call(\"\", args[0], args[1]); +} +f([ \"\", 0 ]); // OK +f([ \"\", \"\" ]); // error: string ~> number (2nd arg) +f([ 0, 0 ]); // error: number ~> string (1st arg) // expect 3 errors: // - lookup length on Number (0 used as \`this\`) // - number !~> string (param a) // - string !~> number (param b) -// args are optional -function test(a: string, b: number): number { - return this.length; -} -test.call(\"\", \"\", 0); -test.call(0, \"\", 0); -test.call(\"\", \"\"); -test.call(\"\", \"\", \"\"); -test.call(\"\", 0, 0); -function f(args) { - test.call(\"\", args[0], args[1]); -} -f([ \"\", 0 ]); -f([ \"\", \"\" ]); -f([ 0, 0 ]); (test.apply.call(test, 0, [ 0, \"foo\" ]): number); + +// args are optional function test2(): number { return 0; } (test2.call(): number); -(test2.call(\"\"): number); -" +(test2.call(\"\"): number);" `; exports[`test function.js 1`] = ` @@ -265,76 +268,81 @@ var e = (d.bind(1): Function)(); /** * @flow */ + // Previously we represented Function as (...rest: any) => any // This means the following wouldn\'t pass, because that arrow function // can only be called with 3 arguments. -// Function is an Object -// Error -// Error -// Object is not a Function -// error, it\'s a number -// error, it\'s a number -// error, it\'s a number -// error, it\'s a string -// error, it\'s a string -// error, it\'s a string -// error, it\'s a number -// error, it\'s a number -// error, it\'s a number -// error, it\'s a string -// error, it\'s a string -// error, it\'s a string -// Non-(Function.prototype) properties on a \`Function\` type should be \`any\` -// \`Function\` types can be bound (resulting in a \`Function\` type) var a: Function = (a, b, c) => 123; + var b: Function = function(a: number, b: number): number { return a + b; }; + class C {} + var c: Function = C; + function good(x: Function, MyThing: Function): number { var o: Object = x; + // Function is an Object x.foo = 123; x[\"foo\"] = 456; x(); - ; + ; var { ...something } = x; Object.assign(x, { hi: \"there\" }); Object.keys(x); return x.bar + x[\"bar\"] + x.lala(); } + function bad(x: Function, y: Object): void { var a: number = x; + // Error var b: string = x; - var c: Function = y; + // Error + var c: Function = y; // Object is not a Function } + let tests = [ function(y: () => void, z: Function) { function x() {} (x.length: void); + // error, it\'s a number (y.length: void); + // error, it\'s a number (z.length: void); + // error, it\'s a number (x.name: void); + // error, it\'s a string (y.name: void); - (z.name: void); + // error, it\'s a string + (z.name: void); // error, it\'s a string }, function(y: () => void, z: Function) { function x() {} x.length = \"foo\"; + // error, it\'s a number y.length = \"foo\"; + // error, it\'s a number z.length = \"foo\"; + // error, it\'s a number x.name = 123; + // error, it\'s a string y.name = 123; + // error, it\'s a string z.name = 123; + // error, it\'s a string + // Non-(Function.prototype) properties on a \`Function\` type should be \`any\` (z.foo: number); (z.foo: string); } ]; + +// \`Function\` types can be bound (resulting in a \`Function\` type) var d: Function = () => 1; var e = (d.bind(1): Function)(); (e: number); -(e: string); -" +(e: string);" `; exports[`test rest.js 1`] = ` @@ -359,19 +367,22 @@ function rest_t>(...xs: T): U { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* regression tests */ -// Warn, singleton tuple types don\'t represent rest params -// Warn, arbitrary subtypes of an array type don\'t represent rest params + function rest_array(...xs: Array): T { return xs[0]; } + +// Warn, singleton tuple types don\'t represent rest params function rest_tuple(...xs: [T]): T { return xs[0]; } + function rest_any(...xs: any): any { return xs[0]; } + +// Warn, arbitrary subtypes of an array type don\'t represent rest params function rest_t>(...xs: T): U { return xs[0]; -} -" +}" `; diff --git a/tests/funrec/__snapshots__/jsfmt.spec.js.snap b/tests/funrec/__snapshots__/jsfmt.spec.js.snap index 575d958b..e001d2b0 100644 --- a/tests/funrec/__snapshots__/jsfmt.spec.js.snap +++ b/tests/funrec/__snapshots__/jsfmt.spec.js.snap @@ -13,6 +13,5 @@ function foo() { return function bound() { return bar(bound); }; -} -" +}" `; diff --git a/tests/generators/__snapshots__/jsfmt.spec.js.snap b/tests/generators/__snapshots__/jsfmt.spec.js.snap index da258ffe..55f74c5e 100644 --- a/tests/generators/__snapshots__/jsfmt.spec.js.snap +++ b/tests/generators/__snapshots__/jsfmt.spec.js.snap @@ -129,129 +129,140 @@ for (var x of examples.delegate_yield_iterable([])) { (x : string) // error: number ~> string } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// ok -// error: string ~> number -// ok -// error: number ~> string -// ok -// error: string ~> number -// error: number ~> boolean -// ok, sherlock -// error: string ~> number -// error: string ~> number -// only generators can make use of a value passed to next -// ok: Iterator has no yield value -// error: number ~> string -// error: number ~> boolean -// error: string ~> boolean -// ok, sherlock -// error: string ~> number -// error: Iterator has no next value -// error: number ~> string class GeneratorExamples { *stmt_yield(): Generator { yield 0; - yield \"\"; + // ok + yield \"\"; // error: string ~> number } + *stmt_next(): Generator { var a = yield; if (a) { - (a: number); + (a: number); // ok } + var b = yield; if (b) { - (b: string); + (b: string); // error: number ~> string } } + *stmt_return_ok(): Generator { - return 0; + return 0; // ok } + *stmt_return_err(): Generator { - return \"\"; + return \"\"; // error: string ~> number } + *infer_stmt() { var x: boolean = yield 0; + // error: number ~> boolean return \"\"; } + *widen_next() { var x = yield 0; if (typeof x === \"number\") {} else if (typeof x === \"boolean\") {} else { - (x: string); + (x: string); // ok, sherlock } } + *widen_yield() { yield 0; yield \"\"; yield true; } + *delegate_next_generator() { function* inner() { - var x: number = yield; + var x: number = yield; // error: string ~> number } yield* inner(); } + *delegate_yield_generator() { function* inner() { yield \"\"; } + yield* inner(); } + *delegate_return_generator() { function* inner() { return \"\"; } - var x: number = yield* inner(); + + var x: number = yield* inner(); // error: string ~> number } + + // only generators can make use of a value passed to next *delegate_next_iterable(xs: Array) { yield* xs; } + *delegate_yield_iterable(xs: Array) { yield* xs; } + *delegate_return_iterable(xs: Array) { - var x: void = yield* xs; + var x: void = yield* xs; // ok: Iterator has no yield value } + *generic_yield(y: Y): Generator { yield y; } + *generic_return(r: R): Generator { return r; } + *generic_next(): Generator { return yield undefined; } } + var examples = new GeneratorExamples(); + for (var x of examples.infer_stmt()) { (x: string); } +// error: number ~> string var infer_stmt_next = examples.infer_stmt().next(0).value; +// error: number ~> boolean if (typeof infer_stmt_next === \"undefined\") {} else if (typeof infer_stmt_next === \"number\") {} else { - (infer_stmt_next: boolean); + (infer_stmt_next: boolean); // error: string ~> boolean } + examples.widen_next().next(0); examples.widen_next().next(\"\"); examples.widen_next().next(true); + for (var x of examples.widen_yield()) { if (typeof x === \"number\") {} else if (typeof x === \"boolean\") {} else { - (x: string); + (x: string); // ok, sherlock } } + examples.delegate_next_generator().next(\"\"); + for (var x of examples.delegate_yield_generator()) { - (x: number); + (x: number); // error: string ~> number } + examples.delegate_next_iterable([]).next(\"\"); +// error: Iterator has no next value for (var x of examples.delegate_yield_iterable([])) { - (x: string); -} -" + (x: string); // error: number ~> string +}" `; exports[`test class_failure.js 1`] = ` @@ -277,27 +288,28 @@ if (typeof infer_stmt_next === \"undefined\") { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // generalization of failure in class.js -// error: number ~> boolean -// error: number ~> string -// error: number ~> boolean -// error: string ~> boolean + class GeneratorExamples { *infer_stmt() { var x: boolean = yield 0; + // error: number ~> boolean return \"\"; } } + var examples = new GeneratorExamples(); + for (var x of examples.infer_stmt()) { (x: string); } +// error: number ~> string var infer_stmt_next = examples.infer_stmt().next(0).value; +// error: number ~> boolean if (typeof infer_stmt_next === \"undefined\") {} else if (typeof infer_stmt_next === \"number\") {} else { - (infer_stmt_next: boolean); -} -" + (infer_stmt_next: boolean); // error: string ~> boolean +}" `; exports[`test generators.js 1`] = ` @@ -431,45 +443,32 @@ if (multiple_return_result.done) { (multiple_return_result.value: void); // error: number|string ~> void } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// ok -// error: string ~> number -// ok -// error: number ~> string -// ok -// error: string ~> number -// error: number ~> string -// error: number ~> boolean -// error: string ~> boolean -// ok, sherlock -// ok, sherlock -// error: string ~> number -// error: string ~> number -// error: string ~> number -// only generators can make use of a value passed to next -// error: Iterator has no next value -// error: number ~> string -// ok: Iterator has no yield value -// error: number|string ~> void function* stmt_yield(): Generator { yield 0; - yield \"\"; + // ok + yield \"\"; // error: string ~> number } + function* stmt_next(): Generator { var a = yield; if (a) { - (a: number); + (a: number); // ok } + var b = yield; if (b) { - (b: string); + (b: string); // error: number ~> string } } + function* stmt_return_ok(): Generator { - return 0; + return 0; // ok } + function* stmt_return_err(): Generator { - return \"\"; + return \"\"; // error: string ~> number } + function* infer_stmt() { var x: boolean = yield 0; return \"\"; @@ -477,23 +476,27 @@ function* infer_stmt() { for (var x of infer_stmt()) { (x: string); } +// error: number ~> string var infer_stmt_next = infer_stmt().next(0).value; +// error: number ~> boolean if (typeof infer_stmt_next === \"undefined\") {} else if (typeof infer_stmt_next === \"number\") {} else { - (infer_stmt_next: boolean); + (infer_stmt_next: boolean); // error: string ~> boolean } + function* widen_next() { var x = yield 0; if (typeof x === \"number\") {} else if (typeof x === \"boolean\") {} else { - (x: string); + (x: string); // ok, sherlock } } widen_next().next(0); widen_next().next(\"\"); widen_next().next(true); + function* widen_yield() { yield 0; yield \"\"; @@ -503,53 +506,66 @@ for (var x of widen_yield()) { if (typeof x === \"number\") {} else if (typeof x === \"boolean\") {} else { - (x: string); + (x: string); // ok, sherlock } } + function* delegate_next_generator() { function* inner() { - var x: number = yield; + var x: number = yield; // error: string ~> number } yield* inner(); } delegate_next_generator().next(\"\"); + function* delegate_yield_generator() { function* inner() { yield \"\"; } + yield* inner(); } for (var x of delegate_yield_generator()) { - (x: number); + (x: number); // error: string ~> number } + function* delegate_return_generator() { function* inner() { return \"\"; } - var x: number = yield* inner(); + + var x: number = yield* inner(); // error: string ~> number } + +// only generators can make use of a value passed to next function* delegate_next_iterable(xs: Array) { yield* xs; } delegate_next_iterable([]).next(\"\"); +// error: Iterator has no next value function* delegate_yield_iterable(xs: Array) { yield* xs; } for (var x of delegate_yield_iterable([])) { - (x: string); + (x: string); // error: number ~> string } + function* delegate_return_iterable(xs: Array) { - var x: void = yield* xs; + var x: void = yield* xs; // ok: Iterator has no yield value } + function* generic_yield(y: Y): Generator { yield y; } + function* generic_return(r: R): Generator { return r; } + function* generic_next(): Generator { return yield undefined; } + function* multiple_return(b) { if (b) { return 0; @@ -559,9 +575,8 @@ function* multiple_return(b) { } let multiple_return_result = multiple_return().next(); if (multiple_return_result.done) { - (multiple_return_result.value: void); -} -" + (multiple_return_result.value: void); // error: number|string ~> void +}" `; exports[`test return.js 1`] = ` @@ -587,16 +602,15 @@ if (refuse_return_result.done) { (refuse_return_result.value: string); // error: number | void ~> string } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// You can pass whatever you like to return, it doesn\'t need to be related to -// the Generator\'s return type -// error: string | number ~> void +function test1(gen: Generator) { + // You can pass whatever you like to return, it doesn\'t need to be related to + // the Generator\'s return type + var ret = gen.return(0); + (ret.value: void); // error: string | number ~> void +} + // However, a generator can \"refuse\" the return by catching an exception and // yielding or returning internally. -// error: number | void ~> string -function test1(gen: Generator) { - var ret = gen.return(0); - (ret.value: void); -} function* refuse_return() { try { yield 1; @@ -607,9 +621,8 @@ function* refuse_return() { var refuse_return_gen = refuse_return(); var refuse_return_result = refuse_return_gen.return(\"string\"); if (refuse_return_result.done) { - (refuse_return_result.value: string); -} -" + (refuse_return_result.value: string); // error: number | void ~> string +}" `; exports[`test throw.js 1`] = ` @@ -639,8 +652,6 @@ if (yield_return_value !== undefined) { (yield_return_value: string); // error: number ~> string } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// error: number ~> string -// error: number ~> string function* catch_return() { try { yield 0; @@ -648,10 +659,12 @@ function* catch_return() { return e; } } + var catch_return_value = catch_return().throw(\"\").value; if (catch_return_value !== undefined) { - (catch_return_value: string); + (catch_return_value: string); // error: number ~> string } + function* yield_return() { try { yield 0; @@ -662,9 +675,8 @@ function* yield_return() { } var yield_return_value = yield_return().throw(\"\").value; if (yield_return_value !== undefined) { - (yield_return_value: string); -} -" + (yield_return_value: string); // error: number ~> string +}" `; exports[`test variance.js 1`] = ` @@ -672,6 +684,5 @@ exports[`test variance.js 1`] = ` var g2: Generator = g1; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ declare var g1: Generator; -var g2: Generator = g1; -" +var g2: Generator = g1;" `; diff --git a/tests/generics/__snapshots__/jsfmt.spec.js.snap b/tests/generics/__snapshots__/jsfmt.spec.js.snap index d9d39010..f36dbc1d 100644 --- a/tests/generics/__snapshots__/jsfmt.spec.js.snap +++ b/tests/generics/__snapshots__/jsfmt.spec.js.snap @@ -43,13 +43,6 @@ var obj : Object = {} // error, arity 0 var fn : Function = function() { return \'foo\'; } // error, arity 0 var fn : function = function() { return \'foo\'; } // error, arity 0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -//x:X; -/*return x;*/ -/*this.x; */ -// error: too few arguments to inherited constructor -// error, arity 0 -// error, arity 0 -// error, arity 0 class C { x: X; constructor(x: X) { @@ -59,6 +52,7 @@ class C { return this.x; } } + class D { x: T; m(z: S, u: T, v): S { @@ -67,19 +61,27 @@ class D { return z; } } + var d = new D(); var o = {}; var b = d.m(true, 0, o); var s: string = d.x; var n: number = o.u; + class E extends C { + //x:X; set(x: X): X { + /*return x;*/ this.x = x; - return this.get(); + return /*this.x; */ + this.get(); } } + var e = new E(); +// error: too few arguments to inherited constructor var x: string = e.set(0); + class F {} class G extends F> {} class H extends G> { @@ -88,15 +90,18 @@ class H extends G> { this.x = x; } } + var h1 = new H(); h1.foo([ \"...\" ]); var h2: F>>> = h1; + var obj: Object = {}; +// error, arity 0 var fn: Function = function() { return \"foo\"; }; +// error, arity 0 var fn: function = function() { return \"foo\"; -}; -" +}; // error, arity 0" `; diff --git a/tests/geolocation/__snapshots__/jsfmt.spec.js.snap b/tests/geolocation/__snapshots__/jsfmt.spec.js.snap index aec7076c..a80a07ce 100644 --- a/tests/geolocation/__snapshots__/jsfmt.spec.js.snap +++ b/tests/geolocation/__snapshots__/jsfmt.spec.js.snap @@ -21,6 +21,7 @@ var id = geolocation.watchPosition( geolocation.clearWatch(id); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + var geolocation = new Geolocation(); var id = geolocation.watchPosition( position => { @@ -38,6 +39,5 @@ var id = geolocation.watchPosition( } } ); -geolocation.clearWatch(id); -" +geolocation.clearWatch(id);" `; diff --git a/tests/get-def/__snapshots__/jsfmt.spec.js.snap b/tests/get-def/__snapshots__/jsfmt.spec.js.snap index 77a9b62c..012099a6 100644 --- a/tests/get-def/__snapshots__/jsfmt.spec.js.snap +++ b/tests/get-def/__snapshots__/jsfmt.spec.js.snap @@ -16,16 +16,20 @@ add(lib.iTakeAString(42), 7); lib.bar(); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// t123456 -// D123456 + var lib = require(\"./library\"); + function add(a: number, b: number): number { return a + b; } + var re = /^keynote (talk){2} (lightning){3,5} (talk){2} closing partytime!!!/; + +// t123456 add(lib.iTakeAString(42), 7); -lib.bar(); -" + +// D123456 +lib.bar();" `; exports[`test imports.js 1`] = ` @@ -42,14 +46,16 @@ import * as things from \"./helpers/exports_named.js\"; things; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + import thing from \"./helpers/exports_default.js\"; thing; + import {foo, bar as baz} from \"./helpers/exports_named.js\"; foo; baz; + import * as things from \"./helpers/exports_named.js\"; -things; -" +things;" `; exports[`test library.js 1`] = ` @@ -68,6 +74,7 @@ module.exports = { }; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + module.exports = { iTakeAString: function(name: string): number { return 42; @@ -75,6 +82,5 @@ module.exports = { bar: function(): number { return 42; } -}; -" +};" `; diff --git a/tests/get-def/helpers/__snapshots__/jsfmt.spec.js.snap b/tests/get-def/helpers/__snapshots__/jsfmt.spec.js.snap index fa3b3479..c3659383 100644 --- a/tests/get-def/helpers/__snapshots__/jsfmt.spec.js.snap +++ b/tests/get-def/helpers/__snapshots__/jsfmt.spec.js.snap @@ -6,9 +6,10 @@ const x = \"foo\"; export default x; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + const x = \"foo\"; -export default x -" + +export default x" `; exports[`test exports_named.js 1`] = ` @@ -18,7 +19,7 @@ export const foo = \"foo\"; export const bar = \"bar\"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + export const foo = \"foo\"; -export const bar = \"bar\"; -" +export const bar = \"bar\";" `; diff --git a/tests/get-def2/__snapshots__/jsfmt.spec.js.snap b/tests/get-def2/__snapshots__/jsfmt.spec.js.snap index 6f0c1417..c8dd4bb6 100644 --- a/tests/get-def2/__snapshots__/jsfmt.spec.js.snap +++ b/tests/get-def2/__snapshots__/jsfmt.spec.js.snap @@ -5,9 +5,9 @@ var ParentFoo = {foo: \'bar\'}; module.exports = {ParentFoo}; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + var ParentFoo = { foo: \"bar\" }; -module.exports = { ParentFoo }; -" +module.exports = { ParentFoo };" `; exports[`test main.js 1`] = ` @@ -36,26 +36,28 @@ foo; import type {Foo} from \'./types\'; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// Hops through destructuring -// Points to lval in line above this -// Follows assignment on simple/\"non-destructuring\" patterns -// Points to LHS of line above this -// Follows assignment with declaration -// Points to LHS of line above this -// Follows non-destructured property access of \`require(\'Parent\')\` + var Parent = require(\"./Parent\"); + +// Hops through destructuring let ParentFoo; ({ ParentFoo } = Parent); ParentFoo; +// Points to lval in line above this +// Follows assignment on simple/\"non-destructuring\" patterns let ParentFoo2; ParentFoo2 = Parent; ParentFoo2; +// Points to LHS of line above this +// Follows assignment with declaration let ParentFoo3 = Parent; ParentFoo3; +// Points to LHS of line above this +// Follows non-destructured property access of \`require(\'Parent\')\` let foo = require(\"./Parent\").ParentFoo.foo; foo; -import type {Foo} from \"./types\"; -" + +import type {Foo} from \"./types\";" `; exports[`test override.js 1`] = ` @@ -72,9 +74,11 @@ class D extends C { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + class C { override() {} } + class D extends C { foo() { this.override(); @@ -83,8 +87,7 @@ class D extends C { this.override; } override() {} -} -" +}" `; exports[`test react.js 1`] = ` @@ -101,13 +104,16 @@ let msg = \"hello\"; (
); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ var React = require(\"react\"); + class C extends React.Component { props: { x: string }; } + let msg = \"hello\"; -; -
; -" + +; + +
;" `; exports[`test types.js 1`] = ` @@ -116,6 +122,6 @@ exports[`test types.js 1`] = ` export type Foo = {}; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -export type Foo = {}; -" + +export type Foo = {};" `; diff --git a/tests/get-def2/lib/__snapshots__/jsfmt.spec.js.snap b/tests/get-def2/lib/__snapshots__/jsfmt.spec.js.snap index fc8b5bab..5f9724f3 100644 --- a/tests/get-def2/lib/__snapshots__/jsfmt.spec.js.snap +++ b/tests/get-def2/lib/__snapshots__/jsfmt.spec.js.snap @@ -7,12 +7,12 @@ type $JSXIntrinsics = { span: $JSXIntrinsic<{id: string, class: string}>, }; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// fake import declare var $React: $Exports<\"react\">; +// fake import type $JSXIntrinsic = Class<$React.Component>; + type $JSXIntrinsics = { div: $JSXIntrinsic<{ id: string }>, span: $JSXIntrinsic<{ id: string, class: string }> -}; -" +};" `; diff --git a/tests/get-imports-and-importers/__snapshots__/jsfmt.spec.js.snap b/tests/get-imports-and-importers/__snapshots__/jsfmt.spec.js.snap index 2a1fec9b..4ce0980e 100644 --- a/tests/get-imports-and-importers/__snapshots__/jsfmt.spec.js.snap +++ b/tests/get-imports-and-importers/__snapshots__/jsfmt.spec.js.snap @@ -1,8 +1,6 @@ exports[`test a.js 1`] = ` "// @flow ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// @flow - " `; @@ -17,8 +15,7 @@ require(\'./a\'); * @flow * @providesModule b */ -require(\"./a\"); -" +require(\"./a\");" `; exports[`test c.js 1`] = ` @@ -28,6 +25,5 @@ require(\'b\'); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow require(\"./a.js\"); -require(\"b\"); -" +require(\"b\");" `; diff --git a/tests/getters_and_setters_disabled/__snapshots__/jsfmt.spec.js.snap b/tests/getters_and_setters_disabled/__snapshots__/jsfmt.spec.js.snap index 1220ec52..a3957a1c 100644 --- a/tests/getters_and_setters_disabled/__snapshots__/jsfmt.spec.js.snap +++ b/tests/getters_and_setters_disabled/__snapshots__/jsfmt.spec.js.snap @@ -12,6 +12,7 @@ var f = { /** * @flow */ + var f = { get a() { return 4; @@ -20,6 +21,5 @@ var f = { this.c = b; }, c: 10 -}; -" +};" `; diff --git a/tests/getters_and_setters_enabled/__snapshots__/jsfmt.spec.js.snap b/tests/getters_and_setters_enabled/__snapshots__/jsfmt.spec.js.snap index a2aad7e4..941d350d 100644 --- a/tests/getters_and_setters_enabled/__snapshots__/jsfmt.spec.js.snap +++ b/tests/getters_and_setters_enabled/__snapshots__/jsfmt.spec.js.snap @@ -58,20 +58,9 @@ foo.propOverriddenWithSetter = 123; // Error number ~> string /** * @flow */ -// The getter and setter need not have the same type - no error -// The getter and setter need not have the same type - no error -// doesn\'t match getter (OK) -// Test getting properties with getters -// Error number ~> string -// Error number ~> string -// Test setting properties with getters -// TODO: Why does no annotation mean no error? -// Error string ~> number -// Error string ~> number -// Error ?number ~> number -// Error string ~> number -// Error number ~> string + var z: number = 123; + class Foo { get goodGetterNoAnnotation() { return 4; @@ -79,48 +68,69 @@ class Foo { get goodGetterWithAnnotation(): number { return 4; } + set goodSetterNoAnnotation(x) { z = x; } set goodSetterWithAnnotation(x: number) { z = x; } + get propWithMatchingGetterAndSetter(): number { return 4; } set propWithMatchingGetterAndSetter(x: number) {} + + // The getter and setter need not have the same type - no error get propWithSubtypingGetterAndSetter(): ?number { return 4; } set propWithSubtypingGetterAndSetter(x: number) {} + + // The getter and setter need not have the same type - no error set propWithSubtypingGetterAndSetterReordered(x: number) {} get propWithSubtypingGetterAndSetterReordered(): ?number { return 4; } + get propWithMismatchingGetterAndSetter(): number { return 4; } set propWithMismatchingGetterAndSetter(x: string) {} + // doesn\'t match getter (OK) propOverriddenWithGetter: number; get propOverriddenWithGetter() { return \"hello\"; } + propOverriddenWithSetter: number; set propOverriddenWithSetter(x: string) {} } + var foo = new Foo(); + +// Test getting properties with getters var testGetterNoError1: number = foo.goodGetterNoAnnotation; var testGetterNoError2: number = foo.goodGetterWithAnnotation; + var testGetterWithError1: string = foo.goodGetterNoAnnotation; +// Error number ~> string var testGetterWithError2: string = foo.goodGetterWithAnnotation; +// Error number ~> string +// Test setting properties with getters foo.goodSetterNoAnnotation = 123; foo.goodSetterWithAnnotation = 123; + +// TODO: Why does no annotation mean no error? foo.goodSetterNoAnnotation = \"hello\"; +// Error string ~> number foo.goodSetterWithAnnotation = \"hello\"; +// Error string ~> number var testSubtypingGetterAndSetter: number = foo.propWithSubtypingGetterAndSetter; +// Error ?number ~> number var testPropOverridenWithGetter: number = foo.propOverriddenWithGetter; -foo.propOverriddenWithSetter = 123; -" +// Error string ~> number +foo.propOverriddenWithSetter = 123; // Error number ~> string" `; exports[`test object.js 1`] = ` @@ -188,26 +198,13 @@ var testExampleOrOrderOfGetterAndSetterReordered: number = /** * @flow */ -// The getter and setter need not have the same type -// OK -// OK -// Test getting properties with getters -// Error number ~> string -// Error number ~> string -// Test setting properties with getters -// Error string ~> number -// Error string ~> number -// Error ?number ~> number -// When building this feature, it was tempting to flow the setter into the -// getter and then use either the getter or setter as the type of the property. -// This example shows the danger of using the getter\'s type -// Error C ~> B -// And this example shows the danger of using the setter\'s type. -// Error A ~> B + var z: number = 123; + class A {} class B extends A {} class C extends A {} + var obj = { get goodGetterNoAnnotation() { return 4; @@ -225,11 +222,14 @@ var obj = { return 4; }, set propWithMatchingGetterAndSetter(x: number) {}, + // The getter and setter need not have the same type get propWithSubtypingGetterAndSetter(): ?number { return 4; }, + // OK set propWithSubtypingGetterAndSetter(x: number) {}, set propWithSubtypingGetterAndSetterReordered(x: number) {}, + // OK get propWithSubtypingGetterAndSetterReordered(): ?number { return 4; }, @@ -242,18 +242,32 @@ var obj = { return new A(); } }; + +// Test getting properties with getters var testGetterNoError1: number = obj.goodGetterNoAnnotation; var testGetterNoError2: number = obj.goodGetterWithAnnotation; + var testGetterWithError1: string = obj.goodGetterNoAnnotation; +// Error number ~> string var testGetterWithError2: string = obj.goodGetterWithAnnotation; +// Error number ~> string +// Test setting properties with getters obj.goodSetterNoAnnotation = 123; obj.goodSetterWithAnnotation = 123; + obj.goodSetterNoAnnotation = \"hello\"; +// Error string ~> number obj.goodSetterWithAnnotation = \"hello\"; +// Error string ~> number var testSubtypingGetterAndSetter: number = obj.propWithSubtypingGetterAndSetter; +// Error ?number ~> number +// When building this feature, it was tempting to flow the setter into the +// getter and then use either the getter or setter as the type of the property. +// This example shows the danger of using the getter\'s type obj.exampleOfOrderOfGetterAndSetter = new C(); -var testExampleOrOrderOfGetterAndSetterReordered: number = obj.exampleOfOrderOfGetterAndSetterReordered; -" +// Error C ~> B +// And this example shows the danger of using the setter\'s type. +var testExampleOrOrderOfGetterAndSetterReordered: number = obj.exampleOfOrderOfGetterAndSetterReordered; // Error A ~> B" `; exports[`test react.js 1`] = ` @@ -272,6 +286,7 @@ React.createClass({ /** * @flow */ + React.createClass({ propTypes: { get a() { @@ -282,8 +297,7 @@ React.createClass({ }, c: 10 } -}); -" +});" `; exports[`test variance.js 1`] = ` @@ -359,22 +373,15 @@ class Base { }); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// error: getter incompatible with read/write property -// error: setter incompatible with read/write property -// ok: get/set co/contra with read/write property, resp. -// error: setter incompatible with read-only property -// ok: getter covariant with read-only property -// error: getter incompatible with write-only property -// ok: setter contravariant with write-only property -// ok: read/write covariant with getter -// ok: read/write contravariant with setter -// ok: read/write invariant with get/set + class A {} class B extends A {} class C extends B {} + declare var a: A; declare var b: B; declare var c: C; + class Base { x: B; +pos: B; @@ -382,54 +389,76 @@ class Base { get get(): B { return this.x; } + set set(value: B): void { this.x = value; } + get getset(): B { return this.x; } + set getset(value: B): void { this.x = value; } } + (class extends Base { + // error: getter incompatible with read/write property get x(): B { return b; } }); + (class extends Base { + // error: setter incompatible with read/write property set x(value: B): void {} }); + (class extends Base { + // ok: get/set co/contra with read/write property, resp. get x(): C { return c; } set x(value: A): void {} }); + (class extends Base { + // error: setter incompatible with read-only property set pos(value: B): void {} }); + (class extends Base { + // ok: getter covariant with read-only property get pos(): C { return c; } }); + (class extends Base { + // error: getter incompatible with write-only property get neg(): B { return b; } }); + (class extends Base { + // ok: setter contravariant with write-only property set neg(value: A): void {} }); + (class extends Base { + // ok: read/write covariant with getter get: C; }); + (class extends Base { + // ok: read/write contravariant with setter set: A; }); + (class extends Base { + // ok: read/write invariant with get/set getset: B; -}); -" +});" `; diff --git a/tests/haste_cycle/__snapshots__/jsfmt.spec.js.snap b/tests/haste_cycle/__snapshots__/jsfmt.spec.js.snap index de063e9d..45f32885 100644 --- a/tests/haste_cycle/__snapshots__/jsfmt.spec.js.snap +++ b/tests/haste_cycle/__snapshots__/jsfmt.spec.js.snap @@ -4,6 +4,6 @@ exports[`test API.js 1`] = ` var OpenGraphObject = require(\'./models/OpenGraphObject.js\'); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -var OpenGraphObject = require(\"./models/OpenGraphObject.js\"); -" + +var OpenGraphObject = require(\"./models/OpenGraphObject.js\");" `; diff --git a/tests/haste_cycle/models/__snapshots__/jsfmt.spec.js.snap b/tests/haste_cycle/models/__snapshots__/jsfmt.spec.js.snap index b9d5ecea..7fbb4cfa 100644 --- a/tests/haste_cycle/models/__snapshots__/jsfmt.spec.js.snap +++ b/tests/haste_cycle/models/__snapshots__/jsfmt.spec.js.snap @@ -4,8 +4,8 @@ exports[`test OpenGraphAction.js 1`] = ` var OpenGraphValueContainer = require(\'./OpenGraphValueContainer.js\'); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -var OpenGraphValueContainer = require(\"./OpenGraphValueContainer.js\"); -" + +var OpenGraphValueContainer = require(\"./OpenGraphValueContainer.js\");" `; exports[`test OpenGraphObject.js 1`] = ` @@ -14,8 +14,8 @@ exports[`test OpenGraphObject.js 1`] = ` var OpenGraphValueContainer = require(\'./OpenGraphValueContainer.js\'); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -var OpenGraphValueContainer = require(\"./OpenGraphValueContainer.js\"); -" + +var OpenGraphValueContainer = require(\"./OpenGraphValueContainer.js\");" `; exports[`test OpenGraphValueContainer.js 1`] = ` @@ -24,6 +24,6 @@ exports[`test OpenGraphValueContainer.js 1`] = ` var OpenGraphObject = require(\'./OpenGraphObject.js\'); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -var OpenGraphObject = require(\"./OpenGraphObject.js\"); -" + +var OpenGraphObject = require(\"./OpenGraphObject.js\");" `; diff --git a/tests/haste_dupe/__snapshots__/jsfmt.spec.js.snap b/tests/haste_dupe/__snapshots__/jsfmt.spec.js.snap index daebb535..8dd7c603 100644 --- a/tests/haste_dupe/__snapshots__/jsfmt.spec.js.snap +++ b/tests/haste_dupe/__snapshots__/jsfmt.spec.js.snap @@ -11,8 +11,7 @@ module.exports = \"dupe1\"; * @providesModule Dupe * @flow */ -module.exports = \"dupe1\"; -" +module.exports = \"dupe1\";" `; exports[`test dupe2.js 1`] = ` @@ -28,8 +27,7 @@ module.exports = \"dupe2\"; * @providesModule Dupe * @flow */ -module.exports = \"dupe2\"; -" +module.exports = \"dupe2\";" `; exports[`test requires_dupe.js 1`] = ` @@ -43,6 +41,5 @@ var dupe = require(\'Dupe\'); * depends on doubly-provided module * @flow */ -var dupe = require(\"Dupe\"); -" +var dupe = require(\"Dupe\");" `; diff --git a/tests/ignore_package/__snapshots__/jsfmt.spec.js.snap b/tests/ignore_package/__snapshots__/jsfmt.spec.js.snap index de3a76b7..05f17840 100644 --- a/tests/ignore_package/__snapshots__/jsfmt.spec.js.snap +++ b/tests/ignore_package/__snapshots__/jsfmt.spec.js.snap @@ -22,9 +22,10 @@ module.exports = foo; \'Required module not found\'. */ var _ = require(\"underscore\"); + function foo(): string { return _.foo(); } -module.exports = foo; -" + +module.exports = foo;" `; diff --git a/tests/immutable_methods/__snapshots__/jsfmt.spec.js.snap b/tests/immutable_methods/__snapshots__/jsfmt.spec.js.snap index c2bc11be..c1b296bb 100644 --- a/tests/immutable_methods/__snapshots__/jsfmt.spec.js.snap +++ b/tests/immutable_methods/__snapshots__/jsfmt.spec.js.snap @@ -23,6 +23,5 @@ class C extends A {} var a: A = new B(); a.foo = function(): C { return new C(); -}; -" +};" `; diff --git a/tests/import_type/__snapshots__/jsfmt.spec.js.snap b/tests/import_type/__snapshots__/jsfmt.spec.js.snap index cd09a084..8b187734 100644 --- a/tests/import_type/__snapshots__/jsfmt.spec.js.snap +++ b/tests/import_type/__snapshots__/jsfmt.spec.js.snap @@ -15,6 +15,7 @@ module.exports = ClassFoo3; /** * @flow */ + class ClassFoo3 { givesANum(): number { return 42; @@ -23,8 +24,8 @@ class ClassFoo3 { return new ClassFoo3(); } } -module.exports = ClassFoo3; -" + +module.exports = ClassFoo3;" `; exports[`test ExportCJSNamed_Class.js 1`] = ` @@ -54,23 +55,27 @@ exports.foo5Inst = new ClassFoo5(); /** * @flow */ + class ClassFoo4 { returnsANumber(): number { return 42; } } + class ClassFoo5 {} + function givesAFoo4(): ClassFoo4 { return new ClassFoo4(); } + function givesAFoo5(): ClassFoo5 { return new ClassFoo5(); } + exports.ClassFoo4 = ClassFoo4; exports.ClassFoo5 = ClassFoo5; exports.foo4Inst = new ClassFoo4(); -exports.foo5Inst = new ClassFoo5(); -" +exports.foo5Inst = new ClassFoo5();" `; exports[`test ExportDefault_Class.js 1`] = ` @@ -88,14 +93,15 @@ export var foo1Inst = new ClassFoo1(); /** * @flow */ + class ClassFoo1 { returnsANumber(): number { return 42; } } + export default ClassFoo1 -export var foo1Inst = new ClassFoo1(); -" +export var foo1Inst = new ClassFoo1();" `; exports[`test ExportNamed_Alias.js 1`] = ` @@ -115,6 +121,7 @@ export function givesAFoo3Obj(): AliasFoo3 { /** * @flow */ + export type AliasFoo3 = { givesANum(): number }; export function givesAFoo3Obj(): AliasFoo3 { return { @@ -141,14 +148,15 @@ export var foo2Inst = new ClassFoo2(); /** * @flow */ + class ClassFoo2 { returnsANumber(): number { return 42; } } + export {ClassFoo2} -export var foo2Inst = new ClassFoo2(); -" +export var foo2Inst = new ClassFoo2();" `; exports[`test ExportsANumber.js 1`] = ` @@ -157,8 +165,8 @@ exports[`test ExportsANumber.js 1`] = ` export var numValue = 42; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @ flow */ -export var numValue = 42; -" + +export var numValue = 42;" `; exports[`test import_type.js 1`] = ` @@ -248,31 +256,61 @@ function foo() { /** * @flow */ + ///////////////////////////////////////////////// // == Importing Class Type (Default Export) == // ///////////////////////////////////////////////// + +import type ClassFoo1 from \"./ExportDefault_Class\"; +import {foo1Inst} from \"./ExportDefault_Class\"; + +var a1: ClassFoo1 = foo1Inst; +var a2: number = foo1Inst; // Error: ClassFoo1 ~> number +new ClassFoo1(); // Error: ClassFoo1 is not a value-identifier /////////////////////////////////////////////// // == Importing Class Type (Named Export) == // /////////////////////////////////////////////// +import type {ClassFoo2} from \"./ExportNamed_Class\"; +import {foo2Inst} from \"./ExportNamed_Class\"; + +var b1: ClassFoo2 = foo2Inst; +var b2: number = foo2Inst; // Error: ClassFoo2 ~> number +new ClassFoo2(); // Error: ClassFoo2 is not a value-identifier ///////////////////////////////////////////////////// // == Importing Class Type (CJS Default Export) == // ///////////////////////////////////////////////////// +import type ClassFoo3T from \"./ExportCJSDefault_Class\"; +import ClassFoo3 from \"./ExportCJSDefault_Class\"; +var c1: ClassFoo3T = new ClassFoo3(); +new ClassFoo3T(); // Error: ClassFoo3 is not a value-identifier /////////////////////////////////////////////////// // == Importing Class Type (CJS Named Export) == // /////////////////////////////////////////////////// +import type {ClassFoo4, ClassFoo5} from \"./ExportCJSNamed_Class\"; +import {foo4Inst, foo5Inst} from \"./ExportCJSNamed_Class\"; + +var d1: ClassFoo4 = foo4Inst; +var d2: number = foo4Inst; // Error: ClassFoo4 ~> number +new ClassFoo4(); // Error: ClassFoo4 is not a value-identifier // TODO: this errors correctly, but the message is just \'can\'t resolve name\' +var d3: typeof ClassFoo5 = foo5Inst; // Error: Can\'t typeof a type alias //////////////////////////////////////////// // == Import Type Alias (Named Export) == // //////////////////////////////////////////// +import type {AliasFoo3} from \"./ExportNamed_Alias\"; +import {givesAFoo3Obj} from \"./ExportNamed_Alias\"; +var e1: AliasFoo3 = givesAFoo3Obj(); +var e2: number = givesAFoo3Obj(); // Error: AliasFoo3 ~> number +var e3: typeof AliasFoo3 = givesAFoo3Obj(); // Error: Can\'t typeof a type alias ////////////////////////////////////////////// // == Import Type Alias (Default Export) == // @@ -283,44 +321,17 @@ function foo() { /////////////////////////////////////////////////////// // == Import Type With Non-Alias Compatible Value == // /////////////////////////////////////////////////////// +import type {numValue} from \"./ExportsANumber\"; // Error: Cannot import-type a number value //////////////////////////////////////////////////////////////////////// // == Regression Test: https://github.com/facebook/flow/issues/359 == // // Ensure that type bindings stay type bindings across function body // // env contexts. // //////////////////////////////////////////////////////////////////////// -// Error: Not a value binding -import type ClassFoo1 from \"./ExportDefault_Class\"; -import {foo1Inst} from \"./ExportDefault_Class\"; -var a1: ClassFoo1 = foo1Inst; -var a2: number = foo1Inst; -new ClassFoo1(); -import type {ClassFoo2} from \"./ExportNamed_Class\"; -import {foo2Inst} from \"./ExportNamed_Class\"; -var b1: ClassFoo2 = foo2Inst; -var b2: number = foo2Inst; -new ClassFoo2(); -import type ClassFoo3T from \"./ExportCJSDefault_Class\"; -import ClassFoo3 from \"./ExportCJSDefault_Class\"; -var c1: ClassFoo3T = new ClassFoo3(); -new ClassFoo3T(); -import type {ClassFoo4, ClassFoo5} from \"./ExportCJSNamed_Class\"; -import {foo4Inst, foo5Inst} from \"./ExportCJSNamed_Class\"; -var d1: ClassFoo4 = foo4Inst; -var d2: number = foo4Inst; -new ClassFoo4(); -var d3: typeof ClassFoo5 = foo5Inst; -import type {AliasFoo3} from \"./ExportNamed_Alias\"; -import {givesAFoo3Obj} from \"./ExportNamed_Alias\"; -var e1: AliasFoo3 = givesAFoo3Obj(); -var e2: number = givesAFoo3Obj(); -var e3: typeof AliasFoo3 = givesAFoo3Obj(); -import type {numValue} from \"./ExportsANumber\"; import type ClassFoo6 from \"./issue-359\"; function foo() { - ClassFoo6; -} -" + ClassFoo6; // Error: Not a value binding +}" `; exports[`test issue-359.js 1`] = ` @@ -331,7 +342,8 @@ class ClassFoo6 {}; export default ClassFoo6; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + class ClassFoo6 {} -export default ClassFoo6 -" + +export default ClassFoo6" `; diff --git a/tests/import_typeof/__snapshots__/jsfmt.spec.js.snap b/tests/import_typeof/__snapshots__/jsfmt.spec.js.snap index f38d2cdf..a4f83afc 100644 --- a/tests/import_typeof/__snapshots__/jsfmt.spec.js.snap +++ b/tests/import_typeof/__snapshots__/jsfmt.spec.js.snap @@ -15,6 +15,7 @@ module.exports = ClassFoo3; /** * @flow */ + class ClassFoo3 { givesANum(): number { return 42; @@ -23,8 +24,8 @@ class ClassFoo3 { return new ClassFoo3(); } } -module.exports = ClassFoo3; -" + +module.exports = ClassFoo3;" `; exports[`test ExportCJSDefault_Number.js 1`] = ` @@ -33,8 +34,8 @@ exports[`test ExportCJSDefault_Number.js 1`] = ` module.exports = 42; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -module.exports = 42; -" + +module.exports = 42;" `; exports[`test ExportCJSNamed_Class.js 1`] = ` @@ -49,9 +50,10 @@ exports.ClassFoo4 = ClassFoo4; /** * @flow */ + class ClassFoo4 {} -exports.ClassFoo4 = ClassFoo4; -" + +exports.ClassFoo4 = ClassFoo4;" `; exports[`test ExportCJSNamed_Number.js 1`] = ` @@ -60,8 +62,8 @@ exports[`test ExportCJSNamed_Number.js 1`] = ` exports.num = 42; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -exports.num = 42; -" + +exports.num = 42;" `; exports[`test ExportDefault_Class.js 1`] = ` @@ -78,13 +80,14 @@ export default ClassFoo1; /** * @flow */ + class ClassFoo1 { returnsANumber(): number { return 42; } } -export default ClassFoo1 -" + +export default ClassFoo1" `; exports[`test ExportDefault_Number.js 1`] = ` @@ -93,8 +96,8 @@ exports[`test ExportDefault_Number.js 1`] = ` export default 42; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -export default 42 -" + +export default 42" `; exports[`test ExportNamed_Alias.js 1`] = ` @@ -114,6 +117,7 @@ export function givesAFoo3Obj(): AliasFoo3 { /** * @flow */ + export type AliasFoo3 = { givesANum(): number }; export function givesAFoo3Obj(): AliasFoo3 { return { @@ -139,13 +143,14 @@ export {ClassFoo2}; /** * @flow */ + class ClassFoo2 { returnsANumber(): number { return 42; } } -export {ClassFoo2} -" + +export {ClassFoo2}" `; exports[`test ExportNamed_Multi.js 1`] = ` @@ -155,9 +160,9 @@ export var num = 42; export var str = \'asdf\'; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + export var num = 42; -export var str = \"asdf\"; -" +export var str = \"asdf\";" `; exports[`test ExportNamed_Number.js 1`] = ` @@ -166,8 +171,8 @@ exports[`test ExportNamed_Number.js 1`] = ` export var num = 42; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -export var num = 42; -" + +export var num = 42;" `; exports[`test import_typeof.js 1`] = ` @@ -278,27 +283,52 @@ var j2: ModuleNSObjT = {num: 42, str: 42}; // Error: number ~> string /** * @flow */ + /////////////////////////////////////////////////// // == Importing Class Typeof (Default Export) == // /////////////////////////////////////////////////// + +import typeof ClassFoo1T from \"./ExportDefault_Class\"; +import ClassFoo1 from \"./ExportDefault_Class\"; + +var a1: ClassFoo1T = ClassFoo1; +var a2: ClassFoo1T = new ClassFoo1(); // Error: ClassFoo1 (inst) ~> ClassFoo1 (class) +new ClassFoo1T(); // Error: ClassFoo1T is not bound to a value ///////////////////////////////////////////////// // == Importing Class Typeof (Named Export) == // ///////////////////////////////////////////////// +import typeof {ClassFoo2 as ClassFoo2T} from \"./ExportNamed_Class\"; +import {ClassFoo2} from \"./ExportNamed_Class\"; + +var b1: ClassFoo2T = ClassFoo2; +var b2: ClassFoo2T = new ClassFoo2(); // Error: ClassFoo2 (inst) ~> ClassFoo2 (class) +new ClassFoo2T(); // Error: ClassFoo2T is not bound to a value /////////////////////////////////////////////////////// // == Importing Class Typeof (CJS Default Export) == // /////////////////////////////////////////////////////// +import typeof ClassFoo3T from \"./ExportCJSDefault_Class\"; +import ClassFoo3 from \"./ExportCJSDefault_Class\"; + +var c1: ClassFoo3T = ClassFoo3; +var c2: ClassFoo3T = new ClassFoo3(); // Error: ClassFoo3 (inst) ~> ClassFoo3 (class) ///////////////////////////////////////////////////// // == Importing Class Typeof (CJS Named Export) == // ///////////////////////////////////////////////////// +import typeof {ClassFoo4 as ClassFoo4T} from \"./ExportCJSNamed_Class\"; +import {ClassFoo4} from \"./ExportCJSNamed_Class\"; + +var d1: ClassFoo4T = ClassFoo4; +var d2: ClassFoo4T = new ClassFoo4(); // Error: ClassFoo4 (inst) ~> ClassFoo4 (class) ////////////////////////////////////////////// // == Import Typeof Alias (Named Export) == // ////////////////////////////////////////////// +import typeof {AliasFoo3} from \"./ExportNamed_Alias\"; // Error: Can\'t \`import typeof\` type aliases! //////////////////////////////////////////////// // == Import Typeof Alias (Default Export) == // @@ -309,56 +339,39 @@ var j2: ModuleNSObjT = {num: 42, str: 42}; // Error: number ~> string /////////////////////////////////////////////////////////////// // == Import Typeof With Non-Class Value (Default Export) == // /////////////////////////////////////////////////////////////// +import typeof num_default from \"./ExportDefault_Number\"; + +var f1: num_default = 42; +var f2: num_default = \"asdf\"; // Error: string ~> number ///////////////////////////////////////////////////////////// // == Import Typeof With Non-Class Value (Named Export) == // ///////////////////////////////////////////////////////////// +import typeof {num as num_named} from \"./ExportNamed_Number\"; + +var g1: num_named = 42; +var g2: num_named = \"asdf\"; // Error: string ~> number /////////////////////////////////////////////////////////////////// // == Import Typeof With Non-Class Value (CJS Default Export) == // /////////////////////////////////////////////////////////////////// +import typeof num_cjs_default from \"./ExportCJSDefault_Number\"; + +var h1: num_cjs_default = 42; +var h2: num_cjs_default = \"asdf\"; // Error: string ~> number ///////////////////////////////////////////////////////////////// // == Import Typeof With Non-Class Value (CJS Named Export) == // ///////////////////////////////////////////////////////////////// +import typeof {num as num_cjs_named} from \"./ExportCJSNamed_Number\"; + +var i1: num_cjs_named = 42; +var i2: num_cjs_named = \"asdf\"; // Error: string ~> number /////////////////////////////////////////////// // == Import Typeof ModuleNamespaceObject == // /////////////////////////////////////////////// -// Error: number ~> string -import typeof ClassFoo1T from \"./ExportDefault_Class\"; -import ClassFoo1 from \"./ExportDefault_Class\"; -var a1: ClassFoo1T = ClassFoo1; -var a2: ClassFoo1T = new ClassFoo1(); -new ClassFoo1T(); -import typeof {ClassFoo2 as ClassFoo2T} from \"./ExportNamed_Class\"; -import {ClassFoo2} from \"./ExportNamed_Class\"; -var b1: ClassFoo2T = ClassFoo2; -var b2: ClassFoo2T = new ClassFoo2(); -new ClassFoo2T(); -import typeof ClassFoo3T from \"./ExportCJSDefault_Class\"; -import ClassFoo3 from \"./ExportCJSDefault_Class\"; -var c1: ClassFoo3T = ClassFoo3; -var c2: ClassFoo3T = new ClassFoo3(); -import typeof {ClassFoo4 as ClassFoo4T} from \"./ExportCJSNamed_Class\"; -import {ClassFoo4} from \"./ExportCJSNamed_Class\"; -var d1: ClassFoo4T = ClassFoo4; -var d2: ClassFoo4T = new ClassFoo4(); -import typeof {AliasFoo3} from \"./ExportNamed_Alias\"; -import typeof num_default from \"./ExportDefault_Number\"; -var f1: num_default = 42; -var f2: num_default = \"asdf\"; -import typeof {num as num_named} from \"./ExportNamed_Number\"; -var g1: num_named = 42; -var g2: num_named = \"asdf\"; -import typeof num_cjs_default from \"./ExportCJSDefault_Number\"; -var h1: num_cjs_default = 42; -var h2: num_cjs_default = \"asdf\"; -import typeof {num as num_cjs_named} from \"./ExportCJSNamed_Number\"; -var i1: num_cjs_named = 42; -var i2: num_cjs_named = \"asdf\"; import typeof * as ModuleNSObjT from \"./ExportNamed_Multi\"; var j1: ModuleNSObjT = { num: 42, str: \"asdf\" }; -var j2: ModuleNSObjT = { num: 42, str: 42 }; -" +var j2: ModuleNSObjT = { num: 42, str: 42 }; // Error: number ~> string" `; diff --git a/tests/include/foo/batman/__snapshots__/jsfmt.spec.js.snap b/tests/include/foo/batman/__snapshots__/jsfmt.spec.js.snap index 4f3304d6..402932b1 100644 --- a/tests/include/foo/batman/__snapshots__/jsfmt.spec.js.snap +++ b/tests/include/foo/batman/__snapshots__/jsfmt.spec.js.snap @@ -4,7 +4,6 @@ exports[`test baz.js 1`] = ` var x: number = \"not a number\" // Error string ~> number ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// Error string ~> number -var x: number = \"not a number\"; -" + +var x: number = \"not a number\"; // Error string ~> number" `; diff --git a/tests/include/included/__snapshots__/jsfmt.spec.js.snap b/tests/include/included/__snapshots__/jsfmt.spec.js.snap index aa25c1d3..d14ef750 100644 --- a/tests/include/included/__snapshots__/jsfmt.spec.js.snap +++ b/tests/include/included/__snapshots__/jsfmt.spec.js.snap @@ -1,6 +1,5 @@ exports[`test test.js 1`] = ` "(123: string); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -(123: string); -" +(123: string);" `; diff --git a/tests/incremental/__snapshots__/jsfmt.spec.js.snap b/tests/incremental/__snapshots__/jsfmt.spec.js.snap index 096c7563..02158f56 100644 --- a/tests/incremental/__snapshots__/jsfmt.spec.js.snap +++ b/tests/incremental/__snapshots__/jsfmt.spec.js.snap @@ -1,8 +1,6 @@ exports[`test a.js 1`] = ` "/* @providesModule IncrModuleA */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -/* @providesModule IncrModuleA */ - " `; @@ -16,8 +14,8 @@ var A = require(\'IncrModuleA\'); /* @providesModule IncrModuleB @flow */ -var A = require(\"IncrModuleA\"); -" + +var A = require(\"IncrModuleA\");" `; exports[`test dup_a.js 1`] = ` @@ -26,6 +24,6 @@ exports[`test dup_a.js 1`] = ` var x:string = 0; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @providesModule IncrModuleA */ -var x: string = 0; -" + +var x: string = 0;" `; diff --git a/tests/incremental_basic/__snapshots__/jsfmt.spec.js.snap b/tests/incremental_basic/__snapshots__/jsfmt.spec.js.snap index a0eb1b11..a3cc8958 100644 --- a/tests/incremental_basic/__snapshots__/jsfmt.spec.js.snap +++ b/tests/incremental_basic/__snapshots__/jsfmt.spec.js.snap @@ -5,8 +5,7 @@ module.exports = a; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow var a: string = 0; -module.exports = a; -" +module.exports = a;" `; exports[`test b.js 1`] = ` @@ -18,8 +17,7 @@ module.exports = b; // @flow var a = require(\"./a\"); var b: number = a; -module.exports = b; -" +module.exports = b;" `; exports[`test c.js 1`] = ` @@ -31,6 +29,5 @@ module.exports = c; // @flow var b = require(\"./b\"); var c: string = b; -module.exports = c; -" +module.exports = c;" `; diff --git a/tests/incremental_basic/tmp1/__snapshots__/jsfmt.spec.js.snap b/tests/incremental_basic/tmp1/__snapshots__/jsfmt.spec.js.snap index 11d82fe8..d8f0197f 100644 --- a/tests/incremental_basic/tmp1/__snapshots__/jsfmt.spec.js.snap +++ b/tests/incremental_basic/tmp1/__snapshots__/jsfmt.spec.js.snap @@ -7,6 +7,5 @@ module.exports = b; // @flow var a = require(\"./a\"); var b = a; -module.exports = b; -" +module.exports = b;" `; diff --git a/tests/incremental_basic/tmp2/__snapshots__/jsfmt.spec.js.snap b/tests/incremental_basic/tmp2/__snapshots__/jsfmt.spec.js.snap index 5e716253..5f9896ed 100644 --- a/tests/incremental_basic/tmp2/__snapshots__/jsfmt.spec.js.snap +++ b/tests/incremental_basic/tmp2/__snapshots__/jsfmt.spec.js.snap @@ -5,6 +5,5 @@ module.exports = a; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow var a = 0; -module.exports = a; -" +module.exports = a;" `; diff --git a/tests/incremental_basic/tmp3/__snapshots__/jsfmt.spec.js.snap b/tests/incremental_basic/tmp3/__snapshots__/jsfmt.spec.js.snap index b56a5d3b..71c858e3 100644 --- a/tests/incremental_basic/tmp3/__snapshots__/jsfmt.spec.js.snap +++ b/tests/incremental_basic/tmp3/__snapshots__/jsfmt.spec.js.snap @@ -7,6 +7,5 @@ module.exports = b; // @flow var a = require(\"./a\"); var b: number = a; -module.exports = b; -" +module.exports = b;" `; diff --git a/tests/incremental_cycle/__snapshots__/jsfmt.spec.js.snap b/tests/incremental_cycle/__snapshots__/jsfmt.spec.js.snap index 47f24548..9f477227 100644 --- a/tests/incremental_cycle/__snapshots__/jsfmt.spec.js.snap +++ b/tests/incremental_cycle/__snapshots__/jsfmt.spec.js.snap @@ -9,12 +9,13 @@ class A { module.exports = A; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + class A { b: number; c: string; } -module.exports = A; -" + +module.exports = A;" `; exports[`test B.js 1`] = ` @@ -31,11 +32,12 @@ module.exports = B; // @flow var A = require(\"./A\"); import type C from \"./C\"; + class B extends A { c: C; } -module.exports = B; -" + +module.exports = B;" `; exports[`test C.js 1`] = ` @@ -52,9 +54,10 @@ module.exports = C; // @flow var A = require(\"./A\"); import type B from \"./B\"; + class C extends A { b: B; } -module.exports = C; -" + +module.exports = C;" `; diff --git a/tests/incremental_cycle/tmp1/__snapshots__/jsfmt.spec.js.snap b/tests/incremental_cycle/tmp1/__snapshots__/jsfmt.spec.js.snap index 17dfcbbb..ef49f4d4 100644 --- a/tests/incremental_cycle/tmp1/__snapshots__/jsfmt.spec.js.snap +++ b/tests/incremental_cycle/tmp1/__snapshots__/jsfmt.spec.js.snap @@ -8,8 +8,8 @@ export type B = string; // @flow var A = require(\"./A\"); import type C from \"./C\"; -export type B = string; -" + +export type B = string;" `; exports[`test C.js 1`] = ` @@ -26,9 +26,10 @@ module.exports = C; // @flow var A = require(\"./A\"); import type {B} from \"./B\"; + class C extends A { b: B; } -module.exports = C; -" + +module.exports = C;" `; diff --git a/tests/incremental_cycle/tmp2/__snapshots__/jsfmt.spec.js.snap b/tests/incremental_cycle/tmp2/__snapshots__/jsfmt.spec.js.snap index cc9ad232..89067d78 100644 --- a/tests/incremental_cycle/tmp2/__snapshots__/jsfmt.spec.js.snap +++ b/tests/incremental_cycle/tmp2/__snapshots__/jsfmt.spec.js.snap @@ -6,8 +6,7 @@ var A = require (\'./A\'); export type B = string; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -//import type C from \'./C\'; var A = require(\"./A\"); -export type B = string; -" +//import type C from \'./C\'; +export type B = string;" `; diff --git a/tests/incremental_cycle/tmp3/__snapshots__/jsfmt.spec.js.snap b/tests/incremental_cycle/tmp3/__snapshots__/jsfmt.spec.js.snap index 69cb9ed2..bd922577 100644 --- a/tests/incremental_cycle/tmp3/__snapshots__/jsfmt.spec.js.snap +++ b/tests/incremental_cycle/tmp3/__snapshots__/jsfmt.spec.js.snap @@ -9,6 +9,6 @@ export type B = string; // @flow var A = require(\"./A\"); import type C from \"./C\"; -export type B = string; -" + +export type B = string;" `; diff --git a/tests/incremental_delete/__snapshots__/jsfmt.spec.js.snap b/tests/incremental_delete/__snapshots__/jsfmt.spec.js.snap index 85093731..3a0d644d 100644 --- a/tests/incremental_delete/__snapshots__/jsfmt.spec.js.snap +++ b/tests/incremental_delete/__snapshots__/jsfmt.spec.js.snap @@ -5,8 +5,7 @@ module.exports = a; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow var a: string = 0; -module.exports = a; -" +module.exports = a;" `; exports[`test b.js 1`] = ` @@ -18,8 +17,7 @@ module.exports = b; // @flow var a = require(\"./a\"); var b: number = a; -module.exports = b; -" +module.exports = b;" `; exports[`test c.js 1`] = ` @@ -31,8 +29,7 @@ module.exports = c; // @flow var b = require(\"./b\"); var c: string = b; -module.exports = c; -" +module.exports = c;" `; exports[`test dupe1.js 1`] = ` @@ -48,8 +45,7 @@ module.exports = \"dupe1\"; * @providesModule Dupe * @flow */ -module.exports = \"dupe1\"; -" +module.exports = \"dupe1\";" `; exports[`test dupe2.js 1`] = ` @@ -65,8 +61,7 @@ module.exports = \"dupe2\"; * @providesModule Dupe * @flow */ -module.exports = \"dupe2\"; -" +module.exports = \"dupe2\";" `; exports[`test requires_dupe.js 1`] = ` @@ -80,8 +75,7 @@ var dupe = require(\'Dupe\'); * depends on doubly-provided module * @flow */ -var dupe = require(\"Dupe\"); -" +var dupe = require(\"Dupe\");" `; exports[`test requires_unchecked.js 1`] = ` @@ -95,8 +89,7 @@ var unchecked = require(\'Unchecked\'); * depends on an unchecked module, which will be deleted * @flow */ -var unchecked = require(\"Unchecked\"); -" +var unchecked = require(\"Unchecked\");" `; exports[`test unchecked.js 1`] = ` @@ -110,6 +103,5 @@ module.exports = \"unchecked\"; * Not a flow module. * @providesModule Unchecked */ -module.exports = \"unchecked\"; -" +module.exports = \"unchecked\";" `; diff --git a/tests/incremental_duplicate_delete/__snapshots__/jsfmt.spec.js.snap b/tests/incremental_duplicate_delete/__snapshots__/jsfmt.spec.js.snap index 4a2d2ecc..99d8ece1 100644 --- a/tests/incremental_duplicate_delete/__snapshots__/jsfmt.spec.js.snap +++ b/tests/incremental_duplicate_delete/__snapshots__/jsfmt.spec.js.snap @@ -4,10 +4,5 @@ exports[`test A.js 1`] = ` * @flow */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -/** - * @providesModule A - * @flow - */ - " `; diff --git a/tests/incremental_json/__snapshots__/jsfmt.spec.js.snap b/tests/incremental_json/__snapshots__/jsfmt.spec.js.snap index 74c31c79..a9a01abb 100644 --- a/tests/incremental_json/__snapshots__/jsfmt.spec.js.snap +++ b/tests/incremental_json/__snapshots__/jsfmt.spec.js.snap @@ -9,6 +9,5 @@ var x: number = data.x; * @flow */ var data = require(\"./data\"); -var x: number = data.x; -" +var x: number = data.x;" `; diff --git a/tests/incremental_mixed_naming_cycle/__snapshots__/jsfmt.spec.js.snap b/tests/incremental_mixed_naming_cycle/__snapshots__/jsfmt.spec.js.snap index 3d5a61e0..da484851 100644 --- a/tests/incremental_mixed_naming_cycle/__snapshots__/jsfmt.spec.js.snap +++ b/tests/incremental_mixed_naming_cycle/__snapshots__/jsfmt.spec.js.snap @@ -13,10 +13,11 @@ module.exports = \'A\'; * @providesModule A * @flow */ + (require(\"./b\"): void); (require(\"C\"): void); -module.exports = \"A\"; -" + +module.exports = \"A\";" `; exports[`test b.js 1`] = ` @@ -34,10 +35,11 @@ module.exports = \'B\'; * @providesModule B * @flow */ + (require(\"A\"): void); (require(\"D\"): void); -module.exports = \"B\"; -" + +module.exports = \"B\";" `; exports[`test c.js 1`] = ` @@ -55,10 +57,11 @@ module.exports = \'C\'; * @providesModule C * @flow */ + require(\"Root\"); (require(\"./b\"): void); -module.exports = \"C\"; -" + +module.exports = \"C\";" `; exports[`test d.js 1`] = ` @@ -75,9 +78,10 @@ module.exports = \'D\'; * @providesModule D * @flow */ + (require(\"./b\"): void); -module.exports = \"D\"; -" + +module.exports = \"D\";" `; exports[`test root.js 1`] = ` @@ -92,6 +96,6 @@ module.exports = \'Root\'; * @providesModule Root * @flow */ -module.exports = \"Root\"; -" + +module.exports = \"Root\";" `; diff --git a/tests/incremental_mixed_naming_cycle/tmp1/__snapshots__/jsfmt.spec.js.snap b/tests/incremental_mixed_naming_cycle/tmp1/__snapshots__/jsfmt.spec.js.snap index d0a8df0e..f1d9bfbe 100644 --- a/tests/incremental_mixed_naming_cycle/tmp1/__snapshots__/jsfmt.spec.js.snap +++ b/tests/incremental_mixed_naming_cycle/tmp1/__snapshots__/jsfmt.spec.js.snap @@ -11,7 +11,7 @@ module.exports = \'Root\'; * @providesModule Root * @flow */ + // trivial edit (adding this comment) -module.exports = \"Root\"; -" +module.exports = \"Root\";" `; diff --git a/tests/incremental_non_flow_move/__snapshots__/jsfmt.spec.js.snap b/tests/incremental_non_flow_move/__snapshots__/jsfmt.spec.js.snap index 94131559..de714cec 100644 --- a/tests/incremental_non_flow_move/__snapshots__/jsfmt.spec.js.snap +++ b/tests/incremental_non_flow_move/__snapshots__/jsfmt.spec.js.snap @@ -3,10 +3,6 @@ exports[`test foo.js 1`] = ` * @providesModule Foo */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -/* - * @providesModule Foo - */ - " `; @@ -20,6 +16,6 @@ require(\'Foo\'); /** * @flow */ -require(\"Foo\"); -" + +require(\"Foo\");" `; diff --git a/tests/incremental_path/dir/__snapshots__/jsfmt.spec.js.snap b/tests/incremental_path/dir/__snapshots__/jsfmt.spec.js.snap index 630bf072..8fe04010 100644 --- a/tests/incremental_path/dir/__snapshots__/jsfmt.spec.js.snap +++ b/tests/incremental_path/dir/__snapshots__/jsfmt.spec.js.snap @@ -3,6 +3,5 @@ exports[`test a.js 1`] = ` (require(\'b\'): boolean); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -(require(\"b\"): boolean); -" +(require(\"b\"): boolean);" `; diff --git a/tests/indexer/__snapshots__/jsfmt.spec.js.snap b/tests/indexer/__snapshots__/jsfmt.spec.js.snap index a10443ae..a42f56b7 100644 --- a/tests/indexer/__snapshots__/jsfmt.spec.js.snap +++ b/tests/indexer/__snapshots__/jsfmt.spec.js.snap @@ -40,38 +40,44 @@ function foo7(): {[key: string]: number; foo: number} { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // No indexer should be fine -// Matching indexer should be fine -// Indexer with different key type is an error when it matches -// Matching indexer with different value type is an error -// Indexer with different key type and different value type is twice an error -// If key exists in object type then indexer is not matched -// If key exists in object type then indexer is not matched -// Should still complain about mistyped properties function foo0(): {} { return { foo: \"bar\" }; } + +// Matching indexer should be fine function foo1(): { [key: string]: string } { return { foo: \"bar\" }; } + +// Indexer with different key type is an error when it matches function foo2(): { [key: number]: string } { return { foo: \"bar\" }; } + +// Matching indexer with different value type is an error function foo3(): { [key: string]: number } { return { foo: \"bar\" }; } + +// Indexer with different key type and different value type is twice an error function foo4(): { [key: number]: number } { return { foo: \"bar\" }; } + +// If key exists in object type then indexer is not matched function foo5(): { [key: string]: number, foo: string } { return { foo: \"bar\" }; } + +// If key exists in object type then indexer is not matched function foo6(): { [key: number]: number, foo: string } { return { foo: \"bar\" }; } + +// Should still complain about mistyped properties function foo7(): { [key: string]: number, foo: number } { return { foo: \"bar\" }; -} -" +}" `; exports[`test multiple.js 1`] = ` @@ -87,11 +93,13 @@ let tests = [ ]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -/* error: not supported (yet)*/ + let tests = [ function() { - ({}: { [k1: string]: string, [k2: number]: number }); + ({}: { + [k1: string]: string, + [k2: number]: number /* error: not supported (yet)*/ + }); } -]; -" +];" `; diff --git a/tests/init/__snapshots__/jsfmt.spec.js.snap b/tests/init/__snapshots__/jsfmt.spec.js.snap index 1689ae65..8daeb988 100644 --- a/tests/init/__snapshots__/jsfmt.spec.js.snap +++ b/tests/init/__snapshots__/jsfmt.spec.js.snap @@ -50,49 +50,48 @@ function _for_of(arr: Array) { * test initialization tracking in the presence of hoisting * @flow */ -// error, possibly undefined -// error, possibly undefined -// ok -// error, possibly undefined -// error, possibly undefined -// error, possibly undefined + function _if(b: () => boolean) { if (b()) { var f = function() {}; } - f(); + f(); // error, possibly undefined } + function _while(b: () => boolean) { while (b()) { var f = function() {}; } - f(); + f(); // error, possibly undefined } + function _do_while(b: () => boolean) { do { var f = function() {}; } while (b()); - f(); + f(); // ok } + function _for(n: number) { for (var i = 0; i < n; i++) { var f = function() {}; } - f(); + f(); // error, possibly undefined } + function _for_in(obj: Object) { for (var p in obj) { var f = function() {}; } - f(); + f(); // error, possibly undefined } + function _for_of(arr: Array) { for (var x of arr) { var f = function() {}; } - f(); -} -" + f(); // error, possibly undefined +}" `; exports[`test hoisted2.js 1`] = ` @@ -370,89 +369,55 @@ function for_in_post_init() { * note: for try/catch/finally, see tests/try/init.js * @flow */ + // deferred init on annotated vars is ok -// ...but use of var before init gives undefined -// error -// local use of annotated vars in an if is ok -// but not across if/else -// error -// use of var before if gives undefined -// error -// ...and after -// error -// ...unless both branches have initialized -// use of var after partial init (non-exhaustive if) gives undefined -// error, possibly uninitialized -// use of var after guaranteed init (exhaustive if) is ok -// use of var after partial init (non-exhaustive switch) gives undefined -// error, possibly uninitialized -// use of var after guaranteed init (exhaustive switch) is ok -// no error, all cases covered -// local use of annotated var in switch is ok -// ...but use of var before switch gives undefined -// error -// ...and after -// error -// ...and in a fallthrough case without initialization -// error -// local use of annotated var in while is ok -// ...but use of var before while gives undefined -// error -// ...and after -// error -// local use of annotated var in do-while is ok -// ...but use before do-while gives undefined -// error -// after is ok, because loop is guaranteed to run -// local use of annotated var in for is ok -// ...but use before for gives undefined -// error -// ...and after -// error -// local use of annotated var in for-in is ok -// ...but use before while gives undefined -// error -// ...and after -// error -// local use of annotated var in for-of is ok -// ...but use before while gives undefined -// error -// ...and after -// error function linear_deferred_init() { var x: number; x = 0; var y: number = x; } + +// ...but use of var before init gives undefined function linear_pre_init() { var x: number; - var y: number = x; + var y: number = x; // error } + +// local use of annotated vars in an if is ok function if_scoped_init(b) { if (b) { var x: number = 0; var y: number = x; } } + +// but not across if/else function if_else_partial_init(b) { if (b) { var x: number = 0; } else { - var y: number = x; + var y: number = x; // error } } + +// use of var before if gives undefined function if_pre_init(b) { var y: number = x; + // error if (b) { var x: number = 0; } } + +// ...and after function if_partial_post_init(b) { if (b) { var x: number = 0; } - var y: number = x; + var y: number = x; // error } + +// ...unless both branches have initialized function if_post_init(b) { if (b) { var x: number = 0; @@ -461,13 +426,17 @@ function if_post_init(b) { } var y: number = x; } + +// use of var after partial init (non-exhaustive if) gives undefined function if_partial_post_init(b) { var x: number; if (b) { x = 0; } - var y: number = x; + var y: number = x; // error, possibly uninitialized } + +// use of var after guaranteed init (exhaustive if) is ok function if_post_init(b) { var x: number; if (b) { @@ -477,6 +446,8 @@ function if_post_init(b) { } var y: number = x; } + +// use of var after partial init (non-exhaustive switch) gives undefined function switch_partial_post_init(i) { var x: number; switch (i) { @@ -487,8 +458,10 @@ function switch_partial_post_init(i) { x = 1; break; } - var y: number = x; + var y: number = x; // error, possibly uninitialized } + +// use of var after guaranteed init (exhaustive switch) is ok function switch_post_init(i) { var x: number; switch (i) { @@ -501,8 +474,10 @@ function switch_post_init(i) { default: x = 2; } - var y: number = x; + var y: number = x; // no error, all cases covered } + +// local use of annotated var in switch is ok function switch_scoped_init_1(i) { switch (i) { case 0: @@ -510,119 +485,161 @@ function switch_scoped_init_1(i) { var y: number = x; } } + +// ...but use of var before switch gives undefined function switch_scoped_init_2(i) { var y: number = x; + // error switch (i) { case 0: var x: number = 0; } } + +// ...and after function switch_scoped_init_3(i) { switch (i) { case 0: var x: number = 0; } - var y: number = x; + var y: number = x; // error } + +// ...and in a fallthrough case without initialization function switch_scoped_init_4(i) { switch (i) { case 0: var x: number = 0; + // error case 1: var y: number = x; } } + +// local use of annotated var in while is ok function while_scoped_init(b) { while (b) { var x: number = 0; var y: number = x; } } + +// ...but use of var before while gives undefined function while_pre_init(b) { var y: number = x; + // error while (b) { var x: number = 0; } } + +// ...and after function while_post_init(b) { while (b) { var x: number = 0; } - var y: number = x; + var y: number = x; // error } + +// local use of annotated var in do-while is ok function do_while_scoped_init(b) { do { var x: number = 0; var y: number = x; } while (b); } + +// ...but use before do-while gives undefined function do_while_pre_init(b) { var y: number = x; + // error do { var x: number = 0; } while (b); } + +// after is ok, because loop is guaranteed to run function do_while_post_init(b) { do { var x: number = 0; } while (b); var y: number = x; } + +// local use of annotated var in for is ok function for_scoped_init(b) { for (; b; ) { var x: number = 0; var y: number = x; } } + +// ...but use before for gives undefined function for_pre_init(b) { var y: number = x; + // error for (; b; ) { var x: number = 0; } } + +// ...and after function for_post_init(b) { for (; b; ) { var x: number = 0; } - var y: number = x; + var y: number = x; // error } + +// local use of annotated var in for-in is ok function for_in_scoped_init() { for (var p in { a: 1, b: 2 }) { var x: number = 0; var y: number = x; } } + +// ...but use before while gives undefined function for_in_pre_init() { var y: number = x; + // error for (var p in { a: 1, b: 2 }) { var x: number = 0; } } + +// ...and after function for_in_post_init() { for (var p in { a: 1, b: 2 }) { var x: number = 0; } - var y: number = x; + var y: number = x; // error } + +// local use of annotated var in for-of is ok function for_of_scoped_init() { for (var x of [ 1, 2, 3 ]) { var x: number = 0; var y: number = x; } } + +// ...but use before while gives undefined function for_in_pre_init() { var y: number = x; + // error for (var x of [ 1, 2, 3 ]) { var x: number = 0; } } + +// ...and after function for_in_post_init() { for (var x of [ 1, 2, 3 ]) { var x: number = 0; } - var y: number = x; -} -" + var y: number = x; // error +}" `; exports[`test let.js 1`] = ` @@ -788,59 +805,40 @@ function sub_closure_init_reference() { * test initialization tracking for lets * @flow */ + // deferred init on annotated lets is ok -// use of let before init gives undefined -// ok -// error -// ok -// self-references in let bindings are not ok -// \'x\' not initialized! -// use of let after partial init (non-exhaustive if) gives undefined -// error, possibly uninitialized -// use of let after guaranteed init (exhaustive if) is ok -// use of let after partial init (non-exhaustive switch) gives undefined -// error, possibly uninitialized -// use of let after guaranteed init (exhaustive switch) is ok -// no error, all cases covered -// use in a switch after a skipped decl is an error -// error, skipped declaration -// while leaves it possibly uninitialized -// error -// do-while is ok, because loop is guaranteed to run at least once -// ok -// for-in leaves it possibly uninitialized -// error -// for-of leaves it possibly uninitialized -// error -// use of let after guaranteed init (exhaustive switch + throw) is ok -// ok, definitely initialized -// use of let after guaranteed init (exhaustive switch + throw) is ok -// ok, definitely initialized -// reference of a let-binding is permitted in a sub-closure within the init expr -// var-bindings can reference each other cyclically since they do not incur a -// TDZ (...even though this is weird...) function linear_deferred_init() { let x: number; x = 0; let y: number = x; } + +// use of let before init gives undefined function linear_pre_init() { let x: number; let y: ?number = x; + // ok let z: number = x; + // error x = 0; - let w: number = x; + let w: number = x; // ok } + +// self-references in let bindings are not ok function self_init() { - let x = x; + let x = x; // \'x\' not initialized! } + +// use of let after partial init (non-exhaustive if) gives undefined function if_partial_post_init(b) { let x: number; if (b) { x = 0; } - var y: number = x; + var y: number = x; // error, possibly uninitialized } + +// use of let after guaranteed init (exhaustive if) is ok function if_post_init(b) { let x: number; if (b) { @@ -850,6 +848,8 @@ function if_post_init(b) { } var y: number = x; } + +// use of let after partial init (non-exhaustive switch) gives undefined function switch_partial_post_init(i) { let x: number; switch (i) { @@ -860,8 +860,10 @@ function switch_partial_post_init(i) { x = 1; break; } - var y: number = x; + var y: number = x; // error, possibly uninitialized } + +// use of let after guaranteed init (exhaustive switch) is ok function switch_post_init(i) { let x: number; switch (i) { @@ -874,44 +876,57 @@ function switch_post_init(i) { default: x = 2; } - var y: number = x; + var y: number = x; // no error, all cases covered } + +// use in a switch after a skipped decl is an error function switch_scoped_init_2(i) { switch (i) { case 0: let x: number; + // error, skipped declaration case 1: let y: number = x; } } + +// while leaves it possibly uninitialized function while_post_init(b) { let x: number; while (b) { x = 0; } - var y: number = x; + var y: number = x; // error } + +// do-while is ok, because loop is guaranteed to run at least once function do_while_post_init(b) { let x: number; do { x = 0; } while (b); - var y: number = x; + var y: number = x; // ok } + +// for-in leaves it possibly uninitialized function for_in_post_init() { var x: number; for (var p in {}) { x = 0; } - var y: number = x; + var y: number = x; // error } + +// for-of leaves it possibly uninitialized function for_of_post_init() { var x: number; for (var x of []) { x = 0; } - var y: number = x; + var y: number = x; // error } + +// use of let after guaranteed init (exhaustive switch + throw) is ok function switch_post_init2(i): number { let bar; switch (i) { @@ -921,8 +936,10 @@ function switch_post_init2(i): number { default: throw new Error(\"Invalid state\"); } - return bar; + return bar; // ok, definitely initialized } + +// use of let after guaranteed init (exhaustive switch + throw) is ok function switch_post_init2(i): number { let bar; switch (i) { @@ -932,8 +949,10 @@ function switch_post_init2(i): number { default: throw new Error(\"Invalid state\"); } - return bar; + return bar; // ok, definitely initialized } + +// reference of a let-binding is permitted in a sub-closure within the init expr function sub_closure_init_reference() { let x = function() { return x; @@ -941,9 +960,11 @@ function sub_closure_init_reference() { const y = function() { return y; }; + + // var-bindings can reference each other cyclically since they do not incur a + // TDZ (...even though this is weird...) var z = z; -} -" +}" `; exports[`test nullable-init.js 1`] = ` @@ -951,6 +972,5 @@ exports[`test nullable-init.js 1`] = ` var a: Array = [null,null]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ var o: { x: ?number } = { x: null }; -var a: Array = [ null, null ]; -" +var a: Array = [ null, null ];" `; diff --git a/tests/instanceof/__snapshots__/jsfmt.spec.js.snap b/tests/instanceof/__snapshots__/jsfmt.spec.js.snap index 2acb79b4..742ebf3f 100644 --- a/tests/instanceof/__snapshots__/jsfmt.spec.js.snap +++ b/tests/instanceof/__snapshots__/jsfmt.spec.js.snap @@ -88,24 +88,20 @@ function foo1(x: Array | number) { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + // x instancof t -// oops -// x.y instanceof t -// oops -// x.y.z instance of t -// oops -// this instanceof t -// error -// error class X1 { foo: number; } + class X2 { foo: string; } + function x(b) { return b ? new X1() : new X2(); } + function consumer1(b) { var g = x(b); if (g instanceof X2) @@ -113,20 +109,26 @@ function consumer1(b) { else g.foo = 1337; } + function consumer2(b) { var g = x(b); if (g instanceof X1) - g.foo = \"1337\"; + g.foo = \"1337\"; // oops } + +// x.y instanceof t class Y1 { bar: X1; } + class Y2 { bar: X2; } + function y(b) { return b ? new Y1() : new Y2(); } + function consumer3(b) { var g = y(b); if (g.bar instanceof X2) @@ -134,20 +136,26 @@ function consumer3(b) { else g.bar.foo = 1337; } + function consumer4(b) { var g = y(b); if (g.bar instanceof X1) - g.bar.foo = \"1337\"; + g.bar.foo = \"1337\"; // oops } + +// x.y.z instance of t class Z1 { baz: Y1; } + class Z2 { baz: Y2; } + function z(b) { return b ? new Z1() : new Z2(); } + function consumer5(b) { var g = z(b); if (g.baz.bar instanceof X2) @@ -155,11 +163,14 @@ function consumer5(b) { else g.baz.bar.foo = 1337; } + function consumer6(b) { var g = z(b); if (g.baz.bar instanceof X1) - g.baz.bar.foo = \"1337\"; + g.baz.bar.foo = \"1337\"; // oops } + +// this instanceof t class C { m() { if (this instanceof D) @@ -168,6 +179,7 @@ class C { alert(\"nope\"); } } + class D extends C { s: string; constructor() { @@ -175,6 +187,7 @@ class D extends C { this.s = \"yup\"; } } + function foo0(x: Array | number) { if (x instanceof Array) { x[0] = 123; @@ -182,12 +195,12 @@ function foo0(x: Array | number) { x++; } } + function foo1(x: Array | number) { if (x instanceof Array) { - x++; + x++; // error } else { - x[0] = 123; + x[0] = 123; // error } -} -" +}" `; diff --git a/tests/integration/__snapshots__/jsfmt.spec.js.snap b/tests/integration/__snapshots__/jsfmt.spec.js.snap index 9ea067be..ff9dc91c 100644 --- a/tests/integration/__snapshots__/jsfmt.spec.js.snap +++ b/tests/integration/__snapshots__/jsfmt.spec.js.snap @@ -1,8 +1,6 @@ exports[`test bar.js 1`] = ` "// @flow ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// @flow - " `; @@ -11,6 +9,5 @@ exports[`test foo.js 1`] = ` require(\'./bar\'); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -require(\"./bar\"); -" +require(\"./bar\");" `; diff --git a/tests/interface/__snapshots__/jsfmt.spec.js.snap b/tests/interface/__snapshots__/jsfmt.spec.js.snap index 9b3cbfb6..aa2b5959 100644 --- a/tests/interface/__snapshots__/jsfmt.spec.js.snap +++ b/tests/interface/__snapshots__/jsfmt.spec.js.snap @@ -2,10 +2,8 @@ exports[`test import.js 1`] = ` "interface I { x: number } export type J = I; // workaround for export interface ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// workaround for export interface interface I { x: number } -export type J = I; -" +export type J = I; // workaround for export interface" `; exports[`test indexer.js 1`] = ` @@ -21,10 +19,13 @@ interface Bad { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -/* error: not supported (yet)*/ + interface Ok { [key: string]: string } -interface Bad { [k1: string]: string, [k2: number]: number } -" + +interface Bad { + [k1: string]: string, + [k2: number]: number /* error: not supported (yet)*/ +}" `; exports[`test interface.js 1`] = ` @@ -41,18 +42,19 @@ function testInterfaceName(o: I) { (o.constructor.name: string); // ok } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// error -// error, name is static -// ok declare class C { x: number } + var x: string = new C().x; + interface I { x: number } + var i = new I(); +// error function testInterfaceName(o: I) { (o.name: string); - (o.constructor.name: string); -} -" + // error, name is static + (o.constructor.name: string); // ok +}" `; exports[`test test.js 1`] = ` @@ -79,31 +81,32 @@ var e: E = { x: \"\", y: \"\", z: \"\" }; // error: x and z should be nu (e.y: string); (e.z: string); // error: z is number ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// error: x should be number -// error: x is number -// error: multiple extends -//declare class E implements I { } // parse error -// error: x and z should be numbers -// error: x is number -// error: z is number interface I { y: string } interface I_ { x: number } interface J extends I, I_ {} interface K extends J {} + var k: K = { x: \"\", y: \"\" }; +// error: x should be number (k.x: string); +// error: x is number (k.y: string); + declare class C { x: number } declare class D extends C, Other {} +// error: multiple extends +//declare class E implements I { } // parse error interface A { y: Y } interface A_ { x: X } interface B extends A, A_ { z: Z } interface E extends B {} + var e: E = { x: \"\", y: \"\", z: \"\" }; +// error: x and z should be numbers (e.x: string); +// error: x is number (e.y: string); -(e.z: string); -" +(e.z: string); // error: z is number" `; exports[`test test2.js 1`] = ` @@ -118,24 +121,24 @@ type M = { y: string } & J & { z: boolean } function bar(m: M) { m.x; m.y; m.z; } // OK ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// error: z not found in L -// interface + multiple inheritance is similar to object type + intersection -// OK import type {J} from \"./import\"; interface K {} interface L extends J, K { y: string } + function foo(l: L) { l.x; l.y; l.z; } +// error: z not found in L +// interface + multiple inheritance is similar to object type + intersection type M = { y: string } & J & { z: boolean }; + function bar(m: M) { m.x; m.y; m.z; -} -" +} // OK" `; exports[`test test3.js 1`] = ` @@ -147,17 +150,15 @@ function foo(k: K) { (k.y: number); // error: y is string in I } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// error: x is number in I -// error: x is string in K -// error: y is string in I interface I { x: number, y: string } interface J { y: number } interface K extends I, J { x: string } +// error: x is number in I function foo(k: K) { (k.x: number); - (k.y: number); -} -" + // error: x is string in K + (k.y: number); // error: y is string in I +}" `; exports[`test test4.js 1`] = ` @@ -171,11 +172,10 @@ declare class C { new C().bar((x: string) => { }); // error, number ~/~> string ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// error, property \`foo\` not found function -// error, number ~/~> string interface I { foo(x: number): void } (function foo(x: number) {}: I); +// error, property \`foo\` not found function declare class C { bar(i: I): void, bar(f: (x: number) => void): void } -new C().bar((x: string) => {}); -" + +new C().bar((x: string) => {}); // error, number ~/~> string" `; diff --git a/tests/intersection/__snapshots__/jsfmt.spec.js.snap b/tests/intersection/__snapshots__/jsfmt.spec.js.snap index 95269c1d..57d7e6b7 100644 --- a/tests/intersection/__snapshots__/jsfmt.spec.js.snap +++ b/tests/intersection/__snapshots__/jsfmt.spec.js.snap @@ -10,10 +10,10 @@ function bar(x: Error & {type:number}): number { function foo(x: $All): number { return x.type; } + function bar(x: Error & { type: number }): number { return x.type; -} -" +}" `; exports[`test objassign.js 1`] = ` @@ -36,10 +36,10 @@ let y: ObjAssignT = { ...x }; // should be fine * * @noflow */ -// should be fine + declare var x: ObjAssignT; -let y: ObjAssignT = { ...x }; -" + +let y: ObjAssignT = { ...x }; // should be fine" `; exports[`test pred.js 1`] = ` @@ -74,7 +74,7 @@ function hasObjectMode_ok(options: DuplexStreamOptions): boolean { * * @flow */ -// error, undefined ~> boolean + type DuplexStreamOptions = ReadableStreamOptions & WritableStreamOptions & { @@ -82,15 +82,16 @@ type DuplexStreamOptions = ReadableStreamOptions & readableObjectMode?: boolean, writableObjectMode?: boolean }; + function hasObjectMode_bad(options: DuplexStreamOptions): boolean { return options.objectMode || options.readableObjectMode || - options.writableObjectMode; + options.writableObjectMode; // error, undefined ~> boolean } + function hasObjectMode_ok(options: DuplexStreamOptions): boolean { return !!(options.objectMode || options.readableObjectMode || options.writableObjectMode); -} -" +}" `; exports[`test test_fun.js 1`] = ` @@ -141,17 +142,22 @@ var g: (_: number | string) => void = f; * * @noflow */ + // intersection of function types satisfies union of param types -// simpler variation + type F = (_: ObjA) => void; type G = (_: ObjB) => void; type FG = (_: ObjA | ObjB) => void; + declare var fun1: F & G; + (fun1: FG); + var fun2: FG = fun1; + +// simpler variation declare var f: ((_: number) => void) & ((_: string) => void); -var g: (_: number | string) => void = f; -" +var g: (_: number | string) => void = f;" `; exports[`test test_obj.js 1`] = ` @@ -190,6 +196,7 @@ var e: E = c; // error * * @noflow */ + // TODO we should give explicit errors for incompatibilities // which make an intersection uninhabitable: // - shared mutable properties with different types @@ -201,16 +208,16 @@ var e: E = c; // error // suboptimal, since eg declared vars require no explicit // provision of values. This leaves the impossible types // free to flow downstream and satisfy impossible constraints. + // intersection of object types satisfies union of properties -// intersection of dictionary types: -// ok -// dict type mismatch -// error declare var a: A; var b: B = a; + +// intersection of dictionary types: declare var c: C; var d: D = c; +// ok +// dict type mismatch type E = { [key: string]: string }; -var e: E = c; -" +var e: E = c; // error" `; diff --git a/tests/intersection/lib/__snapshots__/jsfmt.spec.js.snap b/tests/intersection/lib/__snapshots__/jsfmt.spec.js.snap index 3925636b..38255853 100644 --- a/tests/intersection/lib/__snapshots__/jsfmt.spec.js.snap +++ b/tests/intersection/lib/__snapshots__/jsfmt.spec.js.snap @@ -35,31 +35,37 @@ type C = { [key: string]: number } & { [key: string]: number }; type D = { [key: string]: number }; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + // defs used in tests, here to stress tvar machinery + // used in ObjAssign.js // +type ObjAssignT = { foo: string } & { bar: string }; + // used in pred.js // -// used in test_fun.js -// -// used in test_obj.js -// -type ObjAssignT = { foo: string } & { bar: string }; type ReadableStreamOptions = { highWaterMark?: number, encoding?: ?string, objectMode?: boolean }; + type WritableStreamOptions = { highWaterMark?: number, decodeString?: boolean, objectMode?: boolean }; + +// used in test_fun.js +// type ObjA = { foo: number, bar: string }; type ObjB = { baz: boolean }; + +// used in test_obj.js +// type A = { a: string } & { b: string }; type B = { a: string, b: string }; + type C = { [key: string]: number } & { [key: string]: number }; -type D = { [key: string]: number }; -" +type D = { [key: string]: number };" `; diff --git a/tests/issues-11/__snapshots__/jsfmt.spec.js.snap b/tests/issues-11/__snapshots__/jsfmt.spec.js.snap index 31d0b8f3..c9e9fd45 100644 --- a/tests/issues-11/__snapshots__/jsfmt.spec.js.snap +++ b/tests/issues-11/__snapshots__/jsfmt.spec.js.snap @@ -5,8 +5,7 @@ exports.y = \"\"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ exports.x = 1; -exports.y = \"\"; -" +exports.y = \"\";" `; exports[`test import.js 1`] = ` @@ -18,6 +17,5 @@ var y: number = e.y; /* @flow */ var e = require(\"./export\"); var x: string = e.x; -var y: number = e.y; -" +var y: number = e.y;" `; diff --git a/tests/iter/__snapshots__/jsfmt.spec.js.snap b/tests/iter/__snapshots__/jsfmt.spec.js.snap index ea2a952a..f4fb8be5 100644 --- a/tests/iter/__snapshots__/jsfmt.spec.js.snap +++ b/tests/iter/__snapshots__/jsfmt.spec.js.snap @@ -37,38 +37,38 @@ for (var y in this) { // allowed, even though we can\'t actually enumerate all the keys on \`this\`. } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// k is a string, which shouldn\'t be used for array access -// d is a string, which shouldn\'t be used for array access -// unreachable -// unreachable -// regression test to make sure \`in this\` doesn\'t fatal. it\'s currently -// allowed, even though we can\'t actually enumerate all the keys on \`this\`. var a = [ true, false ]; function foo(x) {} + for (var i = 0; i < 3; i++) { foo(a[i]); } for (var k in a) { - foo(a[k]); + foo(a[k]); // k is a string, which shouldn\'t be used for array access } + var b = (null: ?{ [key: string]: string }); for (var j in b) { foo(b[j]); } + var c; for (var m in c = b) { foo(c[m]); } + var d; for (var n in d = a) { - foo(d[n]); + foo(d[n]); // d is a string, which shouldn\'t be used for array access } + for (var x in undefined) { - foo(x); + foo(x); // unreachable } + for (var x in null) { - foo(x); + foo(x); // unreachable } -for (var y in this) {} -" + +for (var y in this) {}" `; diff --git a/tests/iterable/__snapshots__/jsfmt.spec.js.snap b/tests/iterable/__snapshots__/jsfmt.spec.js.snap index 7de68aa0..9f92f78b 100644 --- a/tests/iterable/__snapshots__/jsfmt.spec.js.snap +++ b/tests/iterable/__snapshots__/jsfmt.spec.js.snap @@ -11,14 +11,15 @@ var arrayTest4: Iterable = [\"hi\"]; var arrayTest5: Iterable = [\"hi\", 1]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// Error string ~> number -// Error string ~> number + var arrayTest1: Iterable = ([ 1, 2 ]: Array); var arrayTest2: Iterable = [ 1, 2, \"hi\" ]; var arrayTest3: Iterable<*> = [ 1, 2, 3 ]; + +// Error string ~> number var arrayTest4: Iterable = [ \"hi\" ]; -var arrayTest5: Iterable = [ \"hi\", 1 ]; -" +// Error string ~> number +var arrayTest5: Iterable = [ \"hi\", 1 ];" `; exports[`test caching_bug.js 1`] = ` @@ -45,6 +46,7 @@ function fill_the_cache(x: Array): Iterable { return x; } function miss_the_cache(x: Array): Iterable { return x; } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + /** * I\'ve hit a bug with the caching in flow_js.ml. Avik is removing that caching * so it should be fixed soon. The basic idea is I flow something like @@ -59,14 +61,15 @@ function miss_the_cache(x: Array): Iterable { return x; * anyway. I\'ve fixed this temporarily by bumping the \"meaningful\" param to * Hashtbl.hash_param */ -// Error: number ~> string + function fill_the_cache(x: Array): Iterable { return x; } + +// Error: number ~> string function miss_the_cache(x: Array): Iterable { return x; -} -" +}" `; exports[`test iter.js 1`] = ` @@ -83,14 +86,16 @@ var m: Map = new Map(); foo(m.keys()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + function foo(strs: Iterable): void { for (var s: string of strs) { console.log(s); } } + var m: Map = new Map(); -foo(m.keys()); -" + +foo(m.keys());" `; exports[`test iterator_result.js 1`] = ` @@ -125,9 +130,7 @@ function makeIterator(coin_flip: () => boolean ): Iterator { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// Whoops, made a mistake and forgot to negate done -// Error string ~> void -// Error void ~> string + function makeIterator(coin_flip: () => boolean): Iterator { return { \"@@iterator\"() { @@ -143,6 +146,7 @@ function makeIterator(coin_flip: () => boolean): Iterator { } }; } + function makeIterator(coin_flip: () => boolean): Iterator { return { \"@@iterator\"() { @@ -151,14 +155,14 @@ function makeIterator(coin_flip: () => boolean): Iterator { next(): IteratorResult { var done = coin_flip(); if (done) { - return { done, value: \"still going...\" }; + // Whoops, made a mistake and forgot to negate done + return { done, value: \"still going...\" }; // Error string ~> void } else { - return { done }; + return { done }; // Error void ~> string } } }; -} -" +}" `; exports[`test map.js 1`] = ` @@ -179,20 +183,21 @@ function mapTest4(map: Map): Iterable { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// Error - Map is an Iterable<[K, V]> + function mapTest1(map: Map): Iterable<[string, number]> { return map; } function mapTest2(map: Map): Iterable<[K, V]> { return map; } + function mapTest3(map: Map): Iterable<*> { return map; } +// Error - Map is an Iterable<[K, V]> function mapTest4(map: Map): Iterable { return map; -} -" +}" `; exports[`test set.js 1`] = ` @@ -213,20 +218,21 @@ function setTest4(set: Set): Iterable { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// Error string ~> number + function setTest1(set: Set): Iterable { return set; } function setTest2(set: Set): Iterable { return set; } + function setTest3(set: Set): Iterable<*> { return set; } +// Error string ~> number function setTest4(set: Set): Iterable { return set; -} -" +}" `; exports[`test string.js 1`] = ` @@ -237,11 +243,10 @@ var stringTest3: Iterable<*> = \"hi\"; var stringTest3: Iterable = \"hi\"; // Error - string is a Iterable ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// Error - string is a Iterable + var stringTest1: Iterable = \"hi\"; var stringTest3: Iterable<*> = \"hi\"; -var stringTest3: Iterable = \"hi\"; -" +var stringTest3: Iterable = \"hi\"; // Error - string is a Iterable" `; exports[`test variance.js 1`] = ` @@ -252,9 +257,8 @@ exports[`test variance.js 1`] = ` (([]: Array).values(): Iterable); // ok, Iterator<+T> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// ok, Iterable<+T> -// ok, Iterator<+T> + (([]: Array): Iterable); -(([]: Array).values(): Iterable); -" +// ok, Iterable<+T> +(([]: Array).values(): Iterable); // ok, Iterator<+T>" `; diff --git a/tests/jsx_intrinsics.builtin/__snapshots__/jsfmt.spec.js.snap b/tests/jsx_intrinsics.builtin/__snapshots__/jsfmt.spec.js.snap index 654f05bb..04df9906 100644 --- a/tests/jsx_intrinsics.builtin/__snapshots__/jsfmt.spec.js.snap +++ b/tests/jsx_intrinsics.builtin/__snapshots__/jsfmt.spec.js.snap @@ -22,24 +22,26 @@ var d: React.Element<{doesntmatch: string}> =
; var e: React.Element<{not_a_real_attr: string}> =
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// Error: Props<{prop}> ~> Props<{prop1}> -// Since intrinsics are typed as \`any\` out of the box, we can pass any -// attributes to intrinsics! -// However, we don\'t allow such elements to be viewed as React elements with -// different attributes. -// No error as long as expectations are consistent, though. + var React = require(\"react\"); + class CustomComponent extends React.Component { props: { prop: string }; } -var a: React.Element<{ prop: string }> = ; -var b: React.Element<{ prop1: string }> = ; -var c: React.Element =
; -var d: React.Element<{ doesntmatch: string }> =
; + +var a: React.Element<{ prop: string }> = ; +var b: React.Element<{ prop1: string }> = ; +// Error: Props<{prop}> ~> Props<{prop1}> +// Since intrinsics are typed as \`any\` out of the box, we can pass any +// attributes to intrinsics! +var c: React.Element =
; +// However, we don\'t allow such elements to be viewed as React elements with +// different attributes. +var d: React.Element<{ doesntmatch: string }> =
; +// No error as long as expectations are consistent, though. var e: React.Element<{ not_a_real_attr: string -}> =
; -" +}> =
;" `; exports[`test strings.js 1`] = ` @@ -63,22 +65,23 @@ React.createElement(\'bad\', {}); // This is fine
; // This is fine ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// The builtin $JSXIntrinsics should allow any string -/* This is fine*/ -/* This is fine*/ -// This is fine -// This is fine -/* This is fine*/ -// This is fine + var React = require(\"react\"); + +// The builtin $JSXIntrinsics should allow any string var Div = \"div\"; var Bad = \"bad\"; var Str: string = \"str\"; -
; -; -; + +
; +/* This is fine*/ +; +/* This is fine*/ +; +// This is fine React.createElement(\"div\", {}); +// This is fine React.createElement(\"bad\", {}); -
; -" +/* This is fine*/ +
; // This is fine" `; diff --git a/tests/jsx_intrinsics.custom/__snapshots__/jsfmt.spec.js.snap b/tests/jsx_intrinsics.custom/__snapshots__/jsfmt.spec.js.snap index f2adad66..276eebb1 100644 --- a/tests/jsx_intrinsics.custom/__snapshots__/jsfmt.spec.js.snap +++ b/tests/jsx_intrinsics.custom/__snapshots__/jsfmt.spec.js.snap @@ -18,20 +18,23 @@ var c: React.Element<{id: string}> =
; var d: React.Element<{id: number}> =
; // Error: Props<{id:string}> ~> Props<{id:number}> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -/* Error: Props<{prop}> ~> Props<{prop1}>*/ -// Error: (\`id\` prop) number ~> string -// Error: Props<{id:string}> ~> Props<{id:number}> + var React = require(\"react\"); + class CustomComponent extends React.Component { props: { prop: string }; } -var a: React.Element<{ prop: string }> = ; -var b: React.Element<{ prop1: string }> = ; -
; -
; -var c: React.Element<{ id: string }> =
; -var d: React.Element<{ id: number }> =
; -" + +var a: React.Element<{ prop: string }> = ; +var b: React.Element<{ prop1: string }> = ; +/* Error: Props<{prop}> ~> Props<{prop1}>*/ +
; +
; +// Error: (\`id\` prop) number ~> string +var c: React.Element<{ id: string }> =
; +var d: React.Element<{ + id: number +}> =
; // Error: Props<{id:string}> ~> Props<{id:number}>" `; exports[`test strings.js 1`] = ` @@ -55,24 +58,25 @@ React.createElement(Str, {}); // Error: string ~> keys of JSXIntrinsics
; // Not an error but should be eventually ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -/* This is fine*/ -/* Error: \'bad\' not in JSXIntrinsics*/ -// Error: string ~> keys of JSXIntrinsics -// This is fine -// Error: \'bad\' not in JSXIntrinsics -/* Error: string ~> keys of JSXIntrinsics*/ -/* TODO: Make this an error*/ -// Not an error but should be eventually + var React = require(\"react\"); + var Div = \"div\"; var Bad = \"bad\"; var Str: string = \"str\"; -
; -; -; + +
; +/* This is fine*/ +; +/* Error: \'bad\' not in JSXIntrinsics*/ +; +// Error: string ~> keys of JSXIntrinsics React.createElement(\"div\", {}); +// This is fine React.createElement(\"bad\", {}); +// Error: \'bad\' not in JSXIntrinsics React.createElement(Str, {}); -
; -" +/* Error: string ~> keys of JSXIntrinsics*/ +/* TODO: Make this an error*/ +
; // Not an error but should be eventually" `; diff --git a/tests/jsx_intrinsics.custom/lib/__snapshots__/jsfmt.spec.js.snap b/tests/jsx_intrinsics.custom/lib/__snapshots__/jsfmt.spec.js.snap index fc8b5bab..5f9724f3 100644 --- a/tests/jsx_intrinsics.custom/lib/__snapshots__/jsfmt.spec.js.snap +++ b/tests/jsx_intrinsics.custom/lib/__snapshots__/jsfmt.spec.js.snap @@ -7,12 +7,12 @@ type $JSXIntrinsics = { span: $JSXIntrinsic<{id: string, class: string}>, }; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// fake import declare var $React: $Exports<\"react\">; +// fake import type $JSXIntrinsic = Class<$React.Component>; + type $JSXIntrinsics = { div: $JSXIntrinsic<{ id: string }>, span: $JSXIntrinsic<{ id: string, class: string }> -}; -" +};" `; diff --git a/tests/keys/__snapshots__/jsfmt.spec.js.snap b/tests/keys/__snapshots__/jsfmt.spec.js.snap index 5429c131..6d146723 100644 --- a/tests/keys/__snapshots__/jsfmt.spec.js.snap +++ b/tests/keys/__snapshots__/jsfmt.spec.js.snap @@ -46,58 +46,53 @@ function testKeysOfOtherObj(str: string, lit: \'hi\') { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// Any string should be fine -// No error, truthy string should be fine -// String literal should be fine -// Error: number -> keys of Object -// Any string should be fine -// No error, truthy string should be fine -// String literal should be fine -// Error: number -> keys of StrDict -// Error: Not all strings are allowed -// Error: Not all truthy strings are allowed -// The right string literal is allowed -// Error: The wrong string literal is not allowed -// Error: number -> keys of StrLitDict -// Error: string -> keys of ObjLit -// Error: truthy string -> keys of ObjLit -// String literal should be fine -// Error: number -> keys of ObjLit + function testKeysOfObject(str: string, lit: \"hi\") { (str: $Keys); + // Any string should be fine if (str) { - (str: $Keys); + (str: $Keys); // No error, truthy string should be fine } (\"hi\": $Keys); - (123: $Keys); + // String literal should be fine + (123: $Keys); // Error: number -> keys of Object } + type StrDict = { [key: string]: mixed }; function testKeysOfStrDict(str: string, lit: \"hi\") { (str: $Keys); + // Any string should be fine if (str) { - (str: $Keys); + (str: $Keys); // No error, truthy string should be fine } (\"hi\": $Keys); - (123: $Keys); + // String literal should be fine + (123: $Keys); // Error: number -> keys of StrDict } + type StrLitDict = { [key: \"hi\"]: mixed }; function testKeysOfStrLitDict(str: string, lit: \"hi\") { (str: $Keys); + // Error: Not all strings are allowed if (str) { - (str: $Keys); + (str: $Keys); // Error: Not all truthy strings are allowed } (\"hi\": $Keys); + // The right string literal is allowed (\"bye\": $Keys); - (123: $Keys); + // Error: The wrong string literal is not allowed + (123: $Keys); // Error: number -> keys of StrLitDict } + type ObjLit = { hi: mixed }; function testKeysOfOtherObj(str: string, lit: \"hi\") { (str: $Keys); + // Error: string -> keys of ObjLit if (str) { - (str: $Keys); + (str: $Keys); // Error: truthy string -> keys of ObjLit } (\"hi\": $Keys); - (123: $Keys); -} -" + // String literal should be fine + (123: $Keys); // Error: number -> keys of ObjLit +}" `; diff --git a/tests/keyvalue/__snapshots__/jsfmt.spec.js.snap b/tests/keyvalue/__snapshots__/jsfmt.spec.js.snap index 78d31136..706068e4 100644 --- a/tests/keyvalue/__snapshots__/jsfmt.spec.js.snap +++ b/tests/keyvalue/__snapshots__/jsfmt.spec.js.snap @@ -8,10 +8,10 @@ let tests = [ ]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + let tests = [ function(x: { [key: number]: string }) { (x[\"\"]: number); } -]; -" +];" `; diff --git a/tests/last_duplicate_property_wins/__snapshots__/jsfmt.spec.js.snap b/tests/last_duplicate_property_wins/__snapshots__/jsfmt.spec.js.snap index 78425ba0..6af6c4d8 100644 --- a/tests/last_duplicate_property_wins/__snapshots__/jsfmt.spec.js.snap +++ b/tests/last_duplicate_property_wins/__snapshots__/jsfmt.spec.js.snap @@ -42,26 +42,9 @@ const o = { (o.qux(): boolean); // last wins ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + // Classes -// last wins -// last wins -// field wins over method -// method loses to field! -// check -// last wins -// last wins -// last wins -// weird outlier where last doesn\'t win in classes -// Objects -// last wins -// last wins -// last wins -// last wins -// check -// last wins -// last wins -// last wins -// last wins + class C { foo(): number { return 0; @@ -69,21 +52,31 @@ class C { foo(): string { return \"hello\"; } + // last wins x: number; x: string; + // last wins bar(): number { return 0; } bar: string; + // field wins over method qux: number; qux(): string { return \"hello\"; - } + } // method loses to field! } + +// check (new C().foo(): boolean); +// last wins (new C().x: boolean); +// last wins (new C().bar: boolean); +// last wins (new C().qux: boolean); +// weird outlier where last doesn\'t win in classes +// Objects const o = { foo(): number { return 0; @@ -91,20 +84,28 @@ const o = { foo(): string { return \"hello\"; }, + // last wins x: 42, x: \"hello\", + // last wins bar(): number { return 0; }, bar: \"hello\", + // last wins qux: 42, + // last wins qux(): string { return \"hello\"; } }; + +// check (o.foo(): boolean); +// last wins (o.x: boolean); +// last wins (o.bar: boolean); -(o.qux(): boolean); -" +// last wins +(o.qux(): boolean); // last wins" `; diff --git a/tests/lib/__snapshots__/jsfmt.spec.js.snap b/tests/lib/__snapshots__/jsfmt.spec.js.snap index 06d844c4..dd2f03b3 100644 --- a/tests/lib/__snapshots__/jsfmt.spec.js.snap +++ b/tests/lib/__snapshots__/jsfmt.spec.js.snap @@ -15,9 +15,10 @@ var x: string = NaN; var y: string = Number.MAX_VALUE; var z: number = new TypeError().name; var w: string = parseInt(\"...\"); + var a = new Map(); a.delete(\"foobar\"); + var b = undefined; -if (undefined) {} -" +if (undefined) {}" `; diff --git a/tests/lib_interfaces/declarations/__snapshots__/jsfmt.spec.js.snap b/tests/lib_interfaces/declarations/__snapshots__/jsfmt.spec.js.snap index df8e026d..8059332a 100644 --- a/tests/lib_interfaces/declarations/__snapshots__/jsfmt.spec.js.snap +++ b/tests/lib_interfaces/declarations/__snapshots__/jsfmt.spec.js.snap @@ -8,6 +8,5 @@ interface CArrays extends C> { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ interface C { foo(): CArrays, bar(): C } -interface CArrays extends C> { bar(): C } -" +interface CArrays extends C> { bar(): C }" `; diff --git a/tests/libconfig/__snapshots__/jsfmt.spec.js.snap b/tests/libconfig/__snapshots__/jsfmt.spec.js.snap index 7fd71f3a..d67d8662 100644 --- a/tests/libconfig/__snapshots__/jsfmt.spec.js.snap +++ b/tests/libconfig/__snapshots__/jsfmt.spec.js.snap @@ -1,15 +1,13 @@ exports[`test libA.js 1`] = ` "declare function foo(x: number): void; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -declare function foo(x: number): void; -" +declare function foo(x: number): void;" `; exports[`test libB.js 1`] = ` "declare function bar(x: string): void; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -declare function bar(x: string): void; -" +declare function bar(x: string): void;" `; exports[`test libtest.js 1`] = ` @@ -17,6 +15,5 @@ exports[`test libtest.js 1`] = ` bar(123); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ foo(123); -bar(123); -" +bar(123);" `; diff --git a/tests/libdef_ignored_module/__snapshots__/jsfmt.spec.js.snap b/tests/libdef_ignored_module/__snapshots__/jsfmt.spec.js.snap index 6bc3f2f4..d7fb8127 100644 --- a/tests/libdef_ignored_module/__snapshots__/jsfmt.spec.js.snap +++ b/tests/libdef_ignored_module/__snapshots__/jsfmt.spec.js.snap @@ -6,8 +6,8 @@ import foo from \"foo\"; (foo.bar : string); // error number ~> string ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// error number ~> string + import foo from \"foo\"; -(foo.bar: string); -" + +(foo.bar: string); // error number ~> string" `; diff --git a/tests/libdef_ignored_module/lib/__snapshots__/jsfmt.spec.js.snap b/tests/libdef_ignored_module/lib/__snapshots__/jsfmt.spec.js.snap index c410d55b..342633e9 100644 --- a/tests/libdef_ignored_module/lib/__snapshots__/jsfmt.spec.js.snap +++ b/tests/libdef_ignored_module/lib/__snapshots__/jsfmt.spec.js.snap @@ -5,6 +5,5 @@ exports[`test foo.js 1`] = ` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ declare module foo { declare var bar: number; -} -" +}" `; diff --git a/tests/liberr/__snapshots__/jsfmt.spec.js.snap b/tests/liberr/__snapshots__/jsfmt.spec.js.snap index 7a818bd7..c6dfc75d 100644 --- a/tests/liberr/__snapshots__/jsfmt.spec.js.snap +++ b/tests/liberr/__snapshots__/jsfmt.spec.js.snap @@ -9,6 +9,5 @@ var x: string = 0; * @flow */ // one error here, to verify lib errors sort to top. -var x: string = 0; -" +var x: string = 0;" `; diff --git a/tests/liberr/libs/__snapshots__/jsfmt.spec.js.snap b/tests/liberr/libs/__snapshots__/jsfmt.spec.js.snap index 59ecef80..c6253440 100644 --- a/tests/liberr/libs/__snapshots__/jsfmt.spec.js.snap +++ b/tests/liberr/libs/__snapshots__/jsfmt.spec.js.snap @@ -3,6 +3,5 @@ exports[`test type_error.js 1`] = ` declare function foo(x: number): Array; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -declare function foo(x: number): Array; -" +declare function foo(x: number): Array;" `; diff --git a/tests/libflow-typed/__snapshots__/jsfmt.spec.js.snap b/tests/libflow-typed/__snapshots__/jsfmt.spec.js.snap index c41c08da..f7e7e238 100644 --- a/tests/libflow-typed/__snapshots__/jsfmt.spec.js.snap +++ b/tests/libflow-typed/__snapshots__/jsfmt.spec.js.snap @@ -3,6 +3,5 @@ exports[`test libtest.js 1`] = ` const dino : Dinosaur = \"Stegosaurus\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -const dino: Dinosaur = \"Stegosaurus\"; -" +const dino: Dinosaur = \"Stegosaurus\";" `; diff --git a/tests/libflow-typed/flow-typed/__snapshots__/jsfmt.spec.js.snap b/tests/libflow-typed/flow-typed/__snapshots__/jsfmt.spec.js.snap index 8d037dfd..8e58db5e 100644 --- a/tests/libflow-typed/flow-typed/__snapshots__/jsfmt.spec.js.snap +++ b/tests/libflow-typed/flow-typed/__snapshots__/jsfmt.spec.js.snap @@ -1,6 +1,5 @@ exports[`test dino.js 1`] = ` "declare type Dinosaur = \"T-Rex\" | \"Apatosaurus\"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -type Dinosaur = \"T-Rex\" | \"Apatosaurus\"; -" +type Dinosaur = \"T-Rex\" | \"Apatosaurus\";" `; diff --git a/tests/librec/__snapshots__/jsfmt.spec.js.snap b/tests/librec/__snapshots__/jsfmt.spec.js.snap index 9d7c8b78..a02856e7 100644 --- a/tests/librec/__snapshots__/jsfmt.spec.js.snap +++ b/tests/librec/__snapshots__/jsfmt.spec.js.snap @@ -3,6 +3,5 @@ exports[`test libtest.js 1`] = ` bar(123); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ foo(123); -bar(123); -" +bar(123);" `; diff --git a/tests/librec/lib/A/__snapshots__/jsfmt.spec.js.snap b/tests/librec/lib/A/__snapshots__/jsfmt.spec.js.snap index 1fd0e097..93539593 100644 --- a/tests/librec/lib/A/__snapshots__/jsfmt.spec.js.snap +++ b/tests/librec/lib/A/__snapshots__/jsfmt.spec.js.snap @@ -1,6 +1,5 @@ exports[`test libA.js 1`] = ` "declare function foo(x: number): void; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -declare function foo(x: number): void; -" +declare function foo(x: number): void;" `; diff --git a/tests/librec/lib/B/__snapshots__/jsfmt.spec.js.snap b/tests/librec/lib/B/__snapshots__/jsfmt.spec.js.snap index eb296503..4661c7ae 100644 --- a/tests/librec/lib/B/__snapshots__/jsfmt.spec.js.snap +++ b/tests/librec/lib/B/__snapshots__/jsfmt.spec.js.snap @@ -1,6 +1,5 @@ exports[`test libB.js 1`] = ` "declare function bar(x: string): void; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -declare function bar(x: string): void; -" +declare function bar(x: string): void;" `; diff --git a/tests/literal/__snapshots__/jsfmt.spec.js.snap b/tests/literal/__snapshots__/jsfmt.spec.js.snap index 3b821102..ba95023f 100644 --- a/tests/literal/__snapshots__/jsfmt.spec.js.snap +++ b/tests/literal/__snapshots__/jsfmt.spec.js.snap @@ -7,8 +7,8 @@ exports[`test enum.js 1`] = ` module.exports = APIKeys; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ var APIKeys = { AGE: \"age\", NAME: \"name\" }; -module.exports = APIKeys; -" + +module.exports = APIKeys;" `; exports[`test enum_client.js 1`] = ` @@ -34,30 +34,28 @@ var indices = { red: 0, green: 1, blue: 2 }; var tuple = [42, \"hello\", false]; var red:string = tuple[indices.red]; // error: tuple[0] is a number ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// object that maps \"AGE\" to \"age\", \"NAME\" to \"name\" -// error -// not an error: APIKeys.AGE = \"age\" -// error: since \"NAME\" is not in the smaller enum -// i.e., object.age = 123 -// i.e., object.name = \"FOO\" -// error: object.name is a string -// error: tuple[0] is a number var APIKeys = require(\"./enum\"); +// object that maps \"AGE\" to \"age\", \"NAME\" to \"name\" function foo(x: $Keys) {} foo(\"AGE\"); foo(\"LOCATION\"); +// error function bar(x: $Keys<{ age: number }>) {} bar(APIKeys.AGE); +// not an error: APIKeys.AGE = \"age\" bar(APIKeys.NAME); +// error: since \"NAME\" is not in the smaller enum var object = {}; object[APIKeys.AGE] = 123; +// i.e., object.age = 123 object[APIKeys.NAME] = \"FOO\"; +// i.e., object.name = \"FOO\" var age: number = object[APIKeys.AGE]; var name: number = object[APIKeys.NAME]; +// error: object.name is a string var indices = { red: 0, green: 1, blue: 2 }; var tuple = [ 42, \"hello\", false ]; -var red: string = tuple[indices.red]; -" +var red: string = tuple[indices.red]; // error: tuple[0] is a number" `; exports[`test number.js 1`] = ` @@ -85,14 +83,16 @@ function test4(flip_times: number): number { return x; } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// sanity checks to make sure merging envs doesn\'t keep creating new NumT\'s -// because of the UnaryMinusT\'s, causing nontermination function test1(x: number): number { return -x; } + function test2(x: string): number { return -x; } + +// sanity checks to make sure merging envs doesn\'t keep creating new NumT\'s +// because of the UnaryMinusT\'s, causing nontermination function test3(x: number, flip_times: number): number { for (var i = 0; i < flip_times; i++) { x = -x; @@ -105,6 +105,5 @@ function test4(flip_times: number): number { x = -x; } return x; -} -" +}" `; diff --git a/tests/locals/__snapshots__/jsfmt.spec.js.snap b/tests/locals/__snapshots__/jsfmt.spec.js.snap index 38f06e4e..839e7ce0 100644 --- a/tests/locals/__snapshots__/jsfmt.spec.js.snap +++ b/tests/locals/__snapshots__/jsfmt.spec.js.snap @@ -60,18 +60,6 @@ function for_of_scope(xs: number[]) { (b : string); // error: number ~> string } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// doesn\'t add lower bound to outer a -// OK -// error: number ~> string -// doesn\'t add lower bound to outer a -// ok -// error: number ~> string -// doesn\'t add lower bound to outer a -// error: number ~> string -// doesn\'t add lower bound to outer a -// error: string ~> number -// doesn\'t add lower bound to outer a -// error: number ~> string function switch_scope(x: mixed) { let a = \"\"; let b = \"\"; @@ -79,11 +67,14 @@ function switch_scope(x: mixed) { case \"foo\": let a; a = 0; + // doesn\'t add lower bound to outer a b = 0; } (a: string); - (b: string); + // OK + (b: string); // error: number ~> string } + function try_scope_finally() { let a; let b; @@ -93,42 +84,49 @@ function try_scope_finally() { } finally { let a; a = 0; + // doesn\'t add lower bound to outer a b = 0; } (a: string); - (b: string); + // ok + (b: string); // error: number ~> string } + function for_scope() { let a = \"\"; let b = \"\"; for (let a; ; ) { a = 0; + // doesn\'t add lower bound to outer a b = 0; } (a: string); - (b: string); + (b: string); // error: number ~> string } + function for_in_scope(o: Object) { let a = 0; let b = 0; for (let a in o) { a = \"\"; + // doesn\'t add lower bound to outer a b = \"\"; } (a: number); - (b: number); + (b: number); // error: string ~> number } + function for_of_scope(xs: number[]) { let a = \"\"; let b = \"\"; for (let a of xs) { a = 0; + // doesn\'t add lower bound to outer a b = 0; } (a: string); - (b: string); -} -" + (b: string); // error: number ~> string +}" `; exports[`test locals.js 1`] = ` @@ -156,11 +154,12 @@ function foo0(b: bool): number { return x; } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -//declare var T: $Type>; -// error: string ~> number var x: string = 0; var x: number = 1; + +//declare var T: $Type>; function foo(p: boolean) {} + function sorry(really: boolean) { if (really) { var x: number | string = 1337; @@ -169,12 +168,12 @@ function sorry(really: boolean) { } foo(x); } + function foo0(b: boolean): number { var x = 0; if (b) { - var x = \"\"; + var x = \"\"; // error: string ~> number } return x; -} -" +}" `; diff --git a/tests/logical/__snapshots__/jsfmt.spec.js.snap b/tests/logical/__snapshots__/jsfmt.spec.js.snap index 77d9ffa3..3fdd1e2a 100644 --- a/tests/logical/__snapshots__/jsfmt.spec.js.snap +++ b/tests/logical/__snapshots__/jsfmt.spec.js.snap @@ -515,366 +515,346 @@ function logical19b(x: { y: string, z: boolean }): boolean { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + /** * A falsy variable on the left side of && */ -// expected \`: boolean\` +function logical1a(): number { + // expected \`: boolean\` + var x = false; + return x && \"123\"; +} + /** * A truthy variable on the left side of && */ +function logical1b(): string { + var x = true; + return x && \"123\"; +} + /** * A literal on the left side of && */ -// expected \`: boolean\` +function logical2a(): number { + // expected \`: boolean\` + return false && \"123\"; +} + /** * A literal on the left side of && */ +function logical2b(): number { + return 0 && \"123\"; +} + /** * A literal on the left side of && */ +function logical2c(): string { + return \"\" && 123; +} + /** * A literal on the left side of && */ +function logical2d(): string { + return true && \"123\"; +} + /** * A literal on the left side of && */ +function logical2e(): number { + return \"foo\" && 123; +} + /** * A literal on the left side of && */ +function logical2f(): string { + return 123 && \"foo\"; +} + /** * A literal on the left side of && */ +function logical2g(): string { + return [ 1, 2, 3 ] && \"foo\"; +} + /** * A literal on the left side of && */ +function logical2h(x: { a: number }): string { + return x && \"foo\"; +} + /** * A literal on the left side of && */ +function logical2i(x: Object): string { + return x && \"foo\"; +} + /** * A literal on the left side of && */ +function logical2j(x: (a: number) => number): string { + return x && \"foo\"; +} + /** * A literal on the left side of && */ +function logical2k(x: Function): string { + return x && \"foo\"; +} + /** * An expression on the left side of && */ -// expected \`: boolean\` +function logical3a(): string { + // expected \`: boolean\` + var x: ?number = null; + return x != null && x > 10; +} + /** * An expression on the left side of && */ -// expected \`: boolean | number\` +function logical3b(): number { + // expected \`: boolean | number\` + var x: ?number = null; + return x != null && x; +} + /** * An expression on the left side of && */ -// expected \`: boolean | ?number\` +function logical3c(): ?number { + // expected \`: boolean | ?number\` + var x: ?number = null; + return x != undefined && x; +} + /** * Maybe truthy returns both types */ -// expected \`: boolean | string\` +function logical4(x: boolean): string { + // expected \`: boolean | string\` + return x && \"123\"; +} + /** * A falsy variable on the left side of || */ +function logical5a(): number { + var x = false; + return x || 0; +} + /** * A maybe variable on the left side of || */ +function logical5b(): number { + var x: ?number = null; + return x || 0; +} + /** * A truthy variable on the left side of || */ -// expected \`: boolean\` +function logical5c(): string { + // expected \`: boolean\` + var x = true; + return x || 0; +} + /** * A literal on the left side of || */ +function logical6a(): string { + return false || \"123\"; +} + /** * A literal on the left side of || */ +function logical6b(): string { + return 0 || \"123\"; +} + /** * A literal on the left side of || */ +function logical6c(): number { + return \"\" || 123; +} + /** * A literal on the left side of || */ -// expected \`: boolean\` +function logical6d(): number { + // expected \`: boolean\` + return true || \"123\"; +} + /** * A literal on the left side of || */ +function logical6e(): string { + return \"foo\" || 123; +} + /** * A literal on the left side of || */ +function logical6f(): number { + return 123 || \"foo\"; +} + /** * A composite && and || */ +function logical7a(): number { + var x: ?number = null; + return x != null && x || 0; +} + /** * A composite && and || where the truthiness is unknown */ +function logical7b(x: boolean, y: number): number { + return x && y || 0; +} + /** * A composite && and || */ +function logical7c(x: string): number { + return x && 1 || 0; +} + /** * A composite && and || */ +function logical7d(x: number): string { + return x && \"foo\" || \"bar\"; +} + /** * A composite && and || */ +function logical7e(x: number): string { + return false && x || \"bar\"; +} + /** * A composite || and && * * \`x || 0\` always returns a number (never a boolean) and then short * circuits the && because 0 is falsy, so this should just return number. */ +function logical8a(): number { + var x = false; + return (x || 0) && \"foo\"; +} + /** * A composite || and && * * \`x || 1\` always returns something truthy, so this returns a string */ +function logical8b(): string { + var x = false; + return (x || 1) && \"foo\"; +} + /** * A composite || and && * * \`x\` is always truthy, so this returns a string */ -/** - * A composite || and && - */ -/** - * A composite || and && - */ -/** - * A composite || and && - */ -// expected \`: boolean\` -/** - * A composite || and || - */ -// expected \`: number | string | boolean\` -/** - * A composite || and || - */ -/** - * A composite || and || - */ -/** - * A composite && and && - */ -// expected \`: number | string | boolean\` -/** - * A composite && and && - */ -// expected \`: boolean\` -/** - * A composite && and && - */ -// expected \`number | boolean\` -/** - * || in a loop - */ -/** - * || in a loop - */ -// expected a number -/** - * && in a loop - */ -/** - * && in a loop - */ -// expected a number -/** - * Complex && - */ -/** - * Complex || - */ -/** - * || in an addition - */ -/** - * || in an addition - */ -/** - * && in an addition - */ -/** - * && in an addition - */ -/** - * || in a comparison - */ -/** - * || in a comparison - */ -/** - * && in a comparison - */ -/** - * && in a comparison - */ -/** - * || in an equality - */ -/** - * || in an equality - */ -/** - * && in an equality - */ -/** - * && in an equality - */ -/** - * Expressions on each side that return truthy things - */ -/** - * Sentinel properties should not interfere - */ -/** - * Layer of indirection in the LHS (get prop) - */ -// error: x.y is a string -// error: x.y is a string -function logical1a(): number { - var x = false; - return x && \"123\"; -} -function logical1b(): string { - var x = true; - return x && \"123\"; -} -function logical2a(): number { - return false && \"123\"; -} -function logical2b(): number { - return 0 && \"123\"; -} -function logical2c(): string { - return \"\" && 123; -} -function logical2d(): string { - return true && \"123\"; -} -function logical2e(): number { - return \"foo\" && 123; -} -function logical2f(): string { - return 123 && \"foo\"; -} -function logical2g(): string { - return [ 1, 2, 3 ] && \"foo\"; -} -function logical2h(x: { a: number }): string { - return x && \"foo\"; -} -function logical2i(x: Object): string { - return x && \"foo\"; -} -function logical2j(x: (a: number) => number): string { - return x && \"foo\"; -} -function logical2k(x: Function): string { - return x && \"foo\"; -} -function logical3a(): string { - var x: ?number = null; - return x != null && x > 10; -} -function logical3b(): number { - var x: ?number = null; - return x != null && x; -} -function logical3c(): ?number { - var x: ?number = null; - return x != undefined && x; -} -function logical4(x: boolean): string { - return x && \"123\"; -} -function logical5a(): number { - var x = false; - return x || 0; -} -function logical5b(): number { - var x: ?number = null; - return x || 0; -} -function logical5c(): string { - var x = true; - return x || 0; -} -function logical6a(): string { - return false || \"123\"; -} -function logical6b(): string { - return 0 || \"123\"; -} -function logical6c(): number { - return \"\" || 123; -} -function logical6d(): number { - return true || \"123\"; -} -function logical6e(): string { - return \"foo\" || 123; -} -function logical6f(): number { - return 123 || \"foo\"; -} -function logical7a(): number { - var x: ?number = null; - return x != null && x || 0; -} -function logical7b(x: boolean, y: number): number { - return x && y || 0; -} -function logical7c(x: string): number { - return x && 1 || 0; -} -function logical7d(x: number): string { - return x && \"foo\" || \"bar\"; -} -function logical7e(x: number): string { - return false && x || \"bar\"; -} -function logical8a(): number { - var x = false; - return (x || 0) && \"foo\"; -} -function logical8b(): string { - var x = false; - return (x || 1) && \"foo\"; -} function logical8c(): string { var x = true; return (x || 1) && \"foo\"; } + +/** + * A composite || and && + */ function logical8d(): number { var x = false; return x || 0 && \"foo\"; } + +/** + * A composite || and && + */ function logical8e(): string { var x = false; return x || 1 && \"foo\"; } + +/** + * A composite || and && + */ function logical8f(): string { + // expected \`: boolean\` var x = true; return x || 1 && \"foo\"; } + +/** + * A composite || and || + */ function logical9a(x: number, y: string): number | string { + // expected \`: number | string | boolean\` return x || y || false; } + +/** + * A composite || and || + */ function logical9b(x: number, y: string): number | string { return false || x || y; } + +/** + * A composite || and || + */ function logical9c(x: number, y: boolean): string { return \"a\" || x || y; } + +/** + * A composite && and && + */ function logical10a(x: number, y: string): number | string { + // expected \`: number | string | boolean\` return x && y && false; } + +/** + * A composite && and && + */ function logical10b(x: number, y: string): Array { + // expected \`: boolean\` return false && x && y; } + +/** + * A composite && and && + */ function logical10c(x: number, y: string): Array { + // expected \`number | boolean\` return x && false && y; } + +/** + * || in a loop + */ function logical11a(): number { var y = 1; for (var x = 0; x < 5; x++) { @@ -882,12 +862,20 @@ function logical11a(): number { } return y; } + +/** + * || in a loop + */ function logical11b(y: number): number { for (var x = 0; x < 5; x++) { - y = y || true; + y = y || true; // expected a number } return y; } + +/** + * && in a loop + */ function logical12a(): number { var y = 1; var z = true; @@ -897,12 +885,20 @@ function logical12a(): number { } return y; } + +/** + * && in a loop + */ function logical12b(y: number): number { for (var x = 0; x < 5; x++) { - y = y && true; + y = y && true; // expected a number } return y; } + +/** + * Complex && + */ function logical13(x: number): Array<{ x: string }> { return [ { x: x && \"bar\" }, @@ -915,6 +911,10 @@ function logical13(x: number): Array<{ x: string }> { { x: \"foo\" && \"bar\" } ]; } + +/** + * Complex || + */ function logical14(x: number): Array<{ x: string }> { return [ { x: x || \"bar\" }, @@ -927,53 +927,112 @@ function logical14(x: number): Array<{ x: string }> { { x: \"foo\" || \"bar\" } ]; } + +/** + * || in an addition + */ function logical15a(x: number): number { return 5 + (x || 7); } + +/** + * || in an addition + */ function logical15b(x: number): number { return (x || 7) + 5; } + +/** + * && in an addition + */ function logical15c(x: number): number { return 5 + (x && 7); } + +/** + * && in an addition + */ function logical15d(x: number): number { return (x && 7) + 5; } + +/** + * || in a comparison + */ function logical16a(x: number): boolean { return 5 < (x || 7); } + +/** + * || in a comparison + */ function logical16b(x: number): boolean { return (x || 7) < 5; } + +/** + * && in a comparison + */ function logical16c(x: number): boolean { return 5 < (x && 7); } + +/** + * && in a comparison + */ function logical16d(x: number): boolean { return (x && 7) < 5; } + +/** + * || in an equality + */ function logical17a(x: number): boolean { return 5 == (x || 7); } + +/** + * || in an equality + */ function logical17b(x: number): boolean { return (x || 7) == 5; } + +/** + * && in an equality + */ function logical17c(x: number): boolean { return 5 == (x && 7); } + +/** + * && in an equality + */ function logical17d(x: number): boolean { return (x && 7) == 5; } + +/** + * Expressions on each side that return truthy things + */ function logical18a(x: number, y: number): number { return x - 1 || y - 1; } + +/** + * Sentinel properties should not interfere + */ function logical18b(x: { a: number }, y: { b: number }): number { return x.a - 1 || y.b - 1; } + +/** + * Layer of indirection in the LHS (get prop) + */ function logical19a(x: { y: string, z: boolean }): boolean { - return x.y && x.z; + return x.y && x.z; // error: x.y is a string } function logical19b(x: { y: string, z: boolean }): boolean { - return x.y || x.z; -} -" + return x.y || x.z; // error: x.y is a string +}" `; diff --git a/tests/loners/__snapshots__/jsfmt.spec.js.snap b/tests/loners/__snapshots__/jsfmt.spec.js.snap index 37c7f72b..8dfc340f 100644 --- a/tests/loners/__snapshots__/jsfmt.spec.js.snap +++ b/tests/loners/__snapshots__/jsfmt.spec.js.snap @@ -9,14 +9,15 @@ var export_f: (u: number) => number = f; //exports = export_o; module.exports = export_f; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -//exports = export_o; var o = { x: 5, y: \"jello\" }; var z = o.z; var export_o: { x: number } = o; + function f(u, v?): number { return u; } var export_f: (u: number) => number = f; -module.exports = export_f; -" + +//exports = export_o; +module.exports = export_f;" `; diff --git a/tests/method_properties/__snapshots__/jsfmt.spec.js.snap b/tests/method_properties/__snapshots__/jsfmt.spec.js.snap index 652cb90f..3ed323de 100644 --- a/tests/method_properties/__snapshots__/jsfmt.spec.js.snap +++ b/tests/method_properties/__snapshots__/jsfmt.spec.js.snap @@ -8,9 +8,10 @@ declare class Foo { export {Foo}; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + declare class Foo { bar?: () => string } -export {Foo} -" + +export {Foo}" `; exports[`test test.js 1`] = ` @@ -33,8 +34,6 @@ function f(x) { } f(foo); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// error, could be undefined -// error. caused by \`f(foo)\`; annotate x to track it down. class C { C() {} foo() {} @@ -46,12 +45,13 @@ class C { C.x; new C().foo.x; C.bar.x; + import {Foo} from \"./exports_optional_prop\"; const foo = new Foo(); (foo.bar(): string); +// error, could be undefined function f(x) { - (x.bar(): string); + (x.bar(): string); // error. caused by \`f(foo)\`; annotate x to track it down. } -f(foo); -" +f(foo);" `; diff --git a/tests/misc/__snapshots__/jsfmt.spec.js.snap b/tests/misc/__snapshots__/jsfmt.spec.js.snap index eec2e231..46cc3a7e 100644 --- a/tests/misc/__snapshots__/jsfmt.spec.js.snap +++ b/tests/misc/__snapshots__/jsfmt.spec.js.snap @@ -15,16 +15,18 @@ A.x = A.y; f(A.x); // A.x is now a string, by def assign ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @providesModule A */ -// A.x is now a string, by def assign + module.exports = {}; + var A = { x: true, ...{} }; module.exports.cls = A; + function f(x: boolean) {} module.exports.fn = f; + A.y = \"?\"; A.x = A.y; -f(A.x); -" +f(A.x); // A.x is now a string, by def assign" `; exports[`test B.js 1`] = ` @@ -45,17 +47,21 @@ B.prototype.fn = f; module.exports = B; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @providesModule B */ + var A = require(\"A\").cls; + function B() { this.b = \"...\"; } + function f(): number { return this.b; } + B.prototype.s = 0; B.prototype.fn = f; -module.exports = B; -" + +module.exports = B;" `; exports[`test C.js 1`] = ` @@ -75,16 +81,18 @@ function C() { module.exports = C; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @providesModule C */ + var B = require(\"B\"); var f = require(\"A\").fn; + function C() { var o = new B(); f(o.b); f(o.s); o.fn(); } -module.exports = C; -" + +module.exports = C;" `; exports[`test D.js 1`] = ` @@ -104,16 +112,20 @@ f(i); module.exports = \"D for dummy\"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @providesModule D */ + var f = require(\"A\").fn; + function g(): string { return this.i; } + var o = { fn: g, ...{} }; o.i = true; + var i = o.fn(); f(i); -module.exports = \"D for dummy\"; -" + +module.exports = \"D for dummy\";" `; exports[`test E.js 1`] = ` @@ -129,12 +141,14 @@ o.fn(false); module.exports = {obj: o}; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @providesModule E */ + function h(x: number) {} var proto = { fn: h }; + var o = Object.create(proto); o.fn(false); -module.exports = { obj: o }; -" + +module.exports = { obj: o };" `; exports[`test F.js 1`] = ` @@ -149,10 +163,10 @@ function fn2(x) { return x.length * 4; } fn2({ length: \"hi\" }); + function foo(x: Array): string { return x.length; -} -" +}" `; exports[`test G.js 1`] = ` @@ -167,8 +181,8 @@ b.length(); var a = { length: \"duck\" }; a.length = 123; a.length(); + var b = [ 123 ]; b.length = \"duck\"; -b.length(); -" +b.length();" `; diff --git a/tests/missing_annotation/__snapshots__/jsfmt.spec.js.snap b/tests/missing_annotation/__snapshots__/jsfmt.spec.js.snap index 8825ef9d..6d1ab156 100644 --- a/tests/missing_annotation/__snapshots__/jsfmt.spec.js.snap +++ b/tests/missing_annotation/__snapshots__/jsfmt.spec.js.snap @@ -6,10 +6,10 @@ var f: Foo = {}; export var arr = [f]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + type Foo = {}; var f: Foo = {}; -export var arr = [ f ]; -" +export var arr = [ f ];" `; exports[`test async_return.js 1`] = ` @@ -20,10 +20,10 @@ export async function foo() { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + export async function foo() { return 123; -} -" +}" `; exports[`test infer.js 1`] = ` @@ -87,51 +87,53 @@ var Bar = { module.exports = Foo, Bar; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// missing arg annotation -// missing arg annotation -// no return annotation required -// return type annotation may be omitted, but if so, input positions on -// observed return type (e.g. param types in a function type) must come -// from annotations -// missing param annotation -// ...if the return type is annotated explicitly, this is unnecessary -// no error -// no annotation required -// object property types are inferred, so make sure that this doesn\'t cause -// us to also infer the parameter\'s type. -// no annotation required -// no annotation required -// no annotation required + var Foo = { a: function(arg) { + // missing arg annotation return arg; }, b: function(arg) { + // missing arg annotation return { bar: arg }; }, c: function(arg: string) { + // no return annotation required return { bar: arg }; }, d: function(arg: string): { bar: string } { return { bar: arg }; }, + // return type annotation may be omitted, but if so, input positions on + // observed return type (e.g. param types in a function type) must come + // from annotations e: function(arg: string) { return function(x) { + // missing param annotation return x; }; }, + // ...if the return type is annotated explicitly, this is unnecessary f: function(arg: string): (x: number) => number { return function(x) { + // no error return x; }; } }; + var Bar = { a: Foo.a(\"Foo\"), + // no annotation required + // object property types are inferred, so make sure that this doesn\'t cause + // us to also infer the parameter\'s type. b: Foo.b(\"bar\"), + // no annotation required c: Foo.c(\"bar\"), + // no annotation required + // no annotation required d: Foo.d(\"bar\") }; -module.exports = Foo, Bar; -" + +module.exports = Foo, Bar;" `; diff --git a/tests/modified_lib/__snapshots__/jsfmt.spec.js.snap b/tests/modified_lib/__snapshots__/jsfmt.spec.js.snap index 2c17a143..782091f1 100644 --- a/tests/modified_lib/__snapshots__/jsfmt.spec.js.snap +++ b/tests/modified_lib/__snapshots__/jsfmt.spec.js.snap @@ -6,7 +6,8 @@ import {bar} from \'foo\'; bar(5); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + import {bar} from \"foo\"; -bar(5); -" + +bar(5);" `; diff --git a/tests/modified_lib/lib/__snapshots__/jsfmt.spec.js.snap b/tests/modified_lib/lib/__snapshots__/jsfmt.spec.js.snap index 4a8925e2..ba0f6c55 100644 --- a/tests/modified_lib/lib/__snapshots__/jsfmt.spec.js.snap +++ b/tests/modified_lib/lib/__snapshots__/jsfmt.spec.js.snap @@ -5,6 +5,5 @@ exports[`test lib.js 1`] = ` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ declare module \"foo\" { declare function bar(str: string): number; -} -" +}" `; diff --git a/tests/module_not_found_errors/src/__snapshots__/jsfmt.spec.js.snap b/tests/module_not_found_errors/src/__snapshots__/jsfmt.spec.js.snap index f0bdd78a..2cfdf7be 100644 --- a/tests/module_not_found_errors/src/__snapshots__/jsfmt.spec.js.snap +++ b/tests/module_not_found_errors/src/__snapshots__/jsfmt.spec.js.snap @@ -8,9 +8,10 @@ require(\'module_completely_absent\'); require(\'module_outside_of_root\'); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + +require(\"module_completely_absent\"); + // node_modules/module_outside_of_root/ sits outside of the Flow project root. // Flow should give a descriptive error about this -require(\"module_completely_absent\"); -require(\"module_outside_of_root\"); -" +require(\"module_outside_of_root\");" `; diff --git a/tests/module_redirect/__snapshots__/jsfmt.spec.js.snap b/tests/module_redirect/__snapshots__/jsfmt.spec.js.snap index 35a4f84e..7332b44a 100644 --- a/tests/module_redirect/__snapshots__/jsfmt.spec.js.snap +++ b/tests/module_redirect/__snapshots__/jsfmt.spec.js.snap @@ -5,8 +5,7 @@ exports[`test A.js 1`] = ` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ declare module A { declare function foo(): string; -} -" +}" `; exports[`test B.js 1`] = ` @@ -21,8 +20,8 @@ module.exports = require(\'A\'); * @providesModule B * @flow */ -module.exports = require(\"A\"); -" + +module.exports = require(\"A\");" `; exports[`test C.js 1`] = ` @@ -37,8 +36,8 @@ module.exports = require(\'B\'); * @providesModule C * @flow */ -module.exports = require(\"B\"); -" + +module.exports = require(\"B\");" `; exports[`test D.js 1`] = ` @@ -55,8 +54,8 @@ var bar3: string = require(\'C\'); * @providesModule D * @flow */ + var bar1: string = require(\"A\"); var bar2: string = require(\"B\"); -var bar3: string = require(\"C\"); -" +var bar3: string = require(\"C\");" `; diff --git a/tests/module_use_strict/__snapshots__/jsfmt.spec.js.snap b/tests/module_use_strict/__snapshots__/jsfmt.spec.js.snap index 4252dec7..4fd6cd9d 100644 --- a/tests/module_use_strict/__snapshots__/jsfmt.spec.js.snap +++ b/tests/module_use_strict/__snapshots__/jsfmt.spec.js.snap @@ -4,6 +4,6 @@ exports[`test test.js 1`] = ` (01: number); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -(1: number); -" + +(1: number);" `; diff --git a/tests/modules/__snapshots__/jsfmt.spec.js.snap b/tests/modules/__snapshots__/jsfmt.spec.js.snap index e604d943..ef5fb0d7 100644 --- a/tests/modules/__snapshots__/jsfmt.spec.js.snap +++ b/tests/modules/__snapshots__/jsfmt.spec.js.snap @@ -6,9 +6,10 @@ var f = require(\'./lib\'); var y:number = f(0); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + var f = require(\"./lib\"); -var y: number = f(0); -" + +var y: number = f(0);" `; exports[`test cli2.js 1`] = ` @@ -19,9 +20,10 @@ var f = require(\'./lib\'); f(\"...\"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + var f = require(\"./lib\"); -f(\"...\"); -" + +f(\"...\");" `; exports[`test lib.js 1`] = ` @@ -36,13 +38,15 @@ function f(x:number):number { g(x); return x; } module.exports = f; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + +function g(x: string) {} + //function f(x) { g(x); return x; } //function f(x:number) { g(x); return x; } -function g(x: string) {} function f(x: number): number { g(x); return x; } -module.exports = f; -" + +module.exports = f;" `; diff --git a/tests/more_annot/__snapshots__/jsfmt.spec.js.snap b/tests/more_annot/__snapshots__/jsfmt.spec.js.snap index 3d7a75d5..2ab283b2 100644 --- a/tests/more_annot/__snapshots__/jsfmt.spec.js.snap +++ b/tests/more_annot/__snapshots__/jsfmt.spec.js.snap @@ -4,8 +4,8 @@ exports[`test client_object.js 1`] = ` var a:number = o.w.z.y; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ var o = require(\"./object\"); -var a: number = o.w.z.y; -" + +var a: number = o.w.z.y;" `; exports[`test object.js 1`] = ` @@ -19,13 +19,14 @@ o3.w = o2; module.exports = o3; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -//declare var exports: { w: any }; var o1 = { x: 0, y: \"\" }; var o2 = { z: o1 }; + var o3 = {}; o3.w = o2; -module.exports = o3; -" + +//declare var exports: { w: any }; +module.exports = o3;" `; exports[`test proto.js 1`] = ` @@ -40,9 +41,10 @@ function Foo() { this.x = 0; } Foo.prototype.m = function() {}; + var o1: { x: number, m(): void } = new Foo(); -var o2: Foo = new Foo(); -" + +var o2: Foo = new Foo();" `; exports[`test super.js 1`] = ` @@ -55,6 +57,6 @@ class C { m() {} } class D extends C {} -var d: { +m: () => void } = new D(); -" + +var d: { +m: () => void } = new D();" `; diff --git a/tests/more_classes/__snapshots__/jsfmt.spec.js.snap b/tests/more_classes/__snapshots__/jsfmt.spec.js.snap index 721db0ca..53e445a2 100644 --- a/tests/more_classes/__snapshots__/jsfmt.spec.js.snap +++ b/tests/more_classes/__snapshots__/jsfmt.spec.js.snap @@ -21,7 +21,9 @@ class Bar { module.exports = Bar; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @providesModule Bar */ + var Qux = require(\"Qux\"); + class Bar { y: number; self: Bar; @@ -29,13 +31,14 @@ class Bar { this.y = y; this.self = this; } + bar(z: string, u: string): string { new Qux().w = \"?\"; return z; } } -module.exports = Bar; -" + +module.exports = Bar;" `; exports[`test Foo.js 1`] = ` @@ -67,13 +70,16 @@ class Foo extends Qux { module.exports = Foo; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @providesModule Foo */ + var Bar = require(\"Bar\"); var Qux = require(\"Qux\"); + class Foo extends Qux { x: string; constructor(x: string) { this.x = x; } + foo(y: string, z): number { this.x = y; var u = new Foo(\"...\").qux(); @@ -81,12 +87,13 @@ class Foo extends Qux { v.self = v; return v.bar(z, u); } + fooqux(x: string) { this.x; } } -module.exports = Foo; -" + +module.exports = Foo;" `; exports[`test Qux.js 1`] = ` @@ -104,13 +111,16 @@ class Qux { module.exports = Qux; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @providesModule Qux */ + class Qux { w: number; + qux() { return this.w; } + fooqux(x: number) {} } -module.exports = Qux; -" + +module.exports = Qux;" `; diff --git a/tests/more_generics/__snapshots__/jsfmt.spec.js.snap b/tests/more_generics/__snapshots__/jsfmt.spec.js.snap index 45b91272..6b3f50da 100644 --- a/tests/more_generics/__snapshots__/jsfmt.spec.js.snap +++ b/tests/more_generics/__snapshots__/jsfmt.spec.js.snap @@ -29,41 +29,46 @@ function foo8(x:U,y):U { foo8(0,void 0); */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +var foo1 = function(x: T): T { + return x; +}; + +function foo2(x: T): S { + return x; +} + +var foo3 = function(x: T): T { + return foo3(x); +}; + +function foo4(x: T): S { + return foo4(x); +} + +var x = []; +function foo5(): Array { + return x; +} /* var a = foo5(); a[0] = 0; var b = foo5(); var y: string = b[0]; */ -/* - foo8(0,void 0); -*/ -var foo1 = function(x: T): T { - return x; -}; -function foo2(x: T): S { - return x; -} -var foo3 = function(x: T): T { - return foo3(x); -}; -function foo4(x: T): S { - return foo4(x); -} -var x = []; -function foo5(): Array { - return x; -} var foo6 = function(x: R): R { return foo1(x); }; + function foo7(x: R): R { return foo5(); } + function foo8(x: U, y): U { var z = foo8(x, x); y(); return x; } -" +/* + foo8(0,void 0); +*/" `; diff --git a/tests/more_path/__snapshots__/jsfmt.spec.js.snap b/tests/more_path/__snapshots__/jsfmt.spec.js.snap index c99ae1ae..efffb41c 100644 --- a/tests/more_path/__snapshots__/jsfmt.spec.js.snap +++ b/tests/more_path/__snapshots__/jsfmt.spec.js.snap @@ -58,33 +58,36 @@ function goofy2() { module.exports = true; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @providesModule Condition */ -//f(y); -// if (typeof x == \'number\') { -//f(x); -//f(y); + function f(x: number) {} function g() { return 42 || \"hello\"; } + var x = g(); if (typeof x === \"string\") { x = 0; } f(x); + class A {} function h() { return 42 || new A(); } + var y = h(); if (y instanceof A) { y = 0; } +//f(y); function bar() { return true; } + class C { qux() {} } + function foo() { var c = \"...\"; c = new C(); @@ -92,12 +95,14 @@ function foo() { c.qux(); } } + function goofy() { var x = g(); if (typeof x == \"function\") { x(); } else {} } + function goofy2() { var o = { x: 0 }; if (typeof o.x == \"function\") { @@ -108,8 +113,8 @@ function goofy2() { y(); } else {} } -module.exports = true; -" + +module.exports = true;" `; exports[`test FlowSA.js 1`] = ` @@ -127,14 +132,16 @@ function FlowSA() { module.exports = FlowSA; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @providesModule FlowSA */ + function check(x: string) {} + function FlowSA() { var x = 0; x = \"...\"; check(x); } -module.exports = FlowSA; -" + +module.exports = FlowSA;" `; exports[`test Sigma.js 1`] = ` @@ -180,47 +187,49 @@ function baz(x:D) { module.exports = \"sigma\"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @providesModule Sigma */ -// error -// TODO no error? since unreachable (x: B implies x: A) -// error -// error -// unreachable, TODO: this shouldn\'t throw + class A { a() {} } + class B extends A { b() {} } + class C extends B { c() {} } + function bar(x: B) { if (x instanceof A) { x.a(); - x.c(); + x.c(); // error } else { - x++; + x++; // TODO no error? since unreachable (x: B implies x: A) } } + function foo(x: A) { if (x instanceof C) { x.a(); x.b(); x.c(); - x.d(); + x.d(); // error } else { x.a(); - x.c(); + x.c(); // error } } + class D { d() {} } + function baz(x: D) { if (x instanceof A) {} } -module.exports = \"sigma\"; -" + +module.exports = \"sigma\";" `; exports[`test test.js 1`] = ` @@ -239,18 +248,18 @@ function test(obj: BaseClass): string { return obj.baseProp; } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// error (obj: ChildClass) class BaseClass { baseProp: string; } + class ChildClass extends BaseClass { childProp: string; } + function test(obj: BaseClass): string { if (obj instanceof ChildClass) { - return obj.childProp_TYPO; + return obj.childProp_TYPO; // error (obj: ChildClass) } return obj.baseProp; -} -" +}" `; diff --git a/tests/more_statics/__snapshots__/jsfmt.spec.js.snap b/tests/more_statics/__snapshots__/jsfmt.spec.js.snap index 11146568..deeebdba 100644 --- a/tests/more_statics/__snapshots__/jsfmt.spec.js.snap +++ b/tests/more_statics/__snapshots__/jsfmt.spec.js.snap @@ -15,12 +15,13 @@ class B { return \"\"; } } + class C extends B { static bar(): string { return \"\"; } } + var x: number = C.bar(); -var y: number = C.foo(); -" +var y: number = C.foo();" `; diff --git a/tests/name_prop/__snapshots__/jsfmt.spec.js.snap b/tests/name_prop/__snapshots__/jsfmt.spec.js.snap index 14f68d41..98fca7d3 100644 --- a/tests/name_prop/__snapshots__/jsfmt.spec.js.snap +++ b/tests/name_prop/__snapshots__/jsfmt.spec.js.snap @@ -10,19 +10,18 @@ var test4 = a.constructor.bar; // Error bar doesn\'t exist var test5: string = a.constructor.name; var test6: number = a.constructor.name; // Error string ~> number ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Error bar doesn\'t exist -// Error string ~> number -// Error bar doesn\'t exist -// Error string ~> number class A {} + var test1 = A.bar; +// Error bar doesn\'t exist var test2: string = A.name; var test3: number = A.name; +// Error string ~> number var a = new A(); var test4 = a.constructor.bar; +// Error bar doesn\'t exist var test5: string = a.constructor.name; -var test6: number = a.constructor.name; -" +var test6: number = a.constructor.name; // Error string ~> number" `; exports[`test function.js 1`] = ` @@ -31,10 +30,5 @@ exports[`test function.js 1`] = ` * know that .name exists */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -/* TODO - we currently say that a function\'s statics are an AnyObjT and - * anything goes. When we start enforcing the statics properly, we\'ll need to - * know that .name exists - */ - " `; diff --git a/tests/namespace/__snapshots__/jsfmt.spec.js.snap b/tests/namespace/__snapshots__/jsfmt.spec.js.snap index 7d6b4a42..a45553f8 100644 --- a/tests/namespace/__snapshots__/jsfmt.spec.js.snap +++ b/tests/namespace/__snapshots__/jsfmt.spec.js.snap @@ -4,8 +4,8 @@ exports[`test client.js 1`] = ` var bar: string = ns.foo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ var ns = require(\"./namespace\"); -var bar: string = ns.foo; -" + +var bar: string = ns.foo;" `; exports[`test namespace.js 1`] = ` @@ -31,14 +31,18 @@ module.exports = { foo: (\"\": number) }; // import type { T } from \'...\' type T = (x: number) => void; var f: T = function(x: string): void {}; + type Map = (x: X) => Y; + function bar(x: U, f: Map): V { return f(x); } + var y: number = bar(0, x => \"\"); + type Seq = number | Array; var s1: Seq = [ 0, [ 0 ] ]; var s2: Seq = [ [ \"\" ] ]; -module.exports = { foo: (\"\": number) }; -" + +module.exports = { foo: (\"\": number) };" `; diff --git a/tests/node_haste/__snapshots__/jsfmt.spec.js.snap b/tests/node_haste/__snapshots__/jsfmt.spec.js.snap index fc391296..e5324a10 100644 --- a/tests/node_haste/__snapshots__/jsfmt.spec.js.snap +++ b/tests/node_haste/__snapshots__/jsfmt.spec.js.snap @@ -1,14 +1,11 @@ exports[`test client.js 1`] = ` "var md5 = require(\'./md5\'); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -var md5 = require(\"./md5\"); -" +var md5 = require(\"./md5\");" `; exports[`test md5.js 1`] = ` "/* @providesModule md5 */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -/* @providesModule md5 */ - " `; diff --git a/tests/node_haste/external/_d3/__snapshots__/jsfmt.spec.js.snap b/tests/node_haste/external/_d3/__snapshots__/jsfmt.spec.js.snap index 89dbe61e..f4edecce 100644 --- a/tests/node_haste/external/_d3/__snapshots__/jsfmt.spec.js.snap +++ b/tests/node_haste/external/_d3/__snapshots__/jsfmt.spec.js.snap @@ -1,5 +1,4 @@ exports[`test min.js 1`] = ` "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - " `; diff --git a/tests/node_haste/foo/bar/__snapshots__/jsfmt.spec.js.snap b/tests/node_haste/foo/bar/__snapshots__/jsfmt.spec.js.snap index c271ad79..22c07513 100644 --- a/tests/node_haste/foo/bar/__snapshots__/jsfmt.spec.js.snap +++ b/tests/node_haste/foo/bar/__snapshots__/jsfmt.spec.js.snap @@ -7,11 +7,11 @@ var corge = require(\'qux/corge\'); // annotations - see node_modules/qux/docblock.js var unreachable = require(\'annotation\'); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// make sure we don\'t pick up non-header @providesModule -// annotations - see node_modules/qux/docblock.js var docblock = require(\"qux/docblock\"); var min = require(\"d3/min.js\"); var corge = require(\"qux/corge\"); -var unreachable = require(\"annotation\"); -" + +// make sure we don\'t pick up non-header @providesModule +// annotations - see node_modules/qux/docblock.js +var unreachable = require(\"annotation\");" `; diff --git a/tests/node_haste/ws/__snapshots__/jsfmt.spec.js.snap b/tests/node_haste/ws/__snapshots__/jsfmt.spec.js.snap index c0fb13f9..b5388480 100644 --- a/tests/node_haste/ws/__snapshots__/jsfmt.spec.js.snap +++ b/tests/node_haste/ws/__snapshots__/jsfmt.spec.js.snap @@ -1,5 +1,4 @@ exports[`test index.js 1`] = ` "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - " `; diff --git a/tests/node_haste/ws/test/__snapshots__/jsfmt.spec.js.snap b/tests/node_haste/ws/test/__snapshots__/jsfmt.spec.js.snap index 188da262..428ec8fd 100644 --- a/tests/node_haste/ws/test/__snapshots__/jsfmt.spec.js.snap +++ b/tests/node_haste/ws/test/__snapshots__/jsfmt.spec.js.snap @@ -1,6 +1,5 @@ exports[`test client.js 1`] = ` "var ws = require(\'../\'); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -var ws = require(\"../\"); -" +var ws = require(\"../\");" `; diff --git a/tests/node_modules_with_symlinks/root/__snapshots__/jsfmt.spec.js.snap b/tests/node_modules_with_symlinks/root/__snapshots__/jsfmt.spec.js.snap index 20acb26b..a9eeae9d 100644 --- a/tests/node_modules_with_symlinks/root/__snapshots__/jsfmt.spec.js.snap +++ b/tests/node_modules_with_symlinks/root/__snapshots__/jsfmt.spec.js.snap @@ -7,6 +7,5 @@ console.log(y); var x = require(\"symlink_lib\"); var y = require(\"symlink_lib_outside_root\"); console.log(x); -console.log(y); -" +console.log(y);" `; diff --git a/tests/node_modules_with_symlinks/root/symlink_lib/__snapshots__/jsfmt.spec.js.snap b/tests/node_modules_with_symlinks/root/symlink_lib/__snapshots__/jsfmt.spec.js.snap index 24978404..c0c8984c 100644 --- a/tests/node_modules_with_symlinks/root/symlink_lib/__snapshots__/jsfmt.spec.js.snap +++ b/tests/node_modules_with_symlinks/root/symlink_lib/__snapshots__/jsfmt.spec.js.snap @@ -1,6 +1,5 @@ exports[`test index.js 1`] = ` "module.exports = { bar: \"bar\" }; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -module.exports = { bar: \"bar\" }; -" +module.exports = { bar: \"bar\" };" `; diff --git a/tests/node_modules_with_symlinks/symlink_lib_outside_root/__snapshots__/jsfmt.spec.js.snap b/tests/node_modules_with_symlinks/symlink_lib_outside_root/__snapshots__/jsfmt.spec.js.snap index 24978404..c0c8984c 100644 --- a/tests/node_modules_with_symlinks/symlink_lib_outside_root/__snapshots__/jsfmt.spec.js.snap +++ b/tests/node_modules_with_symlinks/symlink_lib_outside_root/__snapshots__/jsfmt.spec.js.snap @@ -1,6 +1,5 @@ exports[`test index.js 1`] = ` "module.exports = { bar: \"bar\" }; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -module.exports = { bar: \"bar\" }; -" +module.exports = { bar: \"bar\" };" `; diff --git a/tests/node_modules_without_json/__snapshots__/jsfmt.spec.js.snap b/tests/node_modules_without_json/__snapshots__/jsfmt.spec.js.snap index 5c5b5b4d..5705853e 100644 --- a/tests/node_modules_without_json/__snapshots__/jsfmt.spec.js.snap +++ b/tests/node_modules_without_json/__snapshots__/jsfmt.spec.js.snap @@ -4,6 +4,6 @@ exports[`test test.js 1`] = ` let foo = require(\'foo\'); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -let foo = require(\"foo\"); -" + +let foo = require(\"foo\");" `; diff --git a/tests/node_tests/assert/__snapshots__/jsfmt.spec.js.snap b/tests/node_tests/assert/__snapshots__/jsfmt.spec.js.snap index 35b84c3b..6249f3b5 100644 --- a/tests/node_tests/assert/__snapshots__/jsfmt.spec.js.snap +++ b/tests/node_tests/assert/__snapshots__/jsfmt.spec.js.snap @@ -6,10 +6,9 @@ assert(true) // ok assert.ok(true) // ok ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// ok -// ok + var assert = require(\"assert\"); assert(true); -assert.ok(true); -" +// ok +assert.ok(true); // ok" `; diff --git a/tests/node_tests/basic/__snapshots__/jsfmt.spec.js.snap b/tests/node_tests/basic/__snapshots__/jsfmt.spec.js.snap index da8e1cb6..180d9e15 100644 --- a/tests/node_tests/basic/__snapshots__/jsfmt.spec.js.snap +++ b/tests/node_tests/basic/__snapshots__/jsfmt.spec.js.snap @@ -1,8 +1,7 @@ exports[`test bar.js 1`] = ` "module.exports = \"bar\"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -module.exports = \"bar\"; -" +module.exports = \"bar\";" `; exports[`test foo.js 1`] = ` @@ -10,6 +9,5 @@ exports[`test foo.js 1`] = ` console.log(x); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ var x = require(\"./bar.js\"); -console.log(x); -" +console.log(x);" `; diff --git a/tests/node_tests/basic_file/__snapshots__/jsfmt.spec.js.snap b/tests/node_tests/basic_file/__snapshots__/jsfmt.spec.js.snap index d1b67587..bec759bc 100644 --- a/tests/node_tests/basic_file/__snapshots__/jsfmt.spec.js.snap +++ b/tests/node_tests/basic_file/__snapshots__/jsfmt.spec.js.snap @@ -1,16 +1,14 @@ exports[`test bar.js 1`] = ` "module.exports = \"bar\"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -module.exports = \"bar\"; -" +module.exports = \"bar\";" `; exports[`test foo.js 1`] = ` "var x = require(\'./bar\'); // bar.js does not work console.log(x); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// bar.js does not work var x = require(\"./bar\"); -console.log(x); -" +// bar.js does not work +console.log(x);" `; diff --git a/tests/node_tests/basic_node_modules/__snapshots__/jsfmt.spec.js.snap b/tests/node_tests/basic_node_modules/__snapshots__/jsfmt.spec.js.snap index 4caf098a..91cb3ed8 100644 --- a/tests/node_tests/basic_node_modules/__snapshots__/jsfmt.spec.js.snap +++ b/tests/node_tests/basic_node_modules/__snapshots__/jsfmt.spec.js.snap @@ -3,6 +3,5 @@ exports[`test foo.js 1`] = ` console.log(x); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ var x = require(\"bar.js\"); -console.log(x); -" +console.log(x);" `; diff --git a/tests/node_tests/basic_node_modules_with_path/__snapshots__/jsfmt.spec.js.snap b/tests/node_tests/basic_node_modules_with_path/__snapshots__/jsfmt.spec.js.snap index 68209ae1..8c913109 100644 --- a/tests/node_tests/basic_node_modules_with_path/__snapshots__/jsfmt.spec.js.snap +++ b/tests/node_tests/basic_node_modules_with_path/__snapshots__/jsfmt.spec.js.snap @@ -3,6 +3,5 @@ exports[`test foo.js 1`] = ` console.log(x); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ var x = require(\"bar_lib/bar\"); -console.log(x); -" +console.log(x);" `; diff --git a/tests/node_tests/basic_package/__snapshots__/jsfmt.spec.js.snap b/tests/node_tests/basic_package/__snapshots__/jsfmt.spec.js.snap index bdc2306d..def87351 100644 --- a/tests/node_tests/basic_package/__snapshots__/jsfmt.spec.js.snap +++ b/tests/node_tests/basic_package/__snapshots__/jsfmt.spec.js.snap @@ -2,8 +2,7 @@ exports[`test foo.js 1`] = ` "var x = require(\'./bar_lib\'); // \'bar_lib\' does not work! console.log(x); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// \'bar_lib\' does not work! var x = require(\"./bar_lib\"); -console.log(x); -" +// \'bar_lib\' does not work! +console.log(x);" `; diff --git a/tests/node_tests/basic_package/bar_lib/__snapshots__/jsfmt.spec.js.snap b/tests/node_tests/basic_package/bar_lib/__snapshots__/jsfmt.spec.js.snap index f8677ae2..befe2003 100644 --- a/tests/node_tests/basic_package/bar_lib/__snapshots__/jsfmt.spec.js.snap +++ b/tests/node_tests/basic_package/bar_lib/__snapshots__/jsfmt.spec.js.snap @@ -1,6 +1,5 @@ exports[`test bar.js 1`] = ` "module.exports = \"bar\"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -module.exports = \"bar\"; -" +module.exports = \"bar\";" `; diff --git a/tests/node_tests/buffer/__snapshots__/jsfmt.spec.js.snap b/tests/node_tests/buffer/__snapshots__/jsfmt.spec.js.snap index 40e4aa87..da83729b 100644 --- a/tests/node_tests/buffer/__snapshots__/jsfmt.spec.js.snap +++ b/tests/node_tests/buffer/__snapshots__/jsfmt.spec.js.snap @@ -58,34 +58,35 @@ buffer = Buffer.from(\"foo\", \"utf8\"); buffer = Buffer.from([0x62, 0x75, 0x66, 0x66, 0x65, 0x72], (a:number) => a + 1, {}); // should error but doesn\'t ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// Uint8Array properties. All of these should type check ok. -// A few Uint8Array instance methods. All of these should type check ok. -// static methods -// This call to from() does type check ok, but should not. Unfortunately, Buffer -// extends Uint8Array but gets rid of this signature to .from(). Understandably, -// flow doesn\'t support a subclass hiding a superclass member, so this checks out as -// ok, even though it is not correct. -// should error but doesn\'t + let bool: boolean = false; let buffer: Buffer = new Buffer(0); let num: number = 0; let maybeNum: ?number; + +// Uint8Array properties. All of these should type check ok. buffer.length; buffer.buffer; buffer.byteOffset; buffer.byteLength; buffer[1]; + +// A few Uint8Array instance methods. All of these should type check ok. buffer.copyWithin(0, 0); buffer.copyWithin(0, 0, 0); + const it1: Iterator<[number, number]> = buffer.entries(); + bool = buffer.every((element: number) => false); bool = buffer.every((element: number) => false, buffer); + buffer = buffer.fill(1); buffer = buffer.fill(1, 0, 0); buffer = buffer.fill(\"a\"); buffer = buffer.fill(\"a\", 0, 0); buffer = buffer.fill(\"a\", 0, 0, \"utf8\"); buffer = buffer.fill(\"a\", \"utf8\"); + maybeNum = buffer.find( (element: number, index: number, array: Uint8Array) => false ); @@ -93,6 +94,7 @@ maybeNum = buffer.find( (element: number, index: number, array: Uint8Array) => false, buffer ); + num = buffer.findIndex( (element: number, index: number, array: Uint8Array) => false ); @@ -100,15 +102,20 @@ num = buffer.findIndex( (element: number, index: number, array: Uint8Array) => false, buffer ); + buffer.forEach((value: number) => console.log(value), buffer); buffer.forEach( (value: number, index: number, array: Uint8Array) => console.log(value), buffer ); + bool = buffer.includes(3); bool = buffer.includes(3, 4); + num = buffer.indexOf(3); num = buffer.indexOf(3, 4); + +// static methods buffer = Buffer.from([ 98, 117, 102, 102, 101, 114 ]); const typedArray = new Uint8Array([ 52 ]); buffer = Buffer.from( @@ -118,6 +125,14 @@ buffer = Buffer.from( ); buffer = Buffer.from(new Buffer(0)); buffer = Buffer.from(\"foo\", \"utf8\"); -buffer = Buffer.from([ 98, 117, 102, 102, 101, 114 ], (a: number) => a + 1, {}); -" + +// This call to from() does type check ok, but should not. Unfortunately, Buffer +// extends Uint8Array but gets rid of this signature to .from(). Understandably, +// flow doesn\'t support a subclass hiding a superclass member, so this checks out as +// ok, even though it is not correct. +buffer = Buffer.from( + [ 98, 117, 102, 102, 101, 114 ], + (a: number) => a + 1, + {} +); // should error but doesn\'t" `; diff --git a/tests/node_tests/child_process/__snapshots__/jsfmt.spec.js.snap b/tests/node_tests/child_process/__snapshots__/jsfmt.spec.js.snap index 604ace3e..0246f024 100644 --- a/tests/node_tests/child_process/__snapshots__/jsfmt.spec.js.snap +++ b/tests/node_tests/child_process/__snapshots__/jsfmt.spec.js.snap @@ -17,18 +17,21 @@ exec(\'ls\', {maxBuffer: 100}, function(error, stdout, stderr) { }); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// callback only. -// options only. -// options + callback. + var exec = require(\"child_process\").exec; + +// callback only. exec(\"ls\", function(error, stdout, stderr) { console.info(stdout); }); + +// options only. exec(\"ls\", { timeout: 250 }); + +// options + callback. exec(\"ls\", { maxBuffer: 100 }, function(error, stdout, stderr) { console.info(stdout); -}); -" +});" `; exports[`test execFile.js 1`] = ` @@ -61,26 +64,32 @@ execFile(\'ls\', [\'-l\'], {timeout: 250}, function(error, stdout, stderr) { }); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// args only. -// callback only. -// options only. -// args + callback. -// args + options. -// Put it all together. + var execFile = require(\"child_process\").execFile; + +// args only. execFile(\"ls\", [ \"-lh\" ]); + +// callback only. execFile(\"ls\", function(error, stdout, stderr) { console.info(stdout); }); + +// options only. execFile(\"wc\", { timeout: 250 }); + +// args + callback. execFile(\"ls\", [ \"-l\" ], function(error, stdout, stderr) { console.info(stdout); }); + +// args + options. execFile(\"ls\", [ \"-l\" ], { timeout: 250 }); + +// Put it all together. execFile(\"ls\", [ \"-l\" ], { timeout: 250 }, function(error, stdout, stderr) { console.info(stdout); -}); -" +});" `; exports[`test execSync.js 1`] = ` @@ -96,20 +105,20 @@ var execSync = require(\'child_process\').execSync; (execSync(\'ls\', {stdio: [\'inherit\']})); // error, no signatures match ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// returns Buffer -// returns Buffer -// returns string -// error, no signatures match -// error, no signatures match -// error, no signatures match + var execSync = require(\"child_process\").execSync; + (execSync(\"ls\"): Buffer); +// returns Buffer (execSync(\"ls\", { encoding: \"buffer\" }): Buffer); +// returns Buffer (execSync(\"ls\", { encoding: \"utf8\" }): string); +// returns string execSync(\"ls\", { timeout: \"250\" }); +// error, no signatures match execSync(\"ls\", { stdio: \"inherit\" }); -execSync(\"ls\", { stdio: [ \"inherit\" ] }); -" +// error, no signatures match +execSync(\"ls\", { stdio: [ \"inherit\" ] }); // error, no signatures match" `; exports[`test spawn.js 1`] = ` @@ -145,28 +154,35 @@ wc.stdout.pipe(process.stdout); wc.stderr.pipe(process.stderr); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// args + options. -// options only. + var child_process = require(\"child_process\"); + var ls = child_process.spawn(\"ls\"); var wc = child_process.spawn(\"wc\", [ \"-l\" ]); + +// args + options. child_process.spawn(\"echo\", [ \"-n\", \"\\\"Testing...\\\"\" ], { env: { TEST: \"foo\" } }); + +// options only. child_process.spawn(\"echo\", { env: { FOO: 2 } }); + ls.stdout.on(\"data\", function(data) { wc.stdin.write(data); }); + ls.stderr.on(\"data\", function(data) { console.warn(data); }); + ls.on(\"close\", function(code) { if (code !== 0) { console.warn(\"\`ls\` exited with code %s\", code); } wc.stdin.end(); }); + wc.stdout.pipe(process.stdout); -wc.stderr.pipe(process.stderr); -" +wc.stderr.pipe(process.stderr);" `; diff --git a/tests/node_tests/crypto/__snapshots__/jsfmt.spec.js.snap b/tests/node_tests/crypto/__snapshots__/jsfmt.spec.js.snap index 6d556856..3b375234 100644 --- a/tests/node_tests/crypto/__snapshots__/jsfmt.spec.js.snap +++ b/tests/node_tests/crypto/__snapshots__/jsfmt.spec.js.snap @@ -39,40 +39,43 @@ let tests = [ ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// Hmac is a duplex stream -// 4 errors: null, void, string, Buffer -// 2 errors: not a string or a Buffer -// Hmac supports update and digest functions too -// 1 error -// 1 error: no encoding when passing a buffer -// it\'s also chainable -// 1 error -// 1 error + const crypto = require(\"crypto\"); + let tests = [ + // Hmac is a duplex stream function() { const hmac = crypto.createHmac(\"sha256\", \"a secret\"); + hmac.on(\"readable\", () => { (hmac.read(): ?(string | Buffer)); - (hmac.read(): number); + (hmac.read(): number); // 4 errors: null, void, string, Buffer }); + hmac.write(\"some data to hash\"); hmac.write(123); + // 2 errors: not a string or a Buffer hmac.end(); }, + // Hmac supports update and digest functions too function(buf: Buffer) { const hmac = crypto.createHmac(\"sha256\", \"a secret\"); + hmac.update(\"some data to hash\"); hmac.update(\"foo\", \"utf8\"); hmac.update(\"foo\", \"bogus\"); + // 1 error hmac.update(buf); hmac.update(buf, \"utf8\"); + // 1 error: no encoding when passing a buffer + // it\'s also chainable (hmac.update(\"some data to hash\").update(buf).digest(): Buffer); + (hmac.digest(\"hex\"): string); (hmac.digest(): Buffer); (hmac.digest(\"hex\"): void); - (hmac.digest(): void); + // 1 error + (hmac.digest(): void); // 1 error } -]; -" +];" `; diff --git a/tests/node_tests/fs/__snapshots__/jsfmt.spec.js.snap b/tests/node_tests/fs/__snapshots__/jsfmt.spec.js.snap index baae31ed..89c61936 100644 --- a/tests/node_tests/fs/__snapshots__/jsfmt.spec.js.snap +++ b/tests/node_tests/fs/__snapshots__/jsfmt.spec.js.snap @@ -33,32 +33,35 @@ fs.readFile(\"file.exp\", {}, (_, data) => { (fs.readFileSync(\"file.exp\", {}) : Buffer); (fs.readFileSync(\"file.exp\", {}) : string); // error ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -/* readFile */ -/* readFileSync */ -// error -// error -// error -// error var fs = require(\"fs\"); + +/* readFile */ fs.readFile(\"file.exp\", (_, data) => { (data: Buffer); }); + fs.readFile(\"file.exp\", \"blah\", (_, data) => { (data: string); }); + fs.readFile(\"file.exp\", { encoding: \"blah\" }, (_, data) => { (data: string); }); + fs.readFile(\"file.exp\", {}, (_, data) => { (data: Buffer); }); + +/* readFileSync */ (fs.readFileSync(\"file.exp\"): Buffer); (fs.readFileSync(\"file.exp\"): string); +// error (fs.readFileSync(\"file.exp\", \"blah\"): string); (fs.readFileSync(\"file.exp\", \"blah\"): Buffer); +// error (fs.readFileSync(\"file.exp\", { encoding: \"blah\" }): string); (fs.readFileSync(\"file.exp\", { encoding: \"blah\" }): Buffer); +// error (fs.readFileSync(\"file.exp\", {}): Buffer); -(fs.readFileSync(\"file.exp\", {}): string); -" +(fs.readFileSync(\"file.exp\", {}): string); // error" `; diff --git a/tests/node_tests/json_file/__snapshots__/jsfmt.spec.js.snap b/tests/node_tests/json_file/__snapshots__/jsfmt.spec.js.snap index 722a7156..70e9627d 100644 --- a/tests/node_tests/json_file/__snapshots__/jsfmt.spec.js.snap +++ b/tests/node_tests/json_file/__snapshots__/jsfmt.spec.js.snap @@ -24,34 +24,33 @@ let data4 = require(\'./json_array\'); (require(\'./json_negative_number\'): -1); // ok ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// error, should be object literal -// error, should be boolean -// error, should be ?string -// error, should be string -// error, should be number (not string! index.js wins) -// error, should be Array -// error, should be string -// error, should be number -// error, should be true -// error, should be false -// error, should be null -// ok + let data = require(\"./package/index.json\"); (data.foo: void); +// error, should be object literal (data.foo.bar: void); +// error, should be boolean (data.abc: boolean); +// error, should be ?string let data2 = require(\"./package\"); (data2.baz: void); +// error, should be string let data3 = require(\"./package2\"); (data3.foo: void); +// error, should be number (not string! index.js wins) let data4 = require(\"./json_array\"); (data4: Array); (data4: void); +// error, should be Array (require(\"./json_string\"): void); +// error, should be string (require(\"./json_number\"): void); +// error, should be number (require(\"./json_true\"): void); +// error, should be true (require(\"./json_false\"): void); +// error, should be false (require(\"./json_null\"): void); -(require(\"./json_negative_number\"): -1); -" +// error, should be null +(require(\"./json_negative_number\"): -1); // ok" `; diff --git a/tests/node_tests/json_file/package2/__snapshots__/jsfmt.spec.js.snap b/tests/node_tests/json_file/package2/__snapshots__/jsfmt.spec.js.snap index c7cb946f..33195eff 100644 --- a/tests/node_tests/json_file/package2/__snapshots__/jsfmt.spec.js.snap +++ b/tests/node_tests/json_file/package2/__snapshots__/jsfmt.spec.js.snap @@ -6,6 +6,6 @@ module.exports = { }; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -module.exports = { foo: 123 }; -" + +module.exports = { foo: 123 };" `; diff --git a/tests/node_tests/os/__snapshots__/jsfmt.spec.js.snap b/tests/node_tests/os/__snapshots__/jsfmt.spec.js.snap index bccf9dff..b6f96e1e 100644 --- a/tests/node_tests/os/__snapshots__/jsfmt.spec.js.snap +++ b/tests/node_tests/os/__snapshots__/jsfmt.spec.js.snap @@ -16,18 +16,19 @@ var u3 = os.userInfo({encoding: \'buffer\'}); (u3.username: Buffer); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// error -// error -// error + var os = require(\"os\"); + var u1 = os.userInfo(); (u1.username: string); (u1.username: Buffer); +// error var u2 = os.userInfo({ encoding: \"utf8\" }); (u2.username: string); (u2.username: Buffer); +// error var u3 = os.userInfo({ encoding: \"buffer\" }); (u3.username: string); -(u3.username: Buffer); -" +// error +(u3.username: Buffer);" `; diff --git a/tests/node_tests/package_file/__snapshots__/jsfmt.spec.js.snap b/tests/node_tests/package_file/__snapshots__/jsfmt.spec.js.snap index b71f83ab..35776515 100644 --- a/tests/node_tests/package_file/__snapshots__/jsfmt.spec.js.snap +++ b/tests/node_tests/package_file/__snapshots__/jsfmt.spec.js.snap @@ -1,16 +1,14 @@ exports[`test bar_lib.js 1`] = ` "module.exports = \"bar_lib\"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -module.exports = \"bar_lib\"; -" +module.exports = \"bar_lib\";" `; exports[`test foo.js 1`] = ` "var x: string = require(\'./bar_lib\'); // \'bar_lib\' does not work! console.log(x); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// \'bar_lib\' does not work! var x: string = require(\"./bar_lib\"); -console.log(x); -" +// \'bar_lib\' does not work! +console.log(x);" `; diff --git a/tests/node_tests/package_file/bar_lib/__snapshots__/jsfmt.spec.js.snap b/tests/node_tests/package_file/bar_lib/__snapshots__/jsfmt.spec.js.snap index ef9feb9a..3f6c5555 100644 --- a/tests/node_tests/package_file/bar_lib/__snapshots__/jsfmt.spec.js.snap +++ b/tests/node_tests/package_file/bar_lib/__snapshots__/jsfmt.spec.js.snap @@ -1,6 +1,5 @@ exports[`test bar.js 1`] = ` "module.exports = 0; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -module.exports = 0; -" +module.exports = 0;" `; diff --git a/tests/node_tests/package_file_node_modules/foo/__snapshots__/jsfmt.spec.js.snap b/tests/node_tests/package_file_node_modules/foo/__snapshots__/jsfmt.spec.js.snap index 5604ee51..f2bd5973 100644 --- a/tests/node_tests/package_file_node_modules/foo/__snapshots__/jsfmt.spec.js.snap +++ b/tests/node_tests/package_file_node_modules/foo/__snapshots__/jsfmt.spec.js.snap @@ -2,8 +2,7 @@ exports[`test foo.js 1`] = ` "var x: string = require(\'bar_lib\'); // \'bar_lib\' does not work! console.log(x); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// \'bar_lib\' does not work! var x: string = require(\"bar_lib\"); -console.log(x); -" +// \'bar_lib\' does not work! +console.log(x);" `; diff --git a/tests/node_tests/path_node_modules/__snapshots__/jsfmt.spec.js.snap b/tests/node_tests/path_node_modules/__snapshots__/jsfmt.spec.js.snap index 51bc929a..7f0fe398 100644 --- a/tests/node_tests/path_node_modules/__snapshots__/jsfmt.spec.js.snap +++ b/tests/node_tests/path_node_modules/__snapshots__/jsfmt.spec.js.snap @@ -3,6 +3,5 @@ exports[`test foo.js 1`] = ` console.log(x); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ var x = require(\"bar_lib/src/lib/bar\"); -console.log(x); -" +console.log(x);" `; diff --git a/tests/node_tests/path_node_modules_with_short_main/__snapshots__/jsfmt.spec.js.snap b/tests/node_tests/path_node_modules_with_short_main/__snapshots__/jsfmt.spec.js.snap index d2e4c58f..ddce7851 100644 --- a/tests/node_tests/path_node_modules_with_short_main/__snapshots__/jsfmt.spec.js.snap +++ b/tests/node_tests/path_node_modules_with_short_main/__snapshots__/jsfmt.spec.js.snap @@ -3,6 +3,5 @@ exports[`test foo.js 1`] = ` console.log(x); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ var x = require(\"bar_lib\"); -console.log(x); -" +console.log(x);" `; diff --git a/tests/node_tests/path_node_modules_without_main/__snapshots__/jsfmt.spec.js.snap b/tests/node_tests/path_node_modules_without_main/__snapshots__/jsfmt.spec.js.snap index d2e4c58f..ddce7851 100644 --- a/tests/node_tests/path_node_modules_without_main/__snapshots__/jsfmt.spec.js.snap +++ b/tests/node_tests/path_node_modules_without_main/__snapshots__/jsfmt.spec.js.snap @@ -3,6 +3,5 @@ exports[`test foo.js 1`] = ` console.log(x); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ var x = require(\"bar_lib\"); -console.log(x); -" +console.log(x);" `; diff --git a/tests/node_tests/path_package/__snapshots__/jsfmt.spec.js.snap b/tests/node_tests/path_package/__snapshots__/jsfmt.spec.js.snap index e77df483..359cf638 100644 --- a/tests/node_tests/path_package/__snapshots__/jsfmt.spec.js.snap +++ b/tests/node_tests/path_package/__snapshots__/jsfmt.spec.js.snap @@ -3,6 +3,5 @@ exports[`test foo.js 1`] = ` console.log(x); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ var x = require(\"bar_lib/src/lib\"); -console.log(x); -" +console.log(x);" `; diff --git a/tests/node_tests/stream/__snapshots__/jsfmt.spec.js.snap b/tests/node_tests/stream/__snapshots__/jsfmt.spec.js.snap index 1cf3b543..e3dc0506 100644 --- a/tests/node_tests/stream/__snapshots__/jsfmt.spec.js.snap +++ b/tests/node_tests/stream/__snapshots__/jsfmt.spec.js.snap @@ -34,29 +34,35 @@ new MyReadStream() ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + var child_process = require(\"child_process\"); var fs = require(\"fs\"); var stream = require(\"stream\"); var ls = child_process.spawn(\"ls\"); + var data = \"foo\"; + ls.stdin.write(data); ls.stdin.write(data, \"utf-8\"); ls.stdin.write(data, () => {}); ls.stdin.write(data, \"utf-8\", () => {}); + ls.stdin.end(); ls.stdin.end(data); ls.stdin.end(data, \"utf-8\"); ls.stdin.end(data, () => {}); ls.stdin.end(data, \"utf-8\", () => {}); + var ws = fs.createWriteStream(\"/dev/null\"); ls.stdout.pipe(ws).end(); + class MyReadStream extends stream.Readable {} class MyWriteStream extends stream.Writable {} class MyDuplex extends stream.Duplex {} class MyTransform extends stream.Duplex {} + new MyReadStream() .pipe(new MyDuplex()) .pipe(new MyTransform()) - .pipe(new MyWriteStream()); -" + .pipe(new MyWriteStream());" `; diff --git a/tests/node_tests/timers/__snapshots__/jsfmt.spec.js.snap b/tests/node_tests/timers/__snapshots__/jsfmt.spec.js.snap index 862e8381..30457d28 100644 --- a/tests/node_tests/timers/__snapshots__/jsfmt.spec.js.snap +++ b/tests/node_tests/timers/__snapshots__/jsfmt.spec.js.snap @@ -8,9 +8,10 @@ function setImmediateCallback(): number { setImmediate(setImmediateCallback); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + function setImmediateCallback(): number { return 0; } -setImmediate(setImmediateCallback); -" + +setImmediate(setImmediateCallback);" `; diff --git a/tests/node_tests/url/__snapshots__/jsfmt.spec.js.snap b/tests/node_tests/url/__snapshots__/jsfmt.spec.js.snap index f335f9ef..d631e18c 100644 --- a/tests/node_tests/url/__snapshots__/jsfmt.spec.js.snap +++ b/tests/node_tests/url/__snapshots__/jsfmt.spec.js.snap @@ -3,6 +3,5 @@ exports[`test url.js 1`] = ` url.format(url.parse(\'https://example.com/foo\')); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ const url = require(\"url\"); -url.format(url.parse(\"https://example.com/foo\")); -" +url.format(url.parse(\"https://example.com/foo\"));" `; diff --git a/tests/nullable/__snapshots__/jsfmt.spec.js.snap b/tests/nullable/__snapshots__/jsfmt.spec.js.snap index 8d38dc75..731814d7 100644 --- a/tests/nullable/__snapshots__/jsfmt.spec.js.snap +++ b/tests/nullable/__snapshots__/jsfmt.spec.js.snap @@ -6,12 +6,11 @@ exports[`test maybe.js 1`] = ` ((123: ?(?number)): ?string); // error (only num ~> string) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + // unwrapping nested maybes should work -// ok -// error (only num ~> string) ((\"foo\": ??string): ?string); -((123: ??number): ?string); -" +// ok +((123: ??number): ?string); // error (only num ~> string)" `; exports[`test nullable.js 1`] = ` @@ -34,22 +33,26 @@ if (x != null) { var array_of_nullable: Array = [null, 3]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// x: ?string -// x: ?string | null -// x: ?string | null function foo(): string { return null; } + function bar(): ?string { return null; } + function qux(x: string) {} + function corge(x: number) {} + var x = bar(); +// x: ?string if (x != null) qux(x); +// x: ?string | null if (x != null) corge(x); +// x: ?string | null function grault() { x = null; } @@ -57,8 +60,8 @@ if (x != null) { grault(); qux(x); } -var array_of_nullable: Array = [ null, 3 ]; -" + +var array_of_nullable: Array = [ null, 3 ];" `; exports[`test simple_nullable.js 1`] = ` @@ -74,7 +77,7 @@ function foo(x: ?string) {} function bar(x: ?number) {} foo(\"hmm\"); bar(\"hmm\"); + function fn(data: ?{}) {} -fn({ some: \"literal\" }); -" +fn({ some: \"literal\" });" `; diff --git a/tests/number_constants/__snapshots__/jsfmt.spec.js.snap b/tests/number_constants/__snapshots__/jsfmt.spec.js.snap index e68013db..cac53502 100644 --- a/tests/number_constants/__snapshots__/jsfmt.spec.js.snap +++ b/tests/number_constants/__snapshots__/jsfmt.spec.js.snap @@ -23,6 +23,5 @@ var h: string = Number.MIN_VALUE; var i: number = Number.NaN; var j: string = Number.NaN; var k: number = Number.EPSILON; -var l: string = Number.EPSILON; -" +var l: string = Number.EPSILON;" `; diff --git a/tests/object-method/__snapshots__/jsfmt.spec.js.snap b/tests/object-method/__snapshots__/jsfmt.spec.js.snap index ebb2518e..16e029a4 100644 --- a/tests/object-method/__snapshots__/jsfmt.spec.js.snap +++ b/tests/object-method/__snapshots__/jsfmt.spec.js.snap @@ -4,8 +4,8 @@ exports[`test id.js 1`] = ` module.exports = id; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ declare function id(_: X): X; -module.exports = id; -" + +module.exports = id;" `; exports[`test subtype.js 1`] = ` @@ -18,10 +18,10 @@ function subtypeCheck(x: Interface): ObjectType { return x; } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ interface Interface { m(): void } import type {ObjectType} from \"./test\"; + function subtypeCheck(x: Interface): ObjectType { return x; -} -" +}" `; exports[`test test.js 1`] = ` @@ -40,12 +40,14 @@ module.exports = id( ); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ const id = require(\"./id\"); + export type ObjectType = { +m: () => void }; + function methodCaller(x: ObjectType) { x.m(); } -module.exports = id(methodCaller); -" + +module.exports = id(methodCaller);" `; exports[`test test2.js 1`] = ` @@ -68,16 +70,18 @@ a.f(); // okey-dokie b.f(); // error, property \`p\` not found ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// okey-dokie -// error, property \`p\` not found + function f() { return this.p; } + var a = { p: 0, f }; + var b = { f }; + a.f(); -b.f(); -" +// okey-dokie +b.f(); // error, property \`p\` not found" `; exports[`test test3.js 1`] = ` @@ -101,22 +105,22 @@ function qux(o: { f: () => void }) { qux({ f: foo }); // error, since \`this\` is used non-trivially in \`foo\` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// passing global object as \`this\` -// passing container object as \`this\` -// error, since \`this\` is used non-trivially in \`foo\` -// passing o as \`this\` -// error, since \`this\` is used non-trivially in \`foo\` + function foo() { this.m(); } + function bar(f: () => void) { f(); - ({ f }).f(); + // passing global object as \`this\` + ({ f }).f(); // passing container object as \`this\` } + bar(foo); +// error, since \`this\` is used non-trivially in \`foo\` function qux(o: { f(): void }) { - o.f(); + o.f(); // passing o as \`this\` } -qux({ f: foo }); -" + +qux({ f: foo }); // error, since \`this\` is used non-trivially in \`foo\`" `; diff --git a/tests/object_annot/__snapshots__/jsfmt.spec.js.snap b/tests/object_annot/__snapshots__/jsfmt.spec.js.snap index 173c7a7b..941e391a 100644 --- a/tests/object_annot/__snapshots__/jsfmt.spec.js.snap +++ b/tests/object_annot/__snapshots__/jsfmt.spec.js.snap @@ -8,12 +8,12 @@ function bar(x: Object): Array { return Object.keys(x); } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Make sure Object works with Object.keys() function foo(x: Array): Array { return x.sort((a, b) => a.foo - b.foo); } + +// Make sure Object works with Object.keys() function bar(x: Object): Array { return Object.keys(x); -} -" +}" `; diff --git a/tests/object_api/__snapshots__/jsfmt.spec.js.snap b/tests/object_api/__snapshots__/jsfmt.spec.js.snap index 72b9db44..aeffb1dd 100644 --- a/tests/object_api/__snapshots__/jsfmt.spec.js.snap +++ b/tests/object_api/__snapshots__/jsfmt.spec.js.snap @@ -3,8 +3,8 @@ exports[`test a.js 1`] = ` module.exports = { a() {} };~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -module.exports = { a() {} }; -" + +module.exports = { a() {} };" `; exports[`test b.js 1`] = ` @@ -16,12 +16,12 @@ b.a(); // works here module.exports = b; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// works here + var a = require(\"./a\"); var b = Object.assign({ bar() {}, ...{} }, a); b.a(); -module.exports = b; -" +// works here +module.exports = b;" `; exports[`test c.js 1`] = ` @@ -31,10 +31,10 @@ var c = require(\'./b\'); c.a(); c.foo();~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + var c = require(\"./b\"); c.a(); -c.foo(); -" +c.foo();" `; exports[`test object_assign.js 1`] = ` @@ -52,17 +52,19 @@ Object.assign(anyObj, anyObj); // makes sure this terminates module.exports = export_; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// makes sure this terminates + var export_ = Object.assign({}, { foo: function(param) { return param; } }); + var decl_export_: { foo: any, bar: any } = Object.assign({}, export_); + let anyObj: Object = {}; Object.assign(anyObj, anyObj); -module.exports = export_; -" +// makes sure this terminates +module.exports = export_;" `; exports[`test object_create.js 1`] = ` @@ -85,20 +87,24 @@ declare var o: O; (o: C); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// OK, \`instanceof C\` would be true -// OK, \`instanceof C\` would be true -// error, object literals don\'t structurally match instances -// error, object types don\'t structurally match instances + class C { foo: string; } + +// OK, \`instanceof C\` would be true (Object.create(C.prototype): C); + +// OK, \`instanceof C\` would be true (Object.create(new C()): C); + +// error, object literals don\'t structurally match instances ({ foo: \"foo\" }: C); + +// error, object types don\'t structurally match instances type O = { foo: string }; declare var o: O; -(o: C); -" +(o: C);" `; exports[`test object_getprototypeof.js 1`] = ` @@ -115,15 +121,16 @@ let tests = [ ]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + class Foo {} class Bar extends Foo {} + let tests = [ function() { const x = new Bar(); (Object.getPrototypeOf(x): Foo); } -]; -" +];" `; exports[`test object_keys.js 1`] = ` @@ -161,38 +168,37 @@ class Bar extends Foo { (Object.keys(new Bar()): Array<\'error\'>); // error: bar_prop ~> error ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// error, Array -// error: number ~> string -// error: number ~> string -// error, Array -// constructor and foo not enumerable -// error: prop ~> error -// only own enumerable props -// error: bar_prop ~> error + var sealed = { one: \"one\", two: \"two\" }; (Object.keys(sealed): Array<\"one\" | \"two\">); (Object.keys(sealed): void); +// error, Array var unsealed = {}; Object.keys(unsealed).forEach(k => { - (k: number); + (k: number); // error: number ~> string }); + var dict: { [k: number]: string } = {}; Object.keys(dict).forEach(k => { - (k: number); + (k: number); // error: number ~> string }); + var any: Object = {}; (Object.keys(any): Array); +// error, Array class Foo { prop: string; foo() {} } +// constructor and foo not enumerable (Object.keys(new Foo()): Array<\"error\">); +// error: prop ~> error class Bar extends Foo { bar_prop: string; bar() {} } -(Object.keys(new Bar()): Array<\"error\">); -" +// only own enumerable props +(Object.keys(new Bar()): Array<\"error\">); // error: bar_prop ~> error" `; exports[`test object_missing.js 1`] = ` @@ -205,12 +211,12 @@ let tests = [ ]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + let tests = [ function() { Object.doesNotExist(); } -]; -" +];" `; exports[`test object_prototype.js 1`] = ` @@ -380,75 +386,14 @@ var k : Object = a.constructor; (123).constructor; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// -// toString -// -// call -// ok, even though dict specifies strings, this is a function -// get -// set -// override -// ... on a built-in instance -// error -// error -// ... on an instance -// error -// ... on a primitive -// error -// error -// error -// -// hasOwnProperty -// -// call -// get -// set -// ... on a built-in instance -// error -// error -// ... on an instance -// error -// -// propertyIsEnumerable -// -// call -// get -// set -// ... on a built-in instance -// error -// error -// ... on an instance -// error -// -// valueOf -// -// call -// get -// set -// ... on a built-in instance -// error -// ... on an instance -// error -// ... on a literal -// -// toLocaleString -// -// call -// get -// set -// ... on a built-in instance -// error -// error -// ... on an instance -// error -// -// constructor -// + function takesABool(x: boolean) {} function takesAString(x: string) {} function takesANumber(x: number) {} function takesAnObject(x: Object) {} + class Foo {} + var a = { foo: \"bar\" }; var b = { foo: \"bar\", ...{} }; var c = { @@ -460,80 +405,170 @@ var c = { var d: { [key: string]: string } = { foo: \"bar\" }; var x = new Date(); var y = new Foo(); + +// +// toString +// +// call takesAString(a.toString()); d.toString(); +// ok, even though dict specifies strings, this is a function +// get var aToString: () => string = a.toString; var aToString2 = a.toString; takesAString(aToString2()); + +// set b.toString = function(): string { return \"foo\"; }; c.toString = function(): number { return 123; }; + +// override var cToString: () => number = c.toString; + +// ... on a built-in instance var xToString: number = x.toString; +// error var xToString2: () => number = x.toString; +// error takesAString(x.toString()); + +// ... on an instance var yToString: number = y.toString; +// error takesAString(y.toString()); + +// ... on a primitive (123).toString(); (123).toString; (123).toString = function() {}; +// error (123).toString(2); (123).toString(\"foo\"); +// error (123).toString(null); +// error +// +// hasOwnProperty +// +// call takesABool(a.hasOwnProperty(\"foo\")); + +// get var aHasOwnProperty: (prop: string) => boolean = a.hasOwnProperty; var aHasOwnProperty2 = a.hasOwnProperty; takesABool(aHasOwnProperty2(\"bar\")); + +// set b.hasOwnProperty = function() { return false; }; + +// ... on a built-in instance var xHasOwnProperty: number = x.hasOwnProperty; +// error var xHasOwnProperty2: (prop: string) => number = x.hasOwnProperty; +// error takesABool(x.hasOwnProperty(\"foo\")); + +// ... on an instance var yHasOwnProperty: number = y.hasOwnProperty; +// error takesABool(y.hasOwnProperty(\"foo\")); + +// +// propertyIsEnumerable +// +// call takesABool(a.propertyIsEnumerable(\"foo\")); + +// get var aPropertyIsEnumerable: (prop: string) => boolean = a.propertyIsEnumerable; var aPropertyIsEnumerable2 = a.propertyIsEnumerable; takesABool(aPropertyIsEnumerable2(\"bar\")); + +// set b.propertyIsEnumerable = function() { return false; }; + +// ... on a built-in instance var xPropertyIsEnumerable: number = x.propertyIsEnumerable; +// error var xPropertyIsEnumerable2: (prop: string) => number = x.propertyIsEnumerable; +// error takesABool(x.propertyIsEnumerable(\"foo\")); + +// ... on an instance var yPropertyIsEnumerable: number = y.propertyIsEnumerable; +// error takesABool(y.propertyIsEnumerable(\"foo\")); + +// +// valueOf +// +// call takesAnObject(a.valueOf()); + +// get var aValueOf: () => Object = a.valueOf; var aValueOf2 = a.valueOf; takesAnObject(aValueOf2()); + +// set b.valueOf = function() { return {}; }; + +// ... on a built-in instance var xValueOf: number = x.valueOf; +// error takesANumber(x.valueOf()); + +// ... on an instance var yValueOf: number = y.valueOf; +// error takesAnObject(y.valueOf()); + +// ... on a literal var strValueOf: string = \"foo\".valueOf(); var numValueOf: number = (123).valueOf(); var boolValueOf: boolean = true.valueOf(); + +// +// toLocaleString +// +// call takesAString(a.toLocaleString()); + +// get var aToLocaleString: () => string = a.toLocaleString; var aToLocaleString2 = a.toLocaleString; takesAString(aToLocaleString2()); + +// set b.toLocaleString = function() { return \"derp\"; }; + +// ... on a built-in instance var xToLocaleString: number = x.toLocaleString; +// error var xToLocaleString2: () => number = x.toLocaleString; +// error takesAString(x.toLocaleString()); + +// ... on an instance var yToLocaleString: number = y.toLocaleString; +// error takesAString(y.toLocaleString()); + +// +// constructor +// var k: Object = a.constructor; -(123).constructor; -" +(123).constructor;" `; diff --git a/tests/object_assign/__snapshots__/jsfmt.spec.js.snap b/tests/object_assign/__snapshots__/jsfmt.spec.js.snap index ab008521..a2134fa1 100644 --- a/tests/object_assign/__snapshots__/jsfmt.spec.js.snap +++ b/tests/object_assign/__snapshots__/jsfmt.spec.js.snap @@ -29,26 +29,30 @@ module.exports = { /** * @flow */ -// This pattern seems to cause the trouble. -// Calling Bad.foo() in the same file doesn\'t error -// Doesn\'t repro if I extend the class myself -// Calling Good.foo() in the same file doesn\'t error + var EventEmitter = require(\"events\").EventEmitter; + +// This pattern seems to cause the trouble. var Bad = Object.assign({}, EventEmitter.prototype, { foo: function(): string { return \"hi\"; } }); + +// Calling Bad.foo() in the same file doesn\'t error var bad: number = Bad.foo(); + +// Doesn\'t repro if I extend the class myself class MyEventEmitter extends events$EventEmitter {} var Good = Object.assign({}, MyEventEmitter.prototype, { foo: function(): string { return \"hi\"; } }); +// Calling Good.foo() in the same file doesn\'t error var good: number = Good.foo(); -module.exports = { Bad: Bad, Good: Good }; -" + +module.exports = { Bad: Bad, Good: Good };" `; exports[`test B.js 1`] = ` @@ -73,20 +77,21 @@ A.js|8 col 23 error| object literal /** * @flow */ + +var A = require(\"./A.js\"); + +var good: number = A.Good.foo(); + +var f = A.Bad.foo; // Property access is fine +var bad_: number = f(); // Calling the function is fine -// Method call is not fine +var bad: number = A.Bad.foo(); // Method call is not fine /* B.js|12 col 1 error| call of method foo || Property not found in A.js|8 col 23 error| object literal -*/ -var A = require(\"./A.js\"); -var good: number = A.Good.foo(); -var f = A.Bad.foo; -var bad_: number = f(); -var bad: number = A.Bad.foo(); -" +*/" `; exports[`test apply.js 1`] = ` @@ -96,12 +101,12 @@ exports[`test apply.js 1`] = ` (Object.assign({}, ...[{a: 1}, {b: \'foo\'}]): {a: number, b: string}); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + (Object.assign.apply(null, [ {}, { a: 1 }, { b: \"foo\" } ]): { a: number, b: string }); -(Object.assign({}, ...[ { a: 1 }, { b: \"foo\" } ]): { a: number, b: string }); -" +(Object.assign({}, ...[ { a: 1 }, { b: \"foo\" } ]): { a: number, b: string });" `; exports[`test non_objects.js 1`] = ` @@ -112,10 +117,10 @@ Object.assign(123, {a: \"foo\"}); Object.assign({a: \"foo\"}, 123); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + Object.assign(\"123\", { a: \"foo\" }); Object.assign(123, { a: \"foo\" }); -Object.assign({ a: \"foo\" }, 123); -" +Object.assign({ a: \"foo\" }, 123);" `; exports[`test undefined.js 1`] = ` @@ -141,11 +146,13 @@ class MyReactThing extends React.Component { ; // also works ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -/* works*/ -// also works + var React = require(\"react\"); + type DefaultProps = { foo: number }; + type Props = { foo: number }; + class MyReactThing extends React.Component { props: Props; static defaultProps: DefaultProps; @@ -153,7 +160,8 @@ class MyReactThing extends React.Component { return this.props.foo; } } -; -; -" + +; +/* works*/ +; // also works" `; diff --git a/tests/object_freeze/__snapshots__/jsfmt.spec.js.snap b/tests/object_freeze/__snapshots__/jsfmt.spec.js.snap index f9cd104d..b84f5aa0 100644 --- a/tests/object_freeze/__snapshots__/jsfmt.spec.js.snap +++ b/tests/object_freeze/__snapshots__/jsfmt.spec.js.snap @@ -21,25 +21,27 @@ var x : number = Object.freeze(123); var xx : { x: number } = Object.freeze({ x: \"error\" }) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// error -// error -// error -// error -// error -// error -// error + var foo = Object.freeze({ bar: \"12345\" }); foo.bar = \"23456\"; +// error Object.assign(foo, { bar: \"12345\" }); +// error var baz = { baz: 12345 }; var bliffl = Object.freeze({ bar: \"12345\", ...baz }); bliffl.bar = \"23456\"; +// error bliffl.baz = 3456; +// error bliffl.corge; +// error bliffl.constructor = baz; +// error bliffl.toString = function() {}; +// error baz.baz = 0; + var x: number = Object.freeze(123); -var xx: { x: number } = Object.freeze({ x: \"error\" }); -" + +var xx: { x: number } = Object.freeze({ x: \"error\" });" `; diff --git a/tests/object_is/__snapshots__/jsfmt.spec.js.snap b/tests/object_is/__snapshots__/jsfmt.spec.js.snap index 46b60832..9d8932c9 100644 --- a/tests/object_is/__snapshots__/jsfmt.spec.js.snap +++ b/tests/object_is/__snapshots__/jsfmt.spec.js.snap @@ -30,16 +30,18 @@ Object.is(0, 0); Object.is(0, -0); Object.is(NaN, NaN); Object.is({}, {}); + var emptyObject = {}; var emptyArray = []; Object.is(emptyObject, emptyObject); Object.is(emptyArray, emptyArray); Object.is(emptyObject, emptyArray); + var squared = x => x * x; Object.is(squared, squared); + var a: boolean = Object.is(\"a\", \"a\"); var b: string = Object.is(\"a\", \"a\"); var c: boolean = Object.is(\"a\"); -var d: boolean = Object.is(\"a\", \"b\", \"c\"); -" +var d: boolean = Object.is(\"a\", \"b\", \"c\");" `; diff --git a/tests/objects/__snapshots__/jsfmt.spec.js.snap b/tests/objects/__snapshots__/jsfmt.spec.js.snap index bd87fb09..51901164 100644 --- a/tests/objects/__snapshots__/jsfmt.spec.js.snap +++ b/tests/objects/__snapshots__/jsfmt.spec.js.snap @@ -20,8 +20,7 @@ var z = Object(123); // error (next line makes this not match any signatures) (z.charAt(0): string); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// error -// error (next line makes this not match any signatures) + (Object({ foo: \"bar\" }): { foo: string }); (Object(\"123\"): String); (Object(123): Number); @@ -30,13 +29,16 @@ var z = Object(123); // error (next line makes this not match any signatures) (Object(undefined): {}); (Object(void 0): {}); (Object(undefined): Number); +// error var x = Object(null); x.foo = \"bar\"; + var y = Object(\"123\"); (y.charAt(0): string); + var z = Object(123); -(z.charAt(0): string); -" +// error (next line makes this not match any signatures) +(z.charAt(0): string);" `; exports[`test objects.js 1`] = ` @@ -60,33 +62,32 @@ y[\'bar\'] = \'abc\'; // error, property not found (y[\'hasOwnProperty\']: string); // error, prototype method is not a string ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// error, key doesn\'t exist -// error, key doesn\'t exist -// TODO: use the number\'s value to error here -// error, string !~> boolean -// error, string !~> boolean -// error, boolean !~> string -// TODO: use the number\'s value to error here -// ok since we can\'t tell -// error, key doesn\'t exist -// error, number !~> string -// error, property not found -// error, prototype method is not a string + var x: { \"123\": string, bar: string } = { \"123\": \"val\", bar: \"bar\" }; (x.foo: string); +// error, key doesn\'t exist (x[\"foo\"]: string); +// error, key doesn\'t exist (x[123]: boolean); +// TODO: use the number\'s value to error here (x.bar: boolean); +// error, string !~> boolean (x[\"123\"]: boolean); +// error, string !~> boolean x[\"123\"] = false; +// error, boolean !~> string x[123] = false; +// TODO: use the number\'s value to error here x[\"foo\" + \"bar\"] = \"derp\"; +// ok since we can\'t tell (x[\`foo\`]: string); +// error, key doesn\'t exist var y: { foo: string } = { foo: \"bar\" }; y[\"foo\"] = 123; +// error, number !~> string y[\"bar\"] = \"abc\"; -(y[\"hasOwnProperty\"]: string); -" +// error, property not found +(y[\"hasOwnProperty\"]: string); // error, prototype method is not a string" `; exports[`test unaliased_assign.js 1`] = ` @@ -131,18 +132,18 @@ function assign_then_widen() { * * @flow */ -// error: subsequent assignment might make glob.x a number -// ok, by lvalue\'s given type + var glob: { x: string } = { x: \"hey\" }; + function assign_then_alias() { var obj: { x: string | number }; obj = { x: \"hey\" }; - glob = obj; + glob = obj; // error: subsequent assignment might make glob.x a number } + function assign_then_widen() { var obj: { x: string | number }; obj = { x: \"hey\" }; - obj.x = 10; -} -" + obj.x = 10; // ok, by lvalue\'s given type +}" `; diff --git a/tests/objmap/__snapshots__/jsfmt.spec.js.snap b/tests/objmap/__snapshots__/jsfmt.spec.js.snap index 36d1cec6..0c1683f8 100644 --- a/tests/objmap/__snapshots__/jsfmt.spec.js.snap +++ b/tests/objmap/__snapshots__/jsfmt.spec.js.snap @@ -18,18 +18,18 @@ promiseAllByKey({ (o.bar: \'bar\'); // ok }); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// ok -// error, \'FOO\' incompatible with \'BAR\' -// error, number ~> string -// ok declare function promiseAllByKey(o: O): Promise<$ObjMap>; declare function keyMirror(o: O): $ObjMapi(k: K) => K>; + var o = keyMirror({ FOO: null, BAR: null }); + (o.FOO: \"FOO\"); +// ok (o.FOO: \"BAR\"); +// error, \'FOO\' incompatible with \'BAR\' promiseAllByKey({ foo: Promise.resolve(0), bar: \"bar\" }).then(o => { (o.foo: string); - (o.bar: \"bar\"); -}); -" + // error, number ~> string + (o.bar: \"bar\"); // ok +});" `; diff --git a/tests/optional/__snapshots__/jsfmt.spec.js.snap b/tests/optional/__snapshots__/jsfmt.spec.js.snap index fc738e9b..354b30be 100644 --- a/tests/optional/__snapshots__/jsfmt.spec.js.snap +++ b/tests/optional/__snapshots__/jsfmt.spec.js.snap @@ -4,8 +4,8 @@ exports[`test client_optional.js 1`] = ` qux(0); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ var qux = require(\"./optional\"); -qux(0); -" + +qux(0);" `; exports[`test default.js 1`] = ` @@ -15,8 +15,7 @@ exports[`test default.js 1`] = ` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ function f(foo, bar = foo): [T, T] { return [ foo, bar ]; -} -" +}" `; exports[`test generic.js 1`] = ` @@ -27,10 +26,10 @@ class C { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ function x(x: T = 0) {} + class C { x(x: T = 0) {} -} -" +}" `; exports[`test maybe.js 1`] = ` @@ -40,8 +39,7 @@ exports[`test maybe.js 1`] = ` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ function foo(x?: string): ?string { return x; -} -" +}" `; exports[`test nullable.js 1`] = ` @@ -96,51 +94,54 @@ function optionalNullable8(x: {y?: ?number}) { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// should error -// should error -// should error -// should error + function optionalNullable1(x: { y?: ?number }) { if (x.y !== null && x.y !== undefined) { x.y++; } } + function optionalNullable2(x: { y?: ?number }) { if (x.y !== undefined && x.y !== null) { x.y++; } } + function optionalNullable3(x: { y?: ?number }) { if (!(x.y !== null && x.y !== undefined)) { - x.y++; + x.y++; // should error } } + function optionalNullable4(x: { y?: ?number }) { if (!(x.y !== undefined && x.y !== null)) { - x.y++; + x.y++; // should error } } + function optionalNullable5(x: { y?: ?number }) { if (x.y === null || x.y === undefined) { - x.y++; + x.y++; // should error } } + function optionalNullable6(x: { y?: ?number }) { if (x.y === undefined || x.y === null) { - x.y++; + x.y++; // should error } } + function optionalNullable7(x: { y?: ?number }) { if (!(x.y === null || x.y === undefined)) { x.y++; } } + function optionalNullable8(x: { y?: ?number }) { if (!(x.y === undefined || x.y === null)) { x.y++; } -} -" +}" `; exports[`test optional.js 1`] = ` @@ -161,16 +162,19 @@ function bar(x?, y?) { x * 0; } bar(0); + var foo: (x?: number) => void = bar; foo(); + function qux(x = \"hello\", ...y): string { foo(x); return y[0]; } + qux(0, 0); qux(0, ...[ \"\", 42 ]); -module.exports = qux; -" + +module.exports = qux;" `; exports[`test optional_param.js 1`] = ` @@ -217,41 +221,46 @@ function foo(x?: string): string { } return x; } + function bar(obj: { x?: string }): string { if (obj.x == null) { return \"foo\"; } return obj.x; } + function baz(bar?) { if (!bar) { return 1; } return bar.duck; } + function testOptionalNullable(x?: ?string): string { if (x == null) { return \"foo\"; } return x; } + function testOptionalNullableDefault(x?: ?string = \"hi\"): string { if (x == null) { return \"foo\"; } return x; } + function testOptionalNullableProperty(obj: { x?: ?string }): string { if (obj.x == null) { return \"foo\"; } return obj.x; } + function testOptionalNullableFlowingToNullable(x?: ?string): ?string { var f = function(y: ?string) {}; f(x); -} -" +}" `; exports[`test optional_param2.js 1`] = ` @@ -265,8 +274,7 @@ var j:I = i.map(id => id); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ declare class I { map(mapper: (value?: V) => M): I } var i: I = new I(); -var j: I = i.map(id => id); -" +var j: I = i.map(id => id);" `; exports[`test optional_param3.js 1`] = ` @@ -278,15 +286,13 @@ function bar(x = \"bar\"): string { } bar(undefined); // ok ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// ok -// ok function foo(x?: number) {} foo(undefined); +// ok function bar(x = \"bar\"): string { return x; } -bar(undefined); -" +bar(undefined); // ok" `; exports[`test optional_param4.js 1`] = ` @@ -305,19 +311,19 @@ foo(true); // ERROR boolean ~> number foo(123, true); // ERROR boolean ~> string ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// OK -// OK -// OK -// ERROR boolean ~> number -// ERROR boolean ~> string + function foo(x?: number, ...y: Array): [?number, Array] { return [ x, y ]; } + foo(); -foo(123), foo(123, \"hello\"); +// OK +foo(123), // OK +foo(123, \"hello\"); +// OK foo(true); -foo(123, true); -" +// ERROR boolean ~> number +foo(123, true); // ERROR boolean ~> string" `; exports[`test undefined.js 1`] = ` @@ -332,13 +338,14 @@ function bar() { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ var x; + function foo(bar? = undefined) { x = bar; } + function bar() { return x.duck; -} -" +}" `; exports[`test undefined2.js 1`] = ` @@ -353,11 +360,12 @@ function bar() { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ var x; + function foo(bar?) { x = bar; } + function bar() { return x.duck; -} -" +}" `; diff --git a/tests/optional_props/__snapshots__/jsfmt.spec.js.snap b/tests/optional_props/__snapshots__/jsfmt.spec.js.snap index c8372b5c..e820fd9c 100644 --- a/tests/optional_props/__snapshots__/jsfmt.spec.js.snap +++ b/tests/optional_props/__snapshots__/jsfmt.spec.js.snap @@ -12,19 +12,19 @@ function bar(config: { foo?: number }) {} bar({}); bar({foo: \"\"}); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// OK in TypeScript, not OK in Flow -// OK; we know that narrowing could not have happened -// future widening is constrained var x: {} = { foo: 0 }; var y: { foo?: string } = x; +// OK in TypeScript, not OK in Flow var z: string = y.foo || \"\"; + var o = {}; y = o; +// OK; we know that narrowing could not have happened o.foo = 0; +// future widening is constrained function bar(config: { foo?: number }) {} bar({}); -bar({ foo: \"\" }); -" +bar({ foo: \"\" });" `; exports[`test test2.js 1`] = ` @@ -42,25 +42,23 @@ var d: { foo?: string } = { foo: null }; // But this is an error var e: { foo?: ?string } = { foo: undefined }; // This is fine var f: { foo?: ?string } = { foo: null }; // Also fine ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// This is not an error -// But this is an error -// This is fine -// Also fine -// This is not an error -// But this is an error -// This is fine -// Also fine var a: { foo?: string } = {}; a.foo = undefined; +// This is not an error a.foo = null; +// But this is an error var b: { foo?: ?string } = {}; b.foo = undefined; +// This is fine b.foo = null; +// Also fine var c: { foo?: string } = { foo: undefined }; +// This is not an error var d: { foo?: string } = { foo: null }; +// But this is an error var e: { foo?: ?string } = { foo: undefined }; -var f: { foo?: ?string } = { foo: null }; -" +// This is fine +var f: { foo?: ?string } = { foo: null }; // Also fine" `; exports[`test test3.js 1`] = ` @@ -122,6 +120,7 @@ class A { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + /* object literals are sealed. this is simply a heuristic decision: most of the time, the rule gives the \'right\' @@ -142,37 +141,40 @@ class A { properties, is to have the sealed type acquire the optional properties. */ + // x has optional property b. // (note that the initializer here does not play into // the problem, it\'s just a placeholder. initializers // do not narrow the types of annotated variables as do // subsequent assignments.) // +var x: { a: number, b?: number } = { a: 0 }; + // now assign an object literal lacking property b. // the literal\'s type is sealed and has only a at creation. // but it then flows, specific ~> general, to x\'s annotation // type. at that point, it acquires b as an optional property. // -// ...which allows this assignment to take place. -// T7810506 -// Something similar should happen here, but doesn\'t: the problem is -// made explicit by adding generics (see test3_failure.js introduced by -// D2747512). There is a race between writing b on the object literal -// type and adding b as an optional property to it, since in general we -// cannot guarantee that the flow from the object literal to the -// annotation will be processed before the flow involving the -// access. Here we lose the race and get an error on the write. -var x: { a: number, b?: number } = { a: 0 }; x = { a: 0 }; + +// ...which allows this assignment to take place. x.b = 1; + +// T7810506 class A { x: { a: number, b?: string }; foo() { + // Something similar should happen here, but doesn\'t: the problem is + // made explicit by adding generics (see test3_failure.js introduced by + // D2747512). There is a race between writing b on the object literal + // type and adding b as an optional property to it, since in general we + // cannot guarantee that the flow from the object literal to the + // annotation will be processed before the flow involving the + // access. Here we lose the race and get an error on the write. this.x = { a: 123 }; this.x.b = \"hello\"; } -} -" +}" `; exports[`test test3_failure.js 1`] = ` @@ -187,13 +189,12 @@ class A { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // generalization of failure in test3.js -// this is a spurious error (see test3.js for details) + class A { o: O; foo() { this.o.x = { a: 123 }; - this.o.x.b = \"hello\"; + this.o.x.b = \"hello\"; // this is a spurious error (see test3.js for details) } -} -" +}" `; diff --git a/tests/overload/__snapshots__/jsfmt.spec.js.snap b/tests/overload/__snapshots__/jsfmt.spec.js.snap index 0c5f378d..5274df88 100644 --- a/tests/overload/__snapshots__/jsfmt.spec.js.snap +++ b/tests/overload/__snapshots__/jsfmt.spec.js.snap @@ -56,13 +56,36 @@ var z2:Array = new Dummy().dumber(bar2); * * @flow */ + +var x1: number = \"\".match(0)[0]; +var x2: number = \"\".match(/pattern/)[0]; +var x3: string = \"\".replace(/pattern/, \"...\"); +var x4: number = \"\".split(/pattern/)[0]; + +declare class C { + foo(x: number): number, + foo(x: string): string, + bar(x: { a: number }): number, + bar(x: { a: string }): string +} + +var a = new C(); + +a.foo(0); // ok +a.foo(\"hey\"); // ok +a.foo(true); // error, function cannot be called on intersection type +a.bar({ a: 0 }); // ok +a.bar({ a: \"hey\" }); // ok +a.bar({ a: true }); // error, function cannot be called on intersection type -// error with nested intersection info (outer for bar, inner for x) +declare var x: { a: boolean } & { b: string }; + +a.bar(x); // error with nested intersection info (outer for bar, inner for x) /********** tests ************** interface Dummy { dumb(foo: (x:number) => number):number; @@ -80,27 +103,7 @@ var z1:number = new Dummy().dumber(bar1); function bar2(x:number):string { return \"...\"; } var z2:Array = new Dummy().dumber(bar2); -*/ -var x1: number = \"\".match(0)[0]; -var x2: number = \"\".match(/pattern/)[0]; -var x3: string = \"\".replace(/pattern/, \"...\"); -var x4: number = \"\".split(/pattern/)[0]; -declare class C { - foo(x: number): number, - foo(x: string): string, - bar(x: { a: number }): number, - bar(x: { a: string }): string -} -var a = new C(); -a.foo(0); -a.foo(\"hey\"); -a.foo(true); -a.bar({ a: 0 }); -a.bar({ a: \"hey\" }); -a.bar({ a: true }); -declare var x: { a: boolean } & { b: string }; -a.bar(x); -" +*/" `; exports[`test test.js 1`] = ` @@ -109,12 +112,10 @@ exports[`test test.js 1`] = ` output.set(new FakeUint8Array(), 0); // matches one of the overloads of set } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// matches one of the overloads of set function foo() { var output = new FakeUint8Array(); - output.set(new FakeUint8Array(), 0); -} -" + output.set(new FakeUint8Array(), 0); // matches one of the overloads of set +}" `; exports[`test test2.js 1`] = ` @@ -126,13 +127,11 @@ var foo = new Foo; (foo.bar(\'hmm\'): number); // OK (foo.bar(\'hmmm\'): number); // error ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// OK -// error declare class Foo { bar(x: \"hmm\"): number, bar(x: string): string } var foo = new Foo(); (foo.bar(\"hmm\"): number); -(foo.bar(\"hmmm\"): number); -" +// OK +(foo.bar(\"hmmm\"): number); // error" `; exports[`test test3.js 1`] = ` @@ -160,26 +159,25 @@ h(x_h.p); // ok ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // passing a union-like thing into an overload is ok // if overload handles each branch of union-like thing + // unions -// ok -// maybe -// ok -// optional -// ok declare function f(x: string): void; declare function f(x: number): void; declare var x_f: string | number; f(x_f); +// ok +// maybe declare function g(x: null): void; declare function g(x: void): void; declare function g(x: string): void; declare var x_g: ?string; g(x_g); +// ok +// optional declare function h(x: void): void; declare function h(x: string): void; declare var x_h: { p?: string }; -h(x_h.p); -" +h(x_h.p); // ok" `; exports[`test union.js 1`] = ` @@ -191,7 +189,7 @@ var x2:string = foo([\"\"])[0]; function foo(x: $Either, U>): Array { return []; } + var x1: number = foo(0)[0]; -var x2: string = foo([ \"\" ])[0]; -" +var x2: string = foo([ \"\" ])[0];" `; diff --git a/tests/overload/lib/__snapshots__/jsfmt.spec.js.snap b/tests/overload/lib/__snapshots__/jsfmt.spec.js.snap index 22b1fa79..5d1b7df2 100644 --- a/tests/overload/lib/__snapshots__/jsfmt.spec.js.snap +++ b/tests/overload/lib/__snapshots__/jsfmt.spec.js.snap @@ -7,6 +7,5 @@ exports[`test lib.js 1`] = ` declare class FakeUint8Array { set(index: number, value: number): void, set(array: FakeUint8Array | Array, offset?: number): void -} -" +}" `; diff --git a/tests/parse/__snapshots__/jsfmt.spec.js.snap b/tests/parse/__snapshots__/jsfmt.spec.js.snap index 04b6c231..8b47d23d 100644 --- a/tests/parse/__snapshots__/jsfmt.spec.js.snap +++ b/tests/parse/__snapshots__/jsfmt.spec.js.snap @@ -14,8 +14,9 @@ var z: { /* @flow */ + var x = \"Test\"; var y = 5 / x; -var z: { type: number, y: string } = { type: 1, y: \"hey\" }; -" + +var z: { type: number, y: string } = { type: 1, y: \"hey\" };" `; diff --git a/tests/parse_error_haste/__snapshots__/jsfmt.spec.js.snap b/tests/parse_error_haste/__snapshots__/jsfmt.spec.js.snap index 474ed9f4..3931dac5 100644 --- a/tests/parse_error_haste/__snapshots__/jsfmt.spec.js.snap +++ b/tests/parse_error_haste/__snapshots__/jsfmt.spec.js.snap @@ -16,12 +16,11 @@ var C = require(\"./ParseError\"); // Flow file * triggering/suppressing parse errors. * @flow */ + // non-flow files should not show parse errors -// non-Flow file @providesModule Foo -// non-Flow file -// Flow file var A = require(\"Foo\"); +// non-Flow file @providesModule Foo var B = require(\"./NoProvides\"); -var C = require(\"./ParseError\"); -" +// non-Flow file +var C = require(\"./ParseError\"); // Flow file" `; diff --git a/tests/parse_error_node/__snapshots__/jsfmt.spec.js.snap b/tests/parse_error_node/__snapshots__/jsfmt.spec.js.snap index 19208f23..9d01898a 100644 --- a/tests/parse_error_node/__snapshots__/jsfmt.spec.js.snap +++ b/tests/parse_error_node/__snapshots__/jsfmt.spec.js.snap @@ -15,10 +15,9 @@ var B = require(\"./ParseError\"); // Flow file * triggering/suppressing parse errors. * @flow */ + // non-flow files should not give parse errors -// non-Flow file @providesModule Foo -// Flow file var A = require(\"./Imported\"); -var B = require(\"./ParseError\"); -" +// non-Flow file @providesModule Foo +var B = require(\"./ParseError\"); // Flow file" `; diff --git a/tests/path/__snapshots__/jsfmt.spec.js.snap b/tests/path/__snapshots__/jsfmt.spec.js.snap index 2de635b6..7fd3641a 100644 --- a/tests/path/__snapshots__/jsfmt.spec.js.snap +++ b/tests/path/__snapshots__/jsfmt.spec.js.snap @@ -12,6 +12,5 @@ while (typeof x == \"number\" || typeof x == \"string\") { if (true) x = \"\"; } -var z: number = x; -" +var z: number = x;" `; diff --git a/tests/plsummit/__snapshots__/jsfmt.spec.js.snap b/tests/plsummit/__snapshots__/jsfmt.spec.js.snap index a20611cb..0d238e61 100644 --- a/tests/plsummit/__snapshots__/jsfmt.spec.js.snap +++ b/tests/plsummit/__snapshots__/jsfmt.spec.js.snap @@ -7,9 +7,9 @@ n * s.length; function foo(x) { return [ x, x > 0, \"number \" + x ]; } + var [ n, b, s ] = foo(42); -n * s.length; -" +n * s.length;" `; exports[`test export_class.js 1`] = ` @@ -26,8 +26,8 @@ class C { this.x = x; } } -module.exports = C; -" + +module.exports = C;" `; exports[`test generics.js 1`] = ` @@ -37,12 +37,12 @@ var r: number = 0; function foo(x: X): X { r = x; return x; } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + var r: number = 0; function foo(x: X): X { r = x; return x; -} -" +}" `; exports[`test import_class.js 1`] = ` @@ -51,8 +51,8 @@ exports[`test import_class.js 1`] = ` var c = new C(\"\"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ var C = require(\"./export_class\"); -var c = new C(\"\"); -" + +var c = new C(\"\");" `; exports[`test locals.js 1`] = ` @@ -69,16 +69,17 @@ function bar(x: ?string): number { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + function foo() { var x = 0; var y = x; } + function bar(x: ?string): number { if (x == null) x = \"\"; return x.length; -} -" +}" `; exports[`test objects.js 1`] = ` @@ -102,8 +103,10 @@ function C() { C.prototype.foo = function() { return this.x; }; + var c = new C(); var x: string = c.foo(); + function foo() { return this.y; } @@ -112,7 +115,7 @@ function bar() { } var o = { y: \"\", foo: foo, bar: bar }; var o2 = { y: 0, foo: foo, bar: bar }; + o.bar(); -var y: number = o2.bar(); -" +var y: number = o2.bar();" `; diff --git a/tests/poly/__snapshots__/jsfmt.spec.js.snap b/tests/poly/__snapshots__/jsfmt.spec.js.snap index 8393a1d1..7e8e283f 100644 --- a/tests/poly/__snapshots__/jsfmt.spec.js.snap +++ b/tests/poly/__snapshots__/jsfmt.spec.js.snap @@ -11,20 +11,20 @@ function bar(): A<*> { // error, * can\'t be {} and {x: string} at the same time return (new A: A<{}>) || (new A: A<{x: string}>); } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// OK, implicitly inferred type args -// OK, same as above -// ok but unsafe, caller may assume any type arg -// error, * can\'t be {} and {x: string} at the same time class A {} new A(); +// OK, implicitly inferred type args class B extends A {} +// OK, same as above function foo(b): A { + // ok but unsafe, caller may assume any type arg return b ? (new A(): A) : (new A(): A); } + function bar(): A<*> { + // error, * can\'t be {} and {x: string} at the same time return (new A(): A<{}>) || (new A(): A<{ x: string }>); -} -" +}" `; exports[`test implicit_bounded_instantiation.js 1`] = ` @@ -50,24 +50,26 @@ a.meth(42); // Error: number ~> Middle a.meth(new Base()); // Error: Base ~> Middle ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// T is implicitly (bounded by) Middle in constructor call if not provided. -// Explicit type arg is required in annotation - here a wildcard captures it. -// Error: number ~> Middle -// Error: Base ~> Middle + class Base {} class Middle extends Base {} class Child extends Middle {} + class C { meth(a: T): T { return a; } } + +// T is implicitly (bounded by) Middle in constructor call if not provided. +// Explicit type arg is required in annotation - here a wildcard captures it. var a: C<*> = new C(); + a.meth(new Middle()); a.meth(new Child()); a.meth(42); -a.meth(new Base()); -" +// Error: number ~> Middle +a.meth(new Base()); // Error: Base ~> Middle" `; exports[`test issue-1029.js 1`] = ` @@ -91,8 +93,10 @@ declare function unbox(box: Box): A unbox(bool); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + // naive unification causes combinatorial explosion here, // effectively hangs + type Box = { map1(f: (x: T) => U): Box, map2(f: (x: T) => U): Box, @@ -100,10 +104,12 @@ type Box = { map4(f: (x: T) => U): Box, map5(f: (x: T) => U): Box }; + declare var bool: Box; + declare function unbox(box: Box): A; -unbox(bool); -" + +unbox(bool);" `; exports[`test poly.js 1`] = ` @@ -132,15 +138,18 @@ class Foo { this.x = x; } } + function bar(foo: Foo, y: S): Foo { return new Foo(y); } + var P = { bar: bar }; + declare var Q: { bar(foo: Foo, y: S): Foo }; + var foo = new Foo(0); var x: string = foo.x; -var z: Foo = Q.bar(foo, \"\"); -" +var z: Foo = Q.bar(foo, \"\");" `; exports[`test test.js 1`] = ` @@ -157,10 +166,6 @@ class D extends C { qux(x: X): X { return x; } // OK (generalization) } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// error (specialization, see below) -// OK, but only because the overridden foo accepts no more than number and returns exactly number -// OK -// OK (generalization) class C { foo(x: X): X { return x; @@ -179,15 +184,17 @@ class D extends C { foo(x: number): number { return x; } + // error (specialization, see below) foo_(x: number): number { return x; } + // OK, but only because the overridden foo accepts no more than number and returns exactly number bar(x: X): X { return x; } + // OK qux(x: X): X { return x; - } -} -" + } // OK (generalization) +}" `; diff --git a/tests/poly_class_export/__snapshots__/jsfmt.spec.js.snap b/tests/poly_class_export/__snapshots__/jsfmt.spec.js.snap index a34a5433..b906f798 100644 --- a/tests/poly_class_export/__snapshots__/jsfmt.spec.js.snap +++ b/tests/poly_class_export/__snapshots__/jsfmt.spec.js.snap @@ -8,11 +8,12 @@ class A { module.exports = A; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + class A { x: T; } -module.exports = A; -" + +module.exports = A;" `; exports[`test B.js 1`] = ` @@ -29,14 +30,16 @@ class B extends A { module.exports = new B(); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + let A = require(\"./A\"); + class B extends A { constructor() { super(); } } -module.exports = new B(); -" + +module.exports = new B();" `; exports[`test C.js 1`] = ` @@ -56,15 +59,17 @@ export function f(x: Foo) { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + // This test exports a function whose return type is the class\'s \`this\` type. // It should be inferred (no annotation required). + class Foo { foo(): this { return this; } } + export function f(x: Foo) { return x.foo(); -} -" +}" `; diff --git a/tests/poly_overload/decls/__snapshots__/jsfmt.spec.js.snap b/tests/poly_overload/decls/__snapshots__/jsfmt.spec.js.snap index d0c78cc2..22b37793 100644 --- a/tests/poly_overload/decls/__snapshots__/jsfmt.spec.js.snap +++ b/tests/poly_overload/decls/__snapshots__/jsfmt.spec.js.snap @@ -31,6 +31,5 @@ interface B extends A { foo(s: Some, e: Nada): B, foo(s: Other, e: None): B, foo(s: Other, e: Nada): B -} -" +}" `; diff --git a/tests/predicates-abstract/__snapshots__/jsfmt.spec.js.snap b/tests/predicates-abstract/__snapshots__/jsfmt.spec.js.snap index 01ac8ec8..c0a2205a 100644 --- a/tests/predicates-abstract/__snapshots__/jsfmt.spec.js.snap +++ b/tests/predicates-abstract/__snapshots__/jsfmt.spec.js.snap @@ -14,18 +14,21 @@ function is_string(x): %checks { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + // Filter the contents of an array + declare function my_filter>( v: Array, cb: P ): Array<$Refine>; + declare var arr: Array; const barr = my_filter(arr, is_string); (barr: Array); + function is_string(x): %checks { return typeof x === \"string\"; -} -" +}" `; exports[`test filter-union.js 1`] = ` @@ -48,22 +51,25 @@ declare var ab: Array; (my_filter(ab, (x): %checks => x.kind !== \'A\'): Array); // OK ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + // Filter the contents of an array -// OK -// OK + declare function my_filter>( v: Array, cb: P ): Array<$Refine>; + 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; + (my_filter(ab, (x): %checks => x.kind === \"A\"): Array); -(my_filter(ab, (x): %checks => x.kind !== \"A\"): Array); -" +// OK +(my_filter(ab, (x): %checks => x.kind !== \"A\"): Array); // OK" `; exports[`test refine.js 1`] = ` @@ -115,6 +121,7 @@ function is_string_and_number(x, y): %checks { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + /* $Pred 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 @@ -125,36 +132,40 @@ function is_string_and_number(x, y): %checks { $Refine 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>(v: T, cb: P): $Refine; // function refine(v, cb) // { if (cb(v)) { return v; } else { throw new Error(); } } /* Use case */ -// function refine_fst(v, w, cb) -// { if (cb(v, w)) { return v; } else { throw new Error(); } } -// function refine_fst(v, w, cb) -// { if (cb(v, w)) { return w; } else { throw new Error(); } } -declare function refine>(v: T, cb: P): $Refine; declare var a: mixed; var b = refine(a, is_string); (b: string); + declare function refine_fst>( v: T, w: T, cb: P ): $Refine; +// 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>(v: T, w: T, cb: P): $Refine; + +// 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[`test sanity-filter.js 1`] = ` @@ -182,25 +193,29 @@ function is_string_regular(x): boolean { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// Sanity check A: filtering the wrong type -// Sanity check B: Passing non-predicate function to filter + declare function my_filter>( v: Array, cb: P ): Array<$Refine>; + +// Sanity check A: filtering the wrong type declare var a: Array; const b = my_filter(a, is_string); (b: Array); + +// Sanity check B: Passing non-predicate function to filter declare var c: Array; const d = my_filter(c, is_string_regular); (d: Array); + function is_string(x): boolean %checks { return typeof x === \"string\"; } + function is_string_regular(x): boolean { return typeof x === \"string\"; -} -" +}" `; exports[`test sanity-filter-union.js 1`] = ` @@ -223,22 +238,25 @@ declare var ab: Array; (my_filter(ab, (x): %checks => x.kind !== \'A\'): Array); // ERROR ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + // Filter the contents of an array -// ERROR -// ERROR + declare function my_filter>( v: Array, cb: P ): Array<$Refine>; + 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; + (my_filter(ab, (x): %checks => x.kind === \"A\"): Array); -(my_filter(ab, (x): %checks => x.kind !== \"A\"): Array); -" +// ERROR +(my_filter(ab, (x): %checks => x.kind !== \"A\"): Array); // ERROR" `; exports[`test sanity-refine.js 1`] = ` @@ -288,42 +306,51 @@ function is_string_and_number(x, y): %checks { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + // Sanity check A: the refinment position index is outside of the allowed range -// ERROR: index out of bounds -// Sanity check B: refine2 expects a function that accepts 3 arguments but -// it is called with a function that takes 2 -// Sanity check C: expecting a predicate function but passed a non-predicate one -// ERROR: is_string_regular is not a -// predicate function -//////////////////////////////////////////////////////////////////////////////// declare function refine>(v: T, cb: P): $Refine; + 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>( u: T, v: T, w: T, cb: P ): $Refine; + 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\"; -} -" +}" `; diff --git a/tests/predicates-declared/__snapshots__/jsfmt.spec.js.snap b/tests/predicates-declared/__snapshots__/jsfmt.spec.js.snap index 3139419a..374d79a3 100644 --- a/tests/predicates-declared/__snapshots__/jsfmt.spec.js.snap +++ b/tests/predicates-declared/__snapshots__/jsfmt.spec.js.snap @@ -41,37 +41,44 @@ 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)) {} -" +if (m.bind(this)(x)) {}" `; exports[`test function-union.js 1`] = ` @@ -95,19 +102,22 @@ function foo(x: number | string | Array): number { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// Feature check: + 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): number { var f = cond ? f1 : f2; + if (f(x)) { return x.length; } else { return 1; } -} -" +}" `; exports[`test is-string-decl.js 1`] = ` @@ -131,22 +141,23 @@ function foo(x: string | Array): string { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// Feature check: -// The use of \`is_string\` as a conditional check -// should guarantee the narrowing of the type of \`x\` -// to string. -// Accordingly the negation of the above check -// guarantees that \`x\` here is an Array + 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 { 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 return x.join(); } -} -" +}" `; exports[`test logical-or.js 1`] = ` @@ -174,24 +185,29 @@ function foo(x: mixed) { return 1; } (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; -" + +Number(dollars) || 0;" `; exports[`test object-invariant.js 1`] = ` @@ -221,18 +237,22 @@ function f(_this: { m: ?Meeting }): string { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + // Sanity check: // - preserving \`havoc\` semantics + type Meeting = { organizer: ?Invitee, es: Array }; + 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[`test orig-string-tag-check.js 1`] = ` @@ -250,17 +270,16 @@ function foo(x: string | Array): string { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + // The original first-order case -// [ERROR] x: Array doesn\'t match return type -// [ERROR] x: string doesn\'t have .join method + function foo(x: string | Array): string { if (typeof x === \"string\") { - return x; + return x; // [ERROR] x: Array doesn\'t match return type } else { - return x.join(); + return x.join(); // [ERROR] x: string doesn\'t have .join method } -} -" +}" `; exports[`test sanity-fall-through.js 1`] = ` @@ -279,16 +298,18 @@ function foo(s: Array): string { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + // Sanity check: // - we should still be getting an error at the second return statement + declare function pred(x: T): boolean; + function foo(s: Array): string { if (pred(s)) { return \"1\"; } return 1; -} -" +}" `; exports[`test sanity-invalid-calls.js 1`] = ` @@ -313,19 +334,23 @@ function foo(s: Array): string { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + // Sanity check: // - invalid calls at predicate positions + declare function pred(x: T): boolean; + function foo(s: Array): string { if (1(s)) { return \"1\"; } + if ((pred + 1)(\"s\")) { return \"1\"; } + return \"1\"; -} -" +}" `; exports[`test sanity-is-string-bug.js 1`] = ` @@ -346,19 +371,19 @@ function bar(x: string | Array): string { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// Sanity check: -// - Erroneous logic -// error: both string and Array can flow to x + 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 { if (is_number(x)) { return x; } else { - return x.join(); + return x.join(); // error: both string and Array can flow to x } -} -" +}" `; exports[`test sanity-parameter-mismatch.js 1`] = ` @@ -374,13 +399,15 @@ declare function foo( foo(3, 3); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + // Sanity check: make sure the parameters are checked as usual + declare function foo( input: mixed, types: string | Array ): boolean %checks(typeof input === \"string\" || Array.isArray(input)); -foo(3, 3); -" + +foo(3, 3);" `; exports[`test sanity-pred-with-body.js 1`] = ` @@ -401,19 +428,21 @@ function foo(x: string | Array): string { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + // Sanity check: // - predicate functions cannot have bodies (can only be declarations) -// error: cannot use pred type here + 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 { if (pred(x)) { return x; } return \"1\"; -} -" +}" `; exports[`test sanity-return-type.js 1`] = ` @@ -422,6 +451,6 @@ exports[`test sanity-return-type.js 1`] = ` declare function f2(x: mixed): string %checks(Array.isArray(x)); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -declare function f2(x: mixed): string %checks(Array.isArray(x)); -" + +declare function f2(x: mixed): string %checks(Array.isArray(x));" `; diff --git a/tests/predicates-inferred/__snapshots__/jsfmt.spec.js.snap b/tests/predicates-inferred/__snapshots__/jsfmt.spec.js.snap index 8f85dd8f..fbade231 100644 --- a/tests/predicates-inferred/__snapshots__/jsfmt.spec.js.snap +++ b/tests/predicates-inferred/__snapshots__/jsfmt.spec.js.snap @@ -28,27 +28,32 @@ function bak(z: string | number): number { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + // Sanity check: shouldn\'t be allowed to declare a predicate AND use \`chekcs\` -// Sanity: disallowed body + 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[`test sanity-multi-params.js 1`] = ` @@ -68,18 +73,19 @@ function foo(x: string | Array): string { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + // Feature: multi params function multi_param(w, x, y, z): %checks { return typeof z === \"string\"; } + function foo(x: string | Array): string { if (multi_param(\"1\", \"2\", x, \"3\")) { return x; } else { return x.join(); } -} -" +}" `; exports[`test sanity-ordering.js 1`] = ` @@ -103,11 +109,14 @@ function dotAccess(head, create) { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @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(\".\"); @@ -116,8 +125,7 @@ function dotAccess(head, create) { head = head[key] || create && (head[key] = {}); } while (stack.length && head); return head; -} -" +}" `; exports[`test sanity-unbound-var.js 1`] = ` @@ -140,20 +148,22 @@ function foo(x: string | Array): string { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + +declare var y: mixed; + // Sanity check: this should fail, because the preficate function // checks \`y\` instead of \`x\`. -declare var y: mixed; function err(x): %checks { return typeof y === \"string\"; } + function foo(x: string | Array): string { if (err(x)) { return x; } else { return x.join(); } -} -" +}" `; exports[`test simple-predicate-func.js 1`] = ` @@ -232,30 +242,34 @@ function two_strings(x,y): %checks { declare function from_two_strings(x: string, y: string): void; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// Feature check: -// The use of \`is_string\` as a conditional check -// should guarantee the narrowing of the type of \`x\` -// to string. -// Accordingly the negation of the above check -// guarantees that \`x\` here is an Array -// Same as above but refining an offset -// Feature: multi params + 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 { 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 return x.join(); } } + +// Same as above but refining an offset function bar(z: { f: string | Array }): string { if (is_string(z.f)) { return z.f; @@ -263,9 +277,11 @@ function bar(z: { f: string | Array }): string { 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; @@ -273,9 +289,12 @@ function baz(z: string | number): number { return z.length; } } + +// Feature: multi params function multi_param(w, x, y, z): %checks { return typeof z === \"string\"; } + function foo(x: string | Array): string { if (multi_param(\"1\", \"2\", \"3\", x)) { return x; @@ -283,16 +302,18 @@ function foo(x: string | Array): string { 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; -" + +declare function from_two_strings(x: string, y: string): void;" `; exports[`test simple-predicate-func-post.js 1`] = ` @@ -319,22 +340,24 @@ function is_string(x): %checks { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + // Feature check: // The predicate function is defined after the conditional check -// The use of \`is_string\` as a conditional check -// should guarantee the narrowing of the type of \`x\` -// to string. -// Accordingly the negation of the above check -// guarantees that \`x\` here is an Array + function foo(x: string | Array): 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 return x.join(); } } + function is_string(x): %checks { return typeof x === \"string\"; -} -" +}" `; diff --git a/tests/predicates-parsing/__snapshots__/jsfmt.spec.js.snap b/tests/predicates-parsing/__snapshots__/jsfmt.spec.js.snap index a0ef58a3..9c5d5c41 100644 --- a/tests/predicates-parsing/__snapshots__/jsfmt.spec.js.snap +++ b/tests/predicates-parsing/__snapshots__/jsfmt.spec.js.snap @@ -6,9 +6,10 @@ exports[`test fail-0.js 1`] = ` declare function f2(x: mixed): boolean %checks; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + // Error: \'declare\', \'checks\' but missing predicate -declare function f2(x: mixed): boolean %checks; -" + +declare function f2(x: mixed): boolean %checks;" `; exports[`test fail-1.js 1`] = ` @@ -19,9 +20,10 @@ exports[`test fail-1.js 1`] = ` function f6(x: mixed): %checks (x !== null) { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + // Error: no return statement -function f6(x: mixed): %checks(x !== null) {} -" + +function f6(x: mixed): %checks(x !== null) {}" `; exports[`test fail-2.js 1`] = ` @@ -32,12 +34,12 @@ var a2 = (x: mixed): %checks (x !== null) => { // Error: body form } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// Error: body form + var a2 = (x: mixed): %checks(x !== null) => { + // Error: body form var x = 1; return x; -}; -" +};" `; exports[`test fail-3.js 1`] = ` @@ -50,12 +52,14 @@ 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; -" + +var a2 = (x: mixed): %checks(x !== null) => x !== null;" `; exports[`test pass.js 1`] = ` @@ -88,23 +92,33 @@ 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; -" +typeof x === null;" `; diff --git a/tests/private/__snapshots__/jsfmt.spec.js.snap b/tests/private/__snapshots__/jsfmt.spec.js.snap index fbef504c..2a9958e8 100644 --- a/tests/private/__snapshots__/jsfmt.spec.js.snap +++ b/tests/private/__snapshots__/jsfmt.spec.js.snap @@ -24,12 +24,12 @@ class A { this.__x = 0; } } + class B extends A { foo() { var x: number = this.x; var _x: string = this._x; var __x: number = this.__x; } -} -" +}" `; diff --git a/tests/promises/__snapshots__/jsfmt.spec.js.snap b/tests/promises/__snapshots__/jsfmt.spec.js.snap index 00a1adbd..df27150d 100644 --- a/tests/promises/__snapshots__/jsfmt.spec.js.snap +++ b/tests/promises/__snapshots__/jsfmt.spec.js.snap @@ -40,40 +40,47 @@ function tes2(val: Map>) { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// non-Promise values passed through -// tuple information is preserved -// Error: string ~> number -// Error: number ~> boolean -// Error: boolean ~> string -// array element type is (string | number | boolean) -// Errors: string ~> void, number ~> void, boolean ~> void -// First argument is required -// Error: expected array instead of undefined (too few arguments) -// Mis-typed arg -// Error: expected array instead of number -// Promise.all is a function -// Promise.all supports iterables + declare var pstr: Promise; declare var pnum: Promise; -Promise.all([ pstr, pnum, true ]).then(xs => { + +Promise.all([ + pstr, + pnum, + // non-Promise values passed through + true +]).then(xs => { + // tuple information is preserved let [ a, b, c ] = xs; (a: number); + // Error: string ~> number (b: boolean); + // Error: number ~> boolean (c: string); + // Error: boolean ~> string + // array element type is (string | number | boolean) xs.forEach(x => { - (x: void); + (x: void); // Errors: string ~> void, number ~> void, boolean ~> void }); }); + +// First argument is required Promise.all(); +// Error: expected array instead of undefined (too few arguments) +// Mis-typed arg Promise.all(0); +// Error: expected array instead of number +// Promise.all is a function (Promise.all: Function); + +// Promise.all supports iterables function test(val: Iterable>) { const r: Promise> = Promise.all(val); } + function tes2(val: Map>) { const r: Promise> = Promise.all(val.values()); -} -" +}" `; exports[`test covariance.js 1`] = ` @@ -95,20 +102,21 @@ async function testRace() { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -/* This is a test case from https://github.com/facebook/flow/issues/1143 + +async function testAll() { + /* This is a test case from https://github.com/facebook/flow/issues/1143 * which was previously an error due to Array\'s invariance and an improper * definition of Promise.all */ -async function testAll() { const x: Array> = []; const y: Promise> = Promise.all(x); const z: Array = await y; } + async function testRace() { const x: Array> = []; const y: Promise = Promise.race(x); const z: ?string = await y; -} -" +}" `; exports[`test promise.js 1`] = ` @@ -344,93 +352,40 @@ Promise.resolve(0) /** * @flow */ + ////////////////////////////////////////////////// // == Promise constructor resolve() function == // ////////////////////////////////////////////////// + // Promise constructor resolve(T) -> then(T) -// TODO: The error message that results from this is almost useless -// Error: number ~> string -// Promise constructor with arrow function resolve(T) -> then(T) -// TODO: The error message that results from this is almost useless -// Error: number ~> string -// Promise constructor resolve(Promise) -> then(T) -// Error: number ~> string -// Promise constructor resolve(Promise>) -> then(T) -// Error: number ~> string -// Promise constructor resolve(T); resolve(U); -> then(T|U) -// Error: number|string -> string -///////////////////////////////////////////////// -// == Promise constructor reject() function == // -///////////////////////////////////////////////// -// TODO: Promise constructor reject(T) -> catch(T) -// TODO -// Error: number ~> string -// TODO: Promise constructor reject(Promise) ~> catch(Promise) -// TODO -// Error: Promise ~> number -// TODO: Promise constructor reject(T); reject(U); -> then(T|U) -// TODO -// Error: number|string -> string -///////////////////////////// -// == Promise.resolve() == // -///////////////////////////// -// Promise.resolve(T) -> then(T) -// Error: number ~> string -// Promise.resolve(Promise) -> then(T) -// Error: number ~> string -// Promise.resolve(Promise>) -> then(T) -// Error: number ~> string -//////////////////////////// -// == Promise.reject() == // -//////////////////////////// -// TODO: Promise.reject(T) -> catch(T) -// TODO -// Error: number ~> string -// TODO: Promise.reject(Promise) -> catch(Promise) -// TODO -// Error: Promise ~> number -////////////////////////////////// -// == Promise.prototype.then == // -////////////////////////////////// -// resolvedPromise.then():T -> then(T) -// Error: string ~> number -// resolvedPromise.then():Promise -> then(T) -// Error: string ~> number -// resolvedPromise.then():Promise> -> then(T) -// Error: string ~> number -// TODO: resolvedPromise.then() -> catch(T) -// TODO -// Error: string ~> number -/////////////////////////////////// -// == Promise.prototype.catch == // -/////////////////////////////////// -// rejectedPromise.catch():U -> then(U) -// Error: string ~> number -// rejectedPromise.catch():Promise -> then(U) -// Error: string ~> number -// rejectedPromise.catch():Promise> -> then(U) -// Error: string ~> number -// TODO: resolvedPromise -> catch() -> then():T -// TODO -// Error: string ~> number new Promise(function(resolve, reject) { resolve(0); }).then(function(num) { var a: number = num; - var b: string = num; + + // TODO: The error message that results from this is almost useless + var b: string = num; // Error: number ~> string }); + +// Promise constructor with arrow function resolve(T) -> then(T) new Promise((resolve, reject) => resolve(0)).then(function(num) { var a: number = num; - var b: string = num; + + // TODO: The error message that results from this is almost useless + var b: string = num; // Error: number ~> string }); + +// Promise constructor resolve(Promise) -> then(T) new Promise(function(resolve, reject) { resolve(new Promise(function(resolve, reject) { resolve(0); })); }).then(function(num) { var a: number = num; - var b: string = num; + var b: string = num; // Error: number ~> string }); + +// Promise constructor resolve(Promise>) -> then(T) new Promise(function(resolve, reject) { resolve(new Promise(function(resolve, reject) { resolve(new Promise(function(resolve, reject) { @@ -439,8 +394,10 @@ new Promise(function(resolve, reject) { })); }).then(function(num) { var a: number = num; - var b: string = num; + var b: string = num; // Error: number ~> string }); + +// Promise constructor resolve(T); resolve(U); -> then(T|U) new Promise(function(resolve, reject) { if (Math.random()) { resolve(42); @@ -453,22 +410,35 @@ new Promise(function(resolve, reject) { } else { var b: number = numOrStr; } - var c: string = numOrStr; + var c: string = numOrStr; // Error: number|string -> string }); + +///////////////////////////////////////////////// +// == Promise constructor reject() function == // +///////////////////////////////////////////////// +// TODO: Promise constructor reject(T) -> catch(T) new Promise(function(resolve, reject) { reject(0); }).catch(function(num) { var a: number = num; - var b: string = num; + + // TODO + var b: string = num; // Error: number ~> string }); + +// TODO: Promise constructor reject(Promise) ~> catch(Promise) new Promise(function(resolve, reject) { reject(new Promise(function(resolve, reject) { reject(0); })); }).catch(function(num) { var a: Promise = num; - var b: number = num; + + // TODO + var b: number = num; // Error: Promise ~> number }); + +// TODO: Promise constructor reject(T); reject(U); -> then(T|U) new Promise(function(resolve, reject) { if (Math.random()) { reject(42); @@ -481,28 +451,55 @@ new Promise(function(resolve, reject) { } else { var b: number = numOrStr; } - var c: string = numOrStr; + + // TODO + var c: string = numOrStr; // Error: number|string -> string }); + +///////////////////////////// +// == Promise.resolve() == // +///////////////////////////// +// Promise.resolve(T) -> then(T) Promise.resolve(0).then(function(num) { var a: number = num; - var b: string = num; + var b: string = num; // Error: number ~> string }); + +// Promise.resolve(Promise) -> then(T) Promise.resolve(Promise.resolve(0)).then(function(num) { var a: number = num; - var b: string = num; + var b: string = num; // Error: number ~> string }); + +// Promise.resolve(Promise>) -> then(T) Promise.resolve(Promise.resolve(Promise.resolve(0))).then(function(num) { var a: number = num; - var b: string = num; + var b: string = num; // Error: number ~> string }); + +//////////////////////////// +// == Promise.reject() == // +//////////////////////////// +// TODO: Promise.reject(T) -> catch(T) Promise.reject(0).catch(function(num) { var a: number = num; - var b: string = num; + + // TODO + var b: string = num; // Error: number ~> string }); + +// TODO: Promise.reject(Promise) -> catch(Promise) Promise.reject(Promise.resolve(0)).then(function(num) { var a: Promise = num; - var b: number = num; + + // TODO + var b: number = num; // Error: Promise ~> number }); + +////////////////////////////////// +// == Promise.prototype.then == // +////////////////////////////////// +// resolvedPromise.then():T -> then(T) Promise .resolve(0) .then(function(num) { @@ -510,8 +507,10 @@ Promise }) .then(function(str) { var a: string = str; - var b: number = str; + var b: number = str; // Error: string ~> number }); + +// resolvedPromise.then():Promise -> then(T) Promise .resolve(0) .then(function(num) { @@ -519,8 +518,10 @@ Promise }) .then(function(str) { var a: string = str; - var b: number = str; + var b: number = str; // Error: string ~> number }); + +// resolvedPromise.then():Promise> -> then(T) Promise .resolve(0) .then(function(num) { @@ -528,8 +529,10 @@ Promise }) .then(function(str) { var a: string = str; - var b: number = str; + var b: number = str; // Error: string ~> number }); + +// TODO: resolvedPromise.then() -> catch(T) Promise .resolve(0) .then(function(num) { @@ -537,8 +540,15 @@ Promise }) .catch(function(str) { var a: string = str; - var b: number = str; + + // TODO + var b: number = str; // Error: string ~> number }); + +/////////////////////////////////// +// == Promise.prototype.catch == // +/////////////////////////////////// +// rejectedPromise.catch():U -> then(U) Promise .reject(0) .catch(function(num) { @@ -546,8 +556,10 @@ Promise }) .then(function(str) { var a: string = str; - var b: number = str; + var b: number = str; // Error: string ~> number }); + +// rejectedPromise.catch():Promise -> then(U) Promise .reject(0) .catch(function(num) { @@ -555,8 +567,10 @@ Promise }) .then(function(str) { var a: string = str; - var b: number = str; + var b: number = str; // Error: string ~> number }); + +// rejectedPromise.catch():Promise> -> then(U) Promise .reject(0) .catch(function(num) { @@ -564,16 +578,19 @@ Promise }) .then(function(str) { var a: string = str; - var b: number = str; + var b: number = str; // Error: string ~> number }); + +// TODO: resolvedPromise -> catch() -> then():T Promise .resolve(0) .catch(function(err) {}) .then(function(num) { var a: number = num; - var b: string = num; - }); -" + + // TODO + var b: string = num; // Error: string ~> number + });" `; exports[`test resolve_global.js 1`] = ` @@ -623,19 +640,15 @@ async function baz(): Promise { * test Promise name resolution * @flow */ + /** * 1. introduce shadowing bindings for important names */ +class Promise {} + /** * 2. implicit refs to Promise during desugaring should be unaffected */ -/** - * 3. but explicit name refs from code and annos resolve - * using the usual rules - */ -// error: \`Promise\` in return expr is the local binding -// error: return type anno is a ref to the local binding -class Promise {} async function foo(x: boolean) { if (x) { return { bar: \"baz\" }; @@ -643,18 +656,27 @@ async function foo(x: boolean) { return null; } } + async function run() { console.log(await foo(true)); console.log(await foo(false)); } + run(); + +/** + * 3. but explicit name refs from code and annos resolve + * using the usual rules + */ +// error: \`Promise\` in return expr is the local binding async function bar() { return Promise.resolve(0); } + +// error: return type anno is a ref to the local binding async function baz(): Promise { return 0; -} -" +}" `; exports[`test resolve_void.js 1`] = ` @@ -665,9 +687,8 @@ exports[`test resolve_void.js 1`] = ` (Promise.resolve(undefined): Promise); // error ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// error -// error + (Promise.resolve(): Promise); -(Promise.resolve(undefined): Promise); -" +// error +(Promise.resolve(undefined): Promise); // error" `; diff --git a/tests/pure_component/__snapshots__/jsfmt.spec.js.snap b/tests/pure_component/__snapshots__/jsfmt.spec.js.snap index 8c898746..5dd2d8d7 100644 --- a/tests/pure_component/__snapshots__/jsfmt.spec.js.snap +++ b/tests/pure_component/__snapshots__/jsfmt.spec.js.snap @@ -6,11 +6,10 @@ class C extends React.PureComponent { } (); // error (\`x\` is a required prop) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// error (\`x\` is a required prop) var React = require(\"react\"); + class C extends React.PureComponent { props: { x: number }; } -; -" +; // error (\`x\` is a required prop)" `; diff --git a/tests/qualified/__snapshots__/jsfmt.spec.js.snap b/tests/qualified/__snapshots__/jsfmt.spec.js.snap index f43caef8..81d1e190 100644 --- a/tests/qualified/__snapshots__/jsfmt.spec.js.snap +++ b/tests/qualified/__snapshots__/jsfmt.spec.js.snap @@ -12,14 +12,16 @@ type bar = typeof of_type_foo.bar; var a: bar = 42; var b: bar = \'asdf\'; // Error: string ~> number ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Error: string ~> number class C {} var M = { C: C }; + var x: M.C = 0; + type foo = { bar: number }; + declare var of_type_foo: foo; type bar = typeof of_type_foo.bar; + var a: bar = 42; -var b: bar = \"asdf\"; -" +var b: bar = \"asdf\"; // Error: string ~> number" `; diff --git a/tests/react/__snapshots__/jsfmt.spec.js.snap b/tests/react/__snapshots__/jsfmt.spec.js.snap index 41f8cc68..cb47c004 100644 --- a/tests/react/__snapshots__/jsfmt.spec.js.snap +++ b/tests/react/__snapshots__/jsfmt.spec.js.snap @@ -17,11 +17,11 @@ module.exports = AudienceInsightsContainer; var React = require(\"react\"); var AudienceInsightsContainer = React.createClass({ renderComponent(AudienceInsights: ReactClass<*>) { - return ; + return ; } }); -module.exports = AudienceInsightsContainer; -" + +module.exports = AudienceInsightsContainer;" `; exports[`test createElement_string.js 1`] = ` @@ -39,14 +39,15 @@ class Foo extends React.Component { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow import React from \"react\"; + class Bar extends React.Component {} + class Foo extends React.Component { render() { const Cmp = Math.random() < 0.5 ? \"div\" : Bar; - return ; + return ; } -} -" +}" `; exports[`test createElementRequiredProp_string.js 1`] = ` @@ -75,6 +76,7 @@ class Foo extends React.Component { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow import React from \"react\"; + class Bar extends React.Component { props: { test: number }; render() { @@ -85,13 +87,13 @@ class Bar extends React.Component { ); } } + class Foo extends React.Component { render() { const Cmp = Math.random() < 0.5 ? \"div\" : Bar; - return ; + return ; } -} -" +}" `; exports[`test import_react.js 1`] = ` @@ -104,12 +106,12 @@ var a: Component<*,*,*> = new react.Component(); var b: number = new react.Component(); // Error: ReactComponent ~> number ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// Error: ReactComponent ~> number + import react from \"react\"; import {Component} from \"react\"; + var a: Component<*, *, *> = new react.Component(); -var b: number = new react.Component(); -" +var b: number = new react.Component(); // Error: ReactComponent ~> number" `; exports[`test jsx_spread.js 1`] = ` @@ -126,14 +128,14 @@ var props = {bar: 42}; var blah = ; // error bar, number given string expected ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// error bar, number given string expected + var React = require(\"react\"); var Foo = React.createClass({ propTypes: { bar: React.PropTypes.string.isRequired } }); + var props = { bar: 42 }; -var blah = ; -" +var blah = ; // error bar, number given string expected" `; exports[`test proptype_arrayOf.js 1`] = ` @@ -153,15 +155,17 @@ var fail_not_array = var fail_mistyped_elems = ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + var React = require(\"react\"); var Example = React.createClass({ propTypes: { arr: React.PropTypes.arrayOf(React.PropTypes.number).isRequired } }); -var ok_empty = ; -var ok_numbers = ; -var fail_not_array = ; -var fail_mistyped_elems = ; -" + +var ok_empty = ; +var ok_numbers = ; + +var fail_not_array = ; +var fail_mistyped_elems = ;" `; exports[`test proptype_func.js 1`] = ` @@ -181,15 +185,17 @@ var ok_retval = 1} /> var fail_mistyped = ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + var React = require(\"react\"); var Example = React.createClass({ propTypes: { func: React.PropTypes.func.isRequired } }); -var ok_void = {}}/>; -var ok_args = {}}/>; -var ok_retval = 1}/>; -var fail_mistyped = ; -" + +var ok_void = {}} />; +var ok_args = {}} />; +var ok_retval = 1} />; + +var fail_mistyped = ;" `; exports[`test proptype_missing.js 1`] = ` @@ -225,6 +231,7 @@ var React = React.createClass({ }); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + /* If you create a react component with createClass() but don\'t specify the * propTypes, what should the type of props be? * @@ -238,11 +245,10 @@ var React = React.createClass({ * We may change this back to the empty object at some point and fix the * situations where it didn\'t used to error */ -// So this would have been an error in 0.21.0 if we didn\'t make this.props -// Object -// But this never errored var React = React.createClass({ getID(): string { + // So this would have been an error in 0.21.0 if we didn\'t make this.props + // Object switch (this.props.name) { case \"a\": return \"Bob\"; @@ -251,10 +257,10 @@ var React = React.createClass({ } }, render() { - return
; + // But this never errored + return
; } -}); -" +});" `; exports[`test proptype_object.js 1`] = ` @@ -273,14 +279,16 @@ var ok_props = ; var fail_mistyped = ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + var React = require(\"react\"); var Example = React.createClass({ propTypes: { object: React.PropTypes.object.isRequired } }); -var ok_empty = ; -var ok_props = ; -var fail_mistyped = ; -" + +var ok_empty = ; +var ok_props = ; + +var fail_mistyped = ;" `; exports[`test proptype_objectOf.js 1`] = ` @@ -300,17 +308,19 @@ var fail_not_object = var fail_mistyped_props = ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + var React = require(\"react\"); var Example = React.createClass({ propTypes: { obj: React.PropTypes.objectOf(React.PropTypes.number).isRequired } }); -var ok_empty = ; -var ok_numbers = ; -var fail_not_object = ; -var fail_mistyped_props = ; -" + +var ok_empty = ; +var ok_numbers = ; + +var fail_not_object = ; +var fail_mistyped_props = ;" `; exports[`test proptype_oneOf.js 1`] = ` @@ -327,13 +337,14 @@ var ex1 = ; var ex2 = ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + var React = require(\"react\"); var Example = React.createClass({ propTypes: { literal: React.PropTypes.oneOf([ \"foo\" ]).isRequired } }); -var ex1 = ; -var ex2 = ; -" + +var ex1 = ; +var ex2 = ;" `; exports[`test proptype_oneOfType.js 1`] = ` @@ -362,6 +373,7 @@ var ok_string = ; var fail_bool = ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + var React = require(\"react\"); var Example = React.createClass({ propTypes: { @@ -378,8 +390,9 @@ var Example = React.createClass({ } } }); -var ok_number = ; -var ok_string = ; -var fail_bool = ; -" + +var ok_number = ; +var ok_string = ; + +var fail_bool = ;" `; diff --git a/tests/react_functional/__snapshots__/jsfmt.spec.js.snap b/tests/react_functional/__snapshots__/jsfmt.spec.js.snap index 24592167..193703fa 100644 --- a/tests/react_functional/__snapshots__/jsfmt.spec.js.snap +++ b/tests/react_functional/__snapshots__/jsfmt.spec.js.snap @@ -13,20 +13,19 @@ function G(props: { foo: string|numner }) {} var Z = 0; ; // error, expected React component ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +import React from \"react\"; + +function F(props: { foo: string }) {} +; /* error: missing \`foo\`*/ +; /* error: number ~> string*/ +; // ok // props subtyping is property-wise covariant -// ok -// error, expected React component -import React from \"react\"; -function F(props: { foo: string }) {} -; -; -; function G(props: { foo: string | numner }) {} -; +; +// ok var Z = 0; -; -" +; // error, expected React component" `; diff --git a/tests/react_modules/__snapshots__/jsfmt.spec.js.snap b/tests/react_modules/__snapshots__/jsfmt.spec.js.snap index 061e9dcf..4e626d9b 100644 --- a/tests/react_modules/__snapshots__/jsfmt.spec.js.snap +++ b/tests/react_modules/__snapshots__/jsfmt.spec.js.snap @@ -29,24 +29,26 @@ module.exports = Callsite; /* @flow */ var React = require(\"react\"); var Hello = require(\"./createclass-module\"); + var HelloLocal = React.createClass({ propTypes: { name: React.PropTypes.string.isRequired }, render: function(): React.Element<*> { return
{this.props.name}
; } }); + var Callsite = React.createClass({ render: function(): React.Element<*> { return (
- - + +
); } }); -module.exports = Callsite; -" + +module.exports = Callsite;" `; exports[`test createclass-module.js 1`] = ` @@ -67,14 +69,15 @@ module.exports = Hello; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ var React = require(\"react\"); + var Hello = React.createClass({ propTypes: { name: React.PropTypes.string.isRequired }, render: function(): React.Element<*> { return
{this.props.name}
; } }); -module.exports = Hello; -" + +module.exports = Hello;" `; exports[`test es6class-types-callsite.js 1`] = ` @@ -108,25 +111,29 @@ module.exports = Callsite; /* @flow */ import React from \"react\"; import Hello from \"./es6class-types-module\"; + type Props = { name: string }; + class HelloLocal extends React.Component { props: Props; + render(): React.Element<*> { return
{this.props.name}
; } } + class Callsite extends React.Component { render(): React.Element<*> { return (
- - + +
); } } -module.exports = Callsite; -" + +module.exports = Callsite;" `; exports[`test es6class-types-module.js 1`] = ` @@ -148,14 +155,17 @@ module.exports = Hello; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ import React from \"react\"; + type Props = { name: string }; + class Hello extends React.Component<{}, Props, void> { props: Props; static defaultProps: {}; + render(): React.Element<*> { return
{this.props.name}
; } } -module.exports = Hello; -" + +module.exports = Hello;" `; diff --git a/tests/rec/__snapshots__/jsfmt.spec.js.snap b/tests/rec/__snapshots__/jsfmt.spec.js.snap index 23e1dcda..b72efb5a 100644 --- a/tests/rec/__snapshots__/jsfmt.spec.js.snap +++ b/tests/rec/__snapshots__/jsfmt.spec.js.snap @@ -20,9 +20,11 @@ function identity
(val: A): Functor { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + type F = { foo(x: A): F }; declare function foo(x: any): F; ({ foo }: F); + function bar(y: F): F { return y; } @@ -32,15 +34,16 @@ function bar1(y: F): F { function bar2(y: F): F { return y; } + type Functor = { map(f: (val: A) => B): Functor }; + function identity(val: A): Functor { return { map(f: (_: typeof val) => B): Functor { return identity(f(val)); } }; -} -" +}" `; exports[`test issue-1228.js 1`] = ` @@ -54,15 +57,16 @@ type Task function id(x: Task): Task { return x; } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + type Task = { chain( next: (input: value) => Task ): Task }; + function id(x: Task): Task { return x; -} -" +}" `; exports[`test test.js 1`] = ` @@ -83,29 +87,27 @@ pstar = p; // OK pstar = (new P: P>); // OK (pstar.x: string); // error ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// this is like Promise -// this is like Promise* -// error -// OK -// error, but limit potentially unbounded number of errors! -// e.g., P ~/~ number, P> ~/~ number, ... -// OK -// error -// OK -// error class P { x: X; } +// this is like Promise type Pstar = X | Pstar>; +// this is like Promise* var p: P = new P(); (p.x: string); +// error var pstar: Pstar = 0; +// OK (pstar: number); +// error, but limit potentially unbounded number of errors! +// e.g., P ~/~ number, P> ~/~ number, ... pstar = p; +// OK (pstar.x: string); +// error pstar = (new P(): P>); -(pstar.x: string); -" +// OK +(pstar.x: string); // error" `; exports[`test test2.js 1`] = ` @@ -140,39 +142,37 @@ class B extends D { } class C extends B { } ((new C: C): D) // error: number ~/~ string ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Array ~> a -// terminate despite expanding types: -// a ~> .concat(Array) -// Array ~> .concat(Array) -// Array ~> a -// Array ~> .concat(Array) -// Array ~> a -// terminate despite expanding types -// terminate despite expanding types, OK -// S<*> = { y: S> } -// Both S> and S<*> expand to { y: { y: ... }}. -// error: number ~/~ string var a = []; +// Array ~> a function bar() { - a = a.concat([]); + a = a.concat([]); // terminate despite expanding types: + // a ~> .concat(Array) + // Array ~> .concat(Array) + // Array ~> a + // Array ~> .concat(Array) + // Array ~> a } + class A { x: A>; } var a_ = new A(); function foo0() { - a_ = a_.x; + a_ = a_.x; // terminate despite expanding types } + type T = { y: S }; type S = T>; function foo1(b: S<*>) { - b = b.y; + b = b.y; // terminate despite expanding types, OK + // S<*> = { y: S> } + // Both S> and S<*> expand to { y: { y: ... }}. } + class D {} class B extends D {} class C extends B {} -((new C(): C): D); -" +((new C(): C): D); // error: number ~/~ string" `; exports[`test test3.js 1`] = ` @@ -193,30 +193,28 @@ function bar(x: P): () => P { // () => P = () => () => { x: P } } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// terminate despite expanding types, OK -// I and J both expand to () => () => ... -// terminate despite expanding types, error -// P = () => { x: P } -// () => P = () => () => { x: P } type I = () => I>; type J = () => J>; + function foo(x: I): J { - return x; + return x; // terminate despite expanding types, OK + // I and J both expand to () => () => ... } + type Q = { x: X }; type P = () => Q>; + function bar(x: P): () => P { - return x; -} -" + return x; // terminate despite expanding types, error + // P = () => { x: P } + // () => P = () => () => { x: P } +}" `; exports[`test test4.js 1`] = ` "type T = T // cycle in type alias should not cause non-termination ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// cycle in type alias should not cause non-termination -type T = T; -" +type T = T; // cycle in type alias should not cause non-termination" `; exports[`test test5.js 1`] = ` @@ -232,12 +230,13 @@ function flatten(arrArg: NestedArray) { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + type NestedArray = Array>; + function flatten(arrArg: NestedArray) { let arr = arrArg; while (true) { arr = Array.prototype.concat.apply([], arr); } -} -" +}" `; diff --git a/tests/recheck-haste/__snapshots__/jsfmt.spec.js.snap b/tests/recheck-haste/__snapshots__/jsfmt.spec.js.snap index e00e3195..3ec7f39c 100644 --- a/tests/recheck-haste/__snapshots__/jsfmt.spec.js.snap +++ b/tests/recheck-haste/__snapshots__/jsfmt.spec.js.snap @@ -4,11 +4,6 @@ exports[`test A1.js 1`] = ` * @flow */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -/** - * @providesModule A - * @flow - */ - " `; @@ -18,6 +13,6 @@ exports[`test A3.js 1`] = ` require(\'A\'); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -require(\"A\"); -" + +require(\"A\");" `; diff --git a/tests/recheck-haste/tmp1A/__snapshots__/jsfmt.spec.js.snap b/tests/recheck-haste/tmp1A/__snapshots__/jsfmt.spec.js.snap index 84c29b87..b4da5ec7 100644 --- a/tests/recheck-haste/tmp1A/__snapshots__/jsfmt.spec.js.snap +++ b/tests/recheck-haste/tmp1A/__snapshots__/jsfmt.spec.js.snap @@ -4,10 +4,5 @@ exports[`test A2.js 1`] = ` * @flow */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -/** - * @providesModule B - * @flow - */ - " `; diff --git a/tests/recheck-haste/tmp2A/__snapshots__/jsfmt.spec.js.snap b/tests/recheck-haste/tmp2A/__snapshots__/jsfmt.spec.js.snap index f3ce6d56..c3b67c62 100644 --- a/tests/recheck-haste/tmp2A/__snapshots__/jsfmt.spec.js.snap +++ b/tests/recheck-haste/tmp2A/__snapshots__/jsfmt.spec.js.snap @@ -4,6 +4,6 @@ exports[`test A3.js 1`] = ` require(\'B\'); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -require(\"B\"); -" + +require(\"B\");" `; diff --git a/tests/recheck/__snapshots__/jsfmt.spec.js.snap b/tests/recheck/__snapshots__/jsfmt.spec.js.snap index ecdb2395..1bec7bc0 100644 --- a/tests/recheck/__snapshots__/jsfmt.spec.js.snap +++ b/tests/recheck/__snapshots__/jsfmt.spec.js.snap @@ -8,12 +8,14 @@ foo(0); module.exports = foo; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + function foo(x: number): string { return 5; } + foo(0); -module.exports = foo; -" + +module.exports = foo;" `; exports[`test a2.js 1`] = ` @@ -24,9 +26,10 @@ const foo = require(\'./a1\'); module.exports = foo(\"\"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + const foo = require(\"./a1\"); -module.exports = foo(\"\"); -" + +module.exports = foo(\"\");" `; exports[`test a3.js 1`] = ` @@ -37,9 +40,10 @@ const five = require(\'./a2\'); (five + five: string); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + const five = require(\"./a2\"); -(five + five: string); -" + +(five + five: string);" `; exports[`test b0.js 1`] = ` @@ -51,14 +55,15 @@ class E { x: C; } module.exports = { C, E }; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + class C { x: C; } class E { x: C; } -module.exports = { C, E }; -" + +module.exports = { C, E };" `; exports[`test b1.js 1`] = ` @@ -73,6 +78,7 @@ class D extends F { } module.exports = { C, D }; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + import {C, E} from \"./b0\"; function foo() { return C; @@ -83,8 +89,7 @@ function bar() { let X = foo(); class F extends X {} class D extends F {} -module.exports = { C, D }; -" +module.exports = { C, D };" `; exports[`test b2.js 1`] = ` @@ -93,8 +98,8 @@ exports[`test b2.js 1`] = ` module.exports = require(\"./b1\"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -module.exports = require(\"./b1\"); -" + +module.exports = require(\"./b1\");" `; exports[`test b3.js 1`] = ` @@ -105,9 +110,10 @@ import { C, D } from \"./b2\"; (new D: C); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + import {C, D} from \"./b2\"; -(new D(): C); -" + +(new D(): C);" `; exports[`test c1.js 1`] = ` @@ -116,8 +122,8 @@ exports[`test c1.js 1`] = ` export function foo(props: { x: number }) { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -export function foo(props: { x: number }) {} -" + +export function foo(props: { x: number }) {}" `; exports[`test c2.js 1`] = ` @@ -130,11 +136,12 @@ export function bar(props: { x: number }) { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + import {foo} from \"./c1\"; + export function bar(props: { x: number }) { foo({ x: 0 }); -} -" +}" `; exports[`test c3.js 1`] = ` @@ -145,9 +152,10 @@ import { bar } from \"./c2\"; bar({ x: 0 }); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + import {bar} from \"./c2\"; -bar({ x: 0 }); -" + +bar({ x: 0 });" `; exports[`test d1.js 1`] = ` @@ -158,10 +166,10 @@ export class B {} export var x = new A; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + export class A {} export class B {} -export var x = new A(); -" +export var x = new A();" `; exports[`test d2.js 1`] = ` @@ -171,9 +179,9 @@ import {A, x} from \"./d1\"; export var y: A = x; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + import {A, x} from \"./d1\"; -export var y: A = x; -" +export var y: A = x;" `; exports[`test e1.js 1`] = ` @@ -187,9 +195,10 @@ export type Action = export const LIFE = 42; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + export type Action = { type: \"FOO\" } | { type: \"BAR\" }; -export const LIFE = 42; -" + +export const LIFE = 42;" `; exports[`test e2.js 1`] = ` @@ -206,13 +215,16 @@ import { LIFE } from \'./e1\'; (LIFE: 42); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + import type {Action} from \"./e1\"; + const f = (): Action => { return { type: \"FOO\" }; }; + import {LIFE} from \"./e1\"; -(LIFE: 42); -" + +(LIFE: 42);" `; exports[`test f1.js 1`] = ` @@ -228,13 +240,15 @@ declare var c: T; module.exports = { a, b, c }; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + type T = { x: number }; type S = { x: string }; + declare var a: T; declare var b: S; declare var c: T; -module.exports = { a, b, c }; -" + +module.exports = { a, b, c };" `; exports[`test f2.js 1`] = ` @@ -244,9 +258,9 @@ var { a, b, c } = require(\'./f1\'); (c: { x: number }); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + var { a, b, c } = require(\"./f1\"); -(c: { x: number }); -" +(c: { x: number });" `; exports[`test g1.js 1`] = ` @@ -255,8 +269,8 @@ exports[`test g1.js 1`] = ` export class C { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -export class C {} -" + +export class C {}" `; exports[`test g2.js 1`] = ` @@ -269,10 +283,12 @@ class D extends C { } module.exports = { D }; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + import {C} from \"./g1\"; + class D extends C {} -module.exports = { D }; -" + +module.exports = { D };" `; exports[`test g3.js 1`] = ` @@ -284,10 +300,11 @@ import { D } from \'./g2\'; (new D: C) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + import {C} from \"./g1\"; import {D} from \"./g2\"; -(new D(): C); -" + +(new D(): C);" `; exports[`test h1.js 1`] = ` @@ -296,8 +313,8 @@ exports[`test h1.js 1`] = ` export type Foo = number; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -export type Foo = number; -" + +export type Foo = number;" `; exports[`test h2.js 1`] = ` @@ -306,6 +323,6 @@ exports[`test h2.js 1`] = ` import type { Foo } from \'./h1\'; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -import type {Foo} from \"./h1\"; -" + +import type {Foo} from \"./h1\";" `; diff --git a/tests/recheck/tmp1a/__snapshots__/jsfmt.spec.js.snap b/tests/recheck/tmp1a/__snapshots__/jsfmt.spec.js.snap index 66ae79e5..02c0add4 100644 --- a/tests/recheck/tmp1a/__snapshots__/jsfmt.spec.js.snap +++ b/tests/recheck/tmp1a/__snapshots__/jsfmt.spec.js.snap @@ -8,10 +8,12 @@ foo(0); module.exports = foo; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + function foo(x: number): number { return 5; } + foo(0); -module.exports = foo; -" + +module.exports = foo;" `; diff --git a/tests/recheck/tmp1b/__snapshots__/jsfmt.spec.js.snap b/tests/recheck/tmp1b/__snapshots__/jsfmt.spec.js.snap index 179bc75d..6476459c 100644 --- a/tests/recheck/tmp1b/__snapshots__/jsfmt.spec.js.snap +++ b/tests/recheck/tmp1b/__snapshots__/jsfmt.spec.js.snap @@ -10,6 +10,7 @@ class D extends F { } module.exports = { C, D }; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + import {C, E} from \"./b0\"; function foo() { return C; @@ -20,6 +21,5 @@ function bar() { let X = bar(); class F extends X {} class D extends F {} -module.exports = { C, D }; -" +module.exports = { C, D };" `; diff --git a/tests/recheck/tmp1c/__snapshots__/jsfmt.spec.js.snap b/tests/recheck/tmp1c/__snapshots__/jsfmt.spec.js.snap index 3b49fabf..727442d6 100644 --- a/tests/recheck/tmp1c/__snapshots__/jsfmt.spec.js.snap +++ b/tests/recheck/tmp1c/__snapshots__/jsfmt.spec.js.snap @@ -8,9 +8,10 @@ export function bar(props: { y: number }) { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + import {foo} from \"./c1\"; + export function bar(props: { y: number }) { foo({ y: 0 }); -} -" +}" `; diff --git a/tests/recheck/tmp1d/__snapshots__/jsfmt.spec.js.snap b/tests/recheck/tmp1d/__snapshots__/jsfmt.spec.js.snap index 6e97b3c6..d54f91b8 100644 --- a/tests/recheck/tmp1d/__snapshots__/jsfmt.spec.js.snap +++ b/tests/recheck/tmp1d/__snapshots__/jsfmt.spec.js.snap @@ -6,8 +6,8 @@ export class B {} export var x = new B; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + export class A {} export class B {} -export var x = new B(); -" +export var x = new B();" `; diff --git a/tests/recheck/tmp1e/__snapshots__/jsfmt.spec.js.snap b/tests/recheck/tmp1e/__snapshots__/jsfmt.spec.js.snap index c47943ef..5c8c4737 100644 --- a/tests/recheck/tmp1e/__snapshots__/jsfmt.spec.js.snap +++ b/tests/recheck/tmp1e/__snapshots__/jsfmt.spec.js.snap @@ -12,11 +12,14 @@ import { LIFE } from \'./e1\'; (LIFE: 42); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + import type {Action} from \"./e1\"; + const f = (): Action => { return { type: \"QUX\" }; }; + import {LIFE} from \"./e1\"; -(LIFE: 42); -" + +(LIFE: 42);" `; diff --git a/tests/recheck/tmp1f/__snapshots__/jsfmt.spec.js.snap b/tests/recheck/tmp1f/__snapshots__/jsfmt.spec.js.snap index 67d680d1..e3f5d7d1 100644 --- a/tests/recheck/tmp1f/__snapshots__/jsfmt.spec.js.snap +++ b/tests/recheck/tmp1f/__snapshots__/jsfmt.spec.js.snap @@ -11,11 +11,13 @@ declare var c: S; module.exports = { a, b, c }; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + type T = { x: number }; type S = { x: string }; + declare var a: T; declare var b: S; declare var c: S; -module.exports = { a, b, c }; -" + +module.exports = { a, b, c };" `; diff --git a/tests/recheck/tmp1g/__snapshots__/jsfmt.spec.js.snap b/tests/recheck/tmp1g/__snapshots__/jsfmt.spec.js.snap index 3e6ab7c6..5cf16202 100644 --- a/tests/recheck/tmp1g/__snapshots__/jsfmt.spec.js.snap +++ b/tests/recheck/tmp1g/__snapshots__/jsfmt.spec.js.snap @@ -5,7 +5,7 @@ export class C { } export var extra = null; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + export class C {} -export var extra = null; -" +export var extra = null;" `; diff --git a/tests/recheck/tmp1h/__snapshots__/jsfmt.spec.js.snap b/tests/recheck/tmp1h/__snapshots__/jsfmt.spec.js.snap index c400765e..d19377a6 100644 --- a/tests/recheck/tmp1h/__snapshots__/jsfmt.spec.js.snap +++ b/tests/recheck/tmp1h/__snapshots__/jsfmt.spec.js.snap @@ -4,6 +4,6 @@ exports[`test h1.js 1`] = ` export type Bar = number; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -export type Bar = number; -" + +export type Bar = number;" `; diff --git a/tests/recheck/tmp2a/__snapshots__/jsfmt.spec.js.snap b/tests/recheck/tmp2a/__snapshots__/jsfmt.spec.js.snap index 53e7ab99..d64a51ae 100644 --- a/tests/recheck/tmp2a/__snapshots__/jsfmt.spec.js.snap +++ b/tests/recheck/tmp2a/__snapshots__/jsfmt.spec.js.snap @@ -8,10 +8,12 @@ foo(\"\"); module.exports = foo; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + function foo(x: number): number { return 5; } + foo(\"\"); -module.exports = foo; -" + +module.exports = foo;" `; diff --git a/tests/recheck/tmp2b/__snapshots__/jsfmt.spec.js.snap b/tests/recheck/tmp2b/__snapshots__/jsfmt.spec.js.snap index 66607eac..7627ae79 100644 --- a/tests/recheck/tmp2b/__snapshots__/jsfmt.spec.js.snap +++ b/tests/recheck/tmp2b/__snapshots__/jsfmt.spec.js.snap @@ -7,12 +7,13 @@ class E extends C { x: C; } module.exports = { C, E }; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + class C { x: C; } class E extends C { x: C; } -module.exports = { C, E }; -" + +module.exports = { C, E };" `; diff --git a/tests/recheck/tmp2c/__snapshots__/jsfmt.spec.js.snap b/tests/recheck/tmp2c/__snapshots__/jsfmt.spec.js.snap index 6a1836f4..93670d55 100644 --- a/tests/recheck/tmp2c/__snapshots__/jsfmt.spec.js.snap +++ b/tests/recheck/tmp2c/__snapshots__/jsfmt.spec.js.snap @@ -4,6 +4,6 @@ exports[`test c1.js 1`] = ` export function foo(props: { y: number }) { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -export function foo(props: { y: number }) {} -" + +export function foo(props: { y: number }) {}" `; diff --git a/tests/recheck/tmp2e/__snapshots__/jsfmt.spec.js.snap b/tests/recheck/tmp2e/__snapshots__/jsfmt.spec.js.snap index 297c96fb..7369df73 100644 --- a/tests/recheck/tmp2e/__snapshots__/jsfmt.spec.js.snap +++ b/tests/recheck/tmp2e/__snapshots__/jsfmt.spec.js.snap @@ -9,7 +9,8 @@ export type Action = export const LIFE = 42; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + export type Action = { type: \"QUX\" } | { type: \"BAR\" }; -export const LIFE = 42; -" + +export const LIFE = 42;" `; diff --git a/tests/recheck/tmp2f/__snapshots__/jsfmt.spec.js.snap b/tests/recheck/tmp2f/__snapshots__/jsfmt.spec.js.snap index a0e8a11d..8b7d8947 100644 --- a/tests/recheck/tmp2f/__snapshots__/jsfmt.spec.js.snap +++ b/tests/recheck/tmp2f/__snapshots__/jsfmt.spec.js.snap @@ -11,11 +11,13 @@ declare var c: T; module.exports = { a, b, c }; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + type T = { x: number }; type S = { x: string }; + declare var a: T; declare var b: S; declare var c: T; -module.exports = { a, b, c }; -" + +module.exports = { a, b, c };" `; diff --git a/tests/recheck/tmp3e/__snapshots__/jsfmt.spec.js.snap b/tests/recheck/tmp3e/__snapshots__/jsfmt.spec.js.snap index 75120088..cd336e40 100644 --- a/tests/recheck/tmp3e/__snapshots__/jsfmt.spec.js.snap +++ b/tests/recheck/tmp3e/__snapshots__/jsfmt.spec.js.snap @@ -9,9 +9,10 @@ export type Action = export const LIFE = 0; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + export type Action = { type: \"QUX\" } | { type: \"BAR\" }; -export const LIFE = 0; -" + +export const LIFE = 0;" `; exports[`test e2.js 1`] = ` @@ -28,11 +29,14 @@ import { LIFE } from \'./e1\'; (LIFE: 0); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + import type {Action} from \"./e1\"; + const f = (): Action => { return { type: \"QUX\" }; }; + import {LIFE} from \"./e1\"; -(LIFE: 0); -" + +(LIFE: 0);" `; diff --git a/tests/recheck/tmp3f/__snapshots__/jsfmt.spec.js.snap b/tests/recheck/tmp3f/__snapshots__/jsfmt.spec.js.snap index a5b3f715..37af8fa1 100644 --- a/tests/recheck/tmp3f/__snapshots__/jsfmt.spec.js.snap +++ b/tests/recheck/tmp3f/__snapshots__/jsfmt.spec.js.snap @@ -11,11 +11,13 @@ declare var c: T; module.exports = { a, b, c: a }; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + type T = { x: number }; type S = { x: string }; + declare var a: T; declare var b: S; declare var c: T; -module.exports = { a, b, c: a }; -" + +module.exports = { a, b, c: a };" `; diff --git a/tests/recheck/tmp4f/__snapshots__/jsfmt.spec.js.snap b/tests/recheck/tmp4f/__snapshots__/jsfmt.spec.js.snap index d65ea4c7..1cf1d75d 100644 --- a/tests/recheck/tmp4f/__snapshots__/jsfmt.spec.js.snap +++ b/tests/recheck/tmp4f/__snapshots__/jsfmt.spec.js.snap @@ -11,11 +11,13 @@ declare var c: T; module.exports = { a, b, c: b }; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + type T = { x: number }; type S = { x: string }; + declare var a: T; declare var b: S; declare var c: T; -module.exports = { a, b, c: b }; -" + +module.exports = { a, b, c: b };" `; diff --git a/tests/record/__snapshots__/jsfmt.spec.js.snap b/tests/record/__snapshots__/jsfmt.spec.js.snap index 3c34fd98..ceb3fbc9 100644 --- a/tests/record/__snapshots__/jsfmt.spec.js.snap +++ b/tests/record/__snapshots__/jsfmt.spec.js.snap @@ -24,34 +24,35 @@ class D extends C<{foo: number, bar: string}> { type AnyKey = $Keys; var o3: {[key: AnyKey]: number} = { foo: 0 }; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// make an enum type with known key set -// error: string ~/~ number -// OK -// error: qux not found -// ok -// another way to make an enum type, with unknown key set -// OK to leave out bar -// OK to access bar -// error: qux not found -// object with larger key set than X\'s -// error: qux not found type Key1 = \"foo\" | \"bar\"; -var o1: { [key: Key1]: number } = { foo: 0, bar: \"\" }; +// make an enum type with known key set +var o1: { [key: Key1]: number } = { + foo: 0, + // error: string ~/~ number + bar: \"\" +}; o1.foo; +// OK o1.qux; +// error: qux not found o1.toString(); +// ok type R = { foo: any, bar: any }; type Key2 = $Keys; +// another way to make an enum type, with unknown key set var o2: { [key: Key2]: number } = { foo: 0 }; +// OK to leave out bar o2.bar; +// OK to access bar o2.qux; +// error: qux not found class C { - x: $Subtype<{ [key: $Keys]: any }>; + x: $Subtype<{ [key: $Keys]: any }>; // object with larger key set than X\'s } class D extends C<{ foo: number, bar: string }> { - x: { foo: number, qux: boolean }; + x: { foo: number, qux: boolean }; // error: qux not found } + type AnyKey = $Keys; -var o3: { [key: AnyKey]: number } = { foo: 0 }; -" +var o3: { [key: AnyKey]: number } = { foo: 0 };" `; diff --git a/tests/refi/__snapshots__/jsfmt.spec.js.snap b/tests/refi/__snapshots__/jsfmt.spec.js.snap index b36a96bb..7be65df8 100644 --- a/tests/refi/__snapshots__/jsfmt.spec.js.snap +++ b/tests/refi/__snapshots__/jsfmt.spec.js.snap @@ -66,12 +66,36 @@ var tests = ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // refinements of bound vars (closed-over locals) // should have the same lifetimes as heap objects. -// not ok -// ok -// ok -// ok -// ok -/* TODO we actually allow this currently; fix + +var x: ?string = \"xxx\"; + +var tests = [ + function() { + var y: string = x; // not ok + }, + function() { + if (x != null) { + var y: string = x; // ok + } + }, + function() { + if (x == null) {} + else { + var y: string = x; // ok + } + }, + function() { + if (x == null) + return; + var y: string = x; // ok + }, + function() { + if (!(x != null)) {} + else { + var y: string = x; // ok + } + }, + /* TODO we actually allow this currently; fix // requires further remedial work in Env function() { if (x != null) { @@ -80,55 +104,23 @@ var tests = } }, */ -// not ok -// not ok -// ok -// ok -var x: ?string = \"xxx\"; -var tests = [ - function() { - var y: string = x; - }, - function() { - if (x != null) { - var y: string = x; - } - }, - function() { - if (x == null) {} - else { - var y: string = x; - } - }, - function() { - if (x == null) - return; - var y: string = x; - }, - function() { - if (!(x != null)) {} - else { - var y: string = x; - } - }, function() { if (x != null) {} - var y: string = x; + var y: string = x; // not ok }, function() { if (x != null) {} else { - var y: string = x; + var y: string = x; // not ok } }, function() { - var y: string = x != null ? x : \"\"; + var y: string = x != null ? x : \"\"; // ok }, function() { - var y: string = x || \"\"; + var y: string = x || \"\"; // ok } -]; -" +];" `; exports[`test heap.js 1`] = ` @@ -370,111 +362,77 @@ exports[`test heap.js 1`] = ` }, ]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// not ok -// ok -// ok -// ok -// ok -// not ok -// not ok -// not ok -// not ok -// ok -// ok -// ok -// ok -// error -// error, this got widened to a number -// error, could also be boolean -// error, string -// error -// now x.y can is string | boolean -// now x.y is only boolean -// error -// now x.y can is string | boolean -// now x.y is number | boolean -// error -// error (but only once, string !~> \'b\'; \'a\' is irrelevant) -// error, so \`x.bar\` refinement is empty -// --- nested conditionals --- -// after a branch, the current scope may have changed. this causes the -// subsequent assignment to refine the new scope. these tests make sure that -// 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 -// if statement. -// TODO: annot checked against type of x -// ok var tests = [ function() { var x: { p: ?string } = { p: \"xxx\" }; - var y: string = x.p; + var y: string = x.p; // not ok }, function() { var x: { p: ?string } = { p: \"xxx\" }; if (x.p != null) { - var y: string = x.p; + var y: string = x.p; // ok } }, function() { var x: { p: ?string } = { p: \"xxx\" }; if (x.p == null) {} else { - var y: string = x.p; + var y: string = x.p; // ok } }, function() { var x: { p: ?string } = { p: \"xxx\" }; if (x.p == null) return; - var y: string = x.p; + var y: string = x.p; // ok }, function() { var x: { p: ?string } = { p: \"xxx\" }; if (!(x.p != null)) {} else { - var y: string = x.p; + var y: string = x.p; // ok } }, function() { var x: { p: ?string } = { p: \"xxx\" }; if (x.p != null) { alert(\"\"); - var y: string = x.p; + var y: string = x.p; // not ok } }, function() { var x: { p: ?string } = { p: \"xxx\" }; if (x.p != null) { x.p = null; - var y: string = x.p; + var y: string = x.p; // not ok } }, function() { var x: { p: ?string } = { p: \"xxx\" }; if (x.p != null) {} - var y: string = x.p; + var y: string = x.p; // not ok }, function() { var x: { p: ?string } = { p: \"xxx\" }; if (x.p != null) {} else { - var y: string = x.p; + var y: string = x.p; // not ok } }, function() { var x: { p: ?string } = { p: \"xxx\" }; - var y: string = x.p != null ? x.p : \"\"; + var y: string = x.p != null ? x.p : \"\"; // ok }, function() { var x: { p: ?string } = { p: \"xxx\" }; - var y: string = x.p || \"\"; + var y: string = x.p || \"\"; // ok }, function() { var x: { p: string | string[] } = { p: [ \"xxx\" ] }; if (Array.isArray(x.p)) { - var y: string[] = x.p; + var y: string[] = x.p; // ok } else { - var z: string = x.p; + var z: string = x.p; // ok } }, function() { @@ -495,9 +453,9 @@ var tests = [ function() { var x: { y: ?string } = { y: null }; if (!x.y) { - x.y = 123; + x.y = 123; // error } - (x.y: string); + (x.y: string); // error, this got widened to a number }, function() { var x: { y: ?string } = { y: null }; @@ -513,7 +471,7 @@ var tests = [ if (typeof x.y == \"number\") { x.y = \"foo\"; } - (x.y: string); + (x.y: string); // error, could also be boolean }, function() { var x: { y: string | number | boolean } = { y: false }; @@ -522,7 +480,7 @@ var tests = [ } else if (typeof x.y == \"boolean\") { x.y = \"bar\"; } - (x.y: boolean); + (x.y: boolean); // error, string }, function() { var x: { y: ?string } = { y: null }; @@ -532,27 +490,31 @@ var tests = [ if (x.y) { x.y = null; } - (x.y: string); + (x.y: string); // error }, function() { var x: { y: string | number | boolean } = { y: false }; if (typeof x.y == \"number\") { x.y = \"foo\"; } + // now x.y can is string | boolean if (typeof x.y == \"string\") { x.y = false; } - (x.y: string); + // now x.y is only boolean + (x.y: string); // error }, function() { var x: { y: string | number | boolean } = { y: false }; if (typeof x.y == \"number\") { x.y = \"foo\"; } + // now x.y can is string | boolean if (typeof x.y == \"string\") { x.y = 123; } - (x.y: string); + // now x.y is number | boolean + (x.y: string); // error }, function() { var x: { y: ?string } = { y: null }; @@ -566,12 +528,19 @@ var tests = [ }, function(x: string) { if (x === \"a\") {} - (x: \"b\"); + (x: \"b\"); // error (but only once, string !~> \'b\'; \'a\' is irrelevant) }, function(x: mixed) { if (typeof x.bar === \"string\") {} + // error, so \`x.bar\` refinement is empty (x: string & number); }, + // --- nested conditionals --- + // after a branch, the current scope may have changed. this causes the + // subsequent assignment to refine the new scope. these tests make sure that + // 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 + // if statement. function() { let x: { foo: ?string } = { foo: null }; if (!x.foo) { @@ -600,11 +569,11 @@ var tests = [ var x: { p: ?string } = { p: \"xxx\" }; if (x.p != null) { var { p } = x; - (p: string); + // TODO: annot checked against type of x + (p: string); // ok } } -]; -" +];" `; exports[`test lex.js 1`] = ` @@ -645,50 +614,43 @@ function try_scope_catch(x: string | number) { (x : string); // error: number ~> string } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// doesn\'t refine outer x -// error: number ~> string -// doesn\'t refine outer x -// error: number ~> string -// doesn\'t refine outer x -// refinement would only escape if both sides refined -// error: number ~> string -// refinement would only escape if both sides refined -// doesn\'t refine outer x -// error: number ~> string function block_scope(x: string | number) { { let x; - x = \"\"; + x = \"\"; // doesn\'t refine outer x } - (x: string); + (x: string); // error: number ~> string } + function switch_scope(x: string | number) { switch (x) { + // doesn\'t refine outer x default: let x; x = \"\"; } - (x: string); + (x: string); // error: number ~> string } + function try_scope(x: string | number) { try { let x; - x = \"\"; + x = \"\"; // doesn\'t refine outer x } catch (e) { - x = \"\"; + x = \"\"; // refinement would only escape if both sides refined } - (x: string); + (x: string); // error: number ~> string } + function try_scope_catch(x: string | number) { try { - x = \"\"; + x = \"\"; // refinement would only escape if both sides refined } catch (e) { let x; - x = \"\"; + x = \"\"; // doesn\'t refine outer x } - (x: string); -} -" + (x: string); // error: number ~> string +}" `; exports[`test local.js 1`] = ` @@ -777,82 +739,70 @@ exports[`test local.js 1`] = ` }, ]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// not ok -// ok -// ok -// ok -// ok -// ok -// not ok -// not ok -// ok -// ok -// ok -// ok var paths = [ function() { var x: ?string = \"xxx\"; - var y: string = x; + var y: string = x; // not ok }, function() { var x: ?string = \"xxx\"; if (x != null) { - var y: string = x; + var y: string = x; // ok } }, function() { var x: ?string = \"xxx\"; if (x == null) {} else { - var y: string = x; + var y: string = x; // ok } }, function() { var x: ?string = \"xxx\"; if (x == null) return; - var y: string = x; + var y: string = x; // ok }, function() { var x: ?string = \"xxx\"; if (!(x != null)) {} else { - var y: string = x; + var y: string = x; // ok } }, function() { var x: ?string = \"xxx\"; if (x != null) { alert(\"\"); - var y: string = x; + var y: string = x; // ok } }, function() { var x: ?string = \"xxx\"; if (x != null) {} - var y: string = x; + var y: string = x; // not ok }, function() { var x: ?string = \"xxx\"; if (x != null) {} else { - var y: string = x; + var y: string = x; // not ok } }, function() { var x: ?string = \"xxx\"; - var y: string = x != null ? x : \"\"; + var y: string = x != null ? x : \"\"; // ok }, function() { var x: ?string = \"xxx\"; - var y: string = x || \"\"; + var y: string = x || \"\"; // ok }, function() { var x: string | string[] = [ \"xxx\" ]; if (Array.isArray(x)) { - var y: string[] = x; + var y: string[] = x; // ok } else { - var z: string = x; + var z: string = x; // ok } }, function() { @@ -862,8 +812,7 @@ var paths = [ } var y: string = x; } -]; -" +];" `; exports[`test null_tests.js 1`] = ` @@ -1022,137 +971,129 @@ class D extends C { } } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// expr != null -// ok -// ok -// ok -// ok -// expr == null -// ok -// ok -// ok -// expr !== null -// ok -// ok -// ok -// expr === null -// ok -// ok -// ok -// this.p op null -// super.p op null -// not ok var null_tests = [ + // expr != null function() { var x: ?string = \"xxx\"; if (x != null) { - var y: string = x; + var y: string = x; // ok } }, function() { var x: ?string = \"xxx\"; if (null != x) { - var y: string = x; + var y: string = x; // ok } }, function() { var x: { p: ?string } = { p: \"xxx\" }; if (x.p != null) { - var y: string = x.p; + var y: string = x.p; // ok } }, function() { var x: { p: { q: ?string } } = { p: { q: \"xxx\" } }; if (x.p.q != null) { - var y: string = x.p.q; + var y: string = x.p.q; // ok } }, + // expr == null function() { var x: ?string = \"xxx\"; if (x == null) {} else { - var y: string = x; + var y: string = x; // ok } }, function() { var x: { p: ?string } = { p: \"xxx\" }; if (x.p == null) {} else { - var y: string = x.p; + var y: string = x.p; // ok } }, function() { var x: { p: { q: ?string } } = { p: { q: \"xxx\" } }; if (x.p.q == null) {} else { - var y: string = x.p.q; + var y: string = x.p.q; // ok } }, + // expr !== null function() { var x: ?string = \"xxx\"; if (x !== null) { - var y: string | void = x; + var y: string | void = x; // ok } }, function() { var x: { p: ?string } = { p: \"xxx\" }; if (x.p !== null) { - var y: string | void = x.p; + var y: string | void = x.p; // ok } }, function() { var x: { p: { q: ?string } } = { p: { q: \"xxx\" } }; if (x.p.q !== null) { - var y: string | void = x.p.q; + var y: string | void = x.p.q; // ok } }, + // expr === null function() { var x: ?string = \"xxx\"; if (x === null) {} else { - var y: string | void = x; + var y: string | void = x; // ok } }, function() { var x: { p: ?string } = { p: \"xxx\" }; if (x.p === null) {} else { - var y: string | void = x.p; + var y: string | void = x.p; // ok } }, function() { var x: { p: { q: ?string } } = { p: { q: \"xxx\" } }; if (x.p.q === null) {} else { - var y: string | void = x.p.q; + var y: string | void = x.p.q; // ok } } ]; + +// this.p op null class C { p: ?string; + ensure0(): string { if (this.p != null) return this.p; else return \"\"; } + ensure1(): string { if (this.p == null) return \"\"; return this.p; } + ensure2(): string | void { if (this.p !== null) return this.p; else return \"\"; } + ensure3(): string | void { if (this.p === null) return \"\"; return this.p; } } + +// super.p op null class D extends C { ensure100(): string { if (super.p != null) @@ -1160,21 +1101,22 @@ class D extends C { else return \"\"; } + ensure101(): string { if (super.p == null) return \"\"; else return super.p; } + ensure103(): string { if (super.p != null) { alert(\"\"); - return super.p; + return super.p; // not ok } return \"\"; } -} -" +}" `; exports[`test switch.js 1`] = ` @@ -1243,13 +1185,41 @@ function exhaustion3(x): number { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// OK -// OK +function foo(a, b, c) { + switch (c) { + case a.x.y: + // OK + case b.x.y: + // OK + return; + default: + return; + } +} + // test refis out of switches that are exhaustive without default case -// falls through -// no error -// leaks uninitialized foo out of switch -/** +function exhaustion1(x): number { + var foo; + switch (x) { + case 0: + // falls through + case 1: + foo = 3; + break; + default: + throw new Error(\"Invalid state\"); + } + return foo; // no error +} + +function exhaustion2(x, y): number { + var foo; + switch (x) { + case 0: + if (y) { + break; // leaks uninitialized foo out of switch + } + /** * TODO this shouldn\'t cause an error, because the path that * runs it will always go on to assign a number to foo. But * we\'ll need true isolation in env snapshots to model this. @@ -1258,58 +1228,28 @@ function exhaustion3(x): number { * foo = \"\"; */ -// error, possibly uninitialized -// falls through -// no error -function foo(a, b, c) { - switch (c) { - case a.x.y: - case b.x.y: - return; - default: - return; - } -} -function exhaustion1(x): number { - var foo; - switch (x) { - case 0: case 1: foo = 3; break; default: throw new Error(\"Invalid state\"); } - return foo; -} -function exhaustion2(x, y): number { - var foo; - switch (x) { - case 0: - if (y) { - break; - } - case 1: - foo = 3; - break; - default: - throw new Error(\"Invalid state\"); - } - return foo; + return foo; // error, possibly uninitialized } + function exhaustion3(x): number { let foo = null; switch (x) { case 0: + // falls through case 1: foo = 3; break; default: throw new Error(\"Invalid state\"); } - return foo; -} -" + return foo; // no error +}" `; exports[`test typeof_tests.js 1`] = ` @@ -1444,138 +1384,129 @@ class A { } } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// typeof expr == typename -// ok -// ok -// ok -// ok -// typeof expr != typename -// ok -// ok -// ok -// typeof expr === typename -// ok -// ok -// ok -// typeof expr !== typename -// ok -// ok -// ok -// typeof this.p op typename var null_tests = [ + // typeof expr == typename function() { var x: ?string = \"xxx\"; if (typeof x == \"string\") { - var y: string = x; + var y: string = x; // ok } }, function() { var x: ?string = \"xxx\"; if (\"string\" == typeof x) { - var y: string = x; + var y: string = x; // ok } }, function() { var x: { p: ?string } = { p: \"xxx\" }; if (typeof x.p == \"string\") { - var y: string = x.p; + var y: string = x.p; // ok } }, function() { var x: { p: { q: ?string } } = { p: { q: \"xxx\" } }; if (typeof x.p.q == \"string\") { - var y: string = x.p.q; + var y: string = x.p.q; // ok } }, + // typeof expr != typename function() { var x: ?string = \"xxx\"; if (typeof x != \"string\") {} else { - var y: string = x; + var y: string = x; // ok } }, function() { var x: { p: ?string } = { p: \"xxx\" }; if (typeof x.p != \"string\") {} else { - var y: string = x.p; + var y: string = x.p; // ok } }, function() { var x: { p: { q: ?string } } = { p: { q: \"xxx\" } }; if (typeof x.p.q != \"string\") {} else { - var y: string = x.p.q; + var y: string = x.p.q; // ok } }, + // typeof expr === typename function() { var x: ?string = \"xxx\"; if (typeof x === \"string\") { - var y: string = x; + var y: string = x; // ok } }, function() { var x: { p: ?string } = { p: \"xxx\" }; if (typeof x.p === \"string\") { - var y: string = x.p; + var y: string = x.p; // ok } }, function() { var x: { p: { q: ?string } } = { p: { q: \"xxx\" } }; if (typeof x.p.q === \"string\") { - var y: string = x.p.q; + var y: string = x.p.q; // ok } }, + // typeof expr !== typename function() { var x: ?string = \"xxx\"; if (typeof x !== \"string\") {} else { - var y: string = x; + var y: string = x; // ok } }, function() { var x: { p: ?string } = { p: \"xxx\" }; if (typeof x.p !== \"string\") {} else { - var y: string = x.p; + var y: string = x.p; // ok } }, function() { var x: { p: { q: ?string } } = { p: { q: \"xxx\" } }; if (typeof x.p.q !== \"string\") {} else { - var y: string = x.p.q; + var y: string = x.p.q; // ok } } ]; + +// typeof this.p op typename class A { p: ?string; + ensure0(): string { if (typeof this.p == \"string\") return this.p; else return \"\"; } + ensure1(): string { if (typeof this.p != \"string\") return \"\"; else return this.p; } + ensure2(): string | void { if (typeof this.p === \"string\") return this.p; else return \"\"; } + ensure3(): string | void { if (typeof this.p !== \"string\") return \"\"; else return this.p; } -} -" +}" `; exports[`test undef_tests.js 1`] = ` @@ -1654,80 +1585,75 @@ class A { } } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// NOTE: not (yet?) supporting non-strict eq test for undefined -// expr !== undefined -// ok -// ok -// ok -// ok -// expr === undefined -// ok -// ok -// ok -// this.p op undefined var undef_tests = [ + // NOTE: not (yet?) supporting non-strict eq test for undefined + // expr !== undefined function() { var x: ?string = \"xxx\"; if (x !== undefined && x !== null) { - var y: string = x; + var y: string = x; // ok } }, function() { var x: ?string = \"xxx\"; if (undefined !== x && x !== null) { - var y: string = x; + var y: string = x; // ok } }, function() { var x: { p: ?string } = { p: \"xxx\" }; if (x.p !== undefined && x.p !== null) { - var y: string = x.p; + var y: string = x.p; // ok } }, function() { var x: { p: { q: ?string } } = { p: { q: \"xxx\" } }; if (x.p.q !== undefined && x.p.q !== null) { - var y: string = x.p.q; + var y: string = x.p.q; // ok } }, + // expr === undefined function() { var x: ?string = \"xxx\"; if (x === undefined || x === null) {} else { - var y: string = x; + var y: string = x; // ok } }, function() { var x: { p: ?string } = { p: \"xxx\" }; if (x.p === undefined || x.p === null) {} else { - var y: string = x.p; + var y: string = x.p; // ok } }, function() { var x: { p: { q: ?string } } = { p: { q: \"xxx\" } }; if (x.p.q === undefined || x.p.q === null) {} else { - var y: string = x.p.q; + var y: string = x.p.q; // ok } } ]; + +// this.p op undefined class A { p: ?string; + ensure0(): string { if (this.p !== undefined && this.p !== null) return this.p; else return \"\"; } + ensure1(): string { if (this.p === undefined || this.p === null) return \"\"; else return this.p; } -} -" +}" `; exports[`test void_tests.js 1`] = ` @@ -1806,78 +1732,73 @@ class A { } } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// NOTE: not (yet?) supporting non-strict eq test for undefined -// expr !== void(...) -// ok -// ok -// ok -// ok -// expr === void(...) -// ok -// ok -// ok -// this.p op void(...) var void_tests = [ + // NOTE: not (yet?) supporting non-strict eq test for undefined + // expr !== void(...) function() { var x: ?string = \"xxx\"; if (x !== void 0 && x !== null) { - var y: string = x; + var y: string = x; // ok } }, function() { var x: ?string = \"xxx\"; if (void 0 !== x && x !== null) { - var y: string = x; + var y: string = x; // ok } }, function() { var x: { p: ?string } = { p: \"xxx\" }; if (x.p !== void 0 && x.p !== null) { - var y: string | void = x.p; + var y: string | void = x.p; // ok } }, function() { var x: { p: { q: ?string } } = { p: { q: \"xxx\" } }; if (x.p.q !== void 0 && x.p.q !== null) { - var y: string = x.p.q; + var y: string = x.p.q; // ok } }, + // expr === void(...) function() { var x: ?string = \"xxx\"; if (x === void 0 || x === null) {} else { - var y: string = x; + var y: string = x; // ok } }, function() { var x: { p: ?string } = { p: \"xxx\" }; if (x.p === void 0 || x.p === null) {} else { - var y: string = x.p; + var y: string = x.p; // ok } }, function() { var x: { p: { q: ?string } } = { p: { q: \"xxx\" } }; if (x.p.q === void 0 || x.p.q === null) {} else { - var y: string = x.p.q; + var y: string = x.p.q; // ok } } ]; + +// this.p op void(...) class A { p: ?string; + ensure0(): string { if (this.p !== void 0 && this.p !== null) return this.p; else return \"\"; } + ensure1(): string { if (this.p === void 0 || this.p === null) return \"\"; else return this.p; } -} -" +}" `; diff --git a/tests/refinements/__snapshots__/jsfmt.spec.js.snap b/tests/refinements/__snapshots__/jsfmt.spec.js.snap index b335d4a3..b52aef02 100644 --- a/tests/refinements/__snapshots__/jsfmt.spec.js.snap +++ b/tests/refinements/__snapshots__/jsfmt.spec.js.snap @@ -33,32 +33,36 @@ function bar2(x : Bar) { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// can\'t assign x to ?Bar -// x.parent might be null + function foo(x: ?number) { var y; if (y = x) { var z = y * 1000; } } + type Bar = { parent: ?Bar, doStuff(): void }; + function bar0(x: Bar) { while (x = x.parent) { + // can\'t assign x to ?Bar x.doStuff(); } } + function bar1(x: ?Bar) { while (x = x.parent) { + // x.parent might be null x.doStuff(); } } + function bar2(x: Bar) { var y = x; while (y = y.parent) { y.doStuff(); } -} -" +}" `; exports[`test ast_node.js 1`] = ` @@ -75,9 +79,10 @@ type Node2 = { export type ASTNode = Node1 | Node2; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ type Node1 = { kind: \"Node1\", prop1?: string }; + type Node2 = { kind: \"Node2\", prop2?: string }; -export type ASTNode = Node1 | Node2; -" + +export type ASTNode = Node1 | Node2;" `; exports[`test bool.js 1`] = ` @@ -129,26 +134,27 @@ let tests = [ ]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// error on null and undefined -// error on null and undefined -// error -// error + function foo(x: ?boolean) { if (x === false) { return; } + if (x === true) { return; } - x[0]; + + x[0]; // error on null and undefined } + function bar(x: ?boolean) { if (x !== true) { if (x !== false) { - x[0]; + x[0]; // error on null and undefined } } } + function baz(x: ?boolean) { if (100 * false) { return; @@ -157,21 +163,21 @@ function baz(x: ?boolean) { return; } } + let tests = [ function(x: { done: true, result: string } | { done: false }) { if (x.done === true) { return x.result; } - return x.result; + return x.result; // error }, function(x: { done: true, result: string } | { done: false }) { if (true === x.done) { return x.result; } - return x.result; + return x.result; // error } -]; -" +];" `; exports[`test computed_string_literal.js 1`] = ` @@ -196,19 +202,22 @@ function testLiteralProperty(a: A) { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + type A = { \"b_c\": ?string }; + function stuff(str: string) {} + function testProperty(a: A) { if (a.b_c) { stuff(a.b_c); } } + function testLiteralProperty(a: A) { if (a[\"b_c\"]) { stuff(a[\"b_c\"]); } -} -" +}" `; exports[`test cond_prop.js 1`] = ` @@ -266,59 +275,55 @@ let tests = [ ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// OK -// error, BadType not a subtype of Type -// error -// error, consider { foo: \"herp\", done: \"derp\" } -// error -// error, consider { baz: \"x\", quux: \"y\", foo: \"boom\" } -// ok. since foo is an object (always truthy), the -// else case completely rules out the first branch of -// the union. -// error, consider { baz: \"x\", quux: \"y\", bar: \"boom\" } -// error, consider { foo: {}, bar: \"\" } + type Type = Name | ListType | NonNullType; type Name = { kind: \"Name\", value: string, type: void }; type ListType = { kind: \"ListType\", type: Type }; type NonNullType = { kind: \"NonNullType\", type: Name | ListType | BadType }; type BadType = {}; + function getTypeASTName(typeAST: Type): string { if (!typeAST.type) throw new Error(\"Must be wrapping type\"); - return getTypeASTName(typeAST.type); + // OK + return getTypeASTName(typeAST.type); // error, BadType not a subtype of Type } + let tests = [ function(x: { done: true, result: string } | { done: false }) { if (x.done) { return x.result; } - return x.result; + return x.result; // error }, function(x: { done: true, result: string } | { foo: string }) { if (x.done) { - return x.result; + return x.result; // error, consider { foo: \"herp\", done: \"derp\" } } - return x.result; + return x.result; // error }, function() { type T = { foo: Object, bar: string } | { baz: string, quux: string }; + function testAlwaysTruthyProp(t: T) { if (t.foo) { - (t.bar: string); + (t.bar: string); // error, consider { baz: \"x\", quux: \"y\", foo: \"boom\" } } else { - (t.quux: string); + (t.quux: string); // ok. since foo is an object (always truthy), the + // else case completely rules out the first branch of + // the union. } } + function testSometimesTruthyProp(t: T) { if (t.bar) { - (t.foo: Object); + (t.foo: Object); // error, consider { baz: \"x\", quux: \"y\", bar: \"boom\" } } else { - (t.quux: string); + (t.quux: string); // error, consider { foo: {}, bar: \"\" } } } } -]; -" +];" `; exports[`test constants.js 1`] = ` @@ -328,9 +333,9 @@ export const SUCCESS: \'SUCCESS\' = \'SUCCESS\'; export const ERROR: \'ERROR\' = \'ERROR\'; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + export const SUCCESS: \"SUCCESS\" = \"SUCCESS\"; -export const ERROR: \"ERROR\" = \"ERROR\"; -" +export const ERROR: \"ERROR\" = \"ERROR\";" `; exports[`test eq.js 1`] = ` @@ -358,31 +363,27 @@ let tests = [ ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// error, string & number are not comparable (unsafe casting) -// no error, to match \`let z = (x === y)\` which is allowed -// ok -// ok -// ok -// error -// ok + let tests = [ function(x: string, y: number) { if (x == y) {} - if (x === y) {} + // error, string & number are not comparable (unsafe casting) + if (x === y) {} // no error, to match \`let z = (x === y)\` which is allowed }, function(x: string) { if (x == undefined) {} - if (x == void 0) {} + // ok + if (x == void 0) {} // ok }, function(x: string) { - if (x == null) {} + if (x == null) {} // ok }, function(x: { y: \"foo\" } | { y: \"bar\" }) { if (x.y == 123) {} - if (x.y === 123) {} + // error + if (x.y === 123) {} // ok } -]; -" +];" `; exports[`test exists.js 1`] = ` @@ -403,16 +404,18 @@ function foo2(x: ?Class): string { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ declare class Foo { foo: string } + function foo0(x: ?string): string { return x && x || \"\"; } + function foo1(x: ?Foo): string { return x && x.foo || \"\"; } + function foo2(x: ?Class): string { return x && new x().foo || \"\"; -} -" +}" `; exports[`test func_call.js 1`] = ` @@ -430,18 +433,17 @@ let tests = [ ]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// make sure we visit the AST in the correct order. if we visit z() before -// x.y, then the function call will invalidate the refinement of x.y -// incorrectly. -// no error + let tests = [ function(x: { y?: string }, z: () => string) { if (x.y) { - x.y.indexOf(z()); + // make sure we visit the AST in the correct order. if we visit z() before + // x.y, then the function call will invalidate the refinement of x.y + // incorrectly. + x.y.indexOf(z()); // no error } } -]; -" +];" `; exports[`test hasOwnProperty.js 1`] = ` @@ -468,31 +470,28 @@ function bar(x:Object) { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// error: could be undefined -// error: still could be undefined -// error: unreachable, but we don\'t help you here -// treated as \`any\`, so allowed -// still treated as \`any\`, so allowed -// also treated as \`any\`, so allowed + function foo(x: { y?: () => void }) { x.y(); + // error: could be undefined if (x.hasOwnProperty(\"y\")) { - x.y(); + x.y(); // error: still could be undefined } if (x.hasOwnProperty(\"z\")) { - x.z(); + x.z(); // error: unreachable, but we don\'t help you here } } + function bar(x: Object) { x.y(); + // treated as \`any\`, so allowed if (x.hasOwnProperty(\"y\")) { - x.y(); + x.y(); // still treated as \`any\`, so allowed } if (x.hasOwnProperty(\"z\")) { - x.z(); + x.z(); // also treated as \`any\`, so allowed } -} -" +}" `; exports[`test heap_defassign.js 1`] = ` @@ -582,106 +581,104 @@ function def_assign_setprop_nohavoc(obj: Obj, obj2: Obj2) { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// (obj.p : number) -// clears refi -// error, obj.p : number | string -// (obj.p : number) -// clears refi -// error, obj.p : number | string -// (obj.p : number) -// clears refi -// error, obj.p : number | string -// (obj.p : number) -// ok by def assign -// error, obj.p : number | string -// (obj.p : number) -// ok by def assign -// error, obj.p : number | string -// (obj.p : number) -// ok by def assign -// no error, loop runs at least once -// (obj.p : number) -// clears refi and might throw -// clears refi and might throw -// NOTE: the values understood to flow to obj.p at this point -// include the number 42 written downstream; -// so if we did y:string, we would get at least a spurious error -// (among other reasonable errors caused by values written upstream) -// error, string ~/~ number -// error, number ~/~ string -// (obj.p : number) -// ok by def assign -// error, (number | string) ~/~ number -// --- name-sensitive havoc --- -// (obj.p : number) -// doesn\'t clear refi of .p -// still ok + type Obj = { p: number | string }; + function f() {} + function def_assign_function_havoc(obj: Obj) { obj.p = 10; + // (obj.p : number) f(); - var x: number = obj.p; + // clears refi + var x: number = obj.p; // error, obj.p : number | string } + function def_assign_setprop_havoc(obj: Obj, obj2: Obj) { obj.p = 10; + // (obj.p : number) obj2.p = \"hey\"; - var x: number = obj.p; + // clears refi + var x: number = obj.p; // error, obj.p : number | string } + function def_assign_index_havoc(obj: Obj, obj2: Obj) { obj.p = 10; + // (obj.p : number) obj2[\"p\"] = \"hey\"; - var x: number = obj.p; + // clears refi + var x: number = obj.p; // error, obj.p : number | string } + function def_assign_within_if(b: boolean, obj: Obj) { if (b) { obj.p = 10; - var x: number = obj.p; + // (obj.p : number) + var x: number = obj.p; // ok by def assign } - var y: number = obj.p; + var y: number = obj.p; // error, obj.p : number | string } + function def_assign_within_while(b: boolean, obj: Obj) { while (b) { obj.p = 10; - var x: number = obj.p; + // (obj.p : number) + var x: number = obj.p; // ok by def assign } - var y: number = obj.p; + var y: number = obj.p; // error, obj.p : number | string } + function def_assign_within_do(b: boolean, obj: Obj) { do { obj.p = 10; - var x: number = obj.p; + // (obj.p : number) + var x: number = obj.p; // ok by def assign } while (b); - var y: number = obj.p; + var y: number = obj.p; // no error, loop runs at least once } + function def_assign_within_try(b: boolean, obj: Obj) { obj.p = 10; + // (obj.p : number) try { f(); + // clears refi and might throw obj.p = \"hey\"; } catch (e) { f(); + // clears refi and might throw obj.p = \"hey\"; } finally { + // NOTE: the values understood to flow to obj.p at this point + // include the number 42 written downstream; + // so if we did y:string, we would get at least a spurious error + // (among other reasonable errors caused by values written upstream) var y: number = obj.p; + // error, string ~/~ number obj.p = 42; } - var z: string = obj.p; + var z: string = obj.p; // error, number ~/~ string } + function def_assign_within_for(b: boolean, obj: Obj) { for (; b; ) { obj.p = 10; - var x: number = obj.p; + // (obj.p : number) + var x: number = obj.p; // ok by def assign } - var z: number = obj.p; + var z: number = obj.p; // error, (number | string) ~/~ number } + +// --- name-sensitive havoc --- type Obj2 = { q: number | string }; + function def_assign_setprop_nohavoc(obj: Obj, obj2: Obj2) { obj.p = 10; + // (obj.p : number) obj2.q = \"hey\"; - var x: number = obj.p; -} -" + // doesn\'t clear refi of .p + var x: number = obj.p; // still ok +}" `; exports[`test lib.js 1`] = ` @@ -690,8 +687,8 @@ exports[`test lib.js 1`] = ` declare var BAZ: {stuff?: (x: number) => void} | void; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -declare var BAZ: { stuff?: (x: number) => void } | void; -" + +declare var BAZ: { stuff?: (x: number) => void } | void;" `; exports[`test missing-property-cond.js 1`] = ` @@ -747,39 +744,34 @@ function foo8(o: { p: mixed }) { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// OK, this is an idiomatic way of testing property existence -// OK -// error, since o.p2\'s type is unknown (e.g., could be \`number\`) -// usual error outside conditional -// OK -// currently OK, should be unreachable -// error -// error, any lookup on mixed is unsafe -// error -// ok -// ok -// ok -// this is ok because o.p is truthy, so o.p.q is safe + function foo1(o: { x: number }) { if (o.p1) { + // OK, this is an idiomatic way of testing property existence o.x; } } + function foo2(o: { x: number }) { if (o.p2) { - o.p2.x; + // OK + o.p2.x; // error, since o.p2\'s type is unknown (e.g., could be \`number\`) } } + function foo3(o: { x: number }) { - o.p3.x; + o.p3.x; // usual error outside conditional } + function foo4(o: $Exact<{ x: number }>) { if (o.p4) { - o.p4.x; + // OK + o.p4.x; // currently OK, should be unreachable } else { - o.p4.x; + o.p4.x; // error } } + function foo5() { const o = {}; _foo5(); @@ -790,20 +782,26 @@ function foo5() { o.p = function() {}; } } + function foo6(o: mixed) { - if (o.bar) {} + if (o.bar) {} // error, any lookup on mixed is unsafe } + function foo7(o: mixed) { if (typeof o.bar === \"string\") {} + // error if (o && typeof o.bar === \"string\") {} + // ok if (o != null && typeof o.bar === \"string\") {} - if (o !== null && o !== undefined && typeof o.bar === \"string\") {} + // ok + if (o !== null && o !== undefined && typeof o.bar === \"string\") {} // ok } + function foo8(o: { p: mixed }) { if (o.p && o.p.q) {} + // this is ok because o.p is truthy, so o.p.q is safe if (o.p && o.p.q && o.p.q.r) {} -} -" +}" `; exports[`test mixed.js 1`] = ` @@ -930,114 +928,109 @@ function arr0(x: mixed) { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// error -// error: we don\'t know the truthiness of x -// ok -// ok -// error -// error: we don\'t know the truthiness of x -// ok -// ok -// error -// error: we don\'t know the truthiness of x -// ok -// ok -// error -// error -// error -// error -// error -// error -// error -// error -// error, mixed -// error + function takesNumber(x: number) {} function takesString(x: string) {} + function num(x: mixed) { if (typeof x === \"number\") { takesString(x); - (!x: false); + // error + (!x: false); // error: we don\'t know the truthiness of x } if (typeof x === \"number\" && x) { - (!x: false); + (!x: false); // ok } if (x && typeof x === \"number\") { - (!x: false); + (!x: false); // ok } } + function str(x: mixed) { if (typeof x === \"string\") { takesNumber(x); - (!x: false); + // error + (!x: false); // error: we don\'t know the truthiness of x } if (typeof x === \"string\" && x) { - (!x: false); + (!x: false); // ok } if (x && typeof x === \"string\") { - (!x: false); + (!x: false); // ok } } + function bool(x: mixed) { if (typeof x === \"boolean\") { takesString(x); - (x: true); + // error + (x: true); // error: we don\'t know the truthiness of x } if (typeof x === \"boolean\" && x) { - (x: true); + (x: true); // ok } if (x && typeof x === \"boolean\") { - (x: true); + (x: true); // ok } } + function fun(x: mixed) { if (typeof x === \"function\") { - takesString(x); + takesString(x); // error } } + function obj0(x: mixed) { if (typeof x === \"object\") { - takesString(x); + takesString(x); // error } } + function obj1(x: mixed) { if (Array.isArray(x)) { - takesString(x); + takesString(x); // error } } + function undef(x: mixed) { if (typeof x === \"undefined\") { - takesString(x); + takesString(x); // error } } + function null_(x: mixed) { if (x === null) { - takesString(x); + takesString(x); // error } } + function maybe(x: mixed) { if (x == null) { - takesString(x); + takesString(x); // error } } + function true_(x: mixed) { if (x === true) { - takesString(x); + takesString(x); // error } } + function false_(x: mixed) { if (x === false) { - takesString(x); + takesString(x); // error } } + function obj2(x: mixed) { if (typeof x === \"object\") { (x: { [key: string]: mixed } | null); if (x !== null) { - (x[\"foo\"]: string); + (x[\"foo\"]: string); // error, mixed } } } + function obj2(x: mixed) { if (typeof x === \"object\" && x) { (x: Object); @@ -1052,19 +1045,18 @@ function obj2(x: mixed) { (x: Object); } } + function arr0(x: mixed) { if (Array.isArray(x)) { - takesString(x[0]); + takesString(x[0]); // error } -} -" +}" `; exports[`test node1.js 1`] = ` "module.exports = \'Node1\'; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -module.exports = \"Node1\"; -" +module.exports = \"Node1\";" `; exports[`test not.js 1`] = ` @@ -1122,34 +1114,31 @@ let tests = [ ]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// should error for null, void and bool (false) -// should error for null, void and number (0) -// should error for number (0) -// ok, functions are always truthy -// ok, objects are always truthy -// error, strings are not always truthy -// error, numbers are not always truthy -// error, bools are not always truthy -// ok, classes are always truthy + function foo(x: ?boolean) { if (!x) { - x++; + x++; // should error for null, void and bool (false) } } + function bar(x: ?number) { if (!x) { - x[0]; + x[0]; // should error for null, void and number (0) } } + function baz(x: ?number) { if (x === null || x === undefined) { return; } + if (!x) { - x[0]; + x[0]; // should error for number (0) } } + class TestClass {} + let tests = [ function() { var y = true; @@ -1158,25 +1147,24 @@ let tests = [ } }, function(x: Function) { - (!x: false); + (!x: false); // ok, functions are always truthy }, function(x: Object) { - (!x: false); + (!x: false); // ok, objects are always truthy }, function(x: string) { - (!x: false); + (!x: false); // error, strings are not always truthy }, function(x: number) { - (!x: false); + (!x: false); // error, numbers are not always truthy }, function(x: boolean) { - (!x: false); + (!x: false); // error, bools are not always truthy }, function(x: TestClass) { - (!x: false); + (!x: false); // ok, classes are always truthy } -]; -" +];" `; exports[`test null.js 1`] = ` @@ -1192,6 +1180,7 @@ function null_bogus_comparison() { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + function null_bogus_comparison() { if (100 * null) { return; @@ -1199,8 +1188,7 @@ function null_bogus_comparison() { if (null * 100) { return; } -} -" +}" `; exports[`test number.js 1`] = ` @@ -1327,36 +1315,25 @@ let tests = [ ]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// error -// error -// error -// error -// unreachable, no error -// error -// error -// error -// ok, typos allowed in conditionals -// ok -// error -// error -// no error, inferred to be 0 + type Mode = 0 | 1 | 2; + let tests = [ function(x: number) { if (x === 0) { - (x: void); + (x: void); // error } - (x: 0); + (x: 0); // error }, function(x: number) { if (x !== 0) { - (x: 0); + (x: 0); // error } - (x: void); + (x: void); // error }, function(x: 1): 0 { if (x === 0) { - return x; + return x; // unreachable, no error } return 0; }, @@ -1381,18 +1358,18 @@ let tests = [ function(x: 0 | 1) { if (x === 0) { (x: 0); - (x: void); + (x: void); // error } if (x === 1) { (x: 1); - (x: void); + (x: void); // error } }, function(x: { foo: number }): 0 { if (x.foo === 0) { return x.foo; } - return x.foo; + return x.foo; // error }, function(x: { kind: 0, foo: number } | { kind: 1, bar: number }): number { if (x.kind === 0) { @@ -1417,7 +1394,7 @@ let tests = [ if (s === 0) { return s; } else if (s === 3) { - return s; + return s; // error } }, function(mode: Mode) { @@ -1425,6 +1402,7 @@ let tests = [ case 0: (mode: 0); break; + case 1: case 2: (mode: 1 | 2); @@ -1433,13 +1411,12 @@ let tests = [ }, function(x: number): 0 { if (x) { - return x; + return x; // error } else { - return x; + return x; // no error, inferred to be 0 } } -]; -" +];" `; exports[`test property.js 1`] = ` @@ -1527,81 +1504,89 @@ function c3(x: {[key: string]: ?string}, y: {z: string, a: string}): string { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// --- name-sensitive havoc --- -// error -// ok + function a(x: { [key: string]: ?string }, y: string): string { if (x[y]) { return x[y]; } return \"\"; } + function b(x: { y: { [key: string]: ?string } }, z: string): string { if (x.y[z]) { return x.y[z]; } return \"\"; } + function c(x: { [key: string]: ?string }, y: { z: string }): string { if (x[y.z]) { return x[y.z]; } return \"\"; } + function d(x: { y: { [key: string]: ?string } }, a: { b: string }): string { if (x.y[a.b]) { return x.y[a.b]; } return \"\"; } + function a_array(x: Array, y: number): string { if (x[y]) { return x[y]; } return \"\"; } + function b_array(x: { y: Array }, z: number): string { if (x.y[z]) { return x.y[z]; } return \"\"; } + function c_array(x: Array, y: { z: number }): string { if (x[y.z]) { return x[y.z]; } return \"\"; } + function d_array(x: { y: Array }, a: { b: number }): string { if (x.y[a.b]) { return x.y[a.b]; } return \"\"; } + function e_array(x: Array): string { if (x[0]) { return x[0]; } return \"\"; } + +// --- name-sensitive havoc --- function c2(x: { [key: string]: ?string }, y: { z: string }): string { if (x[y.z]) { y.z = \"HEY\"; - return x[y.z]; + return x[y.z]; // error } return \"\"; } + function c3( x: { [key: string]: ?string }, y: { z: string, a: string } ): string { if (x[y.z]) { y.a = \"HEY\"; - return x[y.z]; + return x[y.z]; // ok } return \"\"; -} -" +}" `; exports[`test refinements.js 1`] = ` @@ -1684,20 +1669,6 @@ function global_in_conditional2(x: number) { } } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// NOTE: the values understood to flow to x at this point -// include the number 42 written downstream; -// so if we did y:string, we would get at least a spurious error -// (among other reasonable errors caused by values written upstream) -// commenting this out would propagate x:string downstream -// regression test: bring a global into scope by testing it. -// this has no refinement consequences and is error-free. -// the way we currently cache global lookups causes uneven -// distribution of the global\'s entries at path merge time, -// so we need to recognize that it\'s legit rather than an -// internal error. -// -// merge_env -// copy_env function foo(b) { var x = b ? 0 : null; while (typeof x == \"string\" || typeof x == \"number\") { @@ -1706,6 +1677,7 @@ function foo(b) { } var z: string = x; } + function bar(b) { var x = b ? 0 : null; do { @@ -1714,6 +1686,7 @@ function bar(b) { } while (x === null); var z: string = x; } + function maybe_throw() {} function qux() { var x = 0; @@ -1724,11 +1697,16 @@ function qux() { maybe_throw(); x = \"hello\"; } finally { + // NOTE: the values understood to flow to x at this point + // include the number 42 written downstream; + // so if we did y:string, we would get at least a spurious error + // (among other reasonable errors caused by values written upstream) var y: number = x; x = 42; } var z: string = x; } + function corge(b) { for ( var x = b ? 0 : null; @@ -1739,25 +1717,36 @@ function corge(b) { } var z: string = x; } + function waldo() { var o = {}; var x = false; for (x in o) { - x = 0; + x = 0; // commenting this out would propagate x:string downstream } var z: number = x; } + +// regression test: bring a global into scope by testing it. +// this has no refinement consequences and is error-free. +// the way we currently cache global lookups causes uneven +// distribution of the global\'s entries at path merge time, +// so we need to recognize that it\'s legit rather than an +// internal error. +// function global_in_conditional0(x: number) { + // merge_env if (x != 0) { if (BAZ) {} } } + function global_in_conditional2(x: number) { + // copy_env for (var i = 0; i < 100; i++) { if (BAZ) {} } -} -" +}" `; exports[`test string.js 1`] = ` @@ -1896,37 +1885,25 @@ let tests = [ ]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// error -// error -// error -// error -// unreachable, no error -// error -// error -// error -// ok, typos allowed in conditionals -// ok -// error -// error -// no error, inferred to be \"\" -// Simple template literals are ok + type Mode = \"a\" | \"b\" | \"c\"; + let tests = [ function(x: string) { if (x === \"foo\") { - (x: void); + (x: void); // error } - (x: \"foo\"); + (x: \"foo\"); // error }, function(x: string) { if (x !== \"foo\") { - (x: \"foo\"); + (x: \"foo\"); // error } - (x: void); + (x: void); // error }, function(x: \"bar\"): \"foo\" { if (x === \"foo\") { - return x; + return x; // unreachable, no error } return \"foo\"; }, @@ -1951,18 +1928,18 @@ let tests = [ function(x: \"foo\" | \"bar\") { if (x === \"foo\") { (x: \"foo\"); - (x: void); + (x: void); // error } if (x === \"bar\") { (x: \"bar\"); - (x: void); + (x: void); // error } }, function(x: { foo: string }): \"foo\" { if (x.foo === \"foo\") { return x.foo; } - return x.foo; + return x.foo; // error }, function( x: { kind: \"foo\", foo: string } | { kind: \"bar\", bar: string } @@ -1990,7 +1967,7 @@ let tests = [ if (s === \"a\") { return s; } else if (s === \"d\") { - return s; + return s; // error } }, function(mode: Mode) { @@ -1998,6 +1975,7 @@ let tests = [ case \"a\": (mode: \"a\"); break; + case \"b\": case \"c\": (mode: \"b\" | \"c\"); @@ -2006,11 +1984,12 @@ let tests = [ }, function(x: string): \"\" { if (x) { - return x; + return x; // error } else { - return x; + return x; // no error, inferred to be \"\" } }, + // Simple template literals are ok function(x: string): \"foo\" { if (x === \`foo\`) { return x; @@ -2020,8 +1999,7 @@ let tests = [ } return \"foo\"; } -]; -" +];" `; exports[`test super_member.js 1`] = ` @@ -2053,32 +2031,32 @@ class C extends A { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// super.prop doesn\'t exist -// error, unknown type passed to string expected -// OK + class A { prop: string; method(): string { return \"A\"; } } + class B { test(): string { if (super.prop) { - return super.prop; + // super.prop doesn\'t exist + return super.prop; // error, unknown type passed to string expected } return \"B\"; } } + class C extends A { test(): string { if (super.prop) { - return super.prop; + return super.prop; // OK } return \"C\"; } -} -" +}" `; exports[`test switch.js 1`] = ` @@ -2139,15 +2117,12 @@ function corge(text: string | number | Array): string { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// error, should return string -// error, [0] on number -// error, [0] on number -// using ++ since it isn\'t valid on arrays or strings. -// should only error for string since Array was filtered out. + function foo(text: string | number): string { switch (typeof text) { case \"string\": return text; + // error, should return string case \"number\": return text; default: @@ -2165,6 +2140,7 @@ function bar(text: string | number): string { function baz1(text: string | number): string { switch (typeof text) { case \"number\": + // error, [0] on number case \"string\": return text[0]; default: @@ -2174,6 +2150,7 @@ function baz1(text: string | number): string { function baz2(text: string | number): string { switch (typeof text) { case \"string\": + // error, [0] on number case \"number\": return text[0]; default: @@ -2185,13 +2162,15 @@ function corge(text: string | number | Array): string { case \"object\": return text[0]; case \"string\": - case \"number\": + case // using ++ since it isn\'t valid on arrays or strings. + // should only error for string since Array was filtered out. + \"number\": return text++ + \"\"; + default: return \"wat\"; } -} -" +}" `; exports[`test tagged_union.js 1`] = ` @@ -2429,113 +2408,54 @@ let tests = [ ]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // example 1 -// OK, since typeAST: Name -// OK, since typeAST: ListType -// example 2 -// Node = \"Node1\" -// typeAST: Node1, but x.prop1 may be undefined -// example 3 -// error, Apple.taste = Bad -// error, Carrot.raw = Maybe -// 2 errors: -// Orange.raw doesn\'t exist -// Carrot.raw is neither Yes nor No -// example 4 -// example 5 -// error, x: C and property A not found in type C -// example 6 -// non-existent props -// typos are allowed to be tested -// typos can\'t be used, though -// nested objects -// error, fooTypo doesn\'t exist -// invalid RHS -// error, method on null -// error, method on null -// non-objects on LHS -// typos are allowed to be tested -// inside the block, it\'s a number -// error: number literal 0 !~> string -// typos are allowed to be tested -// inside the block, it\'s a number -// error: number literal 0 !~> string -// typos are allowed to be tested -// inside the block, it\'s a number -// error: number literal 0 !~> string -// typos are allowed to be tested -// inside the block, it\'s a number -// error: number literal 0 !~> string -// typos are allowed to be tested -// props on AnyObjT are \`any\` -// typos are allowed to be tested -// ok, props on functions are \`any\` :/ -// typos are allowed to be tested -// ok, props on functions are \`any\` :/ -// sentinel props become the RHS -// error: \'str\' !~> \'not str\' -// error: 123 !~> 456 -// error: true !~> false -// even if it doesn\'t exist... -// error: \'bad\' !~> empty -// error: 123 !~> empty -// error: true !~> empty -// type mismatch -// error -// error -// error -// error -// type mismatch, but one is not a literal -// ok, because 123 !== \'foo\' -// error -// error: x.foo could be a string -// error: could still be either case (if foo was a different number) -// error -// error -// type mismatch, neither is a literal -// ok, because 123 !== string -// error -// error: x.foo could be a string -// error: could still be either case (if foo was a different number) -// error -// error: x.foo could be a different string -// error: x.foo could be a number -// type mismatch, neither is a literal, test is not a literal either -// error: flow isn\'t smart enough to figure this out yet -// error + type Type = Name | ListType; type Name = { kind: \"Name\", value: string }; type ListType = { kind: \"ListType\", name: string }; + function getTypeASTName(typeAST: Type): string { if (typeAST.kind === \"Name\") { - return typeAST.value; + return typeAST.value; // OK, since typeAST: Name } else { - return typeAST.name; + return typeAST.name; // OK, since typeAST: ListType } } + +// example 2 import type {ASTNode} from \"./ast_node\"; var Node = require(\"./node1\"); +// Node = \"Node1\" function foo(x: ASTNode) { if (x.kind === Node) { - return x.prop1.charAt(0); + return x.prop1.charAt(0); // typeAST: Node1, but x.prop1 may be undefined } return null; } + +// example 3 type Apple = { kind: \"Fruit\", taste: \"Bad\" }; type Orange = { kind: \"Fruit\", taste: \"Good\" }; type Broccoli = { kind: \"Veg\", taste: \"Bad\", raw: \"No\" }; type Carrot = { kind: \"Veg\", taste: \"Good\", raw: \"Maybe\" }; + type Breakfast = Apple | Orange | Broccoli | Carrot; + function bar(x: Breakfast) { if (x.kind === \"Fruit\") { (x.taste: \"Good\"); - } else - (x.raw: \"No\"); + } // error, Apple.taste = Bad else + (x.raw: \"No\"); // error, Carrot.raw = Maybe } + function qux(x: Breakfast) { if (x.taste === \"Good\") { - (x.raw: \"Yes\" | \"No\"); + (x.raw: \"Yes\" | \"No\"); // 2 errors: + // Orange.raw doesn\'t exist + // Carrot.raw is neither Yes nor No } } + +// example 4 function list(n) { if (n > 0) return { kind: \"cons\", next: list(n - 1) }; @@ -2554,6 +2474,8 @@ function check(n) { return n === length(list(n)); return true; } + +// example 5 var EnumKind = { A: 1, B: 2, C: 3 }; type A = { kind: 1, A: number }; type B = { kind: 2, B: number }; @@ -2564,11 +2486,14 @@ function kind(x: A | B | C): number { return x.A; case EnumKind.B: return x.B; + // error, x: C and property A not found in type C default: return x.A; } } kind({ kind: EnumKind.A, A: 1 }); + +// example 6 type Citizen = { citizen: true }; type NonCitizen = { citizen: false, nationality: string }; function nationality(x: Citizen | NonCitizen) { @@ -2577,20 +2502,27 @@ function nationality(x: Citizen | NonCitizen) { else return x.nationality; } + let tests = [ + // non-existent props function test7(x: A) { if (x.kindTypo === 1) { - (x.kindTypo: string); + // typos are allowed to be tested + (x.kindTypo: string); // typos can\'t be used, though } }, + // nested objects function test8(x: { foo: { bar: 1 } }) { if (x.foo.bar === 1) {} - if (x.fooTypo.bar === 1) {} + if (x.fooTypo.bar === 1) {} // error, fooTypo doesn\'t exist }, + // invalid RHS function(x: A) { if (x.kind === null.toString()) {} - if ({ kind: 1 }.kind === null.toString()) {} + // error, method on null + if ({ kind: 1 }.kind === null.toString()) {} // error, method on null }, + // non-objects on LHS function( x: Array, y: string, @@ -2602,115 +2534,139 @@ let tests = [ ) { if (x.length === 0) {} if (x.legnth === 0) { + // typos are allowed to be tested (x.legnth: number); - (x.legnth: string); + // inside the block, it\'s a number + (x.legnth: string); // error: number literal 0 !~> string } if (y.length === 0) {} if (y.legnth === 0) { + // typos are allowed to be tested (y.legnth: number); - (y.legnth: string); + // inside the block, it\'s a number + (y.legnth: string); // error: number literal 0 !~> string } if (z.toString === 0) {} if (z.toStirng === 0) { + // typos are allowed to be tested (z.toStirng: number); - (z.toStirng: string); + // inside the block, it\'s a number + (z.toStirng: string); // error: number literal 0 !~> string } if (q.valueOf === 0) {} if (q.valeuOf === 0) { + // typos are allowed to be tested (q.valeuOf: number); - (q.valeuOf: string); + // inside the block, it\'s a number + (q.valeuOf: string); // error: number literal 0 !~> string } if (r.toStirng === 0) { - (r.toStirng: empty); + // typos are allowed to be tested + (r.toStirng: empty); // props on AnyObjT are \`any\` } if (s.call === 0) {} if (s.calll === 0) { - (t.calll: empty); + // typos are allowed to be tested + (t.calll: empty); // ok, props on functions are \`any\` :/ } if (t.call === 0) {} if (t.calll === 0) { - (t.calll: empty); + // typos are allowed to be tested + (t.calll: empty); // ok, props on functions are \`any\` :/ } }, + // sentinel props become the RHS function(x: { str: string, num: number, bool: boolean }) { if (x.str === \"str\") { - (x.str: \"not str\"); + (x.str: \"not str\"); // error: \'str\' !~> \'not str\' } if (x.num === 123) { - (x.num: 456); + (x.num: 456); // error: 123 !~> 456 } if (x.bool === true) { - (x.bool: false); + (x.bool: false); // error: true !~> false } + // even if it doesn\'t exist... if (x.badStr === \"bad\") { - (x.badStr: empty); + (x.badStr: empty); // error: \'bad\' !~> empty } if (x.badNum === 123) { - (x.badNum: empty); + (x.badNum: empty); // error: 123 !~> empty } if (x.badBool === true) { - (x.badBool: empty); + (x.badBool: empty); // error: true !~> empty } }, + // type mismatch function(x: { foo: 123, y: string } | { foo: \"foo\", z: string }) { if (x.foo === 123) { (x.y: string); - x.z; + x.z; // error } else { (x.z: string); - x.y; + x.y; // error } if (x.foo === \"foo\") { (x.z: string); - x.y; + x.y; // error } else { (x.y: string); - x.z; + x.z; // error } }, + // type mismatch, but one is not a literal function(x: { foo: number, y: string } | { foo: \"foo\", z: string }) { if (x.foo === 123) { (x.y: string); - x.z; + // ok, because 123 !== \'foo\' + x.z; // error } else { x.y; - x.z; + // error: x.foo could be a string + x.z; // error: could still be either case (if foo was a different number) } + if (x.foo === \"foo\") { (x.z: string); - x.y; + x.y; // error } else { (x.y: string); - x.z; + x.z; // error } }, + // type mismatch, neither is a literal function(x: { foo: number, y: string } | { foo: string, z: string }) { if (x.foo === 123) { (x.y: string); - x.z; + // ok, because 123 !== string + x.z; // error } else { x.y; - x.z; + // error: x.foo could be a string + x.z; // error: could still be either case (if foo was a different number) } + if (x.foo === \"foo\") { (x.z: string); - x.y; + x.y; // error } else { x.y; - x.z; + // error: x.foo could be a different string + x.z; // error: x.foo could be a number } }, + // type mismatch, neither is a literal, test is not a literal either function( x: { foo: number, y: string } | { foo: string, z: string }, num: number ) { if (x.foo === num) { x.y; - x.z; + // error: flow isn\'t smart enough to figure this out yet + x.z; // error } } -]; -" +];" `; exports[`test tagged_union_import.js 1`] = ` @@ -2739,9 +2695,13 @@ function handleStatus(status: Success | Error) { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + import {SUCCESS, ERROR} from \"./constants\"; + type Success = { type: typeof SUCCESS, message: string }; + type Error = { type: typeof ERROR, error: string }; + function handleStatus(status: Success | Error) { switch (status.type) { case SUCCESS: @@ -2750,8 +2710,7 @@ function handleStatus(status: Success | Error) { default: console.log(\`Errored: \${status.error}\`); } -} -" +}" `; exports[`test typeof.js 1`] = ` @@ -2821,70 +2780,71 @@ function testInvalidTemplateLiteral(x: string | number) { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// error for boolean, not number -// error, null -/* refining globals */ -// error, refinement is gone -// error, could be undefined -// ok -// error, refinement is gone -// OK, x refined to \`number\` -// OK, x refined to \`number\` -// error -// error + function foo(x: boolean | number) { if (typeof x === \"boolean\") { - x[0]; + x[0]; // error for boolean, not number } } + function bar(): number { var x = null; if (typeof x === \"object\") { - return x; + return x; // error, null } return 0; } + +/* refining globals */ function fn0() { if (typeof BAZ !== \"undefined\" && typeof BAZ.stuff === \"function\") { BAZ.stuff(123); } - BAZ.stuff(123); + BAZ.stuff(123); // error, refinement is gone } function fn1() { BAZ.stuff; + // error, could be undefined if (typeof BAZ !== \"undefined\" && typeof BAZ.stuff === \"function\") { BAZ.stuff(123); - BAZ.stuff(123); + // ok + BAZ.stuff(123); // error, refinement is gone } } + function anyfun(x: number | Function): number { if (typeof x === \"function\") { return 0; } - return x; + return x; // OK, x refined to \`number\` } + function anyobj(x: number | Object): number { if (typeof x === \"object\") { return 0; } - return x; + return x; // OK, x refined to \`number\` } + function testInvalidValue(x: mixed) { if (typeof x === \"foo\") { + // error return 0; } } + function testTemplateLiteral(x: string | number) { if (typeof x === \`string\`) { return x.length; } } + function testInvalidTemplateLiteral(x: string | number) { if (typeof x === \`foo\`) { + // error return 0; } -} -" +}" `; exports[`test undef.js 1`] = ` @@ -2970,69 +2930,77 @@ function undef_bogus_comparison() { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// unreachable -// unreachable -// error + function undef_var(x: ?number) { if (x !== null && x !== undefined) { var y = x * 1000; } } + function undef_var_rev(x: ?number) { if (x === null || x === undefined) {} else { var y = x * 1000; } } + function undef_prop(x: { x: ?number }) { if (x.x !== null && x.x !== undefined) { var y = x.x * 1000; } } + function undef_prop_rev(x: { x: ?number }) { if (x.x === null || x.x === undefined) {} else { var y = x.x * 1000; } } + function undef_var_fail(x: ?number) { if (x !== undefined) { var y = x * 1000; } } + function undef_var_fail_rev(x: ?number) { if (x === undefined) {} else { var y = x * 1000; } } + function undef_prop_fail(x: { x: ?number }) { if (x.x !== undefined) { var y = x.x * 1000; } } + function undef_prop_fail_rev(x: { x: ?number }) { if (x.x === undefined) {} else { var y = x.x * 1000; } } + function undef_unreachable(x: number) { if (x === undefined) { - var y = x * 1000; + var y = x * 1000; // unreachable } if (x == undefined) { - var z = x * 1000; + var z = x * 1000; // unreachable } } + function undef_var_nonstrict(x: ?number, y: ?number) { if (x != undefined) { var a = x * 1000; } if (y == undefined) { - var b = y * 1000; + var b = y * 1000; // error } } + function undef_bogus_comparison() { if (100 * undefined) { return; @@ -3040,8 +3008,7 @@ function undef_bogus_comparison() { if (undefined * 100) { return; } -} -" +}" `; exports[`test union.js 1`] = ` @@ -3068,26 +3035,26 @@ function baz(x: ?thing) { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// error on boolean -// error on number -// error on number + type thing = number | boolean; + function foo(x: thing) { if (x === true) { - x[0]; + x[0]; // error on boolean } } + function bar(x: thing) { if (x !== true && x !== false) { - x[0]; + x[0]; // error on number } } + function baz(x: ?thing) { if (x && x !== true) { - x[0]; + x[0]; // error on number } -} -" +}" `; exports[`test void.js 1`] = ` @@ -3188,72 +3155,85 @@ function void_redefined_undefined(x: ?number) { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + function void_var(x: ?number) { if (x !== null && x !== void 0) { var y = x * 1000; } } + function void_var_rev(x: ?number) { if (x === null || x === void 0) {} else { var y = x * 1000; } } + function void_pro(x: { x: ?number }) { if (x.x !== null && x.x !== void 0) { var y = x.x * 1000; } } + function void_pro_rev(x: { x: ?number }) { if (x.x === null || x.x === void 0) {} else { var y = x.x * 1000; } } + function void_var_fail(x: ?number) { if (x !== void 0) { var y = x * 1000; } } + function void_var_fail_rev(x: ?number) { if (x === void 0) {} else { var y = x * 1000; } } + function void_pro_fail(x: { x: ?number }) { if (x.x !== void 0) { var y = x.x * 1000; } } + function void_pro_fail_rev(x: { x: ?number }) { if (x.x === void 0) {} else { var y = x.x * 1000; } } + function void_var_side_effect(x: ?number) { if (x !== null && x !== void (x * 1000)) { var y = x * 1000; } } + function void_var_side_effect_rev(x: ?number) { if (x === null || x === void (x * 1000)) {} else { var y = x * 1000; } } + function void_prop_side_effect(x: { x: ?number }) { if (x.x !== null && x.x !== void (x.x * 1000)) { var y = x.x * 1000; } } + function void_prop_side_effect_rev(x: { x: ?number }) { if (x.x === null || x.x === void (x.x * 1000)) {} else { var y = x.x * 1000; } } + function void_bogus_comparison() { if (100 * void 0) { return; @@ -3262,11 +3242,11 @@ function void_bogus_comparison() { return; } } + function void_redefined_undefined(x: ?number) { var undefined = \"foo\"; if (x !== null && x !== void 0) { var y = x * 1000; } -} -" +}" `; diff --git a/tests/reflection/__snapshots__/jsfmt.spec.js.snap b/tests/reflection/__snapshots__/jsfmt.spec.js.snap index adb6543e..bf6c595f 100644 --- a/tests/reflection/__snapshots__/jsfmt.spec.js.snap +++ b/tests/reflection/__snapshots__/jsfmt.spec.js.snap @@ -8,11 +8,11 @@ var x:T = \"...\"; // what about recursive unions? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// what about recursive unions? declare var a: number; var b: typeof a = \"...\"; var c: typeof a = \"...\"; + type T = number; var x: T = \"...\"; -" +// what about recursive unions?" `; diff --git a/tests/regexp/__snapshots__/jsfmt.spec.js.snap b/tests/regexp/__snapshots__/jsfmt.spec.js.snap index 8c701b1b..3b441070 100644 --- a/tests/regexp/__snapshots__/jsfmt.spec.js.snap +++ b/tests/regexp/__snapshots__/jsfmt.spec.js.snap @@ -3,6 +3,5 @@ exports[`test regexp.js 1`] = ` var match:number = patt.test(\"Hello world!\"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ var patt = /Hello/g; -var match: number = patt.test(\"Hello world!\"); -" +var match: number = patt.test(\"Hello world!\");" `; diff --git a/tests/replace/__snapshots__/jsfmt.spec.js.snap b/tests/replace/__snapshots__/jsfmt.spec.js.snap index 172688df..8bd5d757 100644 --- a/tests/replace/__snapshots__/jsfmt.spec.js.snap +++ b/tests/replace/__snapshots__/jsfmt.spec.js.snap @@ -6,7 +6,8 @@ function foo(x) { } foo(\"\"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ var a = 0; + function foo(x) {} -foo(\"\"); -" + +foo(\"\");" `; diff --git a/tests/require/__snapshots__/jsfmt.spec.js.snap b/tests/require/__snapshots__/jsfmt.spec.js.snap index 2ff20ad5..ff41cc2e 100644 --- a/tests/require/__snapshots__/jsfmt.spec.js.snap +++ b/tests/require/__snapshots__/jsfmt.spec.js.snap @@ -4,15 +4,13 @@ exports[`test B.js 1`] = ` exports.numberValue = 42; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -exports.numberValue = 42; -" + +exports.numberValue = 42;" `; exports[`test C.js 1`] = ` "/* @flow */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -/* @flow */ - " `; @@ -29,12 +27,13 @@ module.exports = { exports = {stringValue: \'\'}; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + // Local \`exports\` var is just a ref to module.exports, so mutating the original // value will affect the exports object but re-binding it makes it useless and // does not affect the exports value. module.exports = { numberValue: 42 }; -exports = { stringValue: \"\" }; -" + +exports = { stringValue: \"\" };" `; exports[`test ProvidesModuleA.js 1`] = ` @@ -49,8 +48,8 @@ exports.numberValue = 42; * @providesModule A * @flow */ -exports.numberValue = 42; -" + +exports.numberValue = 42;" `; exports[`test ProvidesModuleD.js 1`] = ` @@ -59,11 +58,6 @@ exports[`test ProvidesModuleD.js 1`] = ` * @flow */ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -/** - * @providesModule D - * @flow - */ - " `; @@ -74,9 +68,9 @@ function require() {} require(\"not a module name\"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + function require() {} -require(\"not a module name\"); -" +require(\"not a module name\");" `; exports[`test not_builtin_require2.js 1`] = ` @@ -86,9 +80,9 @@ type require = number; var a: require = 42; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + type require = number; -var a: require = 42; -" +var a: require = 42;" `; exports[`test require.js 1`] = ` @@ -129,35 +123,40 @@ require(\`\${\'./E\'}\`); // error: but only if they have no expressions require.call(null, \"DoesNotExist\"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// @providesModule -// File path -// C.js exists, but not as a providesModule -// @providesModule D exists, but not as a filename -// E exports an object with a numVal property -// Error: The E exports obj has no \'stringValue\' property -// We require that the param passed to require() be a string literal to support -// guaranteed static extraction -// Error: Param must be string literal -// template literals are ok... -// error: but only if they have no expressions -// require.call is allowed but circumverts Flow\'s static analysis + function takesANumber(num: number): void {} function takesAString(str: string): void {} + +// @providesModule var A = require(\"A\"); takesANumber(A.numberValue); takesAString(A.numberValue); + +// File path var B = require(\"./B\"); takesANumber(B.numberValue); takesAString(B.numberValue); + +// C.js exists, but not as a providesModule require(\"C\"); + +// @providesModule D exists, but not as a filename require(\"./D\"); + +// E exports an object with a numVal property var E = require(\"./E\"); var e_1: number = E.numberValue; E.stringValue; +// Error: The E exports obj has no \'stringValue\' property +// We require that the param passed to require() be a string literal to support +// guaranteed static extraction var a = \"./E\"; require(a); +// Error: Param must be string literal require(\`./E\`); +// template literals are ok... require(\`\${\"./E\"}\`); -require.call(null, \"DoesNotExist\"); -" +// error: but only if they have no expressions +// require.call is allowed but circumverts Flow\'s static analysis +require.call(null, \"DoesNotExist\");" `; diff --git a/tests/requireLazy/__snapshots__/jsfmt.spec.js.snap b/tests/requireLazy/__snapshots__/jsfmt.spec.js.snap index e80f22f7..dec020be 100644 --- a/tests/requireLazy/__snapshots__/jsfmt.spec.js.snap +++ b/tests/requireLazy/__snapshots__/jsfmt.spec.js.snap @@ -13,8 +13,8 @@ module.exports = { * @providesModule A * @flow */ -module.exports = { numberValueA: 1, stringValueA: \"someString\" }; -" + +module.exports = { numberValueA: 1, stringValueA: \"someString\" };" `; exports[`test B.js 1`] = ` @@ -32,8 +32,8 @@ module.exports = { * @providesModule B * @flow */ -module.exports = { numberValueB: 1, stringValueB: \"someString\" }; -" + +module.exports = { numberValueB: 1, stringValueB: \"someString\" };" `; exports[`test requireLazy.js 1`] = ` @@ -63,27 +63,27 @@ requireLazy([\'A\']); // Error: No calback expression /** * @flow */ -// Error: string ~> number -// Error: number ~> string -// Error: string ~> number -// Error: number ~> string -// Error: No args -// Error: Non-stringliteral args -// Error: No calback expression + requireLazy([ \"A\", \"B\" ], function(A, B) { var num1: number = A.numberValueA; var str1: string = A.stringValueA; var num2: number = A.stringValueA; + // Error: string ~> number var str2: string = A.numberValueA; + // Error: number ~> string var num3: number = B.numberValueB; var str3: string = B.stringValueB; var num4: number = B.stringValueB; - var str4: string = B.numberValueB; + // Error: string ~> number + var str4: string = B.numberValueB; // Error: number ~> string }); + var notA: Object = A; var notB: Object = B; + requireLazy(); +// Error: No args requireLazy([ nope ], function() {}); -requireLazy([ \"A\" ]); -" +// Error: Non-stringliteral args +requireLazy([ \"A\" ]); // Error: No calback expression" `; diff --git a/tests/return/__snapshots__/jsfmt.spec.js.snap b/tests/return/__snapshots__/jsfmt.spec.js.snap index 8179ff20..68d00f2b 100644 --- a/tests/return/__snapshots__/jsfmt.spec.js.snap +++ b/tests/return/__snapshots__/jsfmt.spec.js.snap @@ -36,8 +36,6 @@ module.exports = C; //function fn(x:number) { return x; } //module.exports = fn; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -//function fn(x:number) { return x; } -//module.exports = fn; class C { foo() {} bar() { @@ -47,30 +45,36 @@ class C { return x; } } + function f(x): number { if (x > 1) { return 42; } } + function g(x): ?number { if (x > 1) { return 42; } } + function h(x): number { if (x > 1) { return 42; } return; } + function i(x): ?number { if (x > 1) { return 42; } return; } + module.exports = C; -" +//function fn(x:number) { return x; } +//module.exports = fn;" `; exports[`test void.js 1`] = ` @@ -90,7 +94,6 @@ function f(b) { /* This is a regression test. At one point we incorrectly inferred the return type of functions that have an explicit \`undefined\` to be only \`undefined\` -- ignoring other possible exits. */ -// error: string ~> void function f(b) { if (b) { return undefined; @@ -98,6 +101,6 @@ function f(b) { return \"nope\"; } } -(f(true): void); -" + +(f(true): void); // error: string ~> void" `; diff --git a/tests/return_new/__snapshots__/jsfmt.spec.js.snap b/tests/return_new/__snapshots__/jsfmt.spec.js.snap index e2b52572..34bdf3e8 100644 --- a/tests/return_new/__snapshots__/jsfmt.spec.js.snap +++ b/tests/return_new/__snapshots__/jsfmt.spec.js.snap @@ -12,26 +12,24 @@ class A { } function B() { return new A(); } var a: A = new B(); // OK (returns new A) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// error (returns object literal above) -// error (returns new object) -// error (returns new object) -// OK (returns new A) function Foo() { return {}; } var foo: number = new Foo(); +// error (returns object literal above) function Bar() { return 0; } var bar: number = new Bar(); +// error (returns new object) function Qux() {} var qux: number = new Qux(); +// error (returns new object) class A {} function B() { return new A(); } -var a: A = new B(); -" +var a: A = new B(); // OK (returns new A)" `; exports[`test test2.js 1`] = ` @@ -47,13 +45,16 @@ d.x = \"\"; // error, string ~/~ number (but property x is found) module.exports = D; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// OK -// error, string ~/~ number (but property x is found) -// error, new D is an object, D not in proto chain -declare class D { constructor(): { x: number }, y: any } +declare class D { + constructor(): { x: number }, + // OK + y: any +} + var d = new D(); d.x = \"\"; +// error, string ~/~ number (but property x is found) (new D(): D); -module.exports = D; -" +// error, new D is an object, D not in proto chain +module.exports = D;" `; diff --git a/tests/seal/__snapshots__/jsfmt.spec.js.snap b/tests/seal/__snapshots__/jsfmt.spec.js.snap index a6fc1d18..4ffd11f0 100644 --- a/tests/seal/__snapshots__/jsfmt.spec.js.snap +++ b/tests/seal/__snapshots__/jsfmt.spec.js.snap @@ -5,9 +5,9 @@ var imp = require(\'./obj_annot\'); imp({ name: \"imp\" }); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + var imp = require(\"./obj_annot\"); -imp({ name: \"imp\" }); -" +imp({ name: \"imp\" });" `; exports[`test obj_annot.js 1`] = ` @@ -22,10 +22,12 @@ foo({ name: \"test\" }); module.exports = foo; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + function foo(param: { name: string }): number { return param.id; } + foo({ name: \"test\" }); -module.exports = foo; -" + +module.exports = foo;" `; diff --git a/tests/sealed/__snapshots__/jsfmt.spec.js.snap b/tests/sealed/__snapshots__/jsfmt.spec.js.snap index 0123ba78..e82791a9 100644 --- a/tests/sealed/__snapshots__/jsfmt.spec.js.snap +++ b/tests/sealed/__snapshots__/jsfmt.spec.js.snap @@ -10,6 +10,7 @@ Bar.prototype.getY = function(): string { return this.y; } module.exports = Bar; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + function Bar(x: number) { this.x = x; } @@ -19,8 +20,8 @@ Bar.prototype.getX = function() { Bar.prototype.getY = function(): string { return this.y; }; -module.exports = Bar; -" + +module.exports = Bar;" `; exports[`test proto.js 1`] = ` @@ -39,23 +40,26 @@ var export_o: { x:any; } = o; // awkward type cast module.exports = export_o; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// awkward type cast function Foo() {} var o = new Foo(); var x: number = o.x; + Foo.prototype.m = function() { return this.x; }; + var y: number = o.m(); o.x = \"...\"; + Foo.prototype = { m: function() { return false; } }; + var export_o: { x: any } = o; -module.exports = export_o; -" +// awkward type cast +module.exports = export_o;" `; exports[`test sealed.js 1`] = ` @@ -71,15 +75,16 @@ a.y = \'abc\'; // error, needs to be declared in Bar\'s constructor (a.getX(): number); (a.getY(): string); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// error, needs to be declared in Bar\'s constructor var o = require(\"./proto\"); + o.z = 0; var x: string = o.x; + var Bar = require(\"./function\"); var a = new Bar(234); a.x = 123; a.y = \"abc\"; +// error, needs to be declared in Bar\'s constructor (a.getX(): number); -(a.getY(): string); -" +(a.getY(): string);" `; diff --git a/tests/sealed_objects/__snapshots__/jsfmt.spec.js.snap b/tests/sealed_objects/__snapshots__/jsfmt.spec.js.snap index 3e77de11..52b1dd95 100644 --- a/tests/sealed_objects/__snapshots__/jsfmt.spec.js.snap +++ b/tests/sealed_objects/__snapshots__/jsfmt.spec.js.snap @@ -19,28 +19,26 @@ var s6: string = o6.y; // ok (indexers make object types extensible) var o7: { x: number; y?: string; } = ({ x: 0, y: 0 }: { x: number; [_:any]:number}); // error ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// error -// ok -// error -// ok -// ok (spreads make object types extensible) -// ok (indexers make object types extensible) -// error var o1 = { x: 0 }; var s1: string = o1.y; +// error var o2: { x: number, y?: string } = { x: 0 }; var s2: string = o2.y || \"\"; +// ok var o3: { x: number, y?: string } = ({ x: 0, y: 0 }: { x: number }); var s3: string = o3.y || \"\"; +// error var o4: { x: number, y?: string } = ({ x: 0 }: { [_: any]: any, x: number }); var s4: string = o4.y || \"\"; +// ok var o5 = { x: 0, ...{} }; var s5: string = o5.y; +// ok (spreads make object types extensible) var o6: { [_: any]: any, x: number } = { x: 0 }; var s6: string = o6.y; +// ok (indexers make object types extensible) var o7: { x: number, y?: string } = ({ x: 0, y: 0 }: { [_: any]: number, x: number -}); -" +}); // error" `; diff --git a/tests/shape/__snapshots__/jsfmt.spec.js.snap b/tests/shape/__snapshots__/jsfmt.spec.js.snap index 421bf828..16e529ea 100644 --- a/tests/shape/__snapshots__/jsfmt.spec.js.snap +++ b/tests/shape/__snapshots__/jsfmt.spec.js.snap @@ -8,8 +8,8 @@ var y: $Shape = x; (y.field: number) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ type Foo = { field: number }; + var x: { field?: number } = {}; var y: $Shape = x; -(y.field: number); -" +(y.field: number);" `; diff --git a/tests/simple_arrays/__snapshots__/jsfmt.spec.js.snap b/tests/simple_arrays/__snapshots__/jsfmt.spec.js.snap index 3090fcfd..e6c91f98 100644 --- a/tests/simple_arrays/__snapshots__/jsfmt.spec.js.snap +++ b/tests/simple_arrays/__snapshots__/jsfmt.spec.js.snap @@ -21,13 +21,6 @@ bar(0); function baz(i:number): string { return a[i]; } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// \`i\` never gets a lower bound, so the array access is stalled until the -// function is called. -// here, because we call \`bar\`, we the array access constraint is discharged and -// we realize a type error. -// annotations suffice to unblock the access constraint as well, so only -// uncalled internal functions will not find a type error, which is acceptable -// behavior as such functions are dead code. var a = []; for (var i = 0; i < 10; ++i) { if (i % 2 == 0) { @@ -35,18 +28,28 @@ for (var i = 0; i < 10; ++i) { } else { a[i] = \"\"; } + } + +// \`i\` never gets a lower bound, so the array access is stalled until the +// function is called. function foo(i): string { return a[i]; } + +// here, because we call \`bar\`, we the array access constraint is discharged and +// we realize a type error. function bar(i): string { return a[i]; } bar(0); + +// annotations suffice to unblock the access constraint as well, so only +// uncalled internal functions will not find a type error, which is acceptable +// behavior as such functions are dead code. function baz(i: number): string { return a[i]; -} -" +}" `; exports[`test array2.js 1`] = ` @@ -67,9 +70,10 @@ for (var i = 0; i < 10; ++i) { } else { a[i] = \"\"; } + } + function foo(i: number): string { return a[i]; -} -" +}" `; diff --git a/tests/singleton/__snapshots__/jsfmt.spec.js.snap b/tests/singleton/__snapshots__/jsfmt.spec.js.snap index 3dd6356d..3b6e7ae4 100644 --- a/tests/singleton/__snapshots__/jsfmt.spec.js.snap +++ b/tests/singleton/__snapshots__/jsfmt.spec.js.snap @@ -38,21 +38,23 @@ function alwaysFalsy(x: boolean): false { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// error -// test bool conversion -// error -// error + function veryOptimistic(isThisAwesome: true): boolean { return isThisAwesome; } + var x: boolean = veryOptimistic(true); var y: boolean = veryOptimistic(false); +// error function veryPessimistic(isThisAwesome: true): boolean { - return !isThisAwesome; + return !isThisAwesome; // test bool conversion } + var x: boolean = veryPessimistic(true); var y: boolean = veryPessimistic(false); +// error type MyOwnBooleanLOL = true | false; + function bar(x: MyOwnBooleanLOL): false { if (x) { return x; @@ -60,17 +62,18 @@ function bar(x: MyOwnBooleanLOL): false { return !x; } } + bar(true); bar(false); bar(1); +// error function alwaysFalsy(x: boolean): false { if (x) { return !x; } else { return x; } -} -" +}" `; exports[`test number.js 1`] = ` @@ -99,25 +102,27 @@ function sort(fn: (x: any, y: any) => ComparatorResult) {} sort((x, y) => -1); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// there can be only one! -// error -// error + function highlander(howMany: 1): number { - return howMany; + return howMany; // there can be only one! } + highlander(1); highlander(2); +// error type Foo = 1 | 2; + function bar(num: Foo): number { return num + 1; } + bar(1); bar(2); bar(3); +// error type ComparatorResult = -1 | 0 | 1; function sort(fn: (x: any, y: any) => ComparatorResult) {} -sort((x, y) => -1); -" +sort((x, y) => -1);" `; exports[`test string.js 1`] = ` @@ -130,9 +135,10 @@ type HasSpaces = \"foo bar\" (\"foo bar\": HasSpaces); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + type NoSpaces = \"foobar\"; (\"foobar\": NoSpaces); + type HasSpaces = \"foo bar\"; -(\"foo bar\": HasSpaces); -" +(\"foo bar\": HasSpaces);" `; diff --git a/tests/spread/__snapshots__/jsfmt.spec.js.snap b/tests/spread/__snapshots__/jsfmt.spec.js.snap index 76fd2b49..506e7b77 100644 --- a/tests/spread/__snapshots__/jsfmt.spec.js.snap +++ b/tests/spread/__snapshots__/jsfmt.spec.js.snap @@ -33,9 +33,11 @@ function parseTimeframe(line: string): { begin: number; end: number } { function parseTimestamp(timestamp: string): number { return 0; } + function parseCounter(line: string): number { return 0; } + function parseGroup( lines: Array ): { counter: number, begin: number, end: number, text: string } { @@ -43,14 +45,14 @@ function parseGroup( var timeframe = parseTimeframe(lines[1]); return { counter, ...timeframe, text: lines[2] }; } + function parseTimeframe(line: string): { begin: number, end: number } { var timestamps = line.split(\"-->\"); return { begin: parseTimestamp(timestamps[0].trim()), end: parseTimestamp(timestamps[1].trim()) }; -} -" +}" `; exports[`test test2.js 1`] = ` @@ -67,12 +69,12 @@ foo({foo: 42}); /** * @flow */ + function foo(o) { bar({ ...o }); } function bar(_: { foo: number }) {} -foo({ foo: 42 }); -" +foo({ foo: 42 });" `; exports[`test test3.js 1`] = ` @@ -94,17 +96,16 @@ var s = { }; var t: boolean = s.y; // error, string or number ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// test conflicting keys (they get unioned) -// error, string or number var p = { y: \"\" }; var q = { z: \"\" }; var o = { x: 5, ...p, ...q }; var y: number = o.y; var z: number = o.z; + +// test conflicting keys (they get unioned) var r = { y: 123 }; var s = { ...p, ...r }; -var t: boolean = s.y; -" +var t: boolean = s.y; // error, string or number" `; exports[`test test4.js 1`] = ` @@ -115,8 +116,8 @@ test(0, ...[1, 2, 3]); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ function test(...nums: Array) {} -test(0, ...[ 1, 2, 3 ]); -" + +test(0, ...[ 1, 2, 3 ]);" `; exports[`test test5.js 1`] = ` @@ -147,27 +148,28 @@ function test( } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + +declare function map( + obj: { [key: string]: Tv }, + iterator: (obj: Tv) => TNext +): Array; + /** * Tests overriding a property via a spread, where the value is a tvar. the * type of the prop from the object that is being overridden (\`x.kind\` in the * case below) should //not// feed back into the tvar (\`value\`), since the * result is a new object. */ -// OK -declare function map( - obj: { [key: string]: Tv }, - iterator: (obj: Tv) => TNext -): Array; function test( x: { kind: ?string }, kinds: { [key: string]: string } ): Array<{ kind: ?string }> { return map(kinds, value => { (value: string); + // OK return { ...x, kind: value }; }); -} -" +}" `; exports[`test test6.js 1`] = ` @@ -192,20 +194,21 @@ for (var i = 0; i < 10; i++) { } (q: {foo: string}); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// error, p doesn\'t have \`abc\` yet var o = { foo: \"bar\" }; o = { ...o }; (o: { foo: string }); + var p = { foo: \"bar\" }; (p: { foo: string, abc: string }); +// error, p doesn\'t have \`abc\` yet p = { ...p, abc: \"def\" }; (p: { foo: string, abc: string }); + var q = { foo: \"bar\" }; for (var i = 0; i < 10; i++) { q = { ...q }; } -(q: { foo: string }); -" +(q: { foo: string });" `; exports[`test test7.js 1`] = ` @@ -219,12 +222,11 @@ let tests = [ ]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// error, Object + let tests = [ function(x: Object) { ({ ...x }: Object); - ({ ...x }: void); + ({ ...x }: void); // error, Object } -]; -" +];" `; diff --git a/tests/static_overload/__snapshots__/jsfmt.spec.js.snap b/tests/static_overload/__snapshots__/jsfmt.spec.js.snap index c48e3d0b..21b99ca6 100644 --- a/tests/static_overload/__snapshots__/jsfmt.spec.js.snap +++ b/tests/static_overload/__snapshots__/jsfmt.spec.js.snap @@ -1,6 +1,5 @@ exports[`test test.js 1`] = ` "var x: number = StaticOverload.foo(0); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -var x: number = StaticOverload.foo(0); -" +var x: number = StaticOverload.foo(0);" `; diff --git a/tests/static_overload/lib/__snapshots__/jsfmt.spec.js.snap b/tests/static_overload/lib/__snapshots__/jsfmt.spec.js.snap index 1197e85c..f9943c12 100644 --- a/tests/static_overload/lib/__snapshots__/jsfmt.spec.js.snap +++ b/tests/static_overload/lib/__snapshots__/jsfmt.spec.js.snap @@ -7,6 +7,5 @@ exports[`test lib.js 1`] = ` declare class StaticOverload { static foo(x: number): number, static foo(x: string): string -} -" +}" `; diff --git a/tests/statics/__snapshots__/jsfmt.spec.js.snap b/tests/statics/__snapshots__/jsfmt.spec.js.snap index ee746b8f..f566f8e1 100644 --- a/tests/statics/__snapshots__/jsfmt.spec.js.snap +++ b/tests/statics/__snapshots__/jsfmt.spec.js.snap @@ -13,13 +13,14 @@ class C { static f(x: number) {} static x: string; } + C.g = function(x: string) { C.f(x); }; C.g(0); + var x: number = C.x; -C.x = 0; -" +C.x = 0;" `; exports[`test funstatics.js 1`] = ` @@ -36,6 +37,6 @@ C.prototype.f = function() { C.g = function(x) { return x; }; -var x: string = new C().f(); -" + +var x: string = new C().f();" `; diff --git a/tests/strict/__snapshots__/jsfmt.spec.js.snap b/tests/strict/__snapshots__/jsfmt.spec.js.snap index 95f78003..c8a521c0 100644 --- a/tests/strict/__snapshots__/jsfmt.spec.js.snap +++ b/tests/strict/__snapshots__/jsfmt.spec.js.snap @@ -10,6 +10,7 @@ class B extends A { module.exports = B; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ var A = require(\"./unknown_class\"); + class B extends A { foo(x: A): A { return x; @@ -19,8 +20,8 @@ class B extends A { return x; } } -module.exports = B; -" + +module.exports = B;" `; exports[`test fun.js 1`] = ` @@ -41,15 +42,17 @@ module.exports = f; /** * @flow */ + // progressively annotate: + //function f(x) { return x; } -//function f(x:number):string { return x; } function f(x: number) { return x; } +//function f(x:number):string { return x; } var x: string = f(0); -module.exports = f; -" + +module.exports = f;" `; exports[`test obj.js 1`] = ` @@ -69,10 +72,12 @@ module.exports = o; /** * @flow */ + // progressively annotate: -//var o: {x: number;} = { x: 0 } + var o = { x: 0 }; +//var o: {x: number;} = { x: 0 } var x: string = o.x; -module.exports = o; -" + +module.exports = o;" `; diff --git a/tests/strict_requires/__snapshots__/jsfmt.spec.js.snap b/tests/strict_requires/__snapshots__/jsfmt.spec.js.snap index c7ecb582..780e0231 100644 --- a/tests/strict_requires/__snapshots__/jsfmt.spec.js.snap +++ b/tests/strict_requires/__snapshots__/jsfmt.spec.js.snap @@ -3,8 +3,7 @@ exports[`test A.js 1`] = ` module.exports = 0; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -module.exports = 0; -" +module.exports = 0;" `; exports[`test B.js 1`] = ` @@ -12,8 +11,7 @@ exports[`test B.js 1`] = ` module.exports = { foo: \"\" } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -module.exports = { foo: \"\" }; -" +module.exports = { foo: \"\" };" `; exports[`test C.js 1`] = ` @@ -26,8 +24,7 @@ module.exports = o; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ var o = { A: require(\"./A\"), ...require(\"./B\") }; -module.exports = o; -" +module.exports = o;" `; exports[`test D.js 1`] = ` @@ -41,6 +38,5 @@ C.A = false; var C = require(\"./C\"); var x: number = C.foo; var y: string = C.A; -C.A = false; -" +C.A = false;" `; diff --git a/tests/strings/__snapshots__/jsfmt.spec.js.snap b/tests/strings/__snapshots__/jsfmt.spec.js.snap index 3c0c0783..2aa593f9 100644 --- a/tests/strings/__snapshots__/jsfmt.spec.js.snap +++ b/tests/strings/__snapshots__/jsfmt.spec.js.snap @@ -23,18 +23,23 @@ exports[`test strings.js 1`] = ` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \"abc\"; \"abc\"; + \"\'\"; + \"\\\"\"; \"\\\"\"; \"\\\\\\\"\"; + \"\'\"; \"\'\"; \"\\\\\'\"; + \"\'\\\"\"; \"\'\\\"\"; + \"\\\\\"; \"\\\\\"; + \"\\u0000\"; -\"🐶\"; -" +\"🐶\";" `; diff --git a/tests/structural_subtyping/__snapshots__/jsfmt.spec.js.snap b/tests/structural_subtyping/__snapshots__/jsfmt.spec.js.snap index 2a63f7cc..217adf85 100644 --- a/tests/structural_subtyping/__snapshots__/jsfmt.spec.js.snap +++ b/tests/structural_subtyping/__snapshots__/jsfmt.spec.js.snap @@ -15,14 +15,14 @@ var lengthTest4: IHasLength = true; // bool doesn\'t have length /** * @flow */ -// number doesn\'t have length -// bool doesn\'t have length + interface IHasLength { length: number } + var lengthTest1: IHasLength = []; var lengthTest2: IHasLength = \"hello\"; var lengthTest3: IHasLength = 123; -var lengthTest4: IHasLength = true; -" +// number doesn\'t have length +var lengthTest4: IHasLength = true; // bool doesn\'t have length" `; exports[`test class.js 1`] = ` @@ -53,18 +53,21 @@ var testInstance3: IHasYString = new ClassWithXString(); // Error missing prop /** * @flow */ -// Error wrong type -// Error missing prop + class ClassWithXString { x: string; } + interface IHasXString { x: string } + interface IHasXNumber { x: number } + interface IHasYString { y: string } + var testInstance1: IHasXString = new ClassWithXString(); var testInstance2: IHasXNumber = new ClassWithXString(); -var testInstance3: IHasYString = new ClassWithXString(); -" +// Error wrong type +var testInstance3: IHasYString = new ClassWithXString(); // Error missing prop" `; exports[`test obj.js 1`] = ` @@ -92,22 +95,23 @@ function propTest6(y: {[key: string]: number}) { /** * @flow */ -// Error string != number -// Property not found -// OK -// error: string != number + interface IHasXString { x: string } + var propTest1: IHasXString = { x: \"hello\" }; var propTest2: IHasXString = { x: 123 }; +// Error string != number var propTest3: IHasXString = {}; +// Property not found var propTest4: IHasXString = ({}: Object); + function propTest5(y: { [key: string]: string }) { - (y: IHasXString); + (y: IHasXString); // OK } + function propTest6(y: { [key: string]: number }) { - (y: IHasXString); -} -" + (y: IHasXString); // error: string != number +}" `; exports[`test optional.js 1`] = ` @@ -125,11 +129,12 @@ var test2: HasOptional = {}; // Error: missing property a var test3: HasOptional = { a: \"hello\", b: true }; // Error: boolean ~> number ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// Error: missing property a -// Error: boolean ~> number + interface HasOptional { a: string, b?: number } + var test1: HasOptional = { a: \"hello\" }; + var test2: HasOptional = {}; -var test3: HasOptional = { a: \"hello\", b: true }; -" +// Error: missing property a +var test3: HasOptional = { a: \"hello\", b: true }; // Error: boolean ~> number" `; diff --git a/tests/suggest/__snapshots__/jsfmt.spec.js.snap b/tests/suggest/__snapshots__/jsfmt.spec.js.snap index 3e4009b9..1e3dbae8 100644 --- a/tests/suggest/__snapshots__/jsfmt.spec.js.snap +++ b/tests/suggest/__snapshots__/jsfmt.spec.js.snap @@ -6,11 +6,12 @@ function bar(w: number): number { return w; } module.exports = bar; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + function bar(w: number): number { return w; } -module.exports = bar; -" + +module.exports = bar;" `; exports[`test suggest.js 1`] = ` @@ -26,12 +27,15 @@ array; module.exports = {foo:foo}; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + var bar = require(\"./lib\"); + function foo(z: number) { return bar(z); } + var array = [ \"foo\", \"bar\" ]; array; -module.exports = { foo: foo }; -" + +module.exports = { foo: foo };" `; diff --git a/tests/super/__snapshots__/jsfmt.spec.js.snap b/tests/super/__snapshots__/jsfmt.spec.js.snap index 2271b049..0b0a5fbe 100644 --- a/tests/super/__snapshots__/jsfmt.spec.js.snap +++ b/tests/super/__snapshots__/jsfmt.spec.js.snap @@ -154,76 +154,60 @@ class N extends N_ { (new N_(): N_); (new N(): N); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// OK -// error (no super call) -// error (no super call) -// OK -// OK -// error -// error -// error (no super call yet) -// error (no super call) -// OK -// OK -// error (no super call yet) -// error (no super call yet) -// The reason for this error is that super constructor could call the -// closure and therefore access this before calling its own super -// constructor (as shown above). The only safe thing to do in the super -// constructor is to save the closure so that it can be called later, after -// initialization is done (as shown below). -// OK -// even though super() calls the parent\'s constructor(), it does not do the same -// conversion on non-objects. so \`new L_()\` returns an instance of \`L_\` because -// the constructor returns false (a non-object), but \`super()\` returns false, -// which then similarly causes \`new L()\` to return an instance of \`L\`. -// similarly, the converse is true: if the parent\'s constructor returns an -// object, then the child does too. -// however! super() calls the parent constructor with the subclass as its \`this\` -// value (essentially \`super.constructor.call(this)\`). class A { x: number; } + class B { x: number; constructor() { - this.x; + this.x; // OK } } + class C extends A {} + class D extends A { y: number; constructor() { this.y; - this.x; + // error (no super call) + this.x; // error (no super call) } } + class E extends A { y: number; constructor() { super(); this.y; - this.x; + // OK + this.x; // OK } } + function leak(f) { f.y; - f.x; + // error + f.x; // error } class F extends A { y: number; constructor() { leak(this); + // error (no super call yet) super(); this.y; this.x; } } + class G extends A { constructor(b) { - super.x; + super.x; // error (no super call) } } + class H extends A { y: number; constructor() { @@ -232,9 +216,11 @@ class H extends A { else super(); this.y; - this.x; + // OK + this.x; // OK } } + class I_ { constructor(leaked_this) { leaked_this.foo(); @@ -243,9 +229,10 @@ class I_ { } class I extends I_ { constructor() { - super(this); + super(this); // error (no super call yet) } } + class J__ {} class J_ extends J__ { constructor(closure_leaking_this) { @@ -256,9 +243,15 @@ class J_ extends J__ { } class J extends J_ { constructor() { - super(() => this.foo()); + super(() => this.foo()); // error (no super call yet) + // The reason for this error is that super constructor could call the + // closure and therefore access this before calling its own super + // constructor (as shown above). The only safe thing to do in the super + // constructor is to save the closure so that it can be called later, after + // initialization is done (as shown below). } } + class K_ { closure_leaking_this: () => void; constructor(closure_leaking_this) { @@ -272,10 +265,16 @@ class K extends K_ { if (_this) _this.foo(); }); + // OK var _this = this; this.closure_leaking_this(); } } + +// even though super() calls the parent\'s constructor(), it does not do the same +// conversion on non-objects. so \`new L_()\` returns an instance of \`L_\` because +// the constructor returns false (a non-object), but \`super()\` returns false, +// which then similarly causes \`new L()\` to return an instance of \`L\`. class L_ { constructor() { return false; @@ -289,6 +288,9 @@ class L extends L_ { } (new L_(): L_); (new L(): L); + +// similarly, the converse is true: if the parent\'s constructor returns an +// object, then the child does too. class M_ { constructor() { return { foo: \"foo\" }; @@ -301,6 +303,9 @@ class M extends M_ { } (new M_(): { foo: string }); (new M(): { foo: string }); + +// however! super() calls the parent constructor with the subclass as its \`this\` +// value (essentially \`super.constructor.call(this)\`). class N_ { constructor(): this { let x = this; @@ -313,8 +318,7 @@ class N extends N_ { } } (new N_(): N_); -(new N(): N); -" +(new N(): N);" `; exports[`test import.js 1`] = ` @@ -328,8 +332,7 @@ class D { return 0; } } -module.exports = D; -" +module.exports = D;" `; exports[`test super.js 1`] = ` @@ -356,8 +359,6 @@ class B extends A { } } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// error, string !~> number -// error, A doesn\'t have a doesntExist method class A { constructor(x: number) {} static staticMethod(x: string): string { @@ -365,20 +366,23 @@ class A { } f(x: string) {} } + class B extends A { constructor(x: string, y: number) { super(x); } + static anotherStatic() { (super.staticMethod(\"foo\"): number); - super.doesntExist(); + // error, string !~> number + super.doesntExist(); // error, A doesn\'t have a doesntExist method } + g() { super.f(0); return super.g; } -} -" +}" `; exports[`test test.js 1`] = ` @@ -398,6 +402,5 @@ class C extends D { return super.foo(); } } -module.exports = C; -" +module.exports = C;" `; diff --git a/tests/suppress/__snapshots__/jsfmt.spec.js.snap b/tests/suppress/__snapshots__/jsfmt.spec.js.snap index dcc945d8..1c1bb3fb 100644 --- a/tests/suppress/__snapshots__/jsfmt.spec.js.snap +++ b/tests/suppress/__snapshots__/jsfmt.spec.js.snap @@ -25,28 +25,28 @@ var test5: string = 123; // This error should be suppressed var test6: string = 123; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // $FlowFixMe +var test1: string = 123; // This error should be suppressed // $FlowIssue +var test2: string = 123; // This error should be suppressed +function getNum() { + return 123; +} + // $FlowFixMe This was the second loc in the error +var test3: string = getNum(); // This error should be suppressed // $FlowFixMe Error unused suppression +var test4: string = 123; // This error is NOT suppressed // $FlowFixMe Indentation shouldn\'t matter +var test5: string = 123; // This error should be suppressed /* * $FlowNewLine */ -var test1: string = 123; -var test2: string = 123; -function getNum() { - return 123; -} -var test3: string = getNum(); -var test4: string = 123; -var test5: string = 123; -var test6: string = 123; -" +var test6: string = 123;" `; exports[`test B.js 1`] = ` @@ -54,8 +54,7 @@ exports[`test B.js 1`] = ` var test1: string = library_num; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // $FlowFixMe -var test1: string = library_num; -" +var test1: string = library_num;" `; exports[`test C.js 1`] = ` @@ -68,17 +67,18 @@ function runTest(y: number): void { ); } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -/* $FlowFixMe - suppressing the error op location should also work */ function takesAString(x: string): void {} + function runTest(y: number): void { - takesAString(y); -} -" + takesAString( + /* $FlowFixMe - suppressing the error op location should also work */ + y + ); +}" `; exports[`test lib.js 1`] = ` "declare var library_num: number; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -declare var library_num: number; -" +declare var library_num: number;" `; diff --git a/tests/suppress_incremental/__snapshots__/jsfmt.spec.js.snap b/tests/suppress_incremental/__snapshots__/jsfmt.spec.js.snap index eb12712c..4bbbe76b 100644 --- a/tests/suppress_incremental/__snapshots__/jsfmt.spec.js.snap +++ b/tests/suppress_incremental/__snapshots__/jsfmt.spec.js.snap @@ -4,7 +4,6 @@ exports[`test test.js 1`] = ` (123: number); // no errors ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// no errors -(123: number); -" + +(123: number); // no errors" `; diff --git a/tests/suppress_traces/__snapshots__/jsfmt.spec.js.snap b/tests/suppress_traces/__snapshots__/jsfmt.spec.js.snap index ade0d0ba..39749504 100644 --- a/tests/suppress_traces/__snapshots__/jsfmt.spec.js.snap +++ b/tests/suppress_traces/__snapshots__/jsfmt.spec.js.snap @@ -21,14 +21,15 @@ var a: string = foo(\'hi\'); // error number ~> string * sure that we don\'t suppress the error due to a location that only shows up * when --traces is turned on. */ + // $FlowFixMe - Error unused suppression -// error number ~> string function bar(): number { return 5; } + function foo(x: string) { return bar(); } -var a: string = foo(\"hi\"); -" + +var a: string = foo(\"hi\"); // error number ~> string" `; diff --git a/tests/switch/__snapshots__/jsfmt.spec.js.snap b/tests/switch/__snapshots__/jsfmt.spec.js.snap index 4c4e95c7..f54ba636 100644 --- a/tests/switch/__snapshots__/jsfmt.spec.js.snap +++ b/tests/switch/__snapshots__/jsfmt.spec.js.snap @@ -27,6 +27,7 @@ function baz(x): number { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + function foo(x): number { switch (x) { case 0: @@ -36,6 +37,7 @@ function foo(x): number { throw new Error(\"hi\"); } } + function bar(x) { switch (x) { case 0: @@ -45,6 +47,7 @@ function bar(x) { } 1; } + function baz(x): number { switch (x) { case 0: @@ -55,8 +58,7 @@ function baz(x): number { throw new Error(\"hi\"); } return 2; -} -" +}" `; exports[`test switch.js 1`] = ` @@ -101,6 +103,7 @@ function foo(): number { } return 2; } + function bar() { switch (\"bar\") { case \"bar\": @@ -109,6 +112,7 @@ function bar() { break; } } + function qux(b) { var x = b ? 0 : \"\"; switch (\"qux\") { @@ -117,8 +121,7 @@ function qux(b) { case \"qux\": x = x * x; } -} -" +}" `; exports[`test switch_default_fallthrough.js 1`] = ` @@ -173,36 +176,32 @@ function baz(x: mixed): number { /** * @flow */ -// a is now string | number -// error, string | number ~/> string -// error, string | number ~/> number -// b is now number -// ok -// error, number ~/> string -// a is now string | number -// error, string | number ~/> string -// error, string | number ~/> number -// b is now string | number -// error, string | number ~/> string -// error, string | number ~/> number -// error, string ~/> number function foo(x: mixed): string { var a = \"\"; var b = \"\"; + switch (x) { case \"foo\": a = 0; default: b = 0; } + + // a is now string | number (a: string); + // error, string | number ~/> string (a: number); + // error, string | number ~/> number + // b is now number (b: number); - return b; + // ok + return b; // error, number ~/> string } + function baz(x: mixed): number { var a = \"\"; var b = \"\"; + switch (x) { case \"baz\": a = 0; @@ -212,13 +211,19 @@ function baz(x: mixed): number { default: b = 0; } + + // a is now string | number (a: string); + // error, string | number ~/> string (a: number); + // error, string | number ~/> number + // b is now string | number (b: string); + // error, string | number ~/> string (b: number); - return a + b; -} -" + // error, string | number ~/> number + return a + b; // error, string ~/> number +}" `; exports[`test trailing_cases.js 1`] = ` @@ -307,13 +312,9 @@ function baz(x): number { * trailing cases are allowed - spot checks that we handle them as usual * @flow */ -// error, number | string ~/> number -// does not fall through default -// error, number | uninitialized ~/> number -// falls through to subsequent cases -// no error function f1(i) { var x; + switch (i) { case 0: x = 0; @@ -328,31 +329,41 @@ function f1(i) { x = \"2\"; break; } - var y: number = x; + + var y: number = x; // error, number | string ~/> number } + function f2(i) { var x; + switch (i) { case 0: case 1: default: x = 1; break; + // does not fall through default case 2: } - var y: number = x; + + var y: number = x; // error, number | uninitialized ~/> number } + function f3(i) { var x; + switch (i) { case 0: case 1: default: + // falls through to subsequent cases case 2: x = 1; } - var y: number = x; + + var y: number = x; // no error } + function foo(x): number { switch (x) { case 0: @@ -362,6 +373,7 @@ function foo(x): number { return 1; } } + function bar(x) { switch (x) { default: @@ -371,6 +383,7 @@ function bar(x) { } 1; } + function baz(x): number { switch (x) { case 0: @@ -381,6 +394,5 @@ function baz(x): number { return 1; } return 2; -} -" +}" `; diff --git a/tests/symbol/__snapshots__/jsfmt.spec.js.snap b/tests/symbol/__snapshots__/jsfmt.spec.js.snap index 2cdbfa06..b0ee23d9 100644 --- a/tests/symbol/__snapshots__/jsfmt.spec.js.snap +++ b/tests/symbol/__snapshots__/jsfmt.spec.js.snap @@ -5,9 +5,9 @@ var BAR = Symbol(\'bar\'); // TODO: Expected error var WAT = Symbol(\'foo\', \'bar\'); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// TODO: Expected error var FOO = Symbol(); var BAR = Symbol(\"bar\"); -var WAT = Symbol(\"foo\", \"bar\"); -" + +// TODO: Expected error +var WAT = Symbol(\"foo\", \"bar\");" `; diff --git a/tests/symlink/__snapshots__/jsfmt.spec.js.snap b/tests/symlink/__snapshots__/jsfmt.spec.js.snap index 01e98a10..bc6d4ceb 100644 --- a/tests/symlink/__snapshots__/jsfmt.spec.js.snap +++ b/tests/symlink/__snapshots__/jsfmt.spec.js.snap @@ -1,15 +1,13 @@ exports[`test bar.js 1`] = ` "export type Foo = { x: number; } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -export type Foo = { x: number }; -" +export type Foo = { x: number };" `; exports[`test foo.js 1`] = ` "export type Foo = { x: number; } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -export type Foo = { x: number }; -" +export type Foo = { x: number };" `; exports[`test qux.js 1`] = ` @@ -17,6 +15,5 @@ exports[`test qux.js 1`] = ` ({ x: \"\" }: Foo); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ import type {Foo} from \"./bar.js\"; -({ x: \"\" }: Foo); -" +({ x: \"\" }: Foo);" `; diff --git a/tests/tagged-unions/__snapshots__/jsfmt.spec.js.snap b/tests/tagged-unions/__snapshots__/jsfmt.spec.js.snap index 1c32f91f..578443d5 100644 --- a/tests/tagged-unions/__snapshots__/jsfmt.spec.js.snap +++ b/tests/tagged-unions/__snapshots__/jsfmt.spec.js.snap @@ -32,15 +32,19 @@ function bar(x: Bar): string { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + class Foo { type: \"foo\"; foo: string; } + class Bar { type: \"bar\"; bar: string; } + type Foobar = Foo | Bar; + function foobar(x: Foobar): string { if (x.type === \"foo\") { return foo(x); @@ -50,13 +54,14 @@ function foobar(x: Foobar): string { return \"unknown\"; } } + function foo(x: Foo): string { return x.foo; } + function bar(x: Bar): string { return x.bar; -} -" +}" `; exports[`test interfaces-neg.js 1`] = ` @@ -88,15 +93,20 @@ if (data.kind === \"user\") { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + interface IDataBase { id: string, name: string } + interface IUserData extends IDataBase { kind: \"user\" } + interface ISystemData extends IDataBase { kind: \"system\" } + type IData = IUserData | ISystemData; + const data: IData = { id: \"\", name: \"\", kind: \"system\" }; + if (data.kind === \"user\") { (data: ISystemData); -} -" +}" `; exports[`test interfaces-pos.js 1`] = ` @@ -128,15 +138,20 @@ if (data.kind === \"system\") { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + interface IDataBase { id: string, name: string } + interface IUserData extends IDataBase { kind: \"user\" } + interface ISystemData extends IDataBase { kind: \"system\" } + type IData = IUserData | ISystemData; + const data: IData = { id: \"\", name: \"\", kind: \"system\" }; + if (data.kind === \"system\") { (data: ISystemData); -} -" +}" `; exports[`test type-decls-neg.js 1`] = ` @@ -172,15 +187,20 @@ if (data.kind === \"user\") { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + type DataBase = { id: string, name: string }; + type UserData = { id: string, name: string, kind: \"user\" }; + type SystemData = { id: string, name: string, kind: \"system\" }; + type Data = UserData | SystemData; + const data: Data = { id: \"\", name: \"\", kind: \"system\" }; + if (data.kind === \"user\") { (data: SystemData); -} -" +}" `; exports[`test type-decls-pos.js 1`] = ` @@ -216,13 +236,18 @@ if (data.kind === \"system\") { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + type DataBase = { id: string, name: string }; + type UserData = { id: string, name: string, kind: \"user\" }; + type SystemData = { id: string, name: string, kind: \"system\" }; + type Data = UserData | SystemData; + const data: Data = { id: \"\", name: \"\", kind: \"system\" }; + if (data.kind === \"system\") { (data: SystemData); -} -" +}" `; diff --git a/tests/taint/__snapshots__/jsfmt.spec.js.snap b/tests/taint/__snapshots__/jsfmt.spec.js.snap index 15da7235..b437d9e6 100644 --- a/tests/taint/__snapshots__/jsfmt.spec.js.snap +++ b/tests/taint/__snapshots__/jsfmt.spec.js.snap @@ -32,11 +32,7 @@ function f7(x : $Tainted, y : $Tainted) { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// This should cause an error. -// This should cause an error. -// This should cause an error. -// This should cause an error. -// This should cause an error. + function f(x: $Tainted, y: $Tainted) { var z: $Tainted = x + y; } @@ -46,22 +42,26 @@ function f1(x: $Tainted, y: number) { function f2(x: number, y: $Tainted) { var z: $Tainted = x + y; } +// This should cause an error. function f3(x: $Tainted, y: number) { var z: number = x + y; } +// This should cause an error. function f4(x: number, y: $Tainted) { var z: number = x + y; } +// This should cause an error. function f5(x: number, y: $Tainted) { var z: string = x + y; } +// This should cause an error. function f6(x: string, y: $Tainted) { var z: string = x + y; } +// This should cause an error. function f7(x: $Tainted, y: $Tainted) { var z: string = x + y; -} -" +}" `; exports[`test any_object.js 1`] = ` @@ -92,32 +92,29 @@ let tests = [ ]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// setting a property -// error, taint ~> any -// error, taint ~> any -// getting a property -// ok -// calling a method -// error, taint ~> any -// error, taint ~> any + let tests = [ + // setting a property function(x: $Tainted, y: string) { let obj: Object = {}; obj.foo = x; - obj[y] = x; + // error, taint ~> any + obj[y] = x; // error, taint ~> any }, + // getting a property function() { let obj: Object = { foo: \"foo\" }; - (obj.foo: $Tainted); + (obj.foo: $Tainted); // ok }, + // calling a method function(x: $Tainted) { let obj: Object = {}; obj.foo(x); + // error, taint ~> any let foo = obj.foo; - foo(x); + foo(x); // error, taint ~> any } -]; -" +];" `; exports[`test call-object-property.js 1`] = ` @@ -148,9 +145,9 @@ function f_foo3(f1 : Function, o1 : Object, o2 : {t : $Tainted}) { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// Error -// Error + function foo(x: $Tainted, o: Object) { + // Error o.f(x); } function foo1(x: $Tainted, o: { f(y: $Tainted): void }) { @@ -163,6 +160,7 @@ function foo3(x: $Tainted, o: { f(y: $Tainted): void }) { o.f(x); } function f_foo1(x: $Tainted, f: Function) { + // Error f(x); } function f_foo2(f1: Function, o: { t: $Tainted }) { @@ -170,8 +168,7 @@ function f_foo2(f1: Function, o: { t: $Tainted }) { } function f_foo3(f1: Function, o1: Object, o2: { t: $Tainted }) { f1(o1)(o2.t); -} -" +}" `; exports[`test comparator.js 1`] = ` @@ -196,23 +193,22 @@ function f3(x : $Tainted, y : string) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow // Should cause an error. -// Should cause an error. -// Should cause an error. -// Note: We allow removing Taint when two tainted -// values are compared. function f(x: $Tainted, y: $Tainted) { var z: $Tainted = x < y; } +// Should cause an error. function f1(x: string, y: $Tainted) { var z: $Tainted = x < y; } +// Should cause an error. function f2(x: $Tainted, y: number) { var z: $Tainted = x < y; } +// Note: We allow removing Taint when two tainted +// values are compared. function f3(x: $Tainted, y: string) { var z: boolean = x < y; -} -" +}" `; exports[`test function.js 1`] = ` @@ -232,19 +228,18 @@ let tests = [ ]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// flows any to each param -// error, taint ~> any -// calling \`any\` returns \`any\` + let tests = [ + // flows any to each param function(x: any, y: $Tainted) { - x(y); + x(y); // error, taint ~> any }, + // calling \`any\` returns \`any\` function(x: any, y: $Tainted) { let z = x(); z(y); } -]; -" +];" `; exports[`test globals.js 1`] = ` @@ -262,19 +257,18 @@ class A { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// error -// ok -// TODO(rcastano): should cause an error. + class A { f(x: $Tainted) { fakeDocument.location = x; - doStuff(x); + // error + doStuff(x); // ok } f1(x: $Tainted) { + // TODO(rcastano): should cause an error. window.fakeLocation = x; } -} -" +}" `; exports[`test lib.js 1`] = ` @@ -292,11 +286,13 @@ declare var fakeDocument: FakeDocument; declare var fakeLocation: FakeLocation; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ declare class FakeLocation { assign(url: string): void } + declare class FakeDocument { location: FakeLocation } + declare function doStuff(x: $Tainted): void; + declare var fakeDocument: FakeDocument; -declare var fakeLocation: FakeLocation; -" +declare var fakeLocation: FakeLocation;" `; exports[`test taint1.js 1`] = ` @@ -315,13 +311,12 @@ class A { * * @flow */ -// This shouldn\'t give a warning (both are tainted) class A { f(tainted: $Tainted) { + // This shouldn\'t give a warning (both are tainted) var also_tainted: $Tainted = tainted; } -} -" +}" `; exports[`test taint2.js 1`] = ` @@ -340,13 +335,12 @@ class A { * * @flow */ -// This *should* give a warning. class A { f(tainted: $Tainted) { + // This *should* give a warning. fakeDocument.location.assign(tainted); } -} -" +}" `; exports[`test taint3.js 1`] = ` @@ -367,15 +361,14 @@ class A { * * @flow */ -// The Tainted annotation should still flow. -// This should give a warning. class A { f(tainted: $Tainted) { + // The Tainted annotation should still flow. var safe = tainted; + // This should give a warning. var loc: string = safe; } -} -" +}" `; exports[`test taint4.js 1`] = ` @@ -397,14 +390,15 @@ function f(x : $Tainted) { * * @flow */ -// This should be allowed. -// Should cause error. + var safe: string = \"safe\"; +// This should be allowed. var tainted: $Tainted = safe; + function f(x: $Tainted) { + // Should cause error. var y: any = x; -} -" +}" `; exports[`test use-types.js 1`] = ` @@ -444,31 +438,33 @@ function foo6 (a : $Tainted>) { /* * @flow */ + // Should cause an error. -// Should cause an error. -// Should cause an error. -// Should cause an error. -// Type error. function foo(x: $Tainted) { var should_fail: number = x * 42; } +// Should cause an error. function foo1(x: $Tainted<{ f: number }>) { var ok: number = x.f; } +// Should cause an error. function foo2(o: { f(y: number): number }, t: $Tainted) { return o.f(t); } + function foo3(x: $Tainted<{ f: number }>) { var also_tainted: $Tainted = x.f; } +// Should cause an error. function foo4(a: $Tainted>) { var trusted: string = a[0]; } +// Type error. function foo5(a: $Tainted>) { var trusted_number: number = a[0]; } + function foo6(a: $Tainted>) { var trusted: $Tainted = a[0]; -} -" +}" `; diff --git a/tests/template/__snapshots__/jsfmt.spec.js.snap b/tests/template/__snapshots__/jsfmt.spec.js.snap index e7ff9907..0a238d8c 100644 --- a/tests/template/__snapshots__/jsfmt.spec.js.snap +++ b/tests/template/__snapshots__/jsfmt.spec.js.snap @@ -32,49 +32,45 @@ let tests = [ ]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// ok -// ok -// error -// ok, number can be appended to string -// error, object can\'t be appended -// ok -// ok -// ok -// ok -// ok -// ok -// error -// error -// error -// error -// error -// error + (\`foo\`: string); +// ok (\`bar\`: \"bar\"); +// ok (\`baz\`: number); +// error \`foo \${123} bar\`; +// ok, number can be appended to string \`foo \${{ bar: 123 }} baz\`; +// error, object can\'t be appended let tests = [ function(x: string) { \`foo \${x}\`; + // ok \`\${x} bar\`; - \`foo \${\"bar\"} \${x}\`; + // ok + \`foo \${\"bar\"} \${x}\`; // ok }, function(x: number) { \`foo \${x}\`; + // ok \`\${x} bar\`; - \`foo \${\"bar\"} \${x}\`; + // ok + \`foo \${\"bar\"} \${x}\`; // ok }, function(x: boolean) { \`foo \${x}\`; + // error \`\${x} bar\`; - \`foo \${\"bar\"} \${x}\`; + // error + \`foo \${\"bar\"} \${x}\`; // error }, function(x: mixed) { \`foo \${x}\`; + // error \`\${x} bar\`; - \`foo \${\"bar\"} \${x}\`; + // error + \`foo \${\"bar\"} \${x}\`; // error } -]; -" +];" `; diff --git a/tests/this/__snapshots__/jsfmt.spec.js.snap b/tests/this/__snapshots__/jsfmt.spec.js.snap index de16a566..a2320e3f 100644 --- a/tests/this/__snapshots__/jsfmt.spec.js.snap +++ b/tests/this/__snapshots__/jsfmt.spec.js.snap @@ -61,73 +61,79 @@ var f2_4 = f2(); // error, (global object).x module.exports = true; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @providesModule This */ -// sets o1.x to 0 -// ok by definite assignment -// setting o1.y to 0 has no effect on o2.y -// sets o3.y to 0 -// ok by definite assignment -// setting o3.y to 0 has no effect on o2.y -/* - * this bindings: - */ -/* standard functions may rebind this */ -// ok -// error, number -> string -// error, string -> number -// TODO make this error blame the call site, rather than the function body -// error, (global object).x -/* arrow functions bind this at point of definition */ -/* top level arrow functions bind this to global object */ -// error, (this:mixed).x -/* nested arrows bind enclosing this (which may itself rebind) */ -// ok -// error, number -> string -// error, string -> number -// TODO make this error blame the call site, rather than the function body -// error, (global object).x + function F() { this.x = 0; } F.prototype.m = function() { this.y = 0; }; + function foo(p: string) {} + var o1 = new F(); +// sets o1.x to 0 o1.x = \"\"; foo(o1.x); +// ok by definite assignment var o2 = new F(); o1.y = 0; o2.y = \"\"; foo(o2.y); +// setting o1.y to 0 has no effect on o2.y var o3 = new F(); o3.m(); +// sets o3.y to 0 o3.y = \"\"; foo(o3.y); +// ok by definite assignment foo(o2.y); +// setting o3.y to 0 has no effect on o2.y +/* + * this bindings: + */ +/* standard functions may rebind this */ function f1(): number { return this.x; } + var f1_1 = f1.bind({ x: 0 })(); +// ok var f1_2: string = f1.bind({ x: 0 })(); +// error, number -> string var f1_3 = f1.bind({ x: \"\" })(); +// error, string -> number +// TODO make this error blame the call site, rather than the function body var f1_4 = f1(); +// error, (global object).x +/* arrow functions bind this at point of definition */ +/* top level arrow functions bind this to global object */ var a1 = () => { return this.x; }; + var ax = a1(); +// error, (this:mixed).x +/* nested arrows bind enclosing this (which may itself rebind) */ function f2(): number { var a2 = () => { return this.x; }; return a2(); } + var f2_1 = f2.bind({ x: 0 })(); +// ok var f2_2: string = f2.bind({ x: 0 })(); +// error, number -> string var f2_3 = f2.bind({ x: \"\" })(); +// error, string -> number +// TODO make this error blame the call site, rather than the function body var f2_4 = f2(); +// error, (global object).x (this: void); -module.exports = true; -" + +module.exports = true;" `; exports[`test arrows.js 1`] = ` @@ -159,42 +165,38 @@ class F extends E { } } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// OK, since this: C -// return type is C -// OK -// OK -// OK -// error, since return type of bar is C, not the type of \`this\` -// OK to override with generalization -// find super method, error due to incorrect arg class C { foo() { return () => { return this.bar(); - }; + }; // OK, since this: C } bar() { return this; - } + } // return type is C } var c = new C(); var f = c.foo(); var i = f(); +// OK (i: C); +// OK class D extends C {} var d = new D(); var g = d.foo(); var j = g(); +// OK (j: D); +// error, since return type of bar is C, not the type of \`this\` class E { foo(x: number) {} } class F extends E { foo() { + // OK to override with generalization (() => { - super.foo(\"\"); + super.foo(\"\"); // find super method, error due to incorrect arg })(); } -} -" +}" `; diff --git a/tests/this_ctor/__snapshots__/jsfmt.spec.js.snap b/tests/this_ctor/__snapshots__/jsfmt.spec.js.snap index e89b888d..4ad3ea3c 100644 --- a/tests/this_ctor/__snapshots__/jsfmt.spec.js.snap +++ b/tests/this_ctor/__snapshots__/jsfmt.spec.js.snap @@ -16,7 +16,6 @@ var a1 = new A(1); var a2: A = new a1.constructor(2); var a3: A = a2.clone(); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Error A ~> number class A { n: number; constructor(n: number) { @@ -26,11 +25,11 @@ class A { return new this.constructor(this.n); } badClone(): number { - return new this.constructor(this.n); + return new this.constructor(this.n); // Error A ~> number } } + var a1 = new A(1); var a2: A = new a1.constructor(2); -var a3: A = a2.clone(); -" +var a3: A = a2.clone();" `; diff --git a/tests/this_type/__snapshots__/jsfmt.spec.js.snap b/tests/this_type/__snapshots__/jsfmt.spec.js.snap index 21960c0f..e1049183 100644 --- a/tests/this_type/__snapshots__/jsfmt.spec.js.snap +++ b/tests/this_type/__snapshots__/jsfmt.spec.js.snap @@ -10,13 +10,12 @@ const Thing = class Thing { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ // issue #1191 -// error: property not found (must be declared) + const Thing = class Thing { zark() { - this.x = 123; + this.x = 123; // error: property not found (must be declared) } -}; -" +};" `; exports[`test contra.js 1`] = ` @@ -76,60 +75,65 @@ class Misc { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Counterexample with contravariant this type -// error (see below for exploit): \`this\` should only appear in -// covariant positions -// sneaky -// error: can\'t hide contravariance using a bound -// error (see above, catches hidden override) -// covariance checks on this type in invariant positions -// covariance checks on this type as type args -// Set has invariant X -// Promise has covariant X -// Generator has covariant X, covariant Y, contravariant Z + class C { - next: this; + next: this; // error (see below for exploit): \`this\` should only appear in + // covariant positions } + class D extends C {} + var d = new D(); (d: C).next = new C(); (d.next: D); +// sneaky class A { - foo(that: X) {} + foo(that: X) {} // error: can\'t hide contravariance using a bound } + class B extends A { - foo(that: Y) {} + foo(that: Y) {} // error (see above, catches hidden override) } + +// covariance checks on this type in invariant positions class Invariant { out_object(): { _: this } { return { _: this }; } in_object(_: { _: this }) {} inout_object: { _: this }; + out_array(): Array { return [ this ]; } in_array(_: Array) {} inout_array: Array; } + +// covariance checks on this type as type args class Misc { + // Set has invariant X out_set(): Set { return new Set().add(this); } in_set(_: Set) {} inout_set: Set; + + // Promise has covariant X async out_promise(): Promise { return this; } in_promise(_: Promise) {} inout_promise: Promise; + + // Generator has covariant X, covariant Y, contravariant Z *out_generator(): Generator { yield this; return this; } in_generator(_: Generator) {} inout_generator: Generator; -} -" +}" `; exports[`test export.js 1`] = ` @@ -154,6 +158,7 @@ export class A1 { return this; } } + export class A2 { foo(): this { return this; @@ -165,8 +170,8 @@ export class A2 { return x; } } -export class A3 extends A2 {} -" + +export class A3 extends A2 {}" `; exports[`test generics.js 1`] = ` @@ -179,12 +184,12 @@ class ImplicitNumber extends Implicit { arg: number; } (new ImplicitNumber().val: string) // error: number ~> string ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// error: number ~> string class Generic { clone(): Generic { return this; } } + class Implicit { arg: X; val: X; @@ -192,8 +197,8 @@ class Implicit { class ImplicitNumber extends Implicit { arg: number; } -(new ImplicitNumber().val: string); -" + +(new ImplicitNumber().val: string); // error: number ~> string" `; exports[`test import.js 1`] = ` @@ -221,34 +226,34 @@ class B3 extends A3 { ((new B3(): A2).qux(0): string); // error ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Check that imports are handled properly with this types -// error -// OK -// error -// OK -// error -// OK -// error -// error + import {A1} from \"./export\"; import type {A2} from \"./export\"; import {A3} from \"./export\"; + class B1 extends A1 { foo(): B1 { return new B1(); - } + } // error } + (new B1().bar(): B1); +// OK class B3 extends A3 { foo(): B3 { return new B3(); - } + } // error } + (new B3().bar(): B3<*>); +// OK (new B3().qux(0): string); +// error (new B3().bar(): A2<*>); +// OK ((new B3().bar(): B3): A2); -((new B3(): A2).qux(0): string); -" +// error +((new B3(): A2).qux(0): string); // error" `; exports[`test interface.js 1`] = ` @@ -274,8 +279,7 @@ function foo(c: C): I { } function bar(c: C): J { return c; -} -" +}" `; exports[`test lib_client.js 1`] = ` @@ -292,14 +296,14 @@ class C { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (new DoublyLinkedList().prev(): DoublyLinkedList); (new DoublyLinkedList().next(): DoublyLinkedList); + var MiniImmutable = require(\"mini-immutable\"); class C { map: MiniImmutable.OrderedMap; update() { this.map = this.map.set(0, \"\"); } -} -" +}" `; exports[`test self.js 1`] = ` @@ -310,22 +314,20 @@ exports[`test self.js 1`] = ` qux(): this { return this.bar(); } // OK (don\'t cascade errors) } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// return of foo is not annotated to get around -// substituting this below -// same as returning : A, so error -// OK (don\'t cascade errors) class A { foo() { return this; } + // return of foo is not annotated to get around + // substituting this below bar(): this { return new A().foo(); } + // same as returning : A, so error qux(): this { return this.bar(); - } -} -" + } // OK (don\'t cascade errors) +}" `; exports[`test statics.js 1`] = ` @@ -348,28 +350,26 @@ class B extends A { } // inherits statics method too, with \`this\` bound to the (A.make(): B); // error ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // supporting \`this\` type in statics -// factory method, whose return type \`this\` (still) -// describes instances of A or subclasses of A: the -// meaning of the \`this\` type is not changed simply by -// switching into a static context -// but in a static context, the value \`this\` is bound to -// the class, instead of instances of the class -// inherits statics method too, with \`this\` bound to the class -// OK -// OK -// OK -// error + class A { static make(): this { - return new this(); + // factory method, whose return type \`this\` (still) + // describes instances of A or subclasses of A: the + // meaning of the \`this\` type is not changed simply by + // switching into a static context + return new this(); // but in a static context, the value \`this\` is bound to + // the class, instead of instances of the class } } class B extends A {} +// inherits statics method too, with \`this\` bound to the class (A.make(): A); +// OK (B.make(): B); +// OK (B.make(): A); -(A.make(): B); -" +// OK +(A.make(): B); // error" `; exports[`test test.js 1`] = ` @@ -445,25 +445,7 @@ class InheritOverride2 extends Override2 { } (new Override2(): Base2).corge(new Base2()); // exploits error above ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Examples without \`this\` types (compare with examples below) -// OK -// OK, too -// OK (cf. error below) -// error (cf. OK below) -// OK -// error -// blame flips below -// Examples with \`this\` types (compare with examples above) -// OK -// OK, too -// error (cf. OK above) -// see exploit below -// error -// see exploit below -// error, too -// OK (cf. error above) -// OK -// exploits error above -// exploits error above + class Base { foo() { return this; @@ -471,6 +453,7 @@ class Base { qux() { return new Base(); } + bar() { return this; } @@ -478,26 +461,38 @@ class Base { return this.bar(); } } + class Inherit extends Base {} + class Override extends Base { foo() { return this; } + // OK qux() { return this; } + // OK, too bar() { return new Override(); - } + } // OK (cf. error below) } + class InheritOverride extends Override {} + (new Inherit().foo(): Base); (new Inherit().foo(): Inherit); +// error (cf. OK below) ((new Inherit(): Base).foo(): Base); (new Override().foo(): Base); (new Override().foo(): Override); +// OK ((new Override(): Base).foo(): Base); + (new InheritOverride().bar_caller(): InheritOverride); +// error +// blame flips below +// Examples with \`this\` types (compare with examples above) class Base2 { foo(): this { return this; @@ -505,37 +500,52 @@ class Base2 { qux(): Base2 { return new Base2(); } + bar(): this { return this; } bar_caller(): this { return this.bar(); } + corge(that: this) {} grault(that: Base2) {} } + class Inherit2 extends Base2 {} + class Override2 extends Base2 { foo(): this { return this; } + // OK qux(): this { return this; } + // OK, too bar(): Override2 { return new Override2(); } + // error (cf. OK above) + // see exploit below corge(that: this) {} - grault(that: this) {} + // error + // see exploit below + grault(that: this) {} // error, too } + class InheritOverride2 extends Override2 {} + (new Inherit2().foo(): Base2); (new Inherit2().foo(): Inherit2); +// OK (cf. error above) ((new Inherit2(): Base2).foo(): Base2); (new Override2().foo(): Base2); (new Override2().foo(): Override2); +// OK ((new Override2(): Base2).foo(): Base2); + (new InheritOverride2().bar_caller(): InheritOverride2); -(new Override2(): Base2).corge(new Base2()); -" +// exploits error above +(new Override2(): Base2).corge(new Base2()); // exploits error above" `; diff --git a/tests/this_type/lib/__snapshots__/jsfmt.spec.js.snap b/tests/this_type/lib/__snapshots__/jsfmt.spec.js.snap index fee1db7a..167bb14b 100644 --- a/tests/this_type/lib/__snapshots__/jsfmt.spec.js.snap +++ b/tests/this_type/lib/__snapshots__/jsfmt.spec.js.snap @@ -22,13 +22,14 @@ declare module \"mini-immutable\" { // The following declare classes use \`this\` types effectively to avoid type // errors in ../lib_client.js. If support for \`this\` types in declare classes // is disabled for perf reasons, these will produce warnings. -/* more precise than Map (see below)*/ -/* inherits set method returning OrderedMap instead of Map*/ + declare class LinkedList { next(): this } declare class DoublyLinkedList extends LinkedList { prev(): this } + declare module \"mini-immutable\" { - declare class Map { set(key: K, value: V): this } + declare class Map { + set(key: K, value: V): this /* more precise than Map (see below)*/ + } declare class OrderedMap extends Map {} -} -" +}" `; diff --git a/tests/throw/__snapshots__/jsfmt.spec.js.snap b/tests/throw/__snapshots__/jsfmt.spec.js.snap index 2ae1e197..f569336a 100644 --- a/tests/throw/__snapshots__/jsfmt.spec.js.snap +++ b/tests/throw/__snapshots__/jsfmt.spec.js.snap @@ -25,23 +25,23 @@ function h(x: number): string { /** * @flow */ -// OK to not return -// a is not null + function f(): number { - throw new Error(); + throw new Error(); // OK to not return } + function g(a: ?string) { if (a == null) { throw new Error(); } - return a * 1; + return a * 1; // a is not null } + function h(x: number): string { if (x) { return \"foo\"; } else { throw new Error(); } -} -" +}" `; diff --git a/tests/traces/__snapshots__/jsfmt.spec.js.snap b/tests/traces/__snapshots__/jsfmt.spec.js.snap index 7d8c67f4..5dd17185 100644 --- a/tests/traces/__snapshots__/jsfmt.spec.js.snap +++ b/tests/traces/__snapshots__/jsfmt.spec.js.snap @@ -21,19 +21,20 @@ function double(n) { return n * 2 } f3(double); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // arg/param type mismatch on arg 0 -// ...on arg n -// h/o call with function expr -// h/o call with function def function g0(y: string) {} function f0(x) { g0(x); } f0(0); + +// ...on arg n function g1(a: string, b: string) {} function f1(x, y) { g1(x, y); } f1(\"hey\", 0); + +// h/o call with function expr function g2(ylam: (s: string) => number) {} function f2(xlam) { g2(xlam); @@ -41,6 +42,8 @@ function f2(xlam) { f2(function(x) { return x * x; }); + +// h/o call with function def function g3(ylam: (s: string) => number) {} function f3(xlam) { g3(xlam); @@ -48,8 +51,7 @@ function f3(xlam) { function double(n) { return n * 2; } -f3(double); -" +f3(double);" `; exports[`test Traces2.js 1`] = ` @@ -74,19 +76,22 @@ function f(b): React.Element<*> { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + var React = require(\"react\"); + var A = React.createClass({ propTypes: { foo: React.PropTypes.string.isRequired } }); + var B = React.createClass({ propTypes: { bar: React.PropTypes.string.isRequired } }); + function f(b): React.Element<*> { if (b) { - return ; + return ; } else { - return ; + return ; } -} -" +}" `; diff --git a/tests/traits/__snapshots__/jsfmt.spec.js.snap b/tests/traits/__snapshots__/jsfmt.spec.js.snap index 3b9f14eb..026a3ea7 100644 --- a/tests/traits/__snapshots__/jsfmt.spec.js.snap +++ b/tests/traits/__snapshots__/jsfmt.spec.js.snap @@ -20,22 +20,26 @@ declare class Baz { ((new Foo).y: string); // error: Bar wins ((new Foo).z: number); // error: Qux wins ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -/* KeyedCollection <: Collection*/ -/* ...KeyedIterable*/ -// KeyedIterable <: Iterable -// Collection <: Iterable -// Iterable -// error: Qux wins -// error: Bar wins -// error: Qux wins declare class Foo extends Qux {} -declare class Bar extends Baz { y: T } -declare class Qux extends Baz { y: T, z: T } -declare class Baz { x: T } +declare class Bar extends Baz { + // KeyedIterable <: Iterable + y: T +} +declare class Qux extends Baz { + // Collection <: Iterable + y: T, + z: T +} +declare class Baz { + // Iterable + x: T +} + (new Foo().x: number); +// error: Qux wins (new Foo().y: string); -(new Foo().z: number); -" +// error: Bar wins +(new Foo().z: number); // error: Qux wins" `; exports[`test test2.js 1`] = ` @@ -43,6 +47,5 @@ exports[`test test2.js 1`] = ` declare class C mixins I { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ interface I {} -declare class C {} -" +declare class C {}" `; diff --git a/tests/try/__snapshots__/jsfmt.spec.js.snap b/tests/try/__snapshots__/jsfmt.spec.js.snap index 3db60317..bc20e064 100644 --- a/tests/try/__snapshots__/jsfmt.spec.js.snap +++ b/tests/try/__snapshots__/jsfmt.spec.js.snap @@ -16,6 +16,7 @@ function foo() { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + /* This test documents an issue we used to have with merging the environment of * the try block and the catch block. The error variable, when inspected and in * the presence of an abnormal, would sometimes kind of leak. It would hit an @@ -27,8 +28,7 @@ function foo() { throw error; } } -} -" +}" `; exports[`test init.js 1`] = ` @@ -191,70 +191,57 @@ function f(b) { * test initialization tracking of hoisted stuff * @flow */ + // for illustrative purposes only - Flow considers a throw possible // anywhere within a block -// local use of annotated var within try is ok -// and within catch -// but not across try/catch -// error -// or try/finally -// error -// or catch/finally -// error -// or try/catch/finally if init doesn\'t dominate -// error -// post-use ok because init dominates here -// ...but if so, suffix is not reached -// and here -// ...but if so, suffix is not reached -// and here -// ...but if so, suffix is not reached -// and here, thank you JS for the wonder that is hoisting -// ...but if so, suffix is not reached -// error if used prior to init -// error -// another non-dominated post -// error -// ditto -// error -// ditto -// error function might_throw() {} + +// local use of annotated var within try is ok function f() { try { var x: number = 0; var y: number = x; } catch (e) {} } + +// and within catch function f() { try {} catch (e) { var x: number = 0; var y: number = x; } } + +// but not across try/catch function f() { try { might_throw(); var x: number = 0; } catch (e) { - var y: number = x; + var y: number = x; // error } } + +// or try/finally function f() { try { might_throw(); var x: number = 0; } finally { - var y: number = x; + var y: number = x; // error } } + +// or catch/finally function f() { try {} catch (e) { var x: number = 0; } finally { - var y: number = x; + var y: number = x; // error } } + +// or try/catch/finally if init doesn\'t dominate function f() { try { var x: number = 0; @@ -262,61 +249,82 @@ function f() { might_throw(); var x: number = 0; } finally { - var y: number = x; + var y: number = x; // error } } + +// post-use ok because init dominates here function f() { try { var x: number = 0; } catch (e) { might_throw(); + // ...but if so, suffix is not reached var x: number = 0; } var y: number = x; } + +// and here function f() { try {} catch (e) {} finally { might_throw(); + // ...but if so, suffix is not reached var x: number = 0; } var y: number = x; } + +// and here function f() { try { var x: number; } catch (e) {} finally { might_throw(); + // ...but if so, suffix is not reached x = 0; } var y: number = x; } + +// and here, thank you JS for the wonder that is hoisting function f() { try {} catch (e) { var x: number; } finally { might_throw(); + // ...but if so, suffix is not reached x = 0; } var y: number = x; } + +// error if used prior to init function f() { var y: number = x; + // error try { var x: number = 0; } catch (e) {} } + +// another non-dominated post function f() { try { var x: number = 0; } catch (e) {} - var y: number = x; + var y: number = x; // error } + +// ditto function f() { try {} catch (e) { var x: number = 0; } - var y: number = x; + var y: number = x; // error } + +// ditto function f(b) { try { var x: number; @@ -325,9 +333,8 @@ function f(b) { } x = 0; } catch (e) {} - var y: number = x; -} -" + var y: number = x; // error +}" `; exports[`test return.js 1`] = ` @@ -400,8 +407,7 @@ function corge(): string { /** * @flow */ -// unreachable -// unreachable + function foo(x: ?number): string { try {} catch (e) { return \"bar\"; @@ -409,6 +415,7 @@ function foo(x: ?number): string { console.log(); return \"foo\"; } + function bar(): string { try { return \"foo\"; @@ -416,14 +423,16 @@ function bar(): string { return \"bar\"; } } + function baz(): string { try { throw new Error(\"foo\"); } catch (e) { return \"foo\"; } - return \"bar\"; + return \"bar\"; // unreachable } + function qux(): string { try { throw new Error(\"foo\"); @@ -431,12 +440,14 @@ function qux(): string { console.log(); return \"bar\"; } + function quux(): string { try { return qux(); } catch (e) {} return \"bar\"; } + function bliffl(): string { try { throw new Error(\"foo\"); @@ -446,15 +457,15 @@ function bliffl(): string { return \"bar\"; } } + function corge(): string { try { return \"foo\"; } catch (e) { throw new Error(\"bar\"); } - bar(); -} -" + bar(); // unreachable +}" `; exports[`test test.js 1`] = ` @@ -505,13 +516,7 @@ function qux() { * test env state tracking thru try/catch/finally * @flow */ -// here via [try; finally] only. -// string ~/> function call (no num or bool error) -// object ~/> function call (no uninitialized error) -// here via [try] only. -// ok -// ... -// unreachable + function foo() { var x = 0; var y; @@ -523,9 +528,12 @@ function foo() { } finally { y = {}; } + // here via [try; finally] only. x(); - y(); + // string ~/> function call (no num or bool error) + y(); // object ~/> function call (no uninitialized error) } + function bar(response) { var payload; try { @@ -533,14 +541,15 @@ function bar(response) { } catch (e) { throw new Error(\"...\"); } + // here via [try] only. if (payload.error) {} } + function qux() { var x = 5; try { throw -1; } finally {} - x(); -} -" + x(); // unreachable +}" `; diff --git a/tests/tuples/__snapshots__/jsfmt.spec.js.snap b/tests/tuples/__snapshots__/jsfmt.spec.js.snap index db7e4c9f..df046621 100644 --- a/tests/tuples/__snapshots__/jsfmt.spec.js.snap +++ b/tests/tuples/__snapshots__/jsfmt.spec.js.snap @@ -10,15 +10,14 @@ function foo(x: Array): [number, ?number] { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// Error, can\'t enforce arity when flowing array to tuple -// OK. This is unsound, but at least arity is enforced + function foo(x: Array): [number, ?number] { - return x; + return x; // Error, can\'t enforce arity when flowing array to tuple } + function foo(x: Array): [number, ?number] { - return [ x[0], x[1] ]; -} -" + return [ x[0], x[1] ]; // OK. This is unsound, but at least arity is enforced +}" `; exports[`test optional.js 1`] = ` @@ -30,13 +29,12 @@ exports[`test optional.js 1`] = ` ([]: [?number, string]); // error, since second element is not marked optional ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// Ok, correct arity -// Error, arity is enforced -// error, since second element is not marked optional + ([ 0, undefined ]: [number, ?string]); +// Ok, correct arity ([ 0 ]: [number, ?string]); -([]: [?number, string]); -" +// Error, arity is enforced +([]: [?number, string]); // error, since second element is not marked optional" `; exports[`test too-few.js 1`] = ` @@ -47,10 +45,10 @@ function foo(a: [Object, Object]) {} foo([ {} ]); // error, too few elements in array passed to a tuple ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// error, too few elements in array passed to a tuple + function foo(a: [Object, Object]) {} -foo([ {} ]); -" + +foo([ {} ]); // error, too few elements in array passed to a tuple" `; exports[`test tuples.js 1`] = ` @@ -61,13 +59,12 @@ var d: [number, string] = [123,\'duck\']; var e: [number, string,] = [123,\'duck\']; var f: [number, string] = [123, 456]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Error - arity mismatch -// nope var a: [] = []; var b: [] = [ 123 ]; +// Error - arity mismatch var c: [number] = []; +// nope var d: [number, string] = [ 123, \"duck\" ]; var e: [number, string] = [ 123, \"duck\" ]; -var f: [number, string] = [ 123, 456 ]; -" +var f: [number, string] = [ 123, 456 ];" `; diff --git a/tests/type-at-pos/__snapshots__/jsfmt.spec.js.snap b/tests/type-at-pos/__snapshots__/jsfmt.spec.js.snap index 5a035d9f..3d705615 100644 --- a/tests/type-at-pos/__snapshots__/jsfmt.spec.js.snap +++ b/tests/type-at-pos/__snapshots__/jsfmt.spec.js.snap @@ -20,13 +20,15 @@ export const X = { }; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + +let [ x, y ] = [ 1, 2 ]; + /** * Test what happens when the destructuring is unevaluated. In this case, * \`this\` in a function is unbound, so we never actually find out the type of * \`this.returnsATuple()\` is; thus, we never evaluate \`b\` and so type-at-pos * returns EmptyT. */ -let [ x, y ] = [ 1, 2 ]; export const X = { returnsATuple: function(): [number, number] { return [ 1, 2 ]; @@ -34,8 +36,7 @@ export const X = { test: function() { let [ a, b ] = this.returnsATuple(); } -}; -" +};" `; exports[`test function_expressions.js 1`] = ` @@ -51,12 +52,13 @@ const y = { }; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + // TODO: type-at-pos between the ()\'s should be () => void // class X { // foo(): void {} // } -const y = { bar(): void {} }; -" + +const y = { bar(): void {} };" `; exports[`test generics.js 1`] = ` @@ -88,29 +90,34 @@ var mn: Mono = new C; // error: application of non-poly type mn; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// error: application of non-poly type + class C {} var cn: C = new C(); cn; + function foo() { return C; } var D = foo(); var dn: D = new C(); dn; + type E = C; var en: E = new C(); en; + type F = C; var fn: F = new C(); fn; + type O = { x: X }; var on: O = { x: 0 }; on; + type Mono = C; var mn: Mono = new C(); -mn; -" +// error: application of non-poly type +mn;" `; exports[`test import.js 1`] = ` @@ -124,8 +131,7 @@ module.exports = num; var num = 42; function bar() {} bar(); -module.exports = num; -" +module.exports = num;" `; exports[`test object_special_cases.js 1`] = ` @@ -139,13 +145,13 @@ let tests = [ ]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + let tests = [ function() { let x = {}; Object.defineProperty(x, \"foo\", { value: \"\" }); } -]; -" +];" `; exports[`test optional.js 1`] = ` @@ -166,17 +172,20 @@ function qux(x?) { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + function foo(x?: string) { return x; } + foo(); + function bar(obj: { x?: string }) { return obj.x; } + function qux(x?) { return x; -} -" +}" `; exports[`test predicates.js 1`] = ` @@ -188,11 +197,11 @@ if (x == undefined) {} if (Array.isArray(x)) {} ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + let x = 0; if (x == null) {} if (x == undefined) {} -if (Array.isArray(x)) {} -" +if (Array.isArray(x)) {}" `; exports[`test react.js 1`] = ` @@ -200,8 +209,7 @@ exports[`test react.js 1`] = ` React.createElement; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ import React from \"react\"; -React.createElement; -" +React.createElement;" `; exports[`test templates.js 1`] = ` @@ -209,8 +217,7 @@ exports[`test templates.js 1`] = ` \`foo bar\`; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -\`foo bar\`; -" +\`foo bar\`;" `; exports[`test test.js 1`] = ` @@ -234,6 +241,7 @@ var str = require(\"./import\"); function foo() {} foo(); str; + type Point = [number, string]; const x: Point = [ 1, \"foo\" ]; type MyStr = \"cool\"; @@ -241,8 +249,7 @@ const y: MyStr = \"cool\"; type MyBool = true; const z: MyBool = true; type MyNum = 42; -const w: MyNum = 42; -" +const w: MyNum = 42;" `; exports[`test trycatch.js 1`] = ` @@ -253,8 +260,8 @@ try { } catch (e) {} ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + try { throw \"foo\"; -} catch (e) {} -" +} catch (e) {}" `; diff --git a/tests/type-destructors/__snapshots__/jsfmt.spec.js.snap b/tests/type-destructors/__snapshots__/jsfmt.spec.js.snap index e163844c..9a69dacb 100644 --- a/tests/type-destructors/__snapshots__/jsfmt.spec.js.snap +++ b/tests/type-destructors/__snapshots__/jsfmt.spec.js.snap @@ -13,21 +13,20 @@ function foo(x: ?string): $NonMaybeType { (0: $NonMaybeType); // ok ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// this should be an error -//(foo(): string); // should not be necessary to expose the error above -// error -// ok -// ok + function foo(x: ?string): $NonMaybeType { if (x != null) { return x; } else - return 0; + return 0; // this should be an error } + +//(foo(): string); // should not be necessary to expose the error above (0: $NonMaybeType); +// error (0: $NonMaybeType); -(0: $NonMaybeType); -" +// ok +(0: $NonMaybeType); // ok" `; exports[`test property_type.js 1`] = ` @@ -44,16 +43,18 @@ function foo(o: Obj): $PropertyType { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ type Malformed = $PropertyType; + type Obj = { x: string }; type Obj_Prop_x = $PropertyType; + (42: Obj_Prop_x); + function foo(o: Obj): $PropertyType { if (false) return o.x; else return 0; -} -" +}" `; exports[`test union.js 1`] = ` @@ -62,13 +63,12 @@ var x1: $NonMaybeType = true; // err, boolean ~> number|string var x2: $PropertyType<{p:number}|{p:string},\'p\'> = 0; // ok, number ~> number|string var x3: $PropertyType<{p:number}|{p:string},\'p\'> = true; // err, boolean ~> number|string ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// ok, number ~> number|string -// err, boolean ~> number|string -// ok, number ~> number|string -// err, boolean ~> number|string var x0: $NonMaybeType = 0; +// ok, number ~> number|string var x1: $NonMaybeType = true; +// err, boolean ~> number|string var x2: $PropertyType<{ p: number } | { p: string }, \"p\"> = 0; -var x3: $PropertyType<{ p: number } | { p: string }, \"p\"> = true; -" +// ok, number ~> number|string +var x3: $PropertyType<{ p: number } | + { p: string }, \"p\"> = true; // err, boolean ~> number|string" `; diff --git a/tests/type-printer/__snapshots__/jsfmt.spec.js.snap b/tests/type-printer/__snapshots__/jsfmt.spec.js.snap index c6f1f442..fe9f6681 100644 --- a/tests/type-printer/__snapshots__/jsfmt.spec.js.snap +++ b/tests/type-printer/__snapshots__/jsfmt.spec.js.snap @@ -20,6 +20,7 @@ function printBinaryExpression( module.exports = printBinaryExpression; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +\"use babel\"; /* @flow */ /* * Copyright (c) 2015-present, Facebook, Inc. @@ -28,13 +29,13 @@ module.exports = printBinaryExpression; * This source code is licensed under the license found in the LICENSE file in * the root directory of this source tree. */ -\"use babel\"; import type {BinaryExpression} from \"./types\"; + function printBinaryExpression(node: BinaryExpression) { console.log(node); } -module.exports = printBinaryExpression; -" + +module.exports = printBinaryExpression;" `; exports[`test types.js 1`] = ` @@ -5087,30 +5088,13 @@ export type JSXSpreadAttribute = { /** * @flow */ + +\"use strict\"; + /* * Flow types for the Babylon AST. */ // Abstract types. Something must extend these. -// Concrete Types. Nothing can extend these. -// Babel concrete types. -// TODO: What is this? -// TODO: Make this correct. -// TODO: Make this correct. -// TODO: Make this correct. -// TODO: Make this correct. -// TODO: Make this correct. -// TODO: Make this correct. -// TODO: Make this correct. -// TODO: Make this correct. -// TODO: Make this correct. -// TODO: Make this correct. -// TODO: Make this correct. -// TODO: Make this correct. -// TODO: Make this correct. -// TODO: Make this correct. -// TODO: Make this correct. -// TODO: Make this correct. -\"use strict\"; export type Comment = { type: \"CommentLine\", _CommentLine: void, @@ -5133,6 +5117,7 @@ export type Comment = { }, start: number }; + export type Declaration = { type: \"ClassBody\", _ClassBody: void, @@ -5242,6 +5227,7 @@ export type Declaration = { start: number, trailingComments: ?Array }; + export type Expression = { type: \"ArrayExpression\", _ArrayExpression: void, @@ -5691,6 +5677,7 @@ export type Expression = { start: number, trailingComments: ?Array }; + export type Function = { type: \"ArrowFunctionExpression\", _ArrowFunctionExpression: void, @@ -5760,6 +5747,7 @@ export type Function = { returnType: ?TypeAnnotation, typeParameters: ?TypeParameterDeclaration }; + export type Node = { type: \"ArrayExpression\", _ArrayExpression: void, @@ -7610,6 +7598,7 @@ export type Node = { start: number, trailingComments: ?Array }; + export type Pattern = { type: \"ArrayPattern\", _ArrayPattern: void, @@ -7685,6 +7674,7 @@ export type Pattern = { start: number, trailingComments: ?Array }; + export type Statement = { type: \"BlockStatement\", _BlockStatement: void, @@ -8034,6 +8024,7 @@ export type Statement = { start: number, trailingComments: ?Array }; + export type Type = { type: \"AnyTypeAnnotation\", _AnyTypeAnnotation: void, @@ -8275,6 +8266,8 @@ export type Type = { start: number, trailingComments: ?Array }; + +// Concrete Types. Nothing can extend these. export type CommentLine = { type: \"CommentLine\", _CommentLine: void, @@ -8286,6 +8279,7 @@ export type CommentLine = { }, start: number }; + export type CommentBlock = { type: \"CommentBlock\", _CommentBlock: void, @@ -8297,6 +8291,8 @@ export type CommentBlock = { }, start: number }; + +// Babel concrete types. export type ArrayExpression = { type: \"ArrayExpression\", _ArrayExpression: void, @@ -8311,6 +8307,7 @@ export type ArrayExpression = { start: number, trailingComments: ?Array }; + export type ArrayPattern = { type: \"ArrayPattern\", _ArrayPattern: void, @@ -8326,6 +8323,7 @@ export type ArrayPattern = { start: number, trailingComments: ?Array }; + export type ArrowFunctionExpression = { type: \"ArrowFunctionExpression\", _ArrowFunctionExpression: void, @@ -8349,6 +8347,7 @@ export type ArrowFunctionExpression = { returnType: ?TypeAnnotation, typeParameters: ?TypeParameterDeclaration }; + type AssignmentOperator = \"=\" | \"+=\" | \"-=\" | @@ -8361,6 +8360,7 @@ type AssignmentOperator = \"=\" | \"|=\" | \"^=\" | \"&=\"; + export type AssignmentExpression = { type: \"AssignmentExpression\", _AssignmentExpression: void, @@ -8377,6 +8377,7 @@ export type AssignmentExpression = { start: number, trailingComments: ?Array }; + export type AssignmentPattern = { type: \"AssignmentPattern\", _AssignmentPattern: void, @@ -8392,6 +8393,7 @@ export type AssignmentPattern = { start: number, trailingComments: ?Array }; + export type AwaitExpression = { type: \"AwaitExpression\", _AwaitExpression: void, @@ -8407,6 +8409,7 @@ export type AwaitExpression = { start: number, trailingComments: ?Array }; + type BinaryOperator = \"==\" | \"!=\" | \"===\" | @@ -8429,6 +8432,7 @@ type BinaryOperator = \"==\" | \"in\" | \"instanceof\" | \"..\"; + export type BinaryExpression = { type: \"BinaryExpression\", _BinaryExpression: void, @@ -8445,6 +8449,8 @@ export type BinaryExpression = { start: number, trailingComments: ?Array }; + +// TODO: What is this? export type BindExpression = { type: \"BindExpression\", _BindExpression: void, @@ -8460,6 +8466,7 @@ export type BindExpression = { start: number, trailingComments: ?Array }; + export type BlockStatement = { type: \"BlockStatement\", _BlockStatement: void, @@ -8474,6 +8481,7 @@ export type BlockStatement = { start: number, trailingComments: ?Array }; + export type BreakStatement = { type: \"BreakStatement\", _BreakStatement: void, @@ -8488,6 +8496,7 @@ export type BreakStatement = { start: number, trailingComments: ?Array }; + export type CallExpression = { type: \"CallExpression\", _CallExpression: void, @@ -8503,6 +8512,7 @@ export type CallExpression = { start: number, trailingComments: ?Array }; + export type CatchClause = { type: \"CatchClause\", _CatchClause: void, @@ -8518,6 +8528,7 @@ export type CatchClause = { start: number, trailingComments: ?Array }; + export type ClassBody = { type: \"ClassBody\", _ClassBody: void, @@ -8532,6 +8543,7 @@ export type ClassBody = { start: number, trailingComments: ?Array }; + export type ClassDeclaration = { type: \"ClassDeclaration\", _ClassDeclaration: void, @@ -8551,6 +8563,7 @@ export type ClassDeclaration = { start: number, trailingComments: ?Array }; + export type ClassExpression = { type: \"ClassExpression\", _ClassExpression: void, @@ -8570,6 +8583,7 @@ export type ClassExpression = { start: number, trailingComments: ?Array }; + export type ComprehensionBlock = { type: \"ComprehensionBlock\", _ComprehensionBlock: void, @@ -8586,6 +8600,7 @@ export type ComprehensionBlock = { start: number, trailingComments: ?Array }; + export type ComprehensionExpression = { type: \"ComprehensionExpression\", _ComprehensionExpression: void, @@ -8602,6 +8617,7 @@ export type ComprehensionExpression = { start: number, trailingComments: ?Array }; + export type ConditionalExpression = { type: \"ConditionalExpression\", _ConditionalExpression: void, @@ -8618,6 +8634,7 @@ export type ConditionalExpression = { start: number, trailingComments: ?Array }; + export type ContinueStatement = { type: \"ContinueStatement\", _ContinueStatement: void, @@ -8632,6 +8649,8 @@ export type ContinueStatement = { start: number, trailingComments: ?Array }; + +// TODO: Make this correct. export type Decorator = { type: \"Decorator\", _Decorator: void, @@ -8646,6 +8665,7 @@ export type Decorator = { start: number, trailingComments: ?Array }; + export type DebuggerStatement = { type: \"DebuggerStatement\", _DebuggerStatement: void, @@ -8659,6 +8679,7 @@ export type DebuggerStatement = { start: number, trailingComments: ?Array }; + export type DoWhileStatement = { type: \"DoWhileStatement\", _DoWhileStatement: void, @@ -8674,6 +8695,8 @@ export type DoWhileStatement = { start: number, trailingComments: ?Array }; + +// TODO: Make this correct. export type DoExpression = { type: \"DoExpression\", _DoExpression: void, @@ -8688,6 +8711,7 @@ export type DoExpression = { start: number, trailingComments: ?Array }; + export type EmptyStatement = { type: \"EmptyStatement\", _EmptyStatement: void, @@ -8701,6 +8725,7 @@ export type EmptyStatement = { start: number, trailingComments: ?Array }; + export type ExpressionStatement = { type: \"ExpressionStatement\", _ExpressionStatement: void, @@ -8715,6 +8740,7 @@ export type ExpressionStatement = { start: number, trailingComments: ?Array }; + export type File = { type: \"File\", _File: void, @@ -8729,6 +8755,7 @@ export type File = { start: number, trailingComments: ?Array }; + export type ForInStatement = { type: \"ForInStatement\", _ForInStatement: void, @@ -8745,6 +8772,8 @@ export type ForInStatement = { start: number, trailingComments: ?Array }; + +// TODO: Make this correct. export type ForOfStatement = { type: \"ForOfStatement\", _ForOfStatement: void, @@ -8761,6 +8790,7 @@ export type ForOfStatement = { start: number, trailingComments: ?Array }; + export type ForStatement = { type: \"ForStatement\", _ForStatement: void, @@ -8778,6 +8808,7 @@ export type ForStatement = { start: number, trailingComments: ?Array }; + export type FunctionDeclaration = { type: \"FunctionDeclaration\", _FunctionDeclaration: void, @@ -8801,6 +8832,7 @@ export type FunctionDeclaration = { returnType: ?TypeAnnotation, typeParameters: ?TypeParameterDeclaration }; + export type FunctionExpression = { type: \"FunctionExpression\", _FunctionExpression: void, @@ -8824,6 +8856,7 @@ export type FunctionExpression = { returnType: ?TypeAnnotation, typeParameters: ?TypeParameterDeclaration }; + export type Identifier = { type: \"Identifier\", _Identifier: void, @@ -8839,6 +8872,7 @@ export type Identifier = { start: number, trailingComments: ?Array }; + export type IfStatement = { type: \"IfStatement\", _IfStatement: void, @@ -8855,6 +8889,8 @@ export type IfStatement = { start: number, trailingComments: ?Array }; + +// TODO: Make this correct. export type ImportDefaultSpecifier = { type: \"ImportDefaultSpecifier\", _ImportDefaultSpecifier: void, @@ -8869,6 +8905,8 @@ export type ImportDefaultSpecifier = { start: number, trailingComments: ?Array }; + +// TODO: Make this correct. export type ImportNamespaceSpecifier = { type: \"ImportNamespaceSpecifier\", _ImportNamespaceSpecifier: void, @@ -8883,6 +8921,8 @@ export type ImportNamespaceSpecifier = { start: number, trailingComments: ?Array }; + +// TODO: Make this correct. export type ImportDeclaration = { type: \"ImportDeclaration\", _ImportDeclaration: void, @@ -8898,6 +8938,8 @@ export type ImportDeclaration = { start: number, trailingComments: ?Array }; + +// TODO: Make this correct. export type ImportSpecifier = { type: \"ImportSpecifier\", _ImportSpecifier: void, @@ -8913,6 +8955,7 @@ export type ImportSpecifier = { start: number, trailingComments: ?Array }; + export type LabeledStatement = { type: \"LabeledStatement\", _LabeledStatement: void, @@ -8928,6 +8971,7 @@ export type LabeledStatement = { start: number, trailingComments: ?Array }; + export type Literal = { type: \"Literal\", _Literal: void, @@ -8944,7 +8988,9 @@ export type Literal = { start: number, trailingComments: ?Array }; + type LogicalOperator = \"||\" | \"&&\"; + export type LogicalExpression = { type: \"LogicalExpression\", _LogicalExpression: void, @@ -8961,6 +9007,7 @@ export type LogicalExpression = { start: number, trailingComments: ?Array }; + export type MemberExpression = { type: \"MemberExpression\", _MemberExpression: void, @@ -8977,6 +9024,8 @@ export type MemberExpression = { start: number, trailingComments: ?Array }; + +// TODO: Make this correct. export type MetaProperty = { type: \"MetaProperty\", _MetaProperty: void, @@ -8992,6 +9041,7 @@ export type MetaProperty = { start: number, trailingComments: ?Array }; + export type MethodDefinition = { type: \"MethodDefinition\", _MethodDefinition: void, @@ -9011,6 +9061,7 @@ export type MethodDefinition = { start: number, trailingComments: ?Array }; + export type NewExpression = { type: \"NewExpression\", _NewExpression: void, @@ -9026,6 +9077,7 @@ export type NewExpression = { start: number, trailingComments: ?Array }; + export type Noop = { type: \"Noop\", _Noop: void, @@ -9039,6 +9091,7 @@ export type Noop = { start: number, trailingComments: ?Array }; + export type ObjectExpression = { type: \"ObjectExpression\", _ObjectExpression: void, @@ -9053,6 +9106,7 @@ export type ObjectExpression = { start: number, trailingComments: ?Array }; + export type ObjectPattern = { type: \"ObjectPattern\", _ObjectPattern: void, @@ -9068,6 +9122,7 @@ export type ObjectPattern = { start: number, trailingComments: ?Array }; + export type Program = { type: \"Program\", _Program: void, @@ -9082,6 +9137,7 @@ export type Program = { start: number, trailingComments: ?Array }; + export type Property = { type: \"Property\", _Property: void, @@ -9102,6 +9158,7 @@ export type Property = { start: number, trailingComments: ?Array }; + export type RestElement = { type: \"RestElement\", _RestElement: void, @@ -9117,6 +9174,7 @@ export type RestElement = { start: number, trailingComments: ?Array }; + export type ReturnStatement = { type: \"ReturnStatement\", _ReturnStatement: void, @@ -9131,6 +9189,7 @@ export type ReturnStatement = { start: number, trailingComments: ?Array }; + export type SequenceExpression = { type: \"SequenceExpression\", _SequenceExpression: void, @@ -9145,6 +9204,7 @@ export type SequenceExpression = { start: number, trailingComments: ?Array }; + export type SpreadElement = { type: \"SpreadElement\", _SpreadElement: void, @@ -9159,6 +9219,7 @@ export type SpreadElement = { start: number, trailingComments: ?Array }; + export type SpreadProperty = { type: \"SpreadProperty\", _SpreadProperty: void, @@ -9173,6 +9234,7 @@ export type SpreadProperty = { start: number, trailingComments: ?Array }; + export type Super = { type: \"Super\", _Super: void, @@ -9186,6 +9248,7 @@ export type Super = { start: number, trailingComments: ?Array }; + export type SwitchCase = { type: \"SwitchCase\", _SwitchCase: void, @@ -9201,6 +9264,7 @@ export type SwitchCase = { start: number, trailingComments: ?Array }; + export type SwitchStatement = { type: \"SwitchStatement\", _SwitchStatement: void, @@ -9217,6 +9281,7 @@ export type SwitchStatement = { start: number, trailingComments: ?Array }; + export type TaggedTemplateExpression = { type: \"TaggedTemplateExpression\", _TaggedTemplateExpression: void, @@ -9232,6 +9297,7 @@ export type TaggedTemplateExpression = { start: number, trailingComments: ?Array }; + export type TemplateElement = { type: \"TemplateElement\", _TemplateElement: void, @@ -9247,6 +9313,7 @@ export type TemplateElement = { start: number, trailingComments: ?Array }; + export type TemplateLiteral = { type: \"TemplateLiteral\", _TemplateLiteral: void, @@ -9262,6 +9329,7 @@ export type TemplateLiteral = { start: number, trailingComments: ?Array }; + export type ThisExpression = { type: \"ThisExpression\", _ThisExpression: void, @@ -9275,6 +9343,7 @@ export type ThisExpression = { start: number, trailingComments: ?Array }; + export type ThrowStatement = { type: \"ThrowStatement\", _ThrowStatement: void, @@ -9289,6 +9358,7 @@ export type ThrowStatement = { start: number, trailingComments: ?Array }; + export type TryStatement = { type: \"TryStatement\", _TryStatement: void, @@ -9307,7 +9377,9 @@ export type TryStatement = { start: number, trailingComments: ?Array }; + type UnaryOperator = \"-\" | \"+\" | \"!\" | \"~\" | \"typeof\" | \"void\" | \"delete\"; + export type UnaryExpression = { type: \"UnaryExpression\", _UnaryExpression: void, @@ -9324,7 +9396,9 @@ export type UnaryExpression = { start: number, trailingComments: ?Array }; + type UpdateOperator = \"++\" | \"--\"; + export type UpdateExpression = { type: \"UpdateExpression\", _UpdateExpression: void, @@ -9341,6 +9415,7 @@ export type UpdateExpression = { start: number, trailingComments: ?Array }; + export type VariableDeclaration = { type: \"VariableDeclaration\", _VariableDeclaration: void, @@ -9356,6 +9431,7 @@ export type VariableDeclaration = { start: number, trailingComments: ?Array }; + export type VariableDeclarator = { type: \"VariableDeclarator\", _VariableDeclarator: void, @@ -9371,6 +9447,7 @@ export type VariableDeclarator = { start: number, trailingComments: ?Array }; + export type WhileStatement = { type: \"WhileStatement\", _WhileStatement: void, @@ -9386,6 +9463,7 @@ export type WhileStatement = { start: number, trailingComments: ?Array }; + export type WithStatement = { type: \"WithStatement\", _WithStatement: void, @@ -9401,6 +9479,7 @@ export type WithStatement = { start: number, trailingComments: ?Array }; + export type YieldExpression = { type: \"YieldExpression\", _YieldExpression: void, @@ -9416,6 +9495,8 @@ export type YieldExpression = { start: number, trailingComments: ?Array }; + +// TODO: Make this correct. export type ExportAllDeclaration = { type: \"ExportAllDeclaration\", _ExportAllDeclaration: void, @@ -9431,6 +9512,8 @@ export type ExportAllDeclaration = { start: number, trailingComments: ?Array }; + +// TODO: Make this correct. export type ExportDefaultDeclaration = { type: \"ExportDefaultDeclaration\", _ExportDefaultDeclaration: void, @@ -9445,6 +9528,8 @@ export type ExportDefaultDeclaration = { start: number, trailingComments: ?Array }; + +// TODO: Make this correct. export type ExportNamedDeclaration = { type: \"ExportNamedDeclaration\", _ExportNamedDeclaration: void, @@ -9461,6 +9546,8 @@ export type ExportNamedDeclaration = { start: number, trailingComments: ?Array }; + +// TODO: Make this correct. export type ExportDefaultSpecifier = { type: \"ExportDefaultSpecifier\", _ExportDefaultSpecifier: void, @@ -9475,6 +9562,8 @@ export type ExportDefaultSpecifier = { start: number, trailingComments: ?Array }; + +// TODO: Make this correct. export type ExportNamespaceSpecifier = { type: \"ExportNamespaceSpecifier\", _ExportNamespaceSpecifier: void, @@ -9489,6 +9578,8 @@ export type ExportNamespaceSpecifier = { start: number, trailingComments: ?Array }; + +// TODO: Make this correct. export type ExportSpecifier = { type: \"ExportSpecifier\", _ExportSpecifier: void, @@ -9504,6 +9595,7 @@ export type ExportSpecifier = { start: number, trailingComments: ?Array }; + export type AnyTypeAnnotation = { type: \"AnyTypeAnnotation\", _AnyTypeAnnotation: void, @@ -9517,6 +9609,7 @@ export type AnyTypeAnnotation = { start: number, trailingComments: ?Array }; + export type ArrayTypeAnnotation = { type: \"ArrayTypeAnnotation\", _ArrayTypeAnnotation: void, @@ -9531,6 +9624,7 @@ export type ArrayTypeAnnotation = { start: number, trailingComments: ?Array }; + export type BooleanLiteralTypeAnnotation = { type: \"BooleanLiteralTypeAnnotation\", _BooleanLiteralTypeAnnotation: void, @@ -9546,6 +9640,7 @@ export type BooleanLiteralTypeAnnotation = { start: number, trailingComments: ?Array }; + export type BooleanTypeAnnotation = { type: \"BooleanTypeAnnotation\", _BooleanTypeAnnotation: void, @@ -9559,6 +9654,7 @@ export type BooleanTypeAnnotation = { start: number, trailingComments: ?Array }; + export type ClassImplements = { type: \"ClassImplements\", _ClassImplements: void, @@ -9575,6 +9671,7 @@ export type ClassImplements = { start: number, trailingComments: ?Array }; + export type ClassProperty = { type: \"ClassProperty\", _ClassProperty: void, @@ -9594,6 +9691,7 @@ export type ClassProperty = { start: number, trailingComments: ?Array }; + export type DeclareClass = { type: \"DeclareClass\", _DeclareClass: void, @@ -9611,6 +9709,8 @@ export type DeclareClass = { start: number, trailingComments: ?Array }; + +// TODO: Make this correct. export type DeclareFunction = { type: \"DeclareFunction\", _DeclareFunction: void, @@ -9625,6 +9725,7 @@ export type DeclareFunction = { start: number, trailingComments: ?Array }; + export type DeclareModule = { type: \"DeclareModule\", _DeclareModule: void, @@ -9640,6 +9741,8 @@ export type DeclareModule = { start: number, trailingComments: ?Array }; + +// TODO: Make this correct. export type DeclareVariable = { type: \"DeclareVariable\", _DeclareVariable: void, @@ -9654,6 +9757,7 @@ export type DeclareVariable = { start: number, trailingComments: ?Array }; + export type FunctionTypeAnnotation = { type: \"FunctionTypeAnnotation\", _FunctionTypeAnnotation: void, @@ -9671,6 +9775,7 @@ export type FunctionTypeAnnotation = { start: number, trailingComments: ?Array }; + export type FunctionTypeParam = { type: \"FunctionTypeParam\", _FunctionTypeParam: void, @@ -9687,6 +9792,7 @@ export type FunctionTypeParam = { start: number, trailingComments: ?Array }; + export type GenericTypeAnnotation = { type: \"GenericTypeAnnotation\", _GenericTypeAnnotation: void, @@ -9702,6 +9808,7 @@ export type GenericTypeAnnotation = { start: number, trailingComments: ?Array }; + export type InterfaceExtends = { type: \"InterfaceExtends\", _InterfaceExtends: void, @@ -9717,6 +9824,7 @@ export type InterfaceExtends = { start: number, trailingComments: ?Array }; + export type InterfaceDeclaration = { type: \"InterfaceDeclaration\", _InterfaceDeclaration: void, @@ -9734,6 +9842,7 @@ export type InterfaceDeclaration = { start: number, trailingComments: ?Array }; + export type IntersectionTypeAnnotation = { type: \"IntersectionTypeAnnotation\", _IntersectionTypeAnnotation: void, @@ -9748,6 +9857,7 @@ export type IntersectionTypeAnnotation = { start: number, trailingComments: ?Array }; + export type MixedTypeAnnotation = { type: \"MixedTypeAnnotation\", _MixedTypeAnnotation: void, @@ -9761,6 +9871,7 @@ export type MixedTypeAnnotation = { start: number, trailingComments: ?Array }; + export type NullableTypeAnnotation = { type: \"NullableTypeAnnotation\", _NullableTypeAnnotation: void, @@ -9775,6 +9886,7 @@ export type NullableTypeAnnotation = { start: number, trailingComments: ?Array }; + export type NumberLiteralTypeAnnotation = { type: \"NumberLiteralTypeAnnotation\", _NumberLiteralTypeAnnotation: void, @@ -9790,6 +9902,7 @@ export type NumberLiteralTypeAnnotation = { start: number, trailingComments: ?Array }; + export type NumberTypeAnnotation = { type: \"NumberTypeAnnotation\", _NumberTypeAnnotation: void, @@ -9803,6 +9916,7 @@ export type NumberTypeAnnotation = { start: number, trailingComments: ?Array }; + export type StringLiteralTypeAnnotation = { type: \"StringLiteralTypeAnnotation\", _StringLiteralTypeAnnotation: void, @@ -9818,6 +9932,7 @@ export type StringLiteralTypeAnnotation = { start: number, trailingComments: ?Array }; + export type StringTypeAnnotation = { type: \"StringTypeAnnotation\", _StringTypeAnnotation: void, @@ -9831,6 +9946,7 @@ export type StringTypeAnnotation = { start: number, trailingComments: ?Array }; + export type TupleTypeAnnotation = { type: \"TupleTypeAnnotation\", _TupleTypeAnnotation: void, @@ -9845,6 +9961,7 @@ export type TupleTypeAnnotation = { start: number, trailingComments: ?Array }; + export type TypeofTypeAnnotation = { type: \"TypeofTypeAnnotation\", _TypeofTypeAnnotation: void, @@ -9859,6 +9976,7 @@ export type TypeofTypeAnnotation = { start: number, trailingComments: ?Array }; + export type TypeAlias = { type: \"TypeAlias\", _TypeAlias: void, @@ -9875,6 +9993,7 @@ export type TypeAlias = { start: number, trailingComments: ?Array }; + export type TypeAnnotation = { type: \"TypeAnnotation\", _TypeAnnotation: void, @@ -9889,6 +10008,7 @@ export type TypeAnnotation = { start: number, trailingComments: ?Array }; + export type TypeCastExpression = { type: \"TypeCastExpression\", _TypeCastExpression: void, @@ -9904,6 +10024,7 @@ export type TypeCastExpression = { start: number, trailingComments: ?Array }; + export type TypeParameterDeclaration = { type: \"TypeParameterDeclaration\", _TypeParameterDeclaration: void, @@ -9918,6 +10039,7 @@ export type TypeParameterDeclaration = { start: number, trailingComments: ?Array }; + export type TypeParameterInstantiation = { type: \"TypeParameterInstantiation\", _TypeParameterInstantiation: void, @@ -9932,6 +10054,7 @@ export type TypeParameterInstantiation = { start: number, trailingComments: ?Array }; + export type ObjectTypeAnnotation = { type: \"ObjectTypeAnnotation\", _ObjectTypeAnnotation: void, @@ -9948,6 +10071,7 @@ export type ObjectTypeAnnotation = { start: number, trailingComments: ?Array }; + export type ObjectTypeCallProperty = { type: \"ObjectTypeCallProperty\", _ObjectTypeCallProperty: void, @@ -9963,6 +10087,7 @@ export type ObjectTypeCallProperty = { start: number, trailingComments: ?Array }; + export type ObjectTypeIndexer = { type: \"ObjectTypeIndexer\", _ObjectTypeIndexer: void, @@ -9979,6 +10104,7 @@ export type ObjectTypeIndexer = { start: number, trailingComments: ?Array }; + export type ObjectTypeProperty = { type: \"ObjectTypeProperty\", _ObjectTypeProperty: void, @@ -9995,6 +10121,7 @@ export type ObjectTypeProperty = { start: number, trailingComments: ?Array }; + export type QualifiedTypeIdentifier = { type: \"QualifiedTypeIdentifier\", _QualifiedTypeIdentifier: void, @@ -10010,6 +10137,7 @@ export type QualifiedTypeIdentifier = { start: number, trailingComments: ?Array }; + export type UnionTypeAnnotation = { type: \"UnionTypeAnnotation\", _UnionTypeAnnotation: void, @@ -10024,6 +10152,7 @@ export type UnionTypeAnnotation = { start: number, trailingComments: ?Array }; + export type VoidTypeAnnotation = { type: \"VoidTypeAnnotation\", _VoidTypeAnnotation: void, @@ -10037,6 +10166,7 @@ export type VoidTypeAnnotation = { start: number, trailingComments: ?Array }; + export type JSXAttribute = { type: \"JSXAttribute\", _JSXAttribute: void, @@ -10052,6 +10182,7 @@ export type JSXAttribute = { start: number, trailingComments: ?Array }; + export type JSXClosingElement = { type: \"JSXClosingElement\", _JSXClosingElement: void, @@ -10066,6 +10197,7 @@ export type JSXClosingElement = { start: number, trailingComments: ?Array }; + export type JSXElement = { type: \"JSXElement\", _JSXElement: void, @@ -10082,6 +10214,7 @@ export type JSXElement = { start: number, trailingComments: ?Array }; + export type JSXEmptyExpression = { type: \"JSXEmptyExpression\", _JSXEmptyExpression: void, @@ -10095,6 +10228,7 @@ export type JSXEmptyExpression = { start: number, trailingComments: ?Array }; + export type JSXExpressionContainer = { type: \"JSXExpressionContainer\", _JSXExpressionContainer: void, @@ -10109,6 +10243,7 @@ export type JSXExpressionContainer = { start: number, trailingComments: ?Array }; + export type JSXIdentifier = { type: \"JSXIdentifier\", _JSXIdentifier: void, @@ -10123,6 +10258,7 @@ export type JSXIdentifier = { start: number, trailingComments: ?Array }; + export type JSXMemberExpression = { type: \"JSXMemberExpression\", _JSXMemberExpression: void, @@ -10139,6 +10275,7 @@ export type JSXMemberExpression = { start: number, trailingComments: ?Array }; + export type JSXNamespacedName = { type: \"JSXNamespacedName\", _JSXNamespacedName: void, @@ -10154,6 +10291,7 @@ export type JSXNamespacedName = { start: number, trailingComments: ?Array }; + export type JSXOpeningElement = { type: \"JSXOpeningElement\", _JSXOpeningElement: void, @@ -10170,6 +10308,7 @@ export type JSXOpeningElement = { start: number, trailingComments: ?Array }; + export type JSXSpreadAttribute = { type: \"JSXSpreadAttribute\", _JSXSpreadAttribute: void, @@ -10183,6 +10322,5 @@ export type JSXSpreadAttribute = { }, start: number, trailingComments: ?Array -}; -" +};" `; diff --git a/tests/type_args_nonstrict/__snapshots__/jsfmt.spec.js.snap b/tests/type_args_nonstrict/__snapshots__/jsfmt.spec.js.snap index 2769d314..49416ba7 100644 --- a/tests/type_args_nonstrict/__snapshots__/jsfmt.spec.js.snap +++ b/tests/type_args_nonstrict/__snapshots__/jsfmt.spec.js.snap @@ -83,27 +83,19 @@ var num_array:Array = singleton(0); // ok, type arg inferred * * @flow */ + // no arity error in type annotation using polymorphic class -// no error -// no arity error in type annotation using polymorphic class with defaulting -// no error -// no arity error in type annotation using polymorphic type alias -// no error -// arity error in type alias rhs -// no error -// arity error in interface extends -// no error -// no arity error in extends of polymorphic class -// ok, type arg inferred -// no arity error in call of polymorphic function -// ok, type arg inferred + class MyClass { x: T; constructor(x: T) { this.x = x; } } + var c: MyClass = new MyClass(0); +// no error +// no arity error in type annotation using polymorphic class with defaulting class MyClass2 { x: T; y: U; @@ -112,21 +104,38 @@ class MyClass2 { this.y = y; } } + var c2: MyClass2 = new MyClass2(0, \"\"); +// no error +// no arity error in type annotation using polymorphic type alias type MyObject = { x: T }; + var o: MyObject = { x: 0 }; +// no error +// arity error in type alias rhs type MySubobject = { y: number } & MyObject; +// no error +// arity error in interface extends interface MyInterface { x: T } -interface MySubinterface extends MyInterface { y: number } + +interface MySubinterface extends MyInterface { + // no error + y: number +} + +// no arity error in extends of polymorphic class class MySubclass extends MyClass { + // ok, type arg inferred y: number; constructor(y: number) { super(y); } } + +// no arity error in call of polymorphic function function singleton(x: T): Array { return [ x ]; } -var num_array: Array = singleton(0); -" + +var num_array: Array = singleton(0); // ok, type arg inferred" `; diff --git a/tests/type_args_strict/__snapshots__/jsfmt.spec.js.snap b/tests/type_args_strict/__snapshots__/jsfmt.spec.js.snap index 73e59e3a..b8efde79 100644 --- a/tests/type_args_strict/__snapshots__/jsfmt.spec.js.snap +++ b/tests/type_args_strict/__snapshots__/jsfmt.spec.js.snap @@ -81,27 +81,19 @@ var num_array:Array = singleton(0); // ok, type arg inferred * * @flow */ + // arity error in type annotation using polymorphic class -// error, missing argument list (1) -// arity error in type annotation using polymorphic class with defaulting -// error, missing argument list (1-2) -// arity error in type annotation using polymorphic type alias -// error, missing argument list -// arity error in type alias rhs -// error, missing argument list -// arity error in interface extends -// error, missing argument list -// *no* arity error in extends of polymorphic class -// ok, type arg inferred -// *no* arity error in call of polymorphic function -// ok, type arg inferred + class MyClass { x: T; constructor(x: T) { this.x = x; } } + var c: MyClass = new MyClass(0); +// error, missing argument list (1) +// arity error in type annotation using polymorphic class with defaulting class MyClass2 { x: T; y: U; @@ -110,21 +102,38 @@ class MyClass2 { this.y = y; } } + var c2: MyClass2 = new MyClass2(0, \"\"); +// error, missing argument list (1-2) +// arity error in type annotation using polymorphic type alias type MyObject = { x: T }; + var o: MyObject = { x: 0 }; +// error, missing argument list +// arity error in type alias rhs type MySubobject = { y: number } & MyObject; +// error, missing argument list +// arity error in interface extends interface MyInterface { x: T } -interface MySubinterface extends MyInterface { y: number } + +interface MySubinterface extends MyInterface { + // error, missing argument list + y: number +} + +// *no* arity error in extends of polymorphic class class MySubclass extends MyClass { + // ok, type arg inferred y: number; constructor(y: number) { super(y); } } + +// *no* arity error in call of polymorphic function function singleton(x: T): Array { return [ x ]; } -var num_array: Array = singleton(0); -" + +var num_array: Array = singleton(0); // ok, type arg inferred" `; diff --git a/tests/type_only_vars/__snapshots__/jsfmt.spec.js.snap b/tests/type_only_vars/__snapshots__/jsfmt.spec.js.snap index 097d8b72..50fee24d 100644 --- a/tests/type_only_vars/__snapshots__/jsfmt.spec.js.snap +++ b/tests/type_only_vars/__snapshots__/jsfmt.spec.js.snap @@ -17,10 +17,12 @@ module.exports = { /** * @flow */ + class Foo {} + class Bar {} -module.exports = { Foo: Foo, Bar: Bar }; -" + +module.exports = { Foo: Foo, Bar: Bar };" `; exports[`test bad_shadowing.js 1`] = ` @@ -46,16 +48,19 @@ var duck: string = \"quack\"; /** * @flow */ -// These string types should confict with the imported types -// This string type should conflict with the typedef + import typeof A from \"./A.js\"; import type {Foo, Bar as Baz} from \"./A.js\"; + type duck = { quack(): string }; + +// These string types should confict with the imported types var A: string = \"Hello\"; var Foo: string = \"Goodbye\"; var Baz: string = \"Go away please\"; -var duck: string = \"quack\"; -" + +// This string type should conflict with the typedef +var duck: string = \"quack\";" `; exports[`test good_shadowing.js 1`] = ` @@ -83,20 +88,23 @@ var b: Foo = new A.Foo(); /** * @flow */ -// errors in prev block leave type bindings in place, so these are errors -// errors from value positions only + import typeof A from \"./A.js\"; import type {Foo, Bar as Baz} from \"./A.js\"; + var A = require(\"./A.js\"); var Foo = A.Foo; var Baz = A.Bar; + +// errors in prev block leave type bindings in place, so these are errors var m = A; var n = Foo; var o = Baz; + +// errors from value positions only var a: Foo = new Foo(); var b: Foo = new A.Foo(); -(new A.Bar(): Baz); -" +(new A.Bar(): Baz);" `; exports[`test import_type.js 1`] = ` @@ -121,17 +129,20 @@ var a: Foo = new actualA.Foo(); /** * @flow */ -// You can\'t use it as an identifier -// But using it in a type should still work + import typeof A from \"./A.js\"; import type {Foo, Bar as Baz} from \"./A.js\"; + var actualA = require(\"./A.js\"); + +// You can\'t use it as an identifier var m = A; var n = Foo; var o = Baz; + +// But using it in a type should still work var a: Foo = new actualA.Foo(); -(new actualA.Bar(): Baz); -" +(new actualA.Bar(): Baz);" `; exports[`test type_alias.js 1`] = ` @@ -152,12 +163,14 @@ type c = Foo; /** * @flow */ -// You can\'t use it as an identifier -// But using it in a type should still work + type Foo = number; + +// You can\'t use it as an identifier var x = Foo; + +// But using it in a type should still work var a: Foo = 123; var b: Array = [ 123 ]; -type c = Foo; -" +type c = Foo;" `; diff --git a/tests/type_param_defaults/__snapshots__/jsfmt.spec.js.snap b/tests/type_param_defaults/__snapshots__/jsfmt.spec.js.snap index 913a7d62..b8c7f197 100644 --- a/tests/type_param_defaults/__snapshots__/jsfmt.spec.js.snap +++ b/tests/type_param_defaults/__snapshots__/jsfmt.spec.js.snap @@ -66,71 +66,80 @@ var i_default: I<> = new I(\'hello\'); var i_star: I<*> = new I(\'hello\'); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// Test out simple defaults -// Error number ~> boolean -// Error void ~> boolean -// Error string ~> boolean -// Error number ~> boolean -// Error number ~> ?string -// Error void ~> boolean -// Error string ~> boolean -// Error string ~> boolean -// Error too few tparams -// Error too many tparams -// error, number ~> string -// Error number ~> boolean -// Error void ~> boolean -// Error string ~> boolean -// Error number ~> boolean -// Error: string ~> number -// Error: number ~> string -// Error string ~> boolean -// Error - can\'t refer to T before it\'s defined -// Error number ~> ?string + class A { p: T; constructor(p: T) { this.p = p; } } + +// Test out simple defaults class B extends A {} + var b_number: B = new B(123); var b_void: B = new B(); var b_default: B<> = new B(\"hello\"); + var b_star: B<*> = new B(123); + (b_number.p: boolean); +// Error number ~> boolean (b_void.p: boolean); +// Error void ~> boolean (b_default.p: boolean); +// Error string ~> boolean (b_star.p: boolean); +// Error number ~> boolean class C extends A {} + var c_number: C = new C(123); +// Error number ~> ?string var c_void: C = new C(); var c_default: C<> = new C(\"hello\"); var c_star: C<*> = new C(\"hello\"); + (c_void.p: boolean); +// Error void ~> boolean (c_default.p: boolean); +// Error string ~> boolean (c_star.p: boolean); +// Error string ~> boolean class D extends A {} var d_number: D = new D(123); var d_void: D = new D(); var d_default: D = new D(\"hello\"); var d_too_few_args: D<> = new D(\"hello\"); +// Error too few tparams var d_too_many: D = new D(\"hello\"); +// Error too many tparams var d_star: D<*> = new D(10); +// error, number ~> string (d_number.p: boolean); +// Error number ~> boolean (d_void.p: boolean); +// Error void ~> boolean (d_default.p: boolean); +// Error string ~> boolean (d_star.p: boolean); +// Error number ~> boolean class E {} +// Error: string ~> number class F {} +// Error: number ~> string class G extends A {} + var g_default: G = new G(\"hello\"); + (g_default.p: boolean); +// Error string ~> boolean class H {} +// Error - can\'t refer to T before it\'s defined class I extends A {} + var i_number: I = new I(123); +// Error number ~> ?string var i_void: I = new I(); var i_default: I<> = new I(\"hello\"); -var i_star: I<*> = new I(\"hello\"); -" +var i_star: I<*> = new I(\"hello\");" `; diff --git a/tests/type_param_scope/__snapshots__/jsfmt.spec.js.snap b/tests/type_param_scope/__snapshots__/jsfmt.spec.js.snap index 5bb63cb2..d96a3c2e 100644 --- a/tests/type_param_scope/__snapshots__/jsfmt.spec.js.snap +++ b/tests/type_param_scope/__snapshots__/jsfmt.spec.js.snap @@ -8,16 +8,15 @@ exports[`test class.js 1`] = ` b(x:T) {} } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// ok -// error: A ~> incompatible instance of T class C { a(x: T, a: A) { this.b(x); - this.b(a); + // ok + this.b(a); // error: A ~> incompatible instance of T } + b(x: T) {} -} -" +}" `; exports[`test default_params.js 1`] = ` @@ -34,26 +33,22 @@ exports[`test default_params.js 1`] = ` } f(0); // ok ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// ok -// ok -// err, T ~> U -// ok -// ok -// error: number ~> T -// ok function f(a: T) { function g(b: U, c: T = a) { function h(d: U = b) {} h(); + // ok h(b); - h(c); + // ok + h(c); // err, T ~> U } g(0); + // ok g(0, a); - g(0, 0); + // ok + g(0, 0); // error: number ~> T } -f(0); -" +f(0); // ok" `; exports[`test method_shadow.js 1`] = ` @@ -114,13 +109,7 @@ class H { // Ensure method type params properly shadow outer type params. Subclass ensures // the generated insttype has the correct tvars. Should behave the same for // classes, interfaces, and declared classes. -// Bounds can refer to parent type params (until they are shadowed). -// T-as-bound is G\'s T -// ok -// err, bool ~> number|string -// err, string ~> number -// Shadow bounds incompatible with parent -// err, m\'s T != H\'s T + class A { x: T; constructor(x: T) { @@ -130,15 +119,22 @@ class A { return new A(x); } } + class B extends A { m(x: T): B { return new B(x); } } + interface C { m(x: T): C } + interface D extends C { m(x: T): D } + declare class E { m(x: T): E } + declare class F extends E { m(x: T): F } + +// Bounds can refer to parent type params (until they are shadowed). class G { x: T; constructor(x: T) { @@ -146,17 +142,21 @@ class G { } m(x: T): G { return new G(x); - } + } // T-as-bound is G\'s T } + declare var g: G; g.m(0); +// ok g.m(true); +// err, bool ~> number|string (g.m(\"\"): G); +// err, string ~> number +// Shadow bounds incompatible with parent class H { x: T; m(x: T) { - this.x = x; + this.x = x; // err, m\'s T != H\'s T } -} -" +}" `; diff --git a/tests/type_param_variance/__snapshots__/jsfmt.spec.js.snap b/tests/type_param_variance/__snapshots__/jsfmt.spec.js.snap index 185e5603..d7cae017 100644 --- a/tests/type_param_variance/__snapshots__/jsfmt.spec.js.snap +++ b/tests/type_param_variance/__snapshots__/jsfmt.spec.js.snap @@ -39,18 +39,19 @@ run() * * @flow */ -// OK, because of covariant type param + async function foo(x: boolean): Promise { if (x) { - return { bar: \"baz\" }; + return { bar: \"baz\" }; // OK, because of covariant type param } else { return null; } } + async function run() { console.log(await foo(true)); console.log(await foo(false)); } -run(); -" + +run();" `; diff --git a/tests/type_param_variance2/__snapshots__/jsfmt.spec.js.snap b/tests/type_param_variance2/__snapshots__/jsfmt.spec.js.snap index adc9efec..558fc71c 100644 --- a/tests/type_param_variance2/__snapshots__/jsfmt.spec.js.snap +++ b/tests/type_param_variance2/__snapshots__/jsfmt.spec.js.snap @@ -33,18 +33,19 @@ run() * * @flow */ -// OK, because of covariant type param + async function foo(x: boolean): Promise { if (x) { - return { bar: \"baz\" }; + return { bar: \"baz\" }; // OK, because of covariant type param } else { return null; } } + async function run() { console.log(await foo(true)); console.log(await foo(false)); } -run(); -" + +run();" `; diff --git a/tests/type_param_variance2/libs/__snapshots__/jsfmt.spec.js.snap b/tests/type_param_variance2/libs/__snapshots__/jsfmt.spec.js.snap index 9646eecf..2cb773e3 100644 --- a/tests/type_param_variance2/libs/__snapshots__/jsfmt.spec.js.snap +++ b/tests/type_param_variance2/libs/__snapshots__/jsfmt.spec.js.snap @@ -48,12 +48,14 @@ declare class Promise { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Copyright 2004-present Facebook. All Rights Reserved. + // These annotations are copy/pasted from the built-in Flow definitions for // Native Promises (https://phabricator.fb.com/P19792689), // with www-specific additions added in. + // Any definitions here will override similarly-named ones in // library files declared earlier, including default flow libs. -// Non-standard APIs + declare class Promise { constructor( callback: ( @@ -72,6 +74,7 @@ declare class Promise { catch(onReject?: (error: any) => ?Promise | U): Promise, static resolve(object?: Promise | T): Promise, static reject(error?: any): Promise, + // Non-standard APIs finally(onSettled?: ?(value: any) => Promise | U): Promise, static cast(object?: T): Promise, static all(promises: Array | T>): Promise>, @@ -79,6 +82,5 @@ declare class Promise { static allObject(promisesByKey: T): Promise<{ [key: $Keys]: any }> -} -" +}" `; diff --git a/tests/typeapp_perf/__snapshots__/jsfmt.spec.js.snap b/tests/typeapp_perf/__snapshots__/jsfmt.spec.js.snap index 2de29582..c09896a1 100644 --- a/tests/typeapp_perf/__snapshots__/jsfmt.spec.js.snap +++ b/tests/typeapp_perf/__snapshots__/jsfmt.spec.js.snap @@ -22,7 +22,9 @@ declare var b: B; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* This test ensures that the code below does not take a long time to check. If * this test is taking a very long time to complete, there is a bug. */ + class A {} + type B = A & { +a: () => B, @@ -35,9 +37,10 @@ type B = A & +h: () => B, +i: () => B }; + declare var b: B; -(b: B); -" + +(b: B);" `; exports[`test test2.js 1`] = ` @@ -64,7 +67,9 @@ declare var b: B; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* This test ensures that the code below does not take a long time to check. If * this test is taking a very long time to complete, there is a bug. */ + class A {} + type B = A & { +a: (x: B) => void, @@ -77,7 +82,8 @@ type B = A & +h: (x: B) => void, +i: (x: B) => void }; + declare var b: B; -(b: B); -" + +(b: B);" `; diff --git a/tests/typecast/__snapshots__/jsfmt.spec.js.snap b/tests/typecast/__snapshots__/jsfmt.spec.js.snap index 3113a4f9..694dfbac 100644 --- a/tests/typecast/__snapshots__/jsfmt.spec.js.snap +++ b/tests/typecast/__snapshots__/jsfmt.spec.js.snap @@ -29,25 +29,19 @@ var tests = [ /** * Copyright 2004-present Facebook. All Rights Reserved. */ -// erroneous typcasts raise errors... -// ...but \'any\' does dynamic downcasts, if you must -// typecasts in sequences -// (parens always required around typecasts) -// TODO pending array element inference issues -// control case: -// var a : Array = [0, 1, 2, 3, 4, 5, 6, 7, null]; -// typecast case: -// var b = [(0 : ?number), 1, 2, 3, 4, 5, 6, 7, null]; var tests = [ () => { + // erroneous typcasts raise errors... var n = (\"hey\": number); + // ...but \'any\' does dynamic downcasts, if you must var x: number = (\"hey\": any); var y = ((\"hey\": any): number); }, () => { + // typecasts in sequences + // (parens always required around typecasts) var s: string = ((0: number), (\"hey\": string)); }, () => {} -]; -" +];" `; diff --git a/tests/typeof/__snapshots__/jsfmt.spec.js.snap b/tests/typeof/__snapshots__/jsfmt.spec.js.snap index 59a90c9e..05585e78 100644 --- a/tests/typeof/__snapshots__/jsfmt.spec.js.snap +++ b/tests/typeof/__snapshots__/jsfmt.spec.js.snap @@ -85,15 +85,25 @@ var f: typeof numberAlias = 42; // Error: \'typeof <>\' makes no sen /** * @flow */ + ////////////////////////////////// // == typeof <> == // ////////////////////////////////// + // MyClass1 is a runtime value, a constructor function // +class MyClass1 { + getNumber(): number { + return 42; + } +} + // a is an instance of MyClass1 - in runtime terms, // an object produced by the MyClass1 constructor // function. // +var a: MyClass1 = new MyClass1(); + // Following tests are errors which conflate the type // of the class value itself with the type of its // instances. @@ -114,47 +124,43 @@ var f: typeof numberAlias = 42; // Error: \'typeof <>\' makes no sen // Error: assign the actual MyClass1 value to a variable // whose annotated type is of instances of MyClass1. // +var b: MyClass1 = MyClass1; + +class MyClass2 { + getNumber1(): number { + return 42; + } +} + // The opposite error: assign an *instance* of MyClass2 // to a variable whose annotated type is the type of // the class value (constructor function) MyClass2 itself. // +var c: typeof MyClass2 = new MyClass2(); + ////////////////////////////////////// // == typeof <> == // ////////////////////////////////////// +var numValue: number = 42; +var d: typeof numValue = 100; +var e: typeof numValue = \"asdf\"; // Error: string ~> number ///////////////////////////////// // == typeof <> == // ///////////////////////////////// +type numberAlias = number; + // This is an error because typeof takes a value, not // a type, as an argument. However, the current error // is suboptimal - just \'cannot resolve name\'. TODO. // +var f: typeof numberAlias = 42; // Error: \'typeof <>\' makes no sense... /** * Use of a non-class/non-function value in type annotation. * These provoke a specific error, not just the generic * \"type is incompatible\" */ -// Error: ineligible value used in type anno -class MyClass1 { - getNumber(): number { - return 42; - } -} -var a: MyClass1 = new MyClass1(); -var b: MyClass1 = MyClass1; -class MyClass2 { - getNumber1(): number { - return 42; - } -} -var c: typeof MyClass2 = new MyClass2(); -var numValue: number = 42; -var d: typeof numValue = 100; -var e: typeof numValue = \"asdf\"; -type numberAlias = number; -var f: typeof numberAlias = 42; var Map = { \"A\": \"this is A\", \"B\": \"this is B\", \"C\": \"this is C\" }; -var keys: $Keys = \"A\"; -" +var keys: $Keys = \"A\"; // Error: ineligible value used in type anno" `; diff --git a/tests/unary/__snapshots__/jsfmt.spec.js.snap b/tests/unary/__snapshots__/jsfmt.spec.js.snap index 8caffa30..f7fc3769 100644 --- a/tests/unary/__snapshots__/jsfmt.spec.js.snap +++ b/tests/unary/__snapshots__/jsfmt.spec.js.snap @@ -20,25 +20,24 @@ function x4(y: string): boolean { (-1: void); // error, number ~> void ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// ok, + exists solely for coercion -// error, we don\'t allow coercion here -// error, we don\'t allow coercion here -// ok, coercion is allowed -// error, number ~> void + function x0(y: string): number { - return +y; + return +y; // ok, + exists solely for coercion } + function x1(y: string): number { - return -y; + return -y; // error, we don\'t allow coercion here } + function x3(y: string) { - return ~y; + return ~y; // error, we don\'t allow coercion here } + function x4(y: string): boolean { - return !y; + return !y; // ok, coercion is allowed } -(-1: void); -" + +(-1: void); // error, number ~> void" `; exports[`test update.js 1`] = ` @@ -82,15 +81,7 @@ let tests = [ ]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// error, we don\'t allow coercion here -// ok, y is a number now -// error, but you still can\'t write a number to a string -// error, we don\'t allow coercion here -// error, we don\'t allow coercion here -// error, we don\'t allow coercion here -// error, can\'t update const -// error, can\'t update const -// ok + let tests = [ function(y: number) { y++; @@ -100,26 +91,28 @@ let tests = [ }, function(y: string) { y++; + // error, we don\'t allow coercion here (y: number); - y++; + // ok, y is a number now + y++; // error, but you still can\'t write a number to a string }, function(y: string) { - y--; + y--; // error, we don\'t allow coercion here }, function(y: string) { - ++y; + ++y; // error, we don\'t allow coercion here }, function(y: string) { - --y; + --y; // error, we don\'t allow coercion here }, function() { const y = 123; y++; - y--; + // error, can\'t update const + y--; // error, can\'t update const }, function(y: any) { - y++; + y++; // ok } -]; -" +];" `; diff --git a/tests/unchecked_haste_module_vs_lib/__snapshots__/jsfmt.spec.js.snap b/tests/unchecked_haste_module_vs_lib/__snapshots__/jsfmt.spec.js.snap index c300345f..6c9ef362 100644 --- a/tests/unchecked_haste_module_vs_lib/__snapshots__/jsfmt.spec.js.snap +++ b/tests/unchecked_haste_module_vs_lib/__snapshots__/jsfmt.spec.js.snap @@ -22,8 +22,8 @@ export var INSPECT_MAX_BYTES = 0; * the same name as an unchecked module, it will be used * to satisfy imports/requires instead. */ -export var INSPECT_MAX_BYTES = 0; -" + +export var INSPECT_MAX_BYTES = 0;" `; exports[`test test.js 1`] = ` @@ -45,14 +45,13 @@ var x: string = buffer.INSPECT_MAX_BYTES; // error, number ~/> string * Copyright 2004-present Facebook. All Rights Reserved. * @flow */ + /* \'buffer\' is the name of both an unchecked module in this directory, * and a module declared in library file node.js. * If the require below resolves to the unchecked module, the mistyping * that follows will cause no errors, but if we resolve to the library * instead, we\'ll get the desired error. */ -// error, number ~/> string var buffer = require(\"buffer\"); -var x: string = buffer.INSPECT_MAX_BYTES; -" +var x: string = buffer.INSPECT_MAX_BYTES; // error, number ~/> string" `; diff --git a/tests/unchecked_node_module_vs_lib/__snapshots__/jsfmt.spec.js.snap b/tests/unchecked_node_module_vs_lib/__snapshots__/jsfmt.spec.js.snap index 9d800772..7d9408e4 100644 --- a/tests/unchecked_node_module_vs_lib/__snapshots__/jsfmt.spec.js.snap +++ b/tests/unchecked_node_module_vs_lib/__snapshots__/jsfmt.spec.js.snap @@ -32,25 +32,24 @@ var x3: string = buffer3.INSPECT_MAX_BYTES; // error, module not found * * @flow */ + // node_modules/buffer/index.js is unchecked, // so we shouldn\'t pick up its boolean redefinition of INSPECT_MAX_BYTES // +var buffer = require(\"buffer\"); +var b: boolean = buffer.INSPECT_MAX_BYTES; // error, number ~/> boolean // node_modules/crypto/index.js is checked, // so we should pick up its boolean redefinition of DEFAULT_ENCODING // +var crypto = require(\"crypto\"); +var b: boolean = crypto.DEFAULT_ENCODING; // no error, we\'ve overridden // names that are explicit paths shouldn\'t fall back to lib defs // -// error, module not found -// error, module not found -var buffer = require(\"buffer\"); -var b: boolean = buffer.INSPECT_MAX_BYTES; -var crypto = require(\"crypto\"); -var b: boolean = crypto.DEFAULT_ENCODING; var buffer2 = require(\"./buffer\"); var x2: string = buffer2.INSPECT_MAX_BYTES; +// error, module not found var buffer3 = require(\"./buffer.js\"); -var x3: string = buffer3.INSPECT_MAX_BYTES; -" +var x3: string = buffer3.INSPECT_MAX_BYTES; // error, module not found" `; diff --git a/tests/undefined/__snapshots__/jsfmt.spec.js.snap b/tests/undefined/__snapshots__/jsfmt.spec.js.snap index 8535e766..1b9c1294 100644 --- a/tests/undefined/__snapshots__/jsfmt.spec.js.snap +++ b/tests/undefined/__snapshots__/jsfmt.spec.js.snap @@ -12,18 +12,18 @@ exports[`test issue-518.js 1`] = ` function foo(x: void) { } foo(); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// OK to leave out arg, same as resolve(undefined) -// simpler repro to show that too few args are fine when expecting void function doSomethingAsync(): Promise { return new Promise((resolve, reject) => { resolve(); + // OK to leave out arg, same as resolve(undefined) var anotherVoidPromise: Promise = Promise.resolve(); resolve(anotherVoidPromise); }); } + +// simpler repro to show that too few args are fine when expecting void function foo(x: void) {} -foo(); -" +foo();" `; exports[`test undefined.js 1`] = ` @@ -43,13 +43,14 @@ function foo() { var x; x.foo(); } + function bar() { var x: ?{ bar(): void }; if (x) x.bar(); } -function qux(x?: number, y: string = \"\", z) {} -" + +function qux(x?: number, y: string = \"\", z) {}" `; exports[`test undefined2.js 1`] = ` @@ -86,29 +87,27 @@ let tests = [ ]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -// error, string or void -// error, string or void -// ok -// should error, could be void -// error, string only + let tests = [ function(x: number) { var id; var name = id ? \"John\" : undefined; (name: boolean); + // error, string or void const bar = [ undefined, \"bar\" ]; - (bar[x]: boolean); + (bar[x]: boolean); // error, string or void }, function(x: number) { var undefined = \"foo\"; (undefined: string); + // ok var x; if (x !== undefined) { - x[0]; + x[0]; // should error, could be void } + const bar = [ undefined, \"bar\" ]; - (bar[x]: boolean); + (bar[x]: boolean); // error, string only } -]; -" +];" `; diff --git a/tests/unicode/__snapshots__/jsfmt.spec.js.snap b/tests/unicode/__snapshots__/jsfmt.spec.js.snap index b9fa1163..e19172c6 100644 --- a/tests/unicode/__snapshots__/jsfmt.spec.js.snap +++ b/tests/unicode/__snapshots__/jsfmt.spec.js.snap @@ -37,10 +37,15 @@ function utf16Length(str, pos) { /** * @flow */ + /** * @param {number} codeUnit A Unicode code-unit, in range [0, 0x10FFFF] * @return {boolean} Whether code-unit is in a surrogate (hi/low) range */ +function inSurrogateRange(codeUnit) { + return 55296 <= codeUnit && codeUnit <= 57343; +} + /** * Return the length of the original Unicode character at given position in the * String by looking into the UTF-16 code unit; that is equal to 1 for any @@ -59,11 +64,7 @@ function utf16Length(str, pos) { * @param {number} pos Position in the string to look for one code unit * @return {number} Number 1 or 2 */ -function inSurrogateRange(codeUnit) { - return 55296 <= codeUnit && codeUnit <= 57343; -} function utf16Length(str, pos) { return 1 + inSurrogateRange(str.charCodeAt(pos)); -} -" +}" `; diff --git a/tests/union-intersection/__snapshots__/jsfmt.spec.js.snap b/tests/union-intersection/__snapshots__/jsfmt.spec.js.snap index 4f6d862e..d8d26a5d 100644 --- a/tests/union-intersection/__snapshots__/jsfmt.spec.js.snap +++ b/tests/union-intersection/__snapshots__/jsfmt.spec.js.snap @@ -5006,8 +5006,7 @@ type TAction = { type: \"a1\", a1: number } | { type: \"a1000\", a100: number }; function foo(x: TAction): TAction { return x; -} -" +}" `; exports[`test test.js 1`] = ` @@ -5030,21 +5029,24 @@ function f4(x: T4): T4 { return x; } type A = { a: number }; type B = { b: number }; type C = { c: number }; + type T1 = (A | B) & C; function f1(x: T1): T1 { return x; } + type T2 = (A & B) | C; function f2(x: T2): T2 { return x; } + type T3 = (A & C) | (B & C); function f3(x: T3): T3 { return x; } + type T4 = (A | C) & (B | C); function f4(x: T4): T4 { return x; -} -" +}" `; diff --git a/tests/union/__snapshots__/jsfmt.spec.js.snap b/tests/union/__snapshots__/jsfmt.spec.js.snap index abb305ad..159b375a 100644 --- a/tests/union/__snapshots__/jsfmt.spec.js.snap +++ b/tests/union/__snapshots__/jsfmt.spec.js.snap @@ -11,8 +11,7 @@ class C { constructor() { this.x = null; } -} -" +}" `; exports[`test fields2.js 1`] = ` @@ -27,14 +26,14 @@ class D { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class C {} + class D { content: string | C; copyContent(content: C): string | C { this.content = content; return this.content; } -} -" +}" `; exports[`test issue-17.js 1`] = ` @@ -56,7 +55,9 @@ var l: Array = [ ]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + type T = { type: \"a\", a: number } | { type: \"b\", b: string }; + var l: Array = [ { type: \"a\", a: 1 }, { type: \"a\", a: 2 }, @@ -66,8 +67,7 @@ var l: Array = [ { type: \"b\", b: \"gorilla\" }, { type: \"b\", b: \"giraffe\" }, { type: \"b\", b: \"penguin\" } -]; -" +];" `; exports[`test issue-198.js 1`] = ` @@ -82,7 +82,6 @@ exports[`test issue-198.js 1`] = ` return str.toFixed(); }); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// This should fail because str is string, not number var p = new Promise(function(resolve, reject) { resolve(5); }) @@ -90,9 +89,9 @@ var p = new Promise(function(resolve, reject) { return num.toFixed(); }) .then(function(str) { + // This should fail because str is string, not number return str.toFixed(); - }); -" + });" `; exports[`test issue-256.js 1`] = ` @@ -106,9 +105,9 @@ myclass.myfun([\"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", function (ar) {} ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ declare class Myclass { myfun(myarray: Array): any } declare var myclass: Myclass; + myclass.myfun([ \"1\", \"2\", \"3\", \"4\", \"5\", \"6\", function(ar) {} ]); -myclass.myfun([ \"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", function(ar) {} ]); -" +myclass.myfun([ \"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", function(ar) {} ]);" `; exports[`test issue-323.js 1`] = ` @@ -118,8 +117,7 @@ var foostr: Foo | string = foo; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ var Foo = require(\"./issue-323-lib\"); var foo = new Foo(); -var foostr: Foo | string = foo; -" +var foostr: Foo | string = foo;" `; exports[`test issue-323-lib.js 1`] = ` @@ -129,8 +127,7 @@ module.exports = Foo; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ class Foo {} -module.exports = Foo; -" +module.exports = Foo;" `; exports[`test issue-324.js 1`] = ` @@ -145,11 +142,13 @@ foostr = barstr; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ class Foo {} + class Bar {} + var foostr: Foo | string = new Foo(); var barstr: Bar | string = new Bar(); -foostr = barstr; -" + +foostr = barstr;" `; exports[`test issue-325.js 1`] = ` @@ -174,14 +173,14 @@ class Tag { var a2: Array = a1; } } + type Node = Tag_ | string; class Tag_ { constructor() { var a1: Array = [ new Tag_() ]; var a2: Array = a1; } -} -" +}" `; exports[`test issue-326.js 1`] = ` @@ -190,11 +189,10 @@ var stringArr:Array = [\'a\',\'b\']; var result = numberAndStringArr.concat(stringArr); // no error ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// no error var numberAndStringArr: Array = [ 1, 2 ]; var stringArr: Array = [ \"a\", \"b\" ]; -var result = numberAndStringArr.concat(stringArr); -" + +var result = numberAndStringArr.concat(stringArr); // no error" `; exports[`test issue-582.js 1`] = ` @@ -217,14 +215,16 @@ var nested2: FooBarBaz = \'baz\'; * nested unions * @flow */ + // inline -// through tvars var nested1: (\"foo\" | \"bar\") | \"baz\" = \"baz\"; + +// through tvars type FooBar = \"foo\" | \"bar\"; type Baz = \"baz\"; type FooBarBaz = FooBar | Baz; -var nested2: FooBarBaz = \"baz\"; -" + +var nested2: FooBarBaz = \"baz\";" `; exports[`test issue-963.js 1`] = ` @@ -267,16 +267,22 @@ const u3 : union2 = { * unions with embedded intersections * @flow */ + type t1 = { p1: number }; + type t2 = { p2: number }; + type t3 = { p3: number }; + type intersected = t1 & t2; type union = intersected | t3; type union2 = t3 | intersected; + const u1: union = { p3: 3 }; + const u2: union = { p1: 1, p2: 2 }; -const u3: union2 = { p1: 1, p2: 2 }; -" + +const u3: union2 = { p1: 1, p2: 2 };" `; exports[`test test.js 1`] = ` @@ -299,26 +305,27 @@ function f() { return \"\"; } function bar(x:Bar) { } bar(f); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +var C = require(\"test-lib\"); + // TODO: spurious error! (replacing C with number makes the error go away) // type Foo = Array | Array; -// workaround -// TODO: spurious error! (replacing C with number makes the error go away) -// type Bar = (() => C) | (() => string); -// workaround -var C = require(\"test-lib\"); type Foo = Array; +// workaround var x: Array = []; var y: Array = []; function foo(x: Foo) {} foo(x); foo(y); + +// TODO: spurious error! (replacing C with number makes the error go away) +// type Bar = (() => C) | (() => string); type Bar = () => C | string; +// workaround function f() { return \"\"; } function bar(x: Bar) {} -bar(f); -" +bar(f);" `; exports[`test test-lib.js 1`] = ` @@ -328,9 +335,9 @@ class C { } module.exports = C; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @providesModule test-lib */ + class C {} -module.exports = C; -" +module.exports = C;" `; exports[`test type-app.js 1`] = ` @@ -352,15 +359,17 @@ var b: Iterator | number = 123; /** * @flow */ + +class LocalClass {} + +var a: LocalClass | number = 123; + // Iterator is defined in a lib file, so the speculative algorithm for the // union type would incorrectly succeed for Iterator. Only later during // the merge would we fine the error, but it would be too late. The diff that // introduces this test fixes this such that the speculative algorithm is // correctly delayed upon encountering a non-concrete TypeAppT -class LocalClass {} -var a: LocalClass | number = 123; -var b: Iterator | number = 123; -" +var b: Iterator | number = 123;" `; exports[`test union.js 1`] = ` @@ -386,26 +395,27 @@ function corge(b) { new F().foo(x); } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// error, since E could be D, and D is not a subtype of C -// this annotation is an error: is it C, or is it D? -// OK function bar(x: Document | string): void {} bar(0); + class C {} class D {} function CD(b) { var E = b ? C : D; var c: C = new E(); + // error, since E could be D, and D is not a subtype of C function qux(e: E) {} + // this annotation is an error: is it C, or is it D? function qux2(e: C | D) {} + // OK qux2(new C()); } + declare class F { foo(x: number): void, foo(x: string): void } function corge(b) { var x = b ? \"\" : 0; new F().foo(x); -} -" +}" `; exports[`test yuge.js 1`] = ` @@ -5447,23 +5457,26 @@ type Data = { * This is a band-aid, though: see second case. * @flow */ -// Bug: right now, any incompatible type coming into a huge -// union might blow the recursion limit. -// TODO real solution is to specialize union reps for obvious cases, -// e.g. (base type, list in decl order, set). Of course we could do -// something quick to get the union size off the Ocaml call stack, -// but not sure it\'s worth doing that before the real solution. -// also, error pos omits this line completely \"use strict\"; + class SecurityCheckupTypedLogger { _data: Data; + setError(value: ErrorCode) { this._data[\"error\"] = value; } + + // Bug: right now, any incompatible type coming into a huge + // union might blow the recursion limit. + // TODO real solution is to specialize union reps for obvious cases, + // e.g. (base type, list in decl order, set). Of course we could do + // something quick to get the union size off the Ocaml call stack, + // but not sure it\'s worth doing that before the real solution. ohThatsNotSoGood() { - (\"\": ErrorCode); + (\"\": ErrorCode); // also, error pos omits this line completely } } + type ErrorCode = 0 | 1 | 2 | @@ -10464,6 +10477,6 @@ type ErrorCode = 0 | 4997 | 4998 | 4999; -type Data = { error?: ErrorCode }; -" + +type Data = { error?: ErrorCode };" `; diff --git a/tests/union_new/__snapshots__/jsfmt.spec.js.snap b/tests/union_new/__snapshots__/jsfmt.spec.js.snap index 8086d870..e2ebbb3e 100644 --- a/tests/union_new/__snapshots__/jsfmt.spec.js.snap +++ b/tests/union_new/__snapshots__/jsfmt.spec.js.snap @@ -24,21 +24,24 @@ class VirtualNode { /* @flow */ type T = A | B; class U {} + declare var children: U; (children: T | U); class A {} + class B {} + type VirtualElement = Thunk | VirtualNode; type Child = VirtualElement; type Children = Array; + class Thunk {} class VirtualNode { children: Child | Children; constructor(type, children: Children) { this.children = children.length === 1 ? children[0] : children; } -} -" +}" `; exports[`test issue-824.js 1`] = ` @@ -60,8 +63,11 @@ export default class A { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ import {B, C} from \"./issue-824-helper\"; + type K = B | C; + type I = { which(): number }; + export default class A { static foo(p: K): boolean { return false; @@ -69,8 +75,7 @@ export default class A { static bar(p: I & K): boolean { return this.foo(p); } -} -" +}" `; exports[`test issue-824-helper.js 1`] = ` @@ -88,6 +93,7 @@ export class C extends A { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ import A from \"./issue-824\"; + export class B extends A { which(): number { return 1; @@ -97,8 +103,7 @@ export class C extends A { which(): number { return 2; } -} -" +}" `; exports[`test issue-1349.js 1`] = ` @@ -110,11 +115,11 @@ var bar: Array<{b: ?boolean, c: number} | {b: boolean}> = [ ]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + var bar: Array<{ b: ?boolean, c: number } | { b: boolean }> = [ { b: true, c: 123 }, { b: true } -]; -" +];" `; exports[`test issue-1371.js 1`] = ` @@ -130,8 +135,7 @@ function create( a: any ): { type: \"B\", data: number } | { type: \"A\", data: string } { return { type: \"A\", data: a }; -} -" +}" `; exports[`test issue-1455.js 1`] = ` @@ -147,11 +151,12 @@ function node(content: ?Foobar | String | Array) { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ import type {Foobar} from \"./issue-1455-helper\"; + function create(content: ?Foobar | String | Array) {} + function node(content: ?Foobar | String | Array) { create(content); -} -" +}" `; exports[`test issue-1455-helper.js 1`] = ` @@ -160,8 +165,8 @@ exports[`test issue-1455-helper.js 1`] = ` export class Foobar { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -export class Foobar {} -" + +export class Foobar {}" `; exports[`test issue-1462-i.js 1`] = ` @@ -188,18 +193,21 @@ function printAll(val: MyType) { print(val.foo); // <--- foo could be an array } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// <--- foo could be an array type Common = {}; + type A = Common & { type: \"A\", foo: number }; + type B = Common & { type: \"B\", foo: Array }; + type MyType = A | B; + function print(x: number) { console.log(x); } + function printAll(val: MyType) { - print(val.foo); -} -" + print(val.foo); // <--- foo could be an array +}" `; exports[`test issue-1462-ii.js 1`] = ` @@ -232,20 +240,24 @@ function printAll(val: MyType) { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ type Common = {}; + type A = { type: \"A\", foo: number } & Common; + type B = { type: \"B\", foo: Array } & Common; + type MyType = A | B; + function print(x: number) { console.log(x); } + function printAll(val: MyType) { if (val.type === \"A\") { print(val.foo); } else { val.foo.forEach(print); } -} -" +}" `; exports[`test issue-1664.js 1`] = ` @@ -277,15 +289,20 @@ if (data.kind === \"system\") { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + type DataBase = { id: string, name: string }; + type UserData = DataBase & { kind: \"user\" }; + type SystemData = DataBase & { kind: \"system\" }; + type Data = UserData | SystemData; + const data: Data = { id: \"\", name: \"\", kind: \"system\" }; + if (data.kind === \"system\") { (data: SystemData); -} -" +}" `; exports[`test issue-1759.js 1`] = ` @@ -299,15 +316,15 @@ function hello(x:X): string { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -//type X = {a:true, b:string} | {a:false, c:string}; // this works. + type X = ({ a: true } & { b: string }) | ({ a: false } & { c: string }); +//type X = {a:true, b:string} | {a:false, c:string}; // this works. function hello(x: X): string { if (x.a === true) return x.b; else return x.c; -} -" +}" `; exports[`test issue-2232.js 1`] = ` @@ -337,16 +354,19 @@ function test(f: Foo| EmptyFoo) { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ + type Entity = { id: T, name: string }; + type StringEntity = Entity; + type Foo = StringEntity & { bars: Object, kind: 1 }; type EmptyFoo = StringEntity & { bars: null, kind: 2 }; + function test(f: Foo | EmptyFoo) { if (f.kind === 1) { (f: Foo); } -} -" +}" `; exports[`test test1.js 1`] = ` @@ -412,49 +432,62 @@ type A5 = B5[]; type A6 = B6[]; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @noflow + /** * Test that shows how the implementation of union types is broken */ + ////////////////////////////// // example with object types ////////////////////////////// + +function obj(a: A1 | A2) { + return a.x; +} + +const obj_result = obj({ x: \"\" }); // currently an error! (expect it to be OK) // Type definitions used above are defined below, but in an order that // deliberately makes their full resolution as lazy as possible. The call above // blocks until A1 is partially resolved. Since the argument partially matches // A1, that branch is selected. Later, that branch errors, but other branches // have been lost by then. +type A1 = { x: B1 }; +type A2 = { x: B2 }; + +type B1 = number; +type B2 = string; + +(obj_result: B1 | B2); + /////////////////////////////////////// // similar example with function types /////////////////////////////////////// -///////////////////////////////////////////// -// similar example with class instance types -///////////////////////////////////////////// -function obj(a: A1 | A2) { - return a.x; -} -const obj_result = obj({ x: \"\" }); -type A1 = { x: B1 }; -type A2 = { x: B2 }; -type B1 = number; -type B2 = string; -(obj_result: B1 | B2); function fun(a: A3 | A4) { return a(); } + const fun_result = fun(() => \"\"); + type A3 = () => B3; type A4 = () => B4; + type B3 = number; type B4 = string; + (fun_result: B3 | B4); + +///////////////////////////////////////////// +// similar example with class instance types +///////////////////////////////////////////// function inst(a: A5 | A6) {} + class B5 {} class B6 {} inst([ new B6() ]); + type A5 = B5[]; -type A6 = B6[]; -" +type A6 = B6[];" `; exports[`test test2.js 1`] = ` @@ -537,53 +570,77 @@ type A6 = [B6,boolean]; type B6 = string; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @noflow + /** * Test that shows how the implementation of union types is broken */ + ////////////////////////////// // example with object types ////////////////////////////// + +function obj(a: { x: number } | { x: string }) {} + +obj(({ x: \"\" }: A1)); + +type A1 = { x: B1 }; + +type B1 = string; + /////////////////////////////////////// // similar example with function types /////////////////////////////////////// +function fun(a: (() => number) | (() => string)) {} + +fun((() => \"\": A2)); + +type A2 = () => B2; + +type B2 = string; + ///////////////////////////////////////////////////// // similar example with generic class instance types ///////////////////////////////////////////////////// +class C {} + +function inst(a: C | C) {} + +inst((new C(): A3)); + +type A3 = C; + +type B3 = string; + ///////////////////////////////////////////// // similar example with generic type aliases ///////////////////////////////////////////// -// class statics -// tuples -function obj(a: { x: number } | { x: string }) {} -obj(({ x: \"\" }: A1)); -type A1 = { x: B1 }; -type B1 = string; -function fun(a: (() => number) | (() => string)) {} -fun((() => \"\": A2)); -type A2 = () => B2; -type B2 = string; -class C {} -function inst(a: C | C) {} -inst((new C(): A3)); -type A3 = C; -type B3 = string; function alias(a: T | T) {} alias({ x: (x: V) => {} }); + type T = { x: U }; type U = (x: V) => void; type V = X; + type B4 = string; + +// class statics function stat(a: { x: number } | { x: string }) {} + class D { static x: B5; } + stat(D); + type B5 = string; + +// tuples function tup(a: [number, boolean] | [string, boolean]) {} + tup(([ \"\", false ]: A6)); + type A6 = [B6, boolean]; -type B6 = string; -" +type B6 = string;" `; exports[`test test3.js 1`] = ` @@ -618,24 +675,33 @@ type A2 = B2[]; type B2 = string; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @noflow + /** * Test that shows how the implementation of union types is broken */ + /////////////////////////////// // example with function types /////////////////////////////// + +function fun(a: ((x: number) => void) | ((x: string) => void)) {} + +fun((x => {}: A1)); + +type A1 = (x: B1) => void; + +type B1 = string; + //////////////////////////// // example with array types //////////////////////////// -function fun(a: ((x: number) => void) | ((x: string) => void)) {} -fun((x => {}: A1)); -type A1 = (x: B1) => void; -type B1 = string; function arr(a: number[] | string[]) {} + arr(([]: A2)); + type A2 = B2[]; -type B2 = string; -" + +type B2 = string;" `; exports[`test test4.js 1`] = ` @@ -677,35 +743,46 @@ type A2 = B2[]; type B2 = string; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @noflow + /** * Test that shows how the implementation of union types is broken */ + /////////////////////////////// // example with function types /////////////////////////////// -//////////////////////////// -// example with array types -//////////////////////////// + function fun(a: ((x: number) => void) | ((x: string) => void)) {} + const a1 = (x => {}: A1); fun(a1); + function fun_call(x: string) { a1(x); } + type A1 = (x: B1) => void; + type B1 = string; + +//////////////////////////// +// example with array types +//////////////////////////// function arr(a: number[] | string[]) {} + const a2 = ([]: A2); arr(a2); + function arr_set(x: string, i: number) { a2[i] = x; } function arr_get(i: number): string { return a2[i]; } + type A2 = B2[]; -type B2 = string; -" + +type B2 = string;" `; exports[`test test5.js 1`] = ` @@ -738,30 +815,37 @@ arr(a2); function arr_set(x: string, i: number) { a2[i] = x; } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @noflow + /** * Test that shows how the implementation of union types is broken */ + /////////////////////////////// // example with function types /////////////////////////////// -///////////////////////////// -// example with array types -///////////////////////////// + function fun(a: ((x: number) => number) | ((x: string) => string)) {} + function a1(x) { return x; } fun(a1); + function fun_call(x: string): string { return a1(x); } + +///////////////////////////// +// example with array types +///////////////////////////// function arr(a: number[] | string[]) {} + var a2 = []; arr(a2); + function arr_set(x: string, i: number) { a2[i] = x; -} -" +}" `; exports[`test test6.js 1`] = ` @@ -792,25 +876,32 @@ class D extends _C { } class C { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @noflow + /** * Test that shows how the implementation of union types is broken */ + ////////////////////////////////////////// // example with generic class inheritance ////////////////////////////////////////// + function inst(a: E): C | C { return a; } + const mk_C = () => C; const mk_D = () => D; const mk_E = () => E; + type B4 = string; + const _D = mk_D(); class E extends _D {} + const _C = mk_C(); class D extends _C {} -class C {} -" + +class C {}" `; exports[`test test7.js 1`] = ` @@ -845,28 +936,33 @@ type PF = PG; type PG = { x: X, y?: PG }; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @noflow + /** * Test that shows how the implementation of union types is broken */ + //////////////////// // recursive types //////////////////// -/////////////////////////////// -// polymorphic recursive types -/////////////////////////////// + function rec(x: F1 | F2) {} rec({ x: 0 }); + type F1 = G1; type F2 = G2; type G1 = { x: H1, y?: G1 }; type G2 = { x: H2, y?: G2 }; type H1 = string; type H2 = number; + +/////////////////////////////// +// polymorphic recursive types +/////////////////////////////// function polyrec(x: PF | PF) {} rec({ x: 0 }); + type PF = PG; -type PG = { x: X, y?: PG }; -" +type PG = { x: X, y?: PG };" `; exports[`test test8.js 1`] = ` @@ -895,14 +991,18 @@ type H2 = boolean; type H2_ = number; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @noflow + /** * Test that shows how the implementation of union types is broken */ + ////////////////////// // nested union types ////////////////////// + function rec(x: F1 | F2) {} rec({ x: 0 }); + type F1 = G1 | G1_; type F2 = G2 | G2_; type G1 = { x: H1 }; @@ -912,8 +1012,7 @@ type G2_ = { x: H2_ }; type H1 = boolean; type H1_ = string; type H2 = boolean; -type H2_ = number; -" +type H2_ = number;" `; exports[`test test9.js 1`] = ` @@ -935,18 +1034,21 @@ function foo(f: ((_: ?number) => ?number) | (() => void)) { } foo((x): number => square(x)) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @noflow + /** * Test that shows how the implementation of union types is broken */ + //////////////// // interference //////////////// + function square(x? = 0) { return x * x; } + function foo(f: ((_: ?number) => ?number) | (() => void)) {} -foo((x): number => square(x)); -" +foo((x): number => square(x));" `; exports[`test test10.js 1`] = ` @@ -1024,57 +1126,73 @@ function check_poly_inst(_: P | P) { } check_poly_inst(new P); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @noflow -///////////////////////// -// primitive annotations -///////////////////////// -// ok -// ...even when they \"flow\" in -////////////////////////////// -// class instance annotations -////////////////////////////// -// ok -// ...even when they \"flow\" in -//////////////////////// -// function annotations -//////////////////////// -// help! -////////////////////// -// object annotations -////////////////////// -// ok -// help! -///////////////////// -// array annotations -///////////////////// -// ok -// help! -////////////////////////////////////// -// generic class instance annotations -////////////////////////////////////// -// help! + function id(x: X): X { return x; } + +///////////////////////// +// primitive annotations +///////////////////////// function check_prim(_: number | string) {} + +// ok check_prim(\"\"); + +// ...even when they \"flow\" in check_prim(id(\"\")); + +////////////////////////////// +// class instance annotations +////////////////////////////// class C {} class D {} function check_inst(_: C | D) {} + +// ok check_inst(new D()); + +// ...even when they \"flow\" in check_inst(id(new C())); + +//////////////////////// +// function annotations +//////////////////////// function check_fun(_: ((_: number) => number) | ((_: string) => string)) {} + +// help! check_fun(x => x); + +////////////////////// +// object annotations +////////////////////// function check_obj(_: { x: number } | { x: string }) {} + +// ok check_obj({ x: \"\" }); + +// help! check_obj({ x: id(\"\") }); + +///////////////////// +// array annotations +///////////////////// function check_arr(_: number[] | string[]) {} + +// ok check_arr([ \"\" ]); + +// help! check_arr([ id(\"\") ]); + +////////////////////////////////////// +// generic class instance annotations +////////////////////////////////////// class P {} function check_poly_inst(_: P | P) {} -check_poly_inst(new P()); -" + +// help! +check_poly_inst(new P());" `; exports[`test test11.js 1`] = ` @@ -1098,23 +1216,25 @@ type Nil = { kind: \"nil\" }; type Cons = { kind: \"cons\", next: List }; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @noflow + // disjoint unions -// missing \`next\` -// \`kind\` not found + function length(list: List) { if (list.kind === \"cons\") return length(list.next) + 1; else return 0; } + length({ kind: \"nil\" }); length({ kind: \"cons\" }); +// missing \`next\` length({ kind: \"cons\", next: { kind: \"nil\" } }); length({ kind: \"empty\" }); +// \`kind\` not found type List = Nil | Cons; type Nil = { kind: \"nil\" }; -type Cons = { kind: \"cons\", next: List }; -" +type Cons = { kind: \"cons\", next: List };" `; exports[`test test12.js 1`] = ` @@ -1129,14 +1249,16 @@ type H = { x: string } function rec(x: F): G | H { return x; } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @noflow + // polymorphic recursive types + type F = { f: F, x: X }; type G = { x: number }; type H = { x: string }; + function rec(x: F): G | H { return x; -} -" +}" `; exports[`test test13.js 1`] = ` @@ -1153,10 +1275,11 @@ exports[`test test13.js 1`] = ` }); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @noflow + /* ensure there are no unintended side effects when trying branches */ + ({ type: \"B\", id: \"hi\" }: { type: \"A\", id: ?string } | - { type: \"B\", id: string }); -" + { type: \"B\", id: string });" `; exports[`test test14.js 1`] = ` @@ -1175,13 +1298,16 @@ function foo(c: C) { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @noflow + // annotations + declare class C { get(): X } + function union(o: { x: string } | { x: number }) {} + function foo(c: C) { union({ x: c.get() }); -} -" +}" `; exports[`test test15.js 1`] = ` @@ -1211,22 +1337,28 @@ function bar(x: (() => void) | { x: number }) { } bar(() => { }); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @noflow + // functions as objects -// example where globals are not yet resolved + function foo(target: EventTarget) { target.addEventListener(\"click\", e => {}); } + declare class EventTarget { addEventListener(type: \"foo\", listener: KeyboardEventHandler): void, addEventListener(type: string, listener: EventHandler): void } + declare class Event {} declare class KeyboardEvent {} + type EventHandler = (event: Event) => mixed; type KeyboardEventHandler = (event: KeyboardEvent) => mixed; + +// example where globals are not yet resolved function bar(x: (() => void) | { x: number }) {} -bar(() => {}); -" + +bar(() => {});" `; exports[`test test16.js 1`] = ` @@ -1250,20 +1382,25 @@ function qux() { return x; } x = \"\"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @noflow + // annotations + type T = number | (() => string); type Foo = T | (() => boolean); + type Bar = number | (() => string) | (() => boolean); + function foo(x: Foo) {} foo(() => qux()); + function bar(x: Bar) {} bar(() => qux()); + var x = false; function qux() { return x; } -x = \"\"; -" +x = \"\";" `; exports[`test test17.js 1`] = ` @@ -1276,10 +1413,12 @@ exports[`test test17.js 1`] = ` ([].concat([0,1])[1]: string) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @noflow + // Array#concat + [].concat([]); -([].concat([ 0, 1 ])[1]: string); -" + +([].concat([ 0, 1 ])[1]: string);" `; exports[`test test18.js 1`] = ` @@ -1297,13 +1436,16 @@ function f() { return 0; } new C().m(f()); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @noflow + // method overloads + declare class C { m(x: number): void, m(x: string): void } + function f() { return 0; } -new C().m(f()); -" + +new C().m(f());" `; exports[`test test19.js 1`] = ` @@ -1321,12 +1463,14 @@ declare class D { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @noflow + // constructor overloads + function m() { return new D(); } -declare class D { constructor(_: void): void, constructor(_: null): void } -" + +declare class D { constructor(_: void): void, constructor(_: null): void }" `; exports[`test test20.js 1`] = ` @@ -1346,16 +1490,19 @@ exports[`test test20.js 1`] = ` [\"\"].reduce((acc,str) => acc * str.length); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @noflow + // Array#reduce + [ 0, 1 ].reduce((x, y, i) => y); + [ \"a\", \"b\" ].reduce( (regex, representation, index) => { return regex + (index ? \"|\" : \"\") + \"(\" + representation + \")\"; }, \"\" ); -[ \"\" ].reduce((acc, str) => acc * str.length); -" + +[ \"\" ].reduce((acc, str) => acc * str.length);" `; exports[`test test21.js 1`] = ` @@ -1382,18 +1529,24 @@ function str() { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @noflow + // annotations for disjoint unions + type T = { type: \"FOO\", x: number } | { type: \"BAR\", x: string }; + ({ type: (bar(): \"BAR\"), x: str() }: T); + ({ type: bar(), x: str() }: T); + ({ type: bar(), x: (str(): string) }: T); + function bar() { return \"BAR\"; } + function str() { return \"hello\"; -} -" +}" `; exports[`test test22.js 1`] = ` @@ -1420,18 +1573,23 @@ function foo(x: T) { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @noflow + // refinement of disjoint unions + type Empty = {}; + type Success = { type: \"SUCCESS\", result: string }; + type Error = { type: \"ERROR\" } & Empty; + export type T = Success | Error; + function foo(x: T) { if (x.type === \"SUCCESS\") return x.result; else return x.result; -} -" +}" `; exports[`test test23.js 1`] = ` @@ -1449,16 +1607,18 @@ function foo(obj: Obj) { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @noflow + // nested intersections (see also lib/test23_lib.js) -// should be OK -// should also be OK (the check above shouldn\'t affect anything) + type NestedObj = {} & { dummy: SomeLibClass }; + type Obj = NestedObj & { x: string }; + function foo(obj: Obj) { obj.x; - obj.x; -} -" + // should be OK + obj.x; // should also be OK (the check above shouldn\'t affect anything) +}" `; exports[`test test24.js 1`] = ` @@ -1494,7 +1654,9 @@ declare class D extends C { (0: D | number); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @noflow + // scaling test for full type resolution + declare class C { addListener(event: string, listener: Function): C, emit(event: string, ...args: Array): boolean, @@ -1506,6 +1668,7 @@ declare class C { removeListener(event: string, listener: Function): C, setMaxListeners(n: number): void } + declare class D extends C { listen( port: number, @@ -1523,8 +1686,8 @@ declare class D extends C { ref(): D, unref(): D } -(0: D | number); -" + +(0: D | number);" `; exports[`test test25.js 1`] = ` @@ -1543,14 +1706,15 @@ function foo(rows: Rows, set: Set) { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @noflow + // termination test (see also lib/test25_lib.js) + function foo(rows: Rows, set: Set) { return rows.reduce_rows( (set, row) => row.reduce_row((set, i) => set.add(i), set), set ); -} -" +}" `; exports[`test test26.js 1`] = ` @@ -1576,19 +1740,25 @@ declare class Record { new Record().set(\'foo\', \"42\"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @noflow + declare function foo(x: number): number; declare function foo(x: string): string; + declare var x: number | string; + (foo(x): number | string); + type T = number | string; declare var y: T; + (foo(y): T); + declare class Record { set(x: \"foo\", y: number): void, set(x: \"bar\", y: string): void } -new Record().set(\"foo\", \"42\"); -" + +new Record().set(\"foo\", \"42\");" `; exports[`test test27.js 1`] = ` @@ -1614,20 +1784,23 @@ function hello4(x:X): string { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @noflow -//type X = {a:true, b:string} | {a:false, c:string}; // this works. + type X = ({ a: true } & { b: string }) | ({ a: false } & { c: string }); +//type X = {a:true, b:string} | {a:false, c:string}; // this works. function hello1(x: X): string { if (x.a === true) return x.b; else return x.c; } + function hello2(x: X): string { if (x.a === false) return x.c; else return x.b; } + function hello3(x: X): string { if (x.a) { return x.b; @@ -1635,14 +1808,14 @@ function hello3(x: X): string { return x.c; } } + function hello4(x: X): string { if (!x.a) { return x.c; } else { return x.b; } -} -" +}" `; exports[`test test29.js 1`] = ` @@ -1679,11 +1852,14 @@ class C { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @noflow + // Make sure caching doesn\'t cause a spurious successful match (e.g., when a // failed match is tried again). This may happen, e.g., when checking // polymorphic definitions, where the same code may be checked multiple times // with different instantiations. + type Row = { x: string }; + declare class D { reduce( callbackfn: (previousValue: T, currentValue: T) => T, @@ -1694,12 +1870,12 @@ declare class D { initialValue: U ): U } + class C { foo(rows: D, minWidth: number): number { return rows.reduce((length, row) => 0, minWidth); } -} -" +}" `; exports[`test test30.js 1`] = ` @@ -1714,10 +1890,12 @@ type ActionType = ({ type: Constants.BAR, x: 0 }: ActionType); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @noflow + const Constants = require(\"./test30-helper\"); + type ActionType = { type: \"foo\", x: number } | { type: \"bar\", x: number }; -({ type: Constants.BAR, x: 0 }: ActionType); -" + +({ type: Constants.BAR, x: 0 }: ActionType);" `; exports[`test test30-helper.js 1`] = ` @@ -1729,8 +1907,8 @@ module.exports = { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @noflow -module.exports = { FOO: \"foo\", BAR: \"bar\" }; -" + +module.exports = { FOO: \"foo\", BAR: \"bar\" };" `; exports[`test test31.js 1`] = ` @@ -1761,22 +1939,28 @@ function foo(): ImmutableMap { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @noflow + // make sure tuples are type arguments (as used e.g. when viewing maps as // key/value iterables) work + interface SomeIterator {} + interface SomeIterable { it(): SomeIterator } + declare class SomeMap { it(): SomeIterator<[K, V]>, set(k: K, v: V): void } + declare class ImmutableMap {} + declare function convert(iter: SomeIterable<[K, V]>): ImmutableMap; + function foo(): ImmutableMap { const countersGlobalMap = new SomeMap(); countersGlobalMap.set(\"\", false); return convert(countersGlobalMap); -} -" +}" `; exports[`test test32.js 1`] = ` @@ -1791,11 +1975,12 @@ function foo(value: Indirect | number): Indirect | number { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow + // make sure that full resolution jobs don\'t cache improperly to signal success // when they have failed earlier + function foo(value: Indirect | number): Indirect | number { const castedValue: number = typeof value === \"number\" ? value : 0; return castedValue; -} -" +}" `; diff --git a/tests/union_new/lib/__snapshots__/jsfmt.spec.js.snap b/tests/union_new/lib/__snapshots__/jsfmt.spec.js.snap index 82ac36a5..c175e1e5 100644 --- a/tests/union_new/lib/__snapshots__/jsfmt.spec.js.snap +++ b/tests/union_new/lib/__snapshots__/jsfmt.spec.js.snap @@ -1,8 +1,7 @@ exports[`test test23_lib.js 1`] = ` "declare class SomeLibClass { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -declare class SomeLibClass {} -" +declare class SomeLibClass {}" `; exports[`test test25_lib.js 1`] = ` @@ -29,6 +28,7 @@ declare class Rows { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ declare class Set { add(): Set } + declare class Row { reduce_row( callbackfn: (previousValue: number, currentValue: number) => number, @@ -39,18 +39,17 @@ declare class Row { initialValue: U ): U } + declare class Rows { reduce_rows( callbackfn: (previousValue: X, currentValue: Row) => X, initialValue: X ): X -} -" +}" `; exports[`test test32_lib.js 1`] = ` "type Indirect = Array; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -type Indirect = Array; -" +type Indirect = Array;" `; diff --git a/tests/unreachable/__snapshots__/jsfmt.spec.js.snap b/tests/unreachable/__snapshots__/jsfmt.spec.js.snap index 2d243973..a3116fea 100644 --- a/tests/unreachable/__snapshots__/jsfmt.spec.js.snap +++ b/tests/unreachable/__snapshots__/jsfmt.spec.js.snap @@ -24,25 +24,28 @@ function test2() { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// regression test for analysis after abnormal control flow: -// consts must not become bot (EmptyT). -// no error, n is still number -// error, n is number (EmptyT would work) + function test1(): string { return bar(); + function bar() { return 0; } } + +// regression test for analysis after abnormal control flow: +// consts must not become bot (EmptyT). function test2() { const n = 0; + return; + function f() { var x: typeof n = 0; - var y: string = n; + // no error, n is still number + var y: string = n; // error, n is number (EmptyT would work) } -} -" +}" `; exports[`test unreachable.js 1`] = ` @@ -75,22 +78,27 @@ function foo(x, y) { foo(1, 2); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -// function declaration is hoisted, should not generate warning -// assignment is not hoisted, should generate warning -// variable declaration is hoisted, should not generate warning -// assignments are not hoisted, should generate 2 warnings + function foo(x, y) { \"use strict\"; return bar(x) + baz(y); + + // function declaration is hoisted, should not generate warning function bar(ecks) { return x + ecks; } + + // assignment is not hoisted, should generate warning var baz = function(why) { return y + why; }; + + // variable declaration is hoisted, should not generate warning var x, y, z; + + // assignments are not hoisted, should generate 2 warnings var t, u = 5, v, w = 7; } -foo(1, 2); -" + +foo(1, 2);" `; diff --git a/tests/value/__snapshots__/jsfmt.spec.js.snap b/tests/value/__snapshots__/jsfmt.spec.js.snap index cb0d055f..f3363e49 100644 --- a/tests/value/__snapshots__/jsfmt.spec.js.snap +++ b/tests/value/__snapshots__/jsfmt.spec.js.snap @@ -9,7 +9,7 @@ table[\"x\"] = \"hello\"; var o = {}; o[\"x\"] = 4; var y: string = o[\"x\"]; + var table: { [_: string]: number } = {}; -table[\"x\"] = \"hello\"; -" +table[\"x\"] = \"hello\";" `; diff --git a/tests/vim_emacs_errors/__snapshots__/jsfmt.spec.js.snap b/tests/vim_emacs_errors/__snapshots__/jsfmt.spec.js.snap index e7c23561..28e52802 100644 --- a/tests/vim_emacs_errors/__snapshots__/jsfmt.spec.js.snap +++ b/tests/vim_emacs_errors/__snapshots__/jsfmt.spec.js.snap @@ -4,6 +4,6 @@ exports[`test test.js 1`] = ` (123: string); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // @flow -(123: string); -" + +(123: string);" `; diff --git a/tests/weakmode/__snapshots__/jsfmt.spec.js.snap b/tests/weakmode/__snapshots__/jsfmt.spec.js.snap index 3b30766d..bc88d41c 100644 --- a/tests/weakmode/__snapshots__/jsfmt.spec.js.snap +++ b/tests/weakmode/__snapshots__/jsfmt.spec.js.snap @@ -12,13 +12,14 @@ function expects_an_int() { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ // This should fail without weak mode, because of the glaring type error. + function returns_a_string() { return \"Hello\"; } + function expects_an_int() { return returns_a_string() * 10; -} -" +}" `; exports[`test should_pass_with_weak.js 1`] = ` @@ -35,11 +36,12 @@ function expects_an_int() { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow weak */ // This should fail without weak mode, because of the glaring type error. + function returns_a_string() { return \"Hello\"; } + function expects_an_int() { return returns_a_string() * 10; -} -" +}" `; diff --git a/tests/while/__snapshots__/jsfmt.spec.js.snap b/tests/while/__snapshots__/jsfmt.spec.js.snap index 9c3cd3b2..a4acff0c 100644 --- a/tests/while/__snapshots__/jsfmt.spec.js.snap +++ b/tests/while/__snapshots__/jsfmt.spec.js.snap @@ -21,8 +21,7 @@ function bar(x: boolean) { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @flow */ -//console.log(\'this is still reachable\'); -//console.log(\'this is still reachable\'); + function foo(x: boolean) { var ii = 10; while (ii-- >= 0) { @@ -31,14 +30,16 @@ function foo(x: boolean) { } return; } + //console.log(\'this is still reachable\'); } + function bar(x: boolean) { var ii = 0; while (ii > 0) { return; } -} -" + //console.log(\'this is still reachable\'); +}" `; exports[`test test.js 1`] = ` @@ -66,6 +67,5 @@ while (node) { var cloneable: C = node; blah(); node = parent.m(); -} -" +}" `; diff --git a/tests/window/__snapshots__/jsfmt.spec.js.snap b/tests/window/__snapshots__/jsfmt.spec.js.snap index 9473c0fd..8fbfdc05 100644 --- a/tests/window/__snapshots__/jsfmt.spec.js.snap +++ b/tests/window/__snapshots__/jsfmt.spec.js.snap @@ -7,8 +7,7 @@ module.exports = window.history; /* @providesModule Window1 */ -module.exports = window.history; -" +module.exports = window.history;" `; exports[`test window2.js 1`] = ` @@ -17,6 +16,6 @@ exports[`test window2.js 1`] = ` module.exports = window.parent; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* @providesModule Window2 */ -module.exports = window.parent; -" + +module.exports = window.parent;" `; diff --git a/tests/x/__snapshots__/jsfmt.spec.js.snap b/tests/x/__snapshots__/jsfmt.spec.js.snap index 492f2dd0..3c0963ae 100644 --- a/tests/x/__snapshots__/jsfmt.spec.js.snap +++ b/tests/x/__snapshots__/jsfmt.spec.js.snap @@ -47,15 +47,16 @@ module.exports = XControllerURIBuilder; * @providesModule XControllerURIBuilder * @typechecks */ -// ... -// ... -// ... + // ... class XControllerURIBuilder { + // ... getURI() { + // ... var tokenRegex = new RegExp(/^\\{(\\?)?(.+?)\\}$/); + // ... } } -module.exports = XControllerURIBuilder; -" + +module.exports = XControllerURIBuilder;" `;