[cli] introduce `--linters` and `--capture`

Summary:
Linters are now considered a "checker", like backend checkers. This makes, eg,
`--racerd-only` disable the linters, which is more intuitive.

We can now express `-a linters` and `--clang-frontend-action` in terms of these
two new options. For instance, `-a linters --clang-frontend-action lint` is the
same as `--linters-only --no-capture`.

This is another step in the direction of getting rid of `--analyzers`.

Reviewed By: dulmarod

Differential Revision: D6147387

fbshipit-source-id: 53622b2
master
Jules Villard 7 years ago committed by Facebook Github Bot
parent e7907032bf
commit 71ed554c57

@ -277,14 +277,16 @@ let add parse_mode sections desc =
() ()
let deprecate_desc parse_mode ~long ~short ~deprecated desc = let deprecate_desc parse_mode ~long ~short ~deprecated doc desc =
let warn () = let warn () =
match parse_mode with match parse_mode with
| Javac | NoParse -> | Javac | NoParse ->
() ()
| InferCommand -> | InferCommand when long <> "" ->
warnf "WARNING: '-%s' is deprecated. Use '--%s'%s instead.@." deprecated long warnf "WARNING: '-%s' is deprecated. Use '--%s'%s instead.@." deprecated long
(if short = "" then "" else Printf.sprintf " or '-%s'" short) (if short = "" then "" else Printf.sprintf " or '-%s'" short)
| InferCommand ->
warnf "WARNING: '-%s' is deprecated. Here is its documentation:@\n%s@." deprecated doc
in in
let warn_then_f f x = warn () ; f x in let warn_then_f f x = warn () ; f x in
let deprecated_spec = let deprecated_spec =
@ -335,7 +337,7 @@ let mk ?(deprecated= []) ?(parse_mode= InferCommand) ?(in_help= []) ~long ?short
if short <> "" then add parse_mode [] {desc with long= ""; meta= ""; doc= ""} ; if short <> "" then add parse_mode [] {desc with long= ""; meta= ""; doc= ""} ;
(* add desc for deprecated options only for parsing, without documentation *) (* add desc for deprecated options only for parsing, without documentation *)
List.iter deprecated ~f:(fun deprecated -> List.iter deprecated ~f:(fun deprecated ->
deprecate_desc parse_mode ~long ~short ~deprecated desc |> add parse_mode [] ) ; deprecate_desc parse_mode ~long ~short ~deprecated doc desc |> add parse_mode [] ) ;
variable variable

