Skip to content

Commit

Permalink
[config] Add first step of generalized filtering system
Browse files Browse the repository at this point in the history
Summary:
This diff takes the first step toward a more general filtering
system. This step is concerned only with filtering at the reporting
stage, filtering for the capture and analysis stages is left for
later.

This diff adds a new command line / config option
```
       --filter-report +string
           Specify a filter for issues to report. If multiple filters are
           specified, they are applied in the order in which they are
           specified. Each filter is applied to each issue detected, and only
           issues which are accepted by all filters are reported. Each filter
           is of the form:
           `<issue_type_regex>:<filename_regex>:<reason_string>`. The first
           two components are OCaml Str regular expressions, with an optional
           `!` character prefix. If a regex has a `!` prefix, the polarity is
           inverted, and the filter becomes a "blacklist" instead of a
           "whitelist". Each filter is interpreted as an implication: an issue
           matches if it does not match the `issue_type_regex` or if it does
           match the `filename_regex`. The filenames that are tested by the
           regex are relative to the `--project-root` directory. The
           `<reason_string>` is a non-empty string used to explain why the
           issue was filtered.
           See also infer-report(1) and infer-run(1).
```

Reviewed By: jvillard

Differential Revision: D6182486

fbshipit-source-id: 9d3922b
  • Loading branch information
jberdine authored and facebook-github-bot committed Nov 1, 2017
1 parent ccd2c76 commit 15d09cc
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 3 deletions.
1 change: 1 addition & 0 deletions infer/src/atd/jsonbug.atd
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ type jsonbug = {
bug_type_hum: string;
?linters_def_file: string option;
?traceview_id: int option;
censored_reason : string;
}

type report = jsonbug list
Expand Down
22 changes: 20 additions & 2 deletions infer/src/backend/InferPrint.ml
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,21 @@ let should_report (issue_kind: Exceptions.err_kind) issue_type error_desc eclass
else true


(* The reason an issue should be censored (that is, not reported). The empty
string (that is "no reason") means that the issue should be reported. *)
let censored_reason (issue_type: IssueType.t) source_file =
let filename = SourceFile.to_rel_path source_file in
let rejected_by ((issue_type_polarity, issue_type_re), (filename_polarity, filename_re), reason) =
let accepted =
(* matches issue_type_re implies matches filename_re *)
not (Bool.equal issue_type_polarity (Str.string_match issue_type_re issue_type.unique_id 0))
|| Bool.equal filename_polarity (Str.string_match filename_re filename 0)
in
Option.some_if (not accepted) reason
in
Option.value ~default:"" (List.find_map Config.filter_report ~f:rejected_by)


module IssuesCsv = struct
let csv_issues_id = ref 0

Expand Down Expand Up @@ -410,7 +425,8 @@ module IssuesJson = struct
; bug_type_hum= key.err_name.IssueType.hum
; linters_def_file= err_data.linters_def_file
; doc_url= err_data.doc_url
; traceview_id= None }
; traceview_id= None
; censored_reason= censored_reason key.err_name source_file }
in
if not !is_first_item then pp "," else is_first_item := false ;
pp "%s@?" (Jsonbug_j.string_of_jsonbug bug)
Expand Down Expand Up @@ -495,7 +511,9 @@ module IssuesTxt = struct
| None ->
err_data.loc.Location.file
in
if key.in_footprint && error_filter source_file key.err_desc key.err_name then
if key.in_footprint && error_filter source_file key.err_desc key.err_name
&& (not Config.filtering || String.is_empty (censored_reason key.err_name source_file))
then
Exceptions.pp_err ~node_key:err_data.node_id_key.node_key err_data.loc key.err_kind
key.err_name key.err_desc None fmt ()

Expand Down
21 changes: 21 additions & 0 deletions infer/src/base/Config.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1275,6 +1275,12 @@ and filter_paths =
CLOpt.mk_bool ~long:"filter-paths" ~default:true "Filters specified in .inferconfig"


and filter_report =
CLOpt.mk_string_list ~long:"filter-report"
~in_help:CLOpt.([(Report, manual_generic); (Run, manual_generic)])
"Specify a filter for issues to report. If multiple filters are specified, they are applied in the order in which they are specified. Each filter is applied to each issue detected, and only issues which are accepted by all filters are reported. Each filter is of the form: `<issue_type_regex>:<filename_regex>:<reason_string>`. The first two components are OCaml Str regular expressions, with an optional `!` character prefix. If a regex has a `!` prefix, the polarity is inverted, and the filter becomes a \"blacklist\" instead of a \"whitelist\". Each filter is interpreted as an implication: an issue matches if it does not match the `issue_type_regex` or if it does match the `filename_regex`. The filenames that are tested by the regex are relative to the `--project-root` directory. The `<reason_string>` is a non-empty string used to explain why the issue was filtered."


and flavors =
CLOpt.mk_bool ~deprecated:["-use-flavors"] ~long:"flavors"
~in_help:CLOpt.([(Capture, manual_buck_flavors)])
Expand Down Expand Up @@ -2402,6 +2408,21 @@ and file_renamings = !file_renamings

and filter_paths = !filter_paths

and filter_report =
List.map !filter_report ~f:(fun str ->
match String.split str ~on:':' with
| [issue_type_re; filename_re; reason_str]
when not String.(is_empty issue_type_re || is_empty filename_re || is_empty reason_str) ->
let polarity_regex re =
let polarity = not (Char.equal '!' re.[0]) in
let regex = Str.regexp (if polarity then re else String.slice re 1 0) in
(polarity, regex)
in
(polarity_regex issue_type_re, polarity_regex filename_re, reason_str)
| _ ->
L.(die UserError) "Ill-formed report filter: %s" str )


and filtering = !filtering

and flavors = !flavors
Expand Down
2 changes: 2 additions & 0 deletions infer/src/base/Config.mli
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,8 @@ val file_renamings : string option

val filter_paths : bool

val filter_report : ((bool * Str.regexp) * (bool * Str.regexp) * string) list

val filtering : bool

val flavors : bool
Expand Down
3 changes: 2 additions & 1 deletion infer/src/unit/DifferentialTestsUtils.ml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ let create_fake_jsonbug ?(bug_class= "bug_class") ?(kind= "kind") ?(bug_type= "b
; bug_type_hum= kind
; linters_def_file
; doc_url
; traceview_id= None }
; traceview_id= None
; censored_reason= "" }


let pp_diff_of_list ~pp group_name fmt (expected, actual) =
Expand Down

0 comments on commit 15d09cc

Please sign in to comment.