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`.