Skip to content

Commit

Permalink
[flow] Add support for backup flowconfigs on ignored files
Browse files Browse the repository at this point in the history
Summary:
This diff allows you to use our typical module-mapping syntax in the flowconfig to specify a backup for explicitly ignored files. It does not provide the same support when these files are passed on the command line.

Changelog: [internal]

Reviewed By: SamChou19815

Differential Revision: D69858997

fbshipit-source-id: 74497e7a70ec9a22c2274babe34fef220a933d5c
  • Loading branch information
jbrown215 authored and facebook-github-bot committed Feb 20, 2025
1 parent d460ae8 commit dcee48a
Show file tree
Hide file tree
Showing 9 changed files with 64 additions and 19 deletions.
27 changes: 20 additions & 7 deletions src/commands/commandUtils.ml
Original file line number Diff line number Diff line change
Expand Up @@ -594,7 +594,7 @@ let assert_version flowconfig =
| Error msg -> Exit.(exit ~msg Invalid_flowconfig)

type flowconfig_params = {
ignores: string list;
ignores: (string * string option) list;
untyped: string list;
declarations: string list;
includes: string list;
Expand All @@ -611,7 +611,7 @@ let list_of_string_arg = function

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 ignores = List.map (fun ignore -> (ignore, None)) (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
Expand All @@ -626,15 +626,26 @@ let remove_exclusion pattern =
pattern

let file_options =
let ignores_of_arg root patterns extras =
let path_pattern_of_arg root pattern =
let expand_project_root_token = Files.expand_project_root_token ~root in
pattern |> remove_exclusion |> expand_project_root_token |> Str.regexp
in
let path_patterns_of_args root patterns extras =
let patterns = Base.List.rev_append extras patterns in
Base.List.map
~f:(fun s ->
let reg = s |> remove_exclusion |> expand_project_root_token |> Str.regexp in
let reg = path_pattern_of_arg root s in
(s, reg))
patterns
in
let ignores_of_args root patterns extras =
let patterns = Base.List.rev_append extras patterns in
Base.List.map
~f:(fun (path, backup) ->
let reg = path_pattern_of_arg root path in
((path, backup), reg))
patterns
in
let includes_of_arg ~implicitly_include_root ~root ~lib_paths paths =
(* Explicitly included paths are always added to the path_matcher *)
let path_matcher =
Expand Down Expand Up @@ -703,9 +714,11 @@ let file_options =
in
Some libdir
in
let ignores = ignores_of_arg root (FlowConfig.ignores flowconfig) ignores in
let untyped = ignores_of_arg root (FlowConfig.untyped flowconfig) untyped in
let declarations = ignores_of_arg root (FlowConfig.declarations flowconfig) declarations in
let ignores = ignores_of_args root (FlowConfig.ignores flowconfig) ignores in
let untyped = path_patterns_of_args root (FlowConfig.untyped flowconfig) untyped in
let declarations =
path_patterns_of_args root (FlowConfig.declarations flowconfig) declarations
in
let lib_paths = lib_paths ~root flowconfig libs in
let includes =
includes
Expand Down
26 changes: 22 additions & 4 deletions src/commands/config/flowConfig.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1201,8 +1201,12 @@ type rollout = {

type config = {
rollouts: rollout SMap.t;
(* completely ignored files (both module resolving and typing) *)
ignores: string list;
(* completely ignored files (both module resolving and typing)
* This type *should* just be a string list, but we have an undocumented feature that allows
* you to specify a backup flowconfig to use if a file is ignored using our module-mapper syntax.
* This should be reverted to string list after we properly support multiplatform flow roots.
*)
ignores: (string * string option) list;
(* files that should be treated as untyped *)
untyped: string list;
(* files that should be treated as declarations *)
Expand Down Expand Up @@ -1230,7 +1234,12 @@ end = struct

let section_header o section = fprintf o "[%s]\n" section

let ignores o = Base.List.iter ~f:(fprintf o "%s\n")
let ignores o =
Base.List.iter ~f:(fun (ignore, backup_opt) ->
match backup_opt with
| None -> fprintf o "%s\n" ignore
| Some backup -> fprintf o "%s -> %s\n" ignore backup
)

let untyped o = Base.List.iter ~f:(fprintf o "%s\n")

Expand Down Expand Up @@ -1368,7 +1377,16 @@ let parse_libs lines config : (config * warning list, error) result =
Ok ({ config with libs }, [])

let parse_ignores lines config =
let ignores = trim_lines lines in
let raw_ignores = trim_lines lines in
let ignores =
raw_ignores
|> Base.List.map ~f:(fun ignore ->
if Str.string_match Opts.mapping_regexp ignore 0 then
(Str.matched_group 1 ignore, Some (Str.matched_group 2 ignore))
else
(ignore, None)
)
in
Ok ({ config with ignores }, [])

let parse_untyped lines config =
Expand Down
2 changes: 1 addition & 1 deletion src/commands/config/flowConfig.mli
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ val write : config -> out_channel -> unit
(* Accessors *)

(* completely ignored files (both module resolving and typing) *)
val ignores : config -> string list
val ignores : config -> (string * string option) list

(* files that should be treated as untyped *)
val untyped : config -> string list
Expand Down
11 changes: 10 additions & 1 deletion src/commands/initCommand.ml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,16 @@ let main base_flags flowconfig_flags options root () =
Exit.(exit ~msg Invalid_flowconfig)
);

let config = FlowConfig.init ~ignores ~untyped ~declarations ~includes ~libs ~options ~lints in
let config =
FlowConfig.init
~ignores:(List.map fst ignores)
~untyped
~declarations
~includes
~libs
~options
~lints
in
let config =
match config with
| Ok (config, []) -> config
Expand Down
4 changes: 3 additions & 1 deletion src/commands/lsCommand.ml
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,9 @@ let rec iter_get_next ~f get_next =

let make_options ~flowconfig ~root ~ignore_flag ~include_flag ~untyped_flag ~declaration_flag =
let includes = CommandUtils.list_of_string_arg include_flag in
let ignores = CommandUtils.list_of_string_arg ignore_flag in
let ignores =
List.map (fun ignore -> (ignore, None)) (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
Expand Down
6 changes: 3 additions & 3 deletions src/common/files.ml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ type lib_dir =

type options = {
default_lib_dir: lib_dir option;
ignores: (string * Str.regexp) list;
ignores: ((string * string option) * Str.regexp) list;
untyped: (string * Str.regexp) list;
declarations: (string * Str.regexp) list;
implicitly_include_root: bool;
Expand Down Expand Up @@ -521,7 +521,7 @@ let dir_filter_of_options (options : options) f =
to be un-ignored. similarly, if an ignore ends in $, we could still prune if
the current path isn't a prefix of it. *)
Base.List.for_all
~f:(fun (pattern, _rx) ->
~f:(fun ((pattern, _), _rx) ->
(not (String.starts_with ~prefix:"!" pattern)) && not (String.ends_with ~suffix:"$" pattern))
options.ignores
in
Expand Down Expand Up @@ -615,7 +615,7 @@ let is_ignored (options : options) 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
is_matching path options.ignores
is_matching path (options.ignores |> List.map (fun ((x, _y), z) -> (x, z)))

(* true if a file path matches an [untyped] entry in config *)
let is_untyped (options : options) path =
Expand Down
4 changes: 2 additions & 2 deletions src/common/files.mli
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ type options

val mk_options :
default_lib_dir:lib_dir option ->
ignores:(string * Str.regexp) list ->
ignores:((string * string option) * Str.regexp) list ->
untyped:(string * Str.regexp) list ->
declarations:(string * Str.regexp) list ->
implicitly_include_root:bool ->
Expand All @@ -35,7 +35,7 @@ val default_options : options

val default_lib_dir : options -> lib_dir option

val ignores : options -> (string * Str.regexp) list
val ignores : options -> ((string * string option) * Str.regexp) list

val untyped : options -> (string * Str.regexp) list

Expand Down
1 change: 1 addition & 0 deletions tests/flowconfig_ignore/.flowconfig
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
!<PROJECT_ROOT>/my_declarations/root_typecheck/.*

[ignore]
'.*/my_ignores_with_backup/.*' -> '.flowconfig'
.*/my_ignores/.*
!.*/my_ignores/typecheck/.*
!.*/my_ignores/actually_typecheck\.js
Expand Down
2 changes: 2 additions & 0 deletions tests/flowconfig_ignore/my_ignores_with_backup/with_backup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// @flow
const x: string = 3; // NO ERROR

0 comments on commit dcee48a

Please sign in to comment.