diff --git a/src/commands/commandUtils.ml b/src/commands/commandUtils.ml
index 4ea94e79824..abccfadaae8 100644
--- a/src/commands/commandUtils.ml
+++ b/src/commands/commandUtils.ml
@@ -382,6 +382,7 @@ let assert_version flowconfig =
type flowconfig_params = {
ignores: string list;
untyped: string list;
+ declarations: string list;
includes: string list;
libs: string list;
(* We store raw_lint_severities as a string list instead of as a LintSettings.t so we
@@ -394,13 +395,14 @@ let list_of_string_arg = function
| None -> []
| Some arg_str -> Str.split (Str.regexp ",") arg_str
-let collect_flowconfig_flags main ignores_str untyped_str includes_str lib_str lints_str =
+let collect_flowconfig_flags main ignores_str untyped_str declarations_str includes_str lib_str lints_str =
let ignores = list_of_string_arg ignores_str in
let untyped = list_of_string_arg untyped_str in
+ let declarations = list_of_string_arg declarations_str in
let includes = list_of_string_arg includes_str in
let libs = list_of_string_arg lib_str in
let raw_lint_severities = list_of_string_arg lints_str in
- main { ignores; includes; libs; raw_lint_severities; untyped; }
+ main { ignores; includes; libs; raw_lint_severities; untyped; declarations; }
let file_options =
let default_lib_dir ~no_flowlib tmp_dir =
@@ -466,7 +468,7 @@ let file_options =
| [] -> config_libs
| _ -> config_libs @ (List.map (Files.make_path_absolute root) extras)
in
- fun ~root ~no_flowlib ~temp_dir ~includes ~ignores ~libs ~untyped flowconfig ->
+ fun ~root ~no_flowlib ~temp_dir ~includes ~ignores ~libs ~untyped ~declarations flowconfig ->
let default_lib_dir =
let no_flowlib = no_flowlib || FlowConfig.no_flowlib flowconfig in
Some (default_lib_dir ~no_flowlib temp_dir)
@@ -479,6 +481,10 @@ let file_options =
root
(FlowConfig.untyped flowconfig)
untyped in
+ let declarations = ignores_of_arg
+ root
+ (FlowConfig.declarations flowconfig)
+ declarations in
let lib_paths = lib_paths ~root flowconfig libs in
let includes =
includes
@@ -488,6 +494,7 @@ let file_options =
default_lib_dir;
ignores;
untyped;
+ declarations;
includes;
lib_paths;
module_file_exts = FlowConfig.module_file_exts flowconfig;
@@ -507,6 +514,12 @@ let untyped_flag prev = CommandSpec.ArgSpec.(
~doc:"Specify one or more patterns, comma separated, for files to treat as untyped"
)
+let declaration_flag prev = CommandSpec.ArgSpec.(
+ prev
+ |> flag "--declaration" (optional string)
+ ~doc:"Specify one or more patterns, comma separated, for files to treat as declarations"
+)
+
let include_flag prev = CommandSpec.ArgSpec.(
prev
|> flag "--include" (optional string)
@@ -536,6 +549,7 @@ let flowconfig_flags prev = CommandSpec.ArgSpec.(
|> collect collect_flowconfig_flags
|> ignore_flag
|> untyped_flag
+ |> declaration_flag
|> include_flag
|> lib_flag
|> lints_flag
@@ -793,8 +807,9 @@ let make_options ~flowconfig ~lazy_mode ~root (options_flags: Options_flags.t) =
libs;
raw_lint_severities=_;
untyped;
+ declarations;
} = options_flags.flowconfig_flags in
- file_options ~root ~no_flowlib ~temp_dir ~includes ~ignores ~libs ~untyped flowconfig
+ file_options ~root ~no_flowlib ~temp_dir ~includes ~ignores ~libs ~untyped ~declarations flowconfig
in
let lint_severities = parse_lints_flag
(FlowConfig.lint_severities flowconfig) options_flags.flowconfig_flags.raw_lint_severities
diff --git a/src/commands/config/flowConfig.ml b/src/commands/config/flowConfig.ml
index 31cdc0c003f..ac8ba6a413a 100644
--- a/src/commands/config/flowConfig.ml
+++ b/src/commands/config/flowConfig.ml
@@ -315,6 +315,8 @@ type config = {
ignores: string list;
(* files that should be treated as untyped *)
untyped: string list;
+ (* files that should be treated as declarations *)
+ declarations: string list;
(* non-root include paths *)
includes: string list;
(* library paths. no wildcards *)
@@ -341,6 +343,9 @@ end = struct
let untyped o untyped =
List.iter (fun ex -> (fprintf o "%s\n" ex)) untyped
+ let declarations o declarations =
+ List.iter (fun ex -> (fprintf o "%s\n" ex)) declarations
+
let includes o includes =
List.iter (fun inc -> (fprintf o "%s\n" inc)) includes
@@ -402,6 +407,7 @@ end = struct
ignores o config.ignores;
fprintf o "\n";
section_if_nonempty o "untyped" untyped config.untyped;
+ section_if_nonempty o "declarations" declarations config.declarations;
section_header o "include";
includes o config.includes;
fprintf o "\n";
@@ -421,6 +427,7 @@ end
let empty_config = {
ignores = [];
untyped = [];
+ declarations = [];
includes = [];
libs = [];
lint_severities = LintSettings.empty_severities;
@@ -474,6 +481,10 @@ let parse_untyped config lines =
let untyped = trim_lines lines in
{ config with untyped; }
+let parse_declarations config lines =
+ let declarations = trim_lines lines in
+ { config with declarations; }
+
let parse_options config lines =
let open Opts in
let (>>=) = Core_result.(>>=) in
@@ -959,6 +970,7 @@ let parse_section config ((section_ln, section), lines) =
| "ignore", _ -> parse_ignores config lines
| "libs", _ -> parse_libs config lines
| "lints", _ -> parse_lints config lines
+ | "declarations", _ -> parse_declarations config lines
| "strict", _ -> parse_strict config lines
| "options", _ -> parse_options config lines
| "untyped", _ -> parse_untyped config lines
@@ -1003,15 +1015,17 @@ let read filename =
} in
parse config lines, hash
-let init ~ignores ~untyped ~includes ~libs ~options ~lints =
+let init ~ignores ~untyped ~declarations ~includes ~libs ~options ~lints =
let ignores_lines = List.map (fun s -> (1, s)) ignores in
let untyped_lines = List.map (fun s -> (1, s)) untyped in
+ let declarations_lines = List.map (fun s -> (1, s)) declarations in
let includes_lines = List.map (fun s -> (1, s)) includes in
let options_lines = List.map (fun s -> (1, s)) options in
let lib_lines = List.map (fun s -> (1, s)) libs in
let lint_lines = List.map (fun s -> (1, s)) lints in
let config = parse_ignores empty_config ignores_lines in
let config = parse_untyped config untyped_lines in
+ let config = parse_declarations config declarations_lines in
let config = parse_includes config includes_lines in
let config = parse_options config options_lines in
let config = parse_libs config lib_lines in
@@ -1048,6 +1062,8 @@ let get_hash ?allow_cache filename =
let ignores config = config.ignores
(* files that should be treated as untyped *)
let untyped config = config.untyped
+(* files that should be treated as declarations *)
+let declarations config = config.declarations
(* non-root include paths *)
let includes config = config.includes
(* library paths. no wildcards *)
diff --git a/src/commands/config/flowConfig.mli b/src/commands/config/flowConfig.mli
index a1dd637e364..b40f0959c22 100644
--- a/src/commands/config/flowConfig.mli
+++ b/src/commands/config/flowConfig.mli
@@ -14,6 +14,7 @@ val empty_config: config
val init:
ignores: string list ->
untyped: string list ->
+ declarations: string list ->
includes: string list ->
libs: string list ->
options: string list ->
@@ -27,6 +28,8 @@ val write: config -> out_channel -> unit
val ignores: config -> string list
(* files that should be treated as untyped *)
val untyped: config -> string list
+(* files that should be treated as declarations *)
+val declarations: config -> string list
(* non-root include paths *)
val includes: config -> string list
(* library paths. no wildcards *)
diff --git a/src/commands/genFlowFilesCommand.ml b/src/commands/genFlowFilesCommand.ml
index 307b6f9b725..fee48b3731e 100644
--- a/src/commands/genFlowFilesCommand.ml
+++ b/src/commands/genFlowFilesCommand.ml
@@ -56,6 +56,7 @@ let spec = {
|> ignore_flag
|> include_flag
|> untyped_flag
+ |> declaration_flag
|> from_flag
|> anon "src" (required string)
|> flag "--out-dir" string
@@ -85,7 +86,7 @@ let write_file strip_root root content perm src_file_path dest_file_path =
Unix.close fd
let main option_values root error_flags strip_root ignore_flag
- include_flag untyped_flag from src out_dir () = (
+ include_flag untyped_flag declaration_flag from src out_dir () = (
FlowEventLogger.set_from from;
let src = expand_path src in
let root = guess_root (
@@ -111,7 +112,7 @@ let main option_values root error_flags strip_root ignore_flag
FlowExitStatus.exit ~msg FlowExitStatus.Commandline_usage_error
);
- let options = LsCommand.make_options ~root ~ignore_flag ~include_flag ~untyped_flag in
+ let options = LsCommand.make_options ~root ~ignore_flag ~include_flag ~untyped_flag ~declaration_flag in
let _, libs = Files.init options in
let next_files =
LsCommand.get_ls_files ~root ~all:false ~options ~libs ~imaginary:false (Some src)
diff --git a/src/commands/initCommand.ml b/src/commands/initCommand.ml
index fad991f2005..5b7b0a7fb3c 100644
--- a/src/commands/initCommand.ml
+++ b/src/commands/initCommand.ml
@@ -50,6 +50,7 @@ let main from flowconfig_flags options root () =
in
let ignores = flowconfig_flags.CommandUtils.ignores in
let untyped = flowconfig_flags.CommandUtils.untyped in
+ let declarations = flowconfig_flags.CommandUtils.declarations in
let includes = flowconfig_flags.CommandUtils.includes in
let libs = flowconfig_flags.CommandUtils.libs in
let lints = flowconfig_flags.CommandUtils.raw_lint_severities in
@@ -61,7 +62,7 @@ let main from flowconfig_flags options root () =
FlowExitStatus.(exit ~msg Invalid_flowconfig)
end;
- let config = FlowConfig.init ~ignores ~untyped ~includes ~libs ~options ~lints in
+ let config = FlowConfig.init ~ignores ~untyped ~declarations ~includes ~libs ~options ~lints in
let out = Sys_utils.open_out_no_fail file in
FlowConfig.write config out;
diff --git a/src/commands/lsCommand.ml b/src/commands/lsCommand.ml
index 4c40fb0888c..bb35c94148c 100644
--- a/src/commands/lsCommand.ml
+++ b/src/commands/lsCommand.ml
@@ -26,6 +26,7 @@ let spec = {
|> ignore_flag
|> include_flag
|> untyped_flag
+ |> declaration_flag
|> root_flag
|> json_flags
|> from_flag
@@ -106,15 +107,16 @@ let rec iter_get_next ~f get_next =
List.iter f result;
iter_get_next ~f get_next
-let make_options ~root ~ignore_flag ~include_flag ~untyped_flag =
+let make_options ~root ~ignore_flag ~include_flag ~untyped_flag ~declaration_flag =
let flowconfig = FlowConfig.get (Server_files_js.config_file root) in
let temp_dir = FlowConfig.temp_dir flowconfig in
let includes = CommandUtils.list_of_string_arg include_flag in
let ignores = CommandUtils.list_of_string_arg ignore_flag in
let untyped = CommandUtils.list_of_string_arg untyped_flag in
+ let declarations = CommandUtils.list_of_string_arg declaration_flag in
let libs = [] in
CommandUtils.file_options flowconfig
- ~root ~no_flowlib:true ~temp_dir ~ignores ~includes ~libs ~untyped
+ ~root ~no_flowlib:true ~temp_dir ~ignores ~includes ~libs ~untyped ~declarations
(* The problem with Files.wanted is that it says yes to everything except ignored files and libs.
* So implicitly ignored files (like files in another directory) pass the Files.wanted check *)
@@ -174,7 +176,7 @@ let get_next_append_const get_next const =
ret
let main
- strip_root ignore_flag include_flag untyped_flag root_flag json pretty from all imaginary reason
+ strip_root ignore_flag include_flag untyped_flag declaration_flag root_flag json pretty from all imaginary reason
input_file root_or_files () =
let files_or_dirs = get_filenames_from_input ~allow_imaginary:true input_file root_or_files in
@@ -194,7 +196,7 @@ let main
| _ -> None)
) in
- let options = make_options ~root ~ignore_flag ~include_flag ~untyped_flag in
+ let options = make_options ~root ~ignore_flag ~include_flag ~untyped_flag ~declaration_flag in
(* Turn on --no-flowlib by default, so that flow ls never reports flowlib files *)
let options = { options with Files.default_lib_dir = None; } in
let _, libs = Files.init options in
diff --git a/src/common/files.ml b/src/common/files.ml
index bc18081b613..98a2c166347 100644
--- a/src/common/files.ml
+++ b/src/common/files.ml
@@ -11,6 +11,7 @@ type options = {
default_lib_dir: Path.t option;
ignores: (string * Str.regexp) list;
untyped: (string * Str.regexp) list;
+ declarations: (string * Str.regexp) list;
includes: Path_matcher.t;
lib_paths: Path.t list;
module_file_exts: SSet.t;
@@ -21,6 +22,7 @@ type options = {
let default_lib_dir options = options.default_lib_dir
let ignores options = options.ignores
let untyped options = options.untyped
+let declarations options = options.declarations
let includes options = options.includes
let lib_paths options = options.lib_paths
let module_file_exts options = options.module_file_exts
@@ -332,6 +334,15 @@ let is_untyped (options: options) =
let path = Sys_utils.normalize_filename_dir_sep path in
List.exists (fun rx -> Str.string_match rx path 0) list
+(* true if a file path matches a [declarations] entry in config *)
+let is_declaration (options: options) =
+ let list = List.map snd options.declarations in
+ fun path ->
+ (* On Windows, the path may use \ instead of /, but let's standardize the
+ * ignore regex to use / *)
+ let path = Sys_utils.normalize_filename_dir_sep path in
+ List.exists (fun rx -> Str.string_match rx path 0) list
+
(* true if a file path matches an [include] path in config *)
let is_included options f =
Path_matcher.matches options.includes f
diff --git a/src/common/files.mli b/src/common/files.mli
index 4c7956c27f5..53faae4249e 100644
--- a/src/common/files.mli
+++ b/src/common/files.mli
@@ -11,6 +11,7 @@ type options = {
default_lib_dir: Path.t option;
ignores: (string * Str.regexp) list;
untyped: (string * Str.regexp) list;
+ declarations: (string * Str.regexp) list;
includes: Path_matcher.t;
lib_paths: Path.t list;
module_file_exts: SSet.t;
@@ -21,6 +22,7 @@ type options = {
val default_lib_dir: options -> Path.t option
val ignores: options -> (string * Str.regexp) list
val untyped: options -> (string * Str.regexp) list
+val declarations: options -> (string * Str.regexp) list
val includes: options -> Path_matcher.t
val lib_paths: options -> Path.t list
val module_file_exts: options -> SSet.t
@@ -42,6 +44,8 @@ val is_flow_file: options: options -> string -> bool
val is_ignored: options -> string -> bool
(* true if a file path matches an [untyped] entry in config *)
val is_untyped: options -> string -> bool
+(* true if a file path matches a [declarations] entry in config *)
+val is_declaration: options -> string -> bool
(* true if a file path matches an [include] path in config *)
val is_included: options -> string -> bool
diff --git a/src/flow_dot_js.ml b/src/flow_dot_js.ml
index e7f9ef88d89..a620e811d64 100644
--- a/src/flow_dot_js.ml
+++ b/src/flow_dot_js.ml
@@ -77,7 +77,7 @@ let load_lib_files ~master_cx ~metadata files
let cx = Context.make sig_cx metadata lib_file Files.lib_module_ref in
Flow_js.mk_builtins cx;
let syms = Type_inference_js.infer_lib_file cx ast
- ~exclude_syms ~file_sig ~lint_severities:LintSettings.empty_severities
+ ~exclude_syms ~file_sig ~lint_severities:LintSettings.empty_severities ~file_options:None
in
Context.merge_into (Context.sig_cx master_cx) sig_cx;
@@ -204,7 +204,7 @@ let infer_and_merge ~root filename ast file_sig =
let strict_mode = StrictModeSettings.empty in
let file_sigs = Utils_js.FilenameMap.singleton filename file_sig in
let cx, _other_cxs = Merge_js.merge_component_strict
- ~metadata ~lint_severities ~strict_mode ~file_sigs
+ ~metadata ~lint_severities ~file_options:None ~strict_mode ~file_sigs
~get_ast_unsafe:(fun _ -> ast)
~get_docblock_unsafe:(fun _ -> stub_docblock)
(Nel.one filename) reqs [] (Context.sig_cx master_cx)
diff --git a/src/services/inference/init_js.ml b/src/services/inference/init_js.ml
index cb2a2834718..824cdfaf8df 100644
--- a/src/services/inference/init_js.ml
+++ b/src/services/inference/init_js.ml
@@ -74,6 +74,7 @@ let load_lib_files ~master_cx ~options files =
let lib_file = File_key.LibFile file in
let lint_severities = options.Options.opt_lint_severities in
+ let file_options = Options.file_options options in
let%lwt result = parse_lib_file options file in
Lwt.return (match result with
| Parsing.Parse_ok (ast, file_sig) ->
@@ -89,7 +90,7 @@ let load_lib_files ~master_cx ~options files =
Flow.mk_builtins cx;
let syms = Infer.infer_lib_file cx ast
- ~exclude_syms ~lint_severities ~file_sig
+ ~exclude_syms ~lint_severities ~file_options:(Some file_options) ~file_sig
in
Context.merge_into (Context.sig_cx master_cx) sig_cx;
diff --git a/src/services/inference/merge_service.ml b/src/services/inference/merge_service.ml
index f074a16722c..780a32ca940 100644
--- a/src/services/inference/merge_service.ml
+++ b/src/services/inference/merge_service.ml
@@ -99,9 +99,10 @@ let merge_strict_context ~options component =
let metadata = Context.metadata_of_options options in
let lint_severities = Options.lint_severities options in
+ let file_options = Some (Options.file_options options) in
let strict_mode = Options.strict_mode options in
let cx, other_cxs = Merge_js.merge_component_strict
- ~metadata ~lint_severities ~strict_mode ~file_sigs
+ ~metadata ~lint_severities ~file_options ~strict_mode ~file_sigs
~get_ast_unsafe:Parsing_service_js.get_ast_unsafe
~get_docblock_unsafe:Parsing_service_js.get_docblock_unsafe
~do_gc:(Options.is_debug_mode options)
@@ -140,9 +141,10 @@ let merge_contents_context options file ast info file_sig ~ensure_checked_depend
let metadata = Context.metadata_of_options options in
let lint_severities = Options.lint_severities options in
+ let file_options = Some (Options.file_options options) in
let strict_mode = Options.strict_mode options in
let cx, _ = Merge_js.merge_component_strict
- ~metadata ~lint_severities ~strict_mode ~file_sigs
+ ~metadata ~lint_severities ~file_options ~strict_mode ~file_sigs
~get_ast_unsafe:(fun _ -> ast)
~get_docblock_unsafe:(fun _ -> info)
component file_reqs dep_cxs master_cx
diff --git a/src/typing/merge_js.ml b/src/typing/merge_js.ml
index 51d02c87c10..b2dae657d1b 100644
--- a/src/typing/merge_js.ml
+++ b/src/typing/merge_js.ml
@@ -244,7 +244,7 @@ let apply_docblock_overrides (metadata: Context.metadata) docblock_info =
5. Link the local references to libraries in master_cx and component_cxs.
*)
-let merge_component_strict ~metadata ~lint_severities ~strict_mode ~file_sigs
+let merge_component_strict ~metadata ~lint_severities ~file_options ~strict_mode ~file_sigs
~get_ast_unsafe ~get_docblock_unsafe ?(do_gc=false)
component reqs dep_cxs (master_cx: Context.sig_t) =
@@ -279,7 +279,7 @@ let merge_component_strict ~metadata ~lint_severities ~strict_mode ~file_sigs
else lint_severities in
let file_sig = FilenameMap.find_unsafe filename file_sigs in
Type_inference_js.infer_ast cx filename ast
- ~lint_severities ~file_sig;
+ ~lint_severities ~file_options ~file_sig;
let gc_state = Option.map gc_state Gc_js.(fun gc_state ->
let gc_state = mark cx gc_state in
diff --git a/src/typing/merge_js.mli b/src/typing/merge_js.mli
index 67ec129fbff..8a8e41eb2c3 100644
--- a/src/typing/merge_js.mli
+++ b/src/typing/merge_js.mli
@@ -18,6 +18,7 @@ end
val merge_component_strict:
metadata: Context.metadata ->
lint_severities: Severity.severity LintSettings.t ->
+ file_options: Files.options option ->
strict_mode: StrictModeSettings.t ->
file_sigs: File_sig.t Utils_js.FilenameMap.t ->
get_ast_unsafe: (File_key.t -> Loc.t Ast.program) ->
diff --git a/src/typing/type_inference_js.ml b/src/typing/type_inference_js.ml
index ba23a99fadc..9b84709a639 100644
--- a/src/typing/type_inference_js.ml
+++ b/src/typing/type_inference_js.ml
@@ -342,9 +342,22 @@ let scan_for_lint_suppressions =
Context.add_severity_cover cx severity_cover;
Context.add_unused_lint_suppressions cx suppression_locs
-let scan_for_suppressions cx base_settings comments =
- scan_for_error_suppressions cx comments;
- scan_for_lint_suppressions cx base_settings comments
+let scan_for_suppressions cx lint_severities file_options comments =
+ let filename = File_key.to_string (Context.file cx) in
+ let declaration = match file_options with
+ | Some file_options -> Files.is_declaration file_options filename
+ | None -> false
+ in
+ if declaration then
+ (* Declaration mode.
+ * We don't report any warnings or errors. *)
+ Context.remove_all_errors cx
+ else
+ (* Scan comments for line suppressions. *)
+ scan_for_error_suppressions cx comments;
+ scan_for_lint_suppressions cx lint_severities comments
+ ;
+ ()
let add_require_tvars =
let add cx desc loc =
@@ -377,7 +390,7 @@ let add_require_tvars =
(* build module graph *)
(* Lint suppressions are handled iff lint_severities is Some. *)
-let infer_ast ~lint_severities ~file_sig cx filename ast =
+let infer_ast ~lint_severities ~file_options ~file_sig cx filename ast =
assert (Context.is_checked cx);
Flow_js.Cache.clear();
@@ -434,7 +447,7 @@ let infer_ast ~lint_severities ~file_sig cx filename ast =
Flow_js.flow_t cx (init_exports, local_exports_var);
infer_core cx statements;
- scan_for_suppressions cx lint_severities comments;
+ scan_for_suppressions cx lint_severities file_options comments;
let module_t = Context.(
match Context.module_kind cx with
@@ -466,7 +479,7 @@ let infer_ast ~lint_severities ~file_sig cx filename ast =
a) symbols from prior library loads are suppressed if found,
b) bindings are added as properties to the builtin object
*)
-let infer_lib_file ~exclude_syms ~lint_severities ~file_sig cx ast =
+let infer_lib_file ~exclude_syms ~lint_severities ~file_options ~file_sig cx ast =
let _, statements, comments = ast in
Flow_js.Cache.clear();
@@ -480,7 +493,7 @@ let infer_lib_file ~exclude_syms ~lint_severities ~file_sig cx ast =
Env.init_env ~exclude_syms cx module_scope;
infer_core cx statements;
- scan_for_suppressions cx lint_severities comments;
+ scan_for_suppressions cx lint_severities file_options comments;
module_scope |> Scope.(iter_entries Entry.(fun name entry ->
Flow_js.set_builtin cx name (actual_type entry)
diff --git a/src/typing/type_inference_js.mli b/src/typing/type_inference_js.mli
index a2a037df6aa..8321203c538 100644
--- a/src/typing/type_inference_js.mli
+++ b/src/typing/type_inference_js.mli
@@ -8,6 +8,7 @@
(* Lint suppressions are handled iff lint_severities is Some. *)
val infer_ast:
lint_severities: Severity.severity LintSettings.t ->
+ file_options: Files.options option ->
file_sig: File_sig.t ->
Context.t ->
File_key.t ->
@@ -17,6 +18,7 @@ val infer_ast:
val infer_lib_file:
exclude_syms: SSet.t ->
lint_severities: Severity.severity LintSettings.t ->
+ file_options: Files.options option ->
file_sig: File_sig.t ->
Context.t ->
Loc.t Ast.program ->
diff --git a/testgen/flowtestgen_utils.ml b/testgen/flowtestgen_utils.ml
index b6f6924ac4b..2c58ae42df7 100644
--- a/testgen/flowtestgen_utils.ml
+++ b/testgen/flowtestgen_utils.ml
@@ -572,7 +572,7 @@ let flow_check (code : string) : string option =
let builtins_cx = Context.make builtins_sig_cx builtin_metadata
File_key.Builtins Files.lib_module_ref in
let _ = Type_inference_js.infer_lib_file builtins_cx builtins_ast
- ~exclude_syms:SSet.empty ~lint_severities ~file_sig:builtins_file_sig in
+ ~exclude_syms:SSet.empty ~lint_severities ~file_options:None ~file_sig:builtins_file_sig in
let () =
let from_t = Context.find_module master_cx Files.lib_module_ref in
let to_t = Context.find_module builtins_cx Files.lib_module_ref in
@@ -603,7 +603,7 @@ let flow_check (code : string) : string option =
let reqs = Merge_js.Reqs.empty in
(* WARNING: This line might crash. That's why we put the entire block into a try catch *)
let final_cx, _other_cxs = Merge_js.merge_component_strict
- ~metadata:builtin_metadata ~lint_severities ~strict_mode ~file_sigs
+ ~metadata:builtin_metadata ~lint_severities ~file_options:None ~strict_mode ~file_sigs
~get_ast_unsafe:(fun _ -> input_ast)
~get_docblock_unsafe:(fun _ -> stub_docblock)
(Nel.one filename) reqs [] master_sig_cx in
diff --git a/tests/config_declarations/.flowconfig b/tests/config_declarations/.flowconfig
new file mode 100644
index 00000000000..99c24d2787f
--- /dev/null
+++ b/tests/config_declarations/.flowconfig
@@ -0,0 +1,16 @@
+[ignore]
+
+[include]
+
+[libs]
+lib.js
+
+[declarations]
+.*/B.js
+.*/C.js
+
+[options]
+suppress_comment=.*\\$FlowFixMe
+suppress_comment=.*\\$FlowIssue
+suppress_comment=\\(.\\|\n\\)*\\$FlowNewLine
+include_warnings=true
diff --git a/tests/config_declarations/A.js b/tests/config_declarations/A.js
new file mode 100644
index 00000000000..9037b64c7c1
--- /dev/null
+++ b/tests/config_declarations/A.js
@@ -0,0 +1,24 @@
+// $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 silenced
+
+// $FlowFixMe Indentation shouldn't matter
+var test5: string = 123; // This error should be suppressed
+
+/*
+ * $FlowNewLine
+ */
+var test6: string = 123;
diff --git a/tests/config_declarations/B.js b/tests/config_declarations/B.js
new file mode 100644
index 00000000000..b4f41e62eb6
--- /dev/null
+++ b/tests/config_declarations/B.js
@@ -0,0 +1,2 @@
+// $FlowFixMe
+var test1: string = library_num;
diff --git a/tests/config_declarations/C.js b/tests/config_declarations/C.js
new file mode 100644
index 00000000000..149c0098c26
--- /dev/null
+++ b/tests/config_declarations/C.js
@@ -0,0 +1,5 @@
+function takesAString(x: string): void {}
+
+function runTest(y: number): void {
+ takesAString(y);
+}
diff --git a/tests/config_declarations/D.js b/tests/config_declarations/D.js
new file mode 100644
index 00000000000..bd5a7bf1624
--- /dev/null
+++ b/tests/config_declarations/D.js
@@ -0,0 +1,8 @@
+declare var x: {
+ x: { foo: string }
+};
+declare var y: {
+ // $FlowFixMe - this location is only mentioned in the extra section
+ x: { bar: number }
+};
+x = y;
diff --git a/tests/config_declarations/config_declarations.exp b/tests/config_declarations/config_declarations.exp
new file mode 100644
index 00000000000..8613ac67069
--- /dev/null
+++ b/tests/config_declarations/config_declarations.exp
@@ -0,0 +1,24 @@
+Error ------------------------------------------------------------------------------------------------------- A.js:16:21
+
+Cannot assign `123` to `test4` because number [1] is incompatible with string [2].
+
+ A.js:16:21
+ 16| var test4: string = 123; // This error is NOT silenced
+ ^^^ [1]
+
+References:
+ A.js:16:12
+ 16| var test4: string = 123; // This error is NOT silenced
+ ^^^^^^ [2]
+
+
+Warning ------------------------------------------------------------------------------------------------------ A.js:14:1
+
+Unused suppression comment.
+
+ 14| // $FlowFixMe Error unused suppression
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+
+
+Found 1 error and 1 warning
diff --git a/tests/config_declarations/lib.js b/tests/config_declarations/lib.js
new file mode 100644
index 00000000000..21cfa88e53e
--- /dev/null
+++ b/tests/config_declarations/lib.js
@@ -0,0 +1 @@
+declare var library_num: number;
diff --git a/tests/json_exit/json_exit.exp b/tests/json_exit/json_exit.exp
index 2866fe02b85..65550329711 100644
--- a/tests/json_exit/json_exit.exp
+++ b/tests/json_exit/json_exit.exp
@@ -7,12 +7,12 @@
"msg":"Could not find file or directory pants; canceling search for .flowconfig.\nSee \"flow init --help\" for more info"
}
}
-{"flowVersion":"0.75.0","exit":{"code":64,"reason":"Commandline_usage_error","msg":"flow: --pants unknown option\nUsage: flow check [OPTION]... [ROOT]\n\nDoes a full Flow check and prints the results.\n\nFlow will search upward for a .flowconfig file, beginning at ROOT.\nROOT is assumed to be the current directory if unspecified.\n\n --all Typecheck all files, not just @flow\n --color Display terminal output in color. never, always, auto (default: auto)\n --debug Print debug info during typecheck\n --from Specify client (for use by editor plugins)\n --help This list of options\n --ignore Specify one or more ignore patterns, comma separated\n --ignore-version Ignore the version constraint in .flowconfig\n --include Specify one or more include patterns, comma separated\n --include-suppressed Ignore any `suppress_comment` lines in .flowconfig\n --include-warnings Include warnings in the error output (warnings are excluded by default)\n --json Output results in JSON format\n --json-version The version of the JSON format (defaults to 1)\n --lib Specify one or more lib files/directories, comma separated\n --lints Specify one or more lint rules, comma separated\n --max-warnings Warnings above this number will cause a nonzero exit code (implies --include-warnings)\n --max-workers Maximum number of workers to create (capped by number of cores)\n --merge-timeout The maximum time in seconds to attempt to typecheck a file or cycle of files. 0 means no timeout (default: 100)\n --message-width Sets the width of messages but not code snippets (defaults to the smaller of 120 or the terminal width)\n --munge-underscore-members Treat any class member name with a leading underscore as private\n --no-flowlib Do not include embedded declarations\n --no-saved-state Do not load from a saved state even if one is available\n --one-line Escapes newlines so that each error prints on one line\n --pretty Pretty-print JSON output (implies --json)\n --profile Output profiling information\n --quiet Suppress output about server startup\n --saved-state-load-script Use this script to fetch the saved state\n --sharedmemory-dep-table-pow The exponent for the size of the shared memory dependency table. The default is 17, implying a size of 2^17 bytes\n --sharedmemory-dirs Directory in which to store shared memory heap (default: /dev/shm/)\n --sharedmemory-hash-table-pow The exponent for the size of the shared memory hash table. The default is 19, implying a size of 2^19 bytes\n --sharedmemory-log-level The logging level for shared memory statistics. 0=none, 1=some\n --sharedmemory-minimum-available Flow will only use a filesystem for shared memory if it has at least these many bytes available (default: 536870912 - which is 512MB)\n --show-all-branches Print all branch errors (the default is to print the most relevant branches)\n --show-all-errors Print all errors (the default is to truncate after 50 errors)\n --strip-root Print paths without the root\n --temp-dir Directory in which to store temp files (default: FLOW_TEMP_DIR, or /tmp/flow/)\n --traces Outline an error path up to a specified level\n --unicode Display terminal output with unicode decoration. never, always, auto (default: auto)\n --untyped Specify one or more patterns, comma separated, for files to treat as untyped\n --verbose Print verbose info during typecheck\n --verbose-depth Recursively print types up to specified depth (default 1, implies --verbose)\n --verbose-indent Indent verbose info during typecheck (implies --verbose)\n --weak Typecheck with weak inference, assuming dynamic types by default"}}
+{"flowVersion":"0.75.0","exit":{"code":64,"reason":"Commandline_usage_error","msg":"flow: --pants unknown option\nUsage: flow check [OPTION]... [ROOT]\n\nDoes a full Flow check and prints the results.\n\nFlow will search upward for a .flowconfig file, beginning at ROOT.\nROOT is assumed to be the current directory if unspecified.\n\n --all Typecheck all files, not just @flow\n --color Display terminal output in color. never, always, auto (default: auto)\n --debug Print debug info during typecheck\n --declaration Specify one or more patterns, comma separated, for files to treat as declarations\n --from Specify client (for use by editor plugins)\n --help This list of options\n --ignore Specify one or more ignore patterns, comma separated\n --ignore-version Ignore the version constraint in .flowconfig\n --include Specify one or more include patterns, comma separated\n --include-suppressed Ignore any `suppress_comment` lines in .flowconfig\n --include-warnings Include warnings in the error output (warnings are excluded by default)\n --json Output results in JSON format\n --json-version The version of the JSON format (defaults to 1)\n --lib Specify one or more lib files/directories, comma separated\n --lints Specify one or more lint rules, comma separated\n --max-warnings Warnings above this number will cause a nonzero exit code (implies --include-warnings)\n --max-workers Maximum number of workers to create (capped by number of cores)\n --merge-timeout The maximum time in seconds to attempt to typecheck a file or cycle of files. 0 means no timeout (default: 100)\n --message-width Sets the width of messages but not code snippets (defaults to the smaller of 120 or the terminal width)\n --munge-underscore-members Treat any class member name with a leading underscore as private\n --no-flowlib Do not include embedded declarations\n --no-saved-state Do not load from a saved state even if one is available\n --one-line Escapes newlines so that each error prints on one line\n --pretty Pretty-print JSON output (implies --json)\n --profile Output profiling information\n --quiet Suppress output about server startup\n --saved-state-load-script Use this script to fetch the saved state\n --sharedmemory-dep-table-pow The exponent for the size of the shared memory dependency table. The default is 17, implying a size of 2^17 bytes\n --sharedmemory-dirs Directory in which to store shared memory heap (default: /dev/shm/)\n --sharedmemory-hash-table-pow The exponent for the size of the shared memory hash table. The default is 19, implying a size of 2^19 bytes\n --sharedmemory-log-level The logging level for shared memory statistics. 0=none, 1=some\n --sharedmemory-minimum-available Flow will only use a filesystem for shared memory if it has at least these many bytes available (default: 536870912 - which is 512MB)\n --show-all-branches Print all branch errors (the default is to print the most relevant branches)\n --show-all-errors Print all errors (the default is to truncate after 50 errors)\n --strip-root Print paths without the root\n --temp-dir Directory in which to store temp files (default: FLOW_TEMP_DIR, or /tmp/flow/)\n --traces Outline an error path up to a specified level\n --unicode Display terminal output with unicode decoration. never, always, auto (default: auto)\n --untyped Specify one or more patterns, comma separated, for files to treat as untyped\n --verbose Print verbose info during typecheck\n --verbose-depth Recursively print types up to specified depth (default 1, implies --verbose)\n --verbose-indent Indent verbose info during typecheck (implies --verbose)\n --weak Typecheck with weak inference, assuming dynamic types by default"}}
{
"flowVersion":"0.75.0",
"exit":{
"code":64,
"reason":"Commandline_usage_error",
- "msg":"flow: --pants unknown option\nUsage: flow check [OPTION]... [ROOT]\n\nDoes a full Flow check and prints the results.\n\nFlow will search upward for a .flowconfig file, beginning at ROOT.\nROOT is assumed to be the current directory if unspecified.\n\n --all Typecheck all files, not just @flow\n --color Display terminal output in color. never, always, auto (default: auto)\n --debug Print debug info during typecheck\n --from Specify client (for use by editor plugins)\n --help This list of options\n --ignore Specify one or more ignore patterns, comma separated\n --ignore-version Ignore the version constraint in .flowconfig\n --include Specify one or more include patterns, comma separated\n --include-suppressed Ignore any `suppress_comment` lines in .flowconfig\n --include-warnings Include warnings in the error output (warnings are excluded by default)\n --json Output results in JSON format\n --json-version The version of the JSON format (defaults to 1)\n --lib Specify one or more lib files/directories, comma separated\n --lints Specify one or more lint rules, comma separated\n --max-warnings Warnings above this number will cause a nonzero exit code (implies --include-warnings)\n --max-workers Maximum number of workers to create (capped by number of cores)\n --merge-timeout The maximum time in seconds to attempt to typecheck a file or cycle of files. 0 means no timeout (default: 100)\n --message-width Sets the width of messages but not code snippets (defaults to the smaller of 120 or the terminal width)\n --munge-underscore-members Treat any class member name with a leading underscore as private\n --no-flowlib Do not include embedded declarations\n --no-saved-state Do not load from a saved state even if one is available\n --one-line Escapes newlines so that each error prints on one line\n --pretty Pretty-print JSON output (implies --json)\n --profile Output profiling information\n --quiet Suppress output about server startup\n --saved-state-load-script Use this script to fetch the saved state\n --sharedmemory-dep-table-pow The exponent for the size of the shared memory dependency table. The default is 17, implying a size of 2^17 bytes\n --sharedmemory-dirs Directory in which to store shared memory heap (default: /dev/shm/)\n --sharedmemory-hash-table-pow The exponent for the size of the shared memory hash table. The default is 19, implying a size of 2^19 bytes\n --sharedmemory-log-level The logging level for shared memory statistics. 0=none, 1=some\n --sharedmemory-minimum-available Flow will only use a filesystem for shared memory if it has at least these many bytes available (default: 536870912 - which is 512MB)\n --show-all-branches Print all branch errors (the default is to print the most relevant branches)\n --show-all-errors Print all errors (the default is to truncate after 50 errors)\n --strip-root Print paths without the root\n --temp-dir Directory in which to store temp files (default: FLOW_TEMP_DIR, or /tmp/flow/)\n --traces Outline an error path up to a specified level\n --unicode Display terminal output with unicode decoration. never, always, auto (default: auto)\n --untyped Specify one or more patterns, comma separated, for files to treat as untyped\n --verbose Print verbose info during typecheck\n --verbose-depth Recursively print types up to specified depth (default 1, implies --verbose)\n --verbose-indent Indent verbose info during typecheck (implies --verbose)\n --weak Typecheck with weak inference, assuming dynamic types by default"
+ "msg":"flow: --pants unknown option\nUsage: flow check [OPTION]... [ROOT]\n\nDoes a full Flow check and prints the results.\n\nFlow will search upward for a .flowconfig file, beginning at ROOT.\nROOT is assumed to be the current directory if unspecified.\n\n --all Typecheck all files, not just @flow\n --color Display terminal output in color. never, always, auto (default: auto)\n --debug Print debug info during typecheck\n --declaration Specify one or more patterns, comma separated, for files to treat as declarations\n --from Specify client (for use by editor plugins)\n --help This list of options\n --ignore Specify one or more ignore patterns, comma separated\n --ignore-version Ignore the version constraint in .flowconfig\n --include Specify one or more include patterns, comma separated\n --include-suppressed Ignore any `suppress_comment` lines in .flowconfig\n --include-warnings Include warnings in the error output (warnings are excluded by default)\n --json Output results in JSON format\n --json-version The version of the JSON format (defaults to 1)\n --lib Specify one or more lib files/directories, comma separated\n --lints Specify one or more lint rules, comma separated\n --max-warnings Warnings above this number will cause a nonzero exit code (implies --include-warnings)\n --max-workers Maximum number of workers to create (capped by number of cores)\n --merge-timeout The maximum time in seconds to attempt to typecheck a file or cycle of files. 0 means no timeout (default: 100)\n --message-width Sets the width of messages but not code snippets (defaults to the smaller of 120 or the terminal width)\n --munge-underscore-members Treat any class member name with a leading underscore as private\n --no-flowlib Do not include embedded declarations\n --no-saved-state Do not load from a saved state even if one is available\n --one-line Escapes newlines so that each error prints on one line\n --pretty Pretty-print JSON output (implies --json)\n --profile Output profiling information\n --quiet Suppress output about server startup\n --saved-state-load-script Use this script to fetch the saved state\n --sharedmemory-dep-table-pow The exponent for the size of the shared memory dependency table. The default is 17, implying a size of 2^17 bytes\n --sharedmemory-dirs Directory in which to store shared memory heap (default: /dev/shm/)\n --sharedmemory-hash-table-pow The exponent for the size of the shared memory hash table. The default is 19, implying a size of 2^19 bytes\n --sharedmemory-log-level The logging level for shared memory statistics. 0=none, 1=some\n --sharedmemory-minimum-available Flow will only use a filesystem for shared memory if it has at least these many bytes available (default: 536870912 - which is 512MB)\n --show-all-branches Print all branch errors (the default is to print the most relevant branches)\n --show-all-errors Print all errors (the default is to truncate after 50 errors)\n --strip-root Print paths without the root\n --temp-dir Directory in which to store temp files (default: FLOW_TEMP_DIR, or /tmp/flow/)\n --traces Outline an error path up to a specified level\n --unicode Display terminal output with unicode decoration. never, always, auto (default: auto)\n --untyped Specify one or more patterns, comma separated, for files to treat as untyped\n --verbose Print verbose info during typecheck\n --verbose-depth Recursively print types up to specified depth (default 1, implies --verbose)\n --verbose-indent Indent verbose info during typecheck (implies --verbose)\n --weak Typecheck with weak inference, assuming dynamic types by default"
}
}
diff --git a/website/en/docs/config/declarations.md b/website/en/docs/config/declarations.md
new file mode 100644
index 00000000000..ec7a6bc6f04
--- /dev/null
+++ b/website/en/docs/config/declarations.md
@@ -0,0 +1,59 @@
+---
+layout: guide
+---
+
+Often third-party libraries have broken type definitions or have type
+definitions only compatible with a certain version of Flow. In those cases it
+may be useful to use type information from the third-party libraries without
+typechecking their contents.
+
+### `[declarations]`
+
+The `[declarations]` section in a `.flowconfig` file tells Flow to parse files
+matching the specified regular expressions in _declaration mode_. In declaration
+mode the code is not typechecked. However, the signatures of functions, classes,
+etc are extracted and used by the typechecker when checking other code.
+
+Conceptually one can think of declaration mode as if Flow still typechecks the
+files but acts as if there is a comment that matches
+[`suppress_comment`](options#toc-suppress-comment-regex") on every line.
+
+Things to keep in mind:
+
+1. Declaration mode should only be used for existing third-party code. You
+ should never use this for code under your control.
+2. These are [OCaml regular expressions](http://caml.inria.fr/pub/docs/manual-ocaml/libref/Str.html#TYPEregexp).
+3. These regular expressions match against absolute paths. They probably should
+ start with `.*`
+
+An example `[declarations]` section might look like:
+
+```
+[declarations]
+.*/third_party/.*
+.*/src/\(foo\|bar\)/.*
+.*\.decl\.js
+```
+
+This `[declarations]` section will parse in declaration mode:
+
+1. Any file or directory under a directory named `third_party`
+2. Any file or directory under `.*/src/foo` or under `.*/src/bar`
+3. Any file that ends with the extension `.decl.js`
+
+Starting with Flow v0.23.0, you may use the `` placeholder in
+your regular expressions. At runtime, Flow will treat the placeholder as if it
+were the absolute path to the project's root directory. This is useful for
+writing regular expressions that are relative rather than absolute.
+
+For example, you can write:
+
+```
+[declarations]
+/third_party/.*
+```
+
+Which would parse in declaration mode any file or directory under the directory
+named `third_party/` within the project root. However, unlike the previous
+example's `.*/third_party/.*`, it would NOT parse files or directories under
+directories named `third_party/`, like `src/third_party/`.
diff --git a/website/en/docs/config/index.md b/website/en/docs/config/index.md
index 42a82957dd3..dcb8359ae14 100644
--- a/website/en/docs/config/index.md
+++ b/website/en/docs/config/index.md
@@ -13,8 +13,9 @@ not proud of our custom format and plan to support a better format in the
future. [GitHub issue #153](https://github.com/facebook/flow/issues/153) tracks
this.
-The `.flowconfig` consists of 6 sections:
+The `.flowconfig` consists of 7 sections:
+* [`[declarations]`](declarations)
* [`[include]`](include)
* [`[ignore]`](ignore)
* [`[libs]`](libs)
@@ -25,7 +26,7 @@ The `.flowconfig` consists of 6 sections:
### Comments
Comment support was added in v0.23.0. Lines beginning with zero or more spaces
-followed by an `#` or `;` or `💩` are ignored. For example:
+followed by an `#` or `;` or `💩` are ignored. For example:
```
# This is a comment
@@ -39,17 +40,16 @@ followed by an `#` or `;` or `💩` are ignored. For example:
### Where to put the `.flowconfig`
The location of the `.flowconfig` is significant. Flow treats the directory that
-contains the `.flowconfig` as the *project root*. By default Flow includes all
+contains the `.flowconfig` as the _project root_. By default Flow includes all
the source code under the project root. The paths in the
[[include] section](include) are relative to the project root. Some other
configuration also lets you reference the project root via the macro
-````.
+``.
Most people put the `.flowconfig` in the root of their project (i.e. next to the
`package.json`). Some people put all their code in a `src/` directory and
therefore put the `.flowconfig` at `src/.flowconfig`.
-
### Example
Say you have the following directory structure, with your `.flowconfig` in
@@ -87,4 +87,4 @@ Here is an example of how you could use the `.flowconfig` directives.
```
Now `flow` will include a directory outside the `.flowconfig` path in its
-check, ignore the `build` directory and use the declarations in `lib`.
+check, ignore the `build` directory and use the declarations in `lib`.