@ -713,6 +713,7 @@ and ( annotation_reachability
, eradicate , eradicate
, fragment_retains_view , fragment_retains_view
, immutable_cast , immutable_cast
, linters
, liveness , liveness
, printf_args , printf_args
, quandary , quandary
@ -750,6 +751,7 @@ and ( annotation_reachability
and immutable_cast = and immutable_cast =
mk_checker ~long:"immutable-cast" ~default:true mk_checker ~long:"immutable-cast" ~default:true
"the detection of object cast from immutable type to mutable type. For instance, it will detect cast from ImmutableList to List, ImmutableMap to Map, and ImmutableSet to Set." "the detection of object cast from immutable type to mutable type. For instance, it will detect cast from ImmutableList to List, ImmutableMap to Map, and ImmutableSet to Set."
and linters = mk_checker ~long:"linters" ~default:true "syntactic linters"
and liveness = and liveness =
mk_checker ~long:"liveness" ~default:true "the detection of dead stores and unused variables" mk_checker ~long:"liveness" ~default:true "the detection of dead stores and unused variables"
and printf_args = and printf_args =
@ -812,6 +814,7 @@ and ( annotation_reachability
, eradicate , eradicate
, fragment_retains_view , fragment_retains_view
, immutable_cast , immutable_cast
, linters
, liveness , liveness
, printf_args , printf_args
, quandary , quandary
@ -898,6 +901,11 @@ and calls_csv =
~meta:"file" "Write individual calls in CSV format to $(i,file)" ~meta:"file" "Write individual calls in CSV format to $(i,file)"
and capture =
CLOpt.mk_bool ~long:"capture" ~default:true
"capture and translate source files into infer's intermediate language for analysis"
and changed_files_index = and changed_files_index =
CLOpt.mk_path_opt ~long:"changed-files-index" CLOpt.mk_path_opt ~long:"changed-files-index"
~in_help:CLOpt.([(Analyze, manual_generic); (Diff, manual_generic)]) ~in_help:CLOpt.([(Analyze, manual_generic); (Diff, manual_generic)])
@ -914,10 +922,10 @@ and clang_biniou_file =
and clang_compilation_dbs = ref [] and clang_compilation_dbs = ref []
and clang_frontend_action = and clang_frontend_action =
CLOpt.mk_symbol_opt ~long:"clang-frontend-action" CLOpt.mk_symbol_opt ~long:"" ~deprecated:["-clang-frontend-action"]
~in_help:CLOpt.([(Capture, manual_clang); (Run, manual_clang)]) ~in_help:CLOpt.([(Capture, manual_clang); (Run, manual_clang)])
"Specify whether the clang frontend should capture or lint or both." (* doc only shows up in deprecation warnings *)
~symbols:clang_frontend_action_symbols "use --capture and --linters instead" ~symbols:clang_frontend_action_symbols
and clang_include_to_override_regex = and clang_include_to_override_regex =
@ -2161,7 +2169,7 @@ let post_parsing_initialization command_opt =
:= List.rev_map ~f:(fun x -> `Raw x) !compilation_database := List.rev_map ~f:(fun x -> `Raw x) !compilation_database
|> List.rev_map_append ~f:(fun x -> `Escaped x) !compilation_database_escaped ; |> List.rev_map_append ~f:(fun x -> `Escaped x) !compilation_database_escaped ;
(* set analyzer mode to linters in linters developer mode *) (* set analyzer mode to linters in linters developer mode *)
if !linters_developer_mode then analyzer := Some Linters ; if !linters_developer_mode then linters := true ;
if !default_linters then linters_def_file := linters_def_default_file :: !linters_def_file ; if !default_linters then linters_def_file := linters_def_default_file :: !linters_def_file ;
( if Option.is_none !analyzer then ( if Option.is_none !analyzer then
match (command_opt : CLOpt.command option) with match (command_opt : CLOpt.command option) with
@ -2179,7 +2187,11 @@ let post_parsing_initialization command_opt =
| Some Crashcontext -> | Some Crashcontext ->
disable_all_checkers () ; disable_all_checkers () ;
crashcontext := true crashcontext := true
| Some (CaptureOnly | Checkers | CompileOnly | Linters) | None -> | Some Linters ->
disable_all_checkers () ;
capture := false ;
linters := true
| Some (CaptureOnly | Checkers | CompileOnly) | None ->
() ) ; () ) ;
Option.value ~default:CLOpt.Run command_opt Option.value ~default:CLOpt.Run command_opt
@ -2294,6 +2306,17 @@ and bufferoverrun = !bufferoverrun
and calls_csv = !calls_csv and calls_csv = !calls_csv
and capture =
(* take `--clang-frontend-action` as the source of truth as long as that option exists *)
match !clang_frontend_action with
| Some (`Capture | `Lint_and_capture) ->
true
| Some `Lint ->
false
| None ->
!capture
and changed_files_index = !changed_files_index and changed_files_index = !changed_files_index
and check_nullable = !check_nullable and check_nullable = !check_nullable
@ -2436,6 +2459,17 @@ and latex = !latex
and linter = !linter and linter = !linter
and linters =
(* take `--clang-frontend-action` as the source of truth as long as that option exists *)
match !clang_frontend_action with
| Some (`Lint | `Lint_and_capture) ->
true
| Some `Capture ->
false
| None ->
!linters
and linters_def_file = !linters_def_file and linters_def_file = !linters_def_file
and linters_def_folder = !linters_def_folder and linters_def_folder = !linters_def_folder
@ -2670,30 +2704,11 @@ and analysis_suppress_errors analyzer =
let captured_dir = results_dir ^/ captured_dir_name let captured_dir = results_dir ^/ captured_dir_name
let clang_frontend_do_capture, clang_frontend_do_lint =
match !clang_frontend_action with
| Some `Lint ->
(false, true) (* no capture, lint *)
| Some `Capture ->
(true, false) (* capture, no lint *)
| Some `Lint_and_capture ->
(true, true) (* capture, lint *)
| None ->
match !analyzer with
| Some Linters ->
(false, true) (* no capture, lint *)
| Some BiAbduction | Some Checkers ->
(true, false) (* capture, no lint *)
| _ ->
(* capture, lint *) (true, true)
let analyzer = match !analyzer with Some a -> a | None -> Checkers let analyzer = match !analyzer with Some a -> a | None -> Checkers
let clang_frontend_action_string = let clang_frontend_action_string =
String.concat ~sep:" and " String.concat ~sep:" and "
( (if clang_frontend_do_capture then ["translating"] else []) ((if capture then ["translating"] else []) @ if linters then ["linting"] else [])
@ if clang_frontend_do_lint then ["linting"] else [] )
let dynamic_dispatch = let dynamic_dispatch =

@ -326,6 +326,8 @@ val bufferoverrun : bool
val calls_csv : string option val calls_csv : string option
val capture : bool
val captured_dir : string val captured_dir : string
(** directory where the results of the capture phase are stored *) (** directory where the results of the capture phase are stored *)
@ -337,10 +339,6 @@ val clang_biniou_file : string option
val clang_frontend_action_string : string val clang_frontend_action_string : string
val clang_frontend_do_capture : bool
val clang_frontend_do_lint : bool
val clang_ignore_regex : string option val clang_ignore_regex : string option
val clang_include_to_override_regex : string option val clang_include_to_override_regex : string option
@ -506,6 +504,8 @@ val latex : string option
val linter : string option val linter : string option
val linters : bool
val linters_def_file : string list val linters_def_file : string list
val linters_def_folder : string list val linters_def_folder : string list

@ -35,7 +35,7 @@ let init_global_state_for_capture_and_linters source_file =
L.(debug Capture Medium) "Processing %s" (Filename.basename (SourceFile.to_abs_path source_file)) ; L.(debug Capture Medium) "Processing %s" (Filename.basename (SourceFile.to_abs_path source_file)) ;
if Config.developer_mode then register_perf_stats_report source_file ; if Config.developer_mode then register_perf_stats_report source_file ;
Config.curr_language := Config.Clang ; Config.curr_language := Config.Clang ;
if Config.clang_frontend_do_capture then DB.Results_dir.init source_file ; if Config.capture then DB.Results_dir.init source_file ;
CFrontend_config.reset_global_state () CFrontend_config.reset_global_state ()
@ -85,9 +85,8 @@ let run_clang_frontend ast_source =
L.(debug Capture Quiet) "Clang frontend action is %s@\n" Config.clang_frontend_action_string ; L.(debug Capture Quiet) "Clang frontend action is %s@\n" Config.clang_frontend_action_string ;
L.(debug Capture Medium) L.(debug Capture Medium)
"Start %s of AST from %a@\n" Config.clang_frontend_action_string pp_ast_filename ast_source ; "Start %s of AST from %a@\n" Config.clang_frontend_action_string pp_ast_filename ast_source ;
if Config.clang_frontend_do_lint then if Config.linters then CFrontend_checkers_main.do_frontend_checks trans_unit_ctx ast_decl ;
CFrontend_checkers_main.do_frontend_checks trans_unit_ctx ast_decl ; if Config.capture then CFrontend.do_source_file trans_unit_ctx ast_decl ;
if Config.clang_frontend_do_capture then CFrontend.do_source_file trans_unit_ctx ast_decl ;
L.(debug Capture Medium) L.(debug Capture Medium)
"End %s of AST file %a... OK!@\n" Config.clang_frontend_action_string pp_ast_filename "End %s of AST file %a... OK!@\n" Config.clang_frontend_action_string pp_ast_filename
ast_source ; ast_source ;

@ -63,18 +63,16 @@ let run_compilation_database compilation_database should_capture_file =
CompilationDatabase.filter_compilation_data compilation_database ~f:should_capture_file CompilationDatabase.filter_compilation_data compilation_database ~f:should_capture_file
in in
let number_of_jobs = List.length compilation_data in let number_of_jobs = List.length compilation_data in
let capture_text = L.(debug Capture Quiet)
if Config.equal_analyzer Config.analyzer Config.Linters then "linting" else "translating" "Starting %s %d files@\n%!" Config.clang_frontend_action_string number_of_jobs ;
in L.progress "Starting %s %d files@\n%!" Config.clang_frontend_action_string number_of_jobs ;
L.(debug Capture Quiet) "Starting %s %d files@\n%!" capture_text number_of_jobs ;
L.progress "Starting %s %d files@\n%!" capture_text number_of_jobs ;
let sequence = Parmap.L (List.map ~f:create_cmd compilation_data) in let sequence = Parmap.L (List.map ~f:create_cmd compilation_data) in
let fail_sentinel_fname = Config.results_dir ^/ Config.linters_failed_sentinel_filename in let fail_sentinel_fname = Config.results_dir ^/ Config.linters_failed_sentinel_filename in
let fail_sentinel = let fail_sentinel =
if Config.linters_ignore_clang_failures then None if Config.linters_ignore_clang_failures then None
else else
match Config.buck_compilation_database with match Config.buck_compilation_database with
| Some NoDeps when Config.clang_frontend_do_lint -> | Some NoDeps when Config.linters ->
Some fail_sentinel_fname Some fail_sentinel_fname
| Some NoDeps | Some Deps _ | None -> | Some NoDeps | Some Deps _ | None ->
None None

@ -127,7 +127,7 @@ let clean_results_dir () =
let check_captured_empty mode = let check_captured_empty mode =
let clean_command_opt = clean_compilation_command mode in let clean_command_opt = clean_compilation_command mode in
if Config.clang_frontend_do_capture && Utils.directory_is_empty Config.captured_dir then ( if Config.capture && Utils.directory_is_empty Config.captured_dir then (
( match clean_command_opt with ( match clean_command_opt with
| Some clean_command -> | Some clean_command ->
L.user_warning "@\nNothing to compile. Try running `%s` first.@." clean_command L.user_warning "@\nNothing to compile. Try running `%s` first.@." clean_command

Loading…
Cancel
Save