Skip to content

Commit

Permalink
Warnings: filter out warnings from @generated files
Browse files Browse the repository at this point in the history
Summary: This has long been in discussion. I'm implementing the simplest solution: when filtering warnings in hh_client, look at the first 50 lines of the files for the "generated" string. I'm also caching the results of that lookup. I'm testing the performance (see test plan), and it looks acceptable.

Differential Revision: D66236754

fbshipit-source-id: 505c6c696aadd94bc2b246c7afc4cce691e9e562
  • Loading branch information
Catherine Gasnier authored and facebook-github-bot committed Nov 25, 2024
1 parent dc3049d commit 0fb414e
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 7 deletions.
4 changes: 1 addition & 3 deletions hphp/hack/src/client/clientArgs.ml
Original file line number Diff line number Diff line change
Expand Up @@ -727,9 +727,7 @@ rewrite to the function names to something like `foo_1` and `foo_2`.
" hide warnings in files matching a regexp" );
( "-Wgenerated",
Arg.Unit (fun () -> add_warning_switch Filter_errors.Generated_files_on),
" show warnings in generated files (the ones specified by .hhconfig flag warnings_generated_files). "
^ "To ignore more files, use -Wignore-files, avoid modifying warnings_generated_files"
);
" show warnings in generated files" );
Common_argspecs.watchman_debug_logging watchman_debug_logging;
(* Please keep these sorted in the alphabetical order *)
]
Expand Down
1 change: 1 addition & 0 deletions hphp/hack/src/client_and_server/dune
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@
(libraries
error_codes
errors
re
user_error
utils_core))

Expand Down
59 changes: 55 additions & 4 deletions hphp/hack/src/client_and_server/filter_errors.ml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

open Hh_prelude
module Code = Error_codes.Warning
module Hashtbl = Stdlib.Hashtbl

type switch =
| WAll
Expand Down Expand Up @@ -72,10 +73,16 @@ end = struct
codes: Warning_set.t;
ignore_files: Str.regexp list;
generated_files: Str.regexp list;
filter_out_generated_files: bool;
}

let empty =
{ codes = Warning_set.empty; ignore_files = []; generated_files = [] }
{
codes = Warning_set.empty;
ignore_files = [];
generated_files = [];
filter_out_generated_files = true;
}

let add_code code filter =
{ filter with codes = Warning_set.add code filter.codes }
Expand All @@ -97,7 +104,8 @@ end = struct
| Code_on code -> add_code code filter
| Code_off code -> remove_code code filter
| Ignored_files re -> add_ignored_files re filter
| Generated_files_on -> { filter with generated_files = [] }
| Generated_files_on ->
{ filter with generated_files = []; filter_out_generated_files = false }

let make ~default_all ~generated_files switches =
let switches =
Expand Down Expand Up @@ -128,12 +136,55 @@ end = struct
let pass_path ignore_files file_path =
not (List.exists ignore_files ~f:(match_regexp file_path))

let pass { codes; ignore_files; generated_files } (code, file_path) =
match Code.of_enum code with
module IsNonGenerated = struct
let is_generated_cache : (path, bool) Hashtbl.t = Hashtbl.create 1000

let at_generated =
Re.str
((* Writing like this to prevent CI from thinking this that file is generated...*)
"@"
^ "generated")
|> Re.compile

let max_lines = 50

let is_generated path =
try
Stdlib.In_channel.with_open_text path @@ fun ic ->
let rec go i =
if i >= max_lines then
false
else
match Stdlib.In_channel.input_line ic with
| None -> false
| Some line -> Re.execp at_generated line || go (i + 1)
in
go 0
with
| Sys_error _ ->
(* File not found. This could be the case for some tests. *) false

let pass ~skip path =
if skip then
true
else
match Hashtbl.find_opt is_generated_cache path with
| Some is_generated -> not is_generated
| None ->
let is_generated = is_generated path in
Hashtbl.add is_generated_cache path is_generated;
not is_generated
end

let pass
{ codes; ignore_files; generated_files; filter_out_generated_files }
(code, file_path) =
match Error_codes.Warning.of_enum code with
| None -> (* This is not a warning, so don't filter out *) true
| Some code ->
pass_code codes code
&& pass_path (ignore_files @ generated_files) file_path
&& IsNonGenerated.pass ~skip:(not filter_out_generated_files) file_path
end

let filter filter (error_list : Errors.finalized_error list) =
Expand Down

0 comments on commit 0fb414e

Please sign in to comment.