From 71ed554c572826252bd977a70aeaa810b0fb4aef Mon Sep 17 00:00:00 2001 From: Jules Villard Date: Wed, 25 Oct 2017 09:27:16 -0700 Subject: [PATCH] [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 --- infer/src/base/CommandLineOption.ml | 8 ++- infer/src/base/Config.ml | 65 ++++++++++++------- infer/src/base/Config.mli | 8 +-- infer/src/clang/Capture.ml | 7 +- .../integration/CaptureCompilationDatabase.ml | 10 ++- infer/src/integration/Driver.ml | 2 +- 6 files changed, 57 insertions(+), 43 deletions(-) diff --git a/infer/src/base/CommandLineOption.ml b/infer/src/base/CommandLineOption.ml index 0b17a5fd3..962564b18 100644 --- a/infer/src/base/CommandLineOption.ml +++ b/infer/src/base/CommandLineOption.ml @@ -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 () = match parse_mode with | Javac | NoParse -> () - | InferCommand -> + | InferCommand when long <> "" -> warnf "WARNING: '-%s' is deprecated. Use '--%s'%s instead.@." deprecated long (if short = "" then "" else Printf.sprintf " or '-%s'" short) + | InferCommand -> + warnf "WARNING: '-%s' is deprecated. Here is its documentation:@\n%s@." deprecated doc in let warn_then_f f x = warn () ; f x in 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= ""} ; (* add desc for deprecated options only for parsing, without documentation *) 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 diff --git a/infer/src/base/Config.ml b/infer/src/base/Config.ml index e15aa85e1..c912c62f0 100644 --- a/infer/src/base/Config.ml +++ b/infer/src/base/Config.ml @@ -713,6 +713,7 @@ and ( annotation_reachability , eradicate , fragment_retains_view , immutable_cast + , linters , liveness , printf_args , quandary @@ -750,6 +751,7 @@ and ( annotation_reachability and immutable_cast = 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." + and linters = mk_checker ~long:"linters" ~default:true "syntactic linters" and liveness = mk_checker ~long:"liveness" ~default:true "the detection of dead stores and unused variables" and printf_args = @@ -812,6 +814,7 @@ and ( annotation_reachability , eradicate , fragment_retains_view , immutable_cast + , linters , liveness , printf_args , quandary @@ -898,6 +901,11 @@ and calls_csv = ~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 = CLOpt.mk_path_opt ~long:"changed-files-index" ~in_help:CLOpt.([(Analyze, manual_generic); (Diff, manual_generic)]) @@ -914,10 +922,10 @@ and clang_biniou_file = and clang_compilation_dbs = ref [] 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)]) - "Specify whether the clang frontend should capture or lint or both." - ~symbols:clang_frontend_action_symbols + (* doc only shows up in deprecation warnings *) + "use --capture and --linters instead" ~symbols:clang_frontend_action_symbols 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_append ~f:(fun x -> `Escaped x) !compilation_database_escaped ; (* 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 Option.is_none !analyzer then match (command_opt : CLOpt.command option) with @@ -2179,7 +2187,11 @@ let post_parsing_initialization command_opt = | Some Crashcontext -> disable_all_checkers () ; 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 @@ -2294,6 +2306,17 @@ and bufferoverrun = !bufferoverrun 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 check_nullable = !check_nullable @@ -2436,6 +2459,17 @@ and latex = !latex 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_folder = !linters_def_folder @@ -2670,30 +2704,11 @@ and analysis_suppress_errors analyzer = 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 clang_frontend_action_string = String.concat ~sep:" and " - ( (if clang_frontend_do_capture then ["translating"] else []) - @ if clang_frontend_do_lint then ["linting"] else [] ) + ((if capture then ["translating"] else []) @ if linters then ["linting"] else []) let dynamic_dispatch = diff --git a/infer/src/base/Config.mli b/infer/src/base/Config.mli index 932c78e90..183321381 100644 --- a/infer/src/base/Config.mli +++ b/infer/src/base/Config.mli @@ -326,6 +326,8 @@ val bufferoverrun : bool val calls_csv : string option +val capture : bool + val captured_dir : string (** 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_do_capture : bool - -val clang_frontend_do_lint : bool - val clang_ignore_regex : string option val clang_include_to_override_regex : string option @@ -506,6 +504,8 @@ val latex : string option val linter : string option +val linters : bool + val linters_def_file : string list val linters_def_folder : string list diff --git a/infer/src/clang/Capture.ml b/infer/src/clang/Capture.ml index f66240b13..8346aba8a 100644 --- a/infer/src/clang/Capture.ml +++ b/infer/src/clang/Capture.ml @@ -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)) ; if Config.developer_mode then register_perf_stats_report source_file ; 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 () @@ -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 Medium) "Start %s of AST from %a@\n" Config.clang_frontend_action_string pp_ast_filename ast_source ; - if Config.clang_frontend_do_lint then - CFrontend_checkers_main.do_frontend_checks trans_unit_ctx ast_decl ; - if Config.clang_frontend_do_capture then CFrontend.do_source_file trans_unit_ctx ast_decl ; + if Config.linters then CFrontend_checkers_main.do_frontend_checks trans_unit_ctx ast_decl ; + if Config.capture then CFrontend.do_source_file trans_unit_ctx ast_decl ; L.(debug Capture Medium) "End %s of AST file %a... OK!@\n" Config.clang_frontend_action_string pp_ast_filename ast_source ; diff --git a/infer/src/integration/CaptureCompilationDatabase.ml b/infer/src/integration/CaptureCompilationDatabase.ml index 68b617f08..a4e0405b2 100644 --- a/infer/src/integration/CaptureCompilationDatabase.ml +++ b/infer/src/integration/CaptureCompilationDatabase.ml @@ -63,18 +63,16 @@ let run_compilation_database compilation_database should_capture_file = CompilationDatabase.filter_compilation_data compilation_database ~f:should_capture_file in let number_of_jobs = List.length compilation_data in - let capture_text = - if Config.equal_analyzer Config.analyzer Config.Linters then "linting" else "translating" - in - 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 ; + L.(debug Capture Quiet) + "Starting %s %d files@\n%!" Config.clang_frontend_action_string number_of_jobs ; + L.progress "Starting %s %d files@\n%!" Config.clang_frontend_action_string number_of_jobs ; 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 = if Config.linters_ignore_clang_failures then None else match Config.buck_compilation_database with - | Some NoDeps when Config.clang_frontend_do_lint -> + | Some NoDeps when Config.linters -> Some fail_sentinel_fname | Some NoDeps | Some Deps _ | None -> None diff --git a/infer/src/integration/Driver.ml b/infer/src/integration/Driver.ml index 0d72e9f6c..68898ad0d 100644 --- a/infer/src/integration/Driver.ml +++ b/infer/src/integration/Driver.ml @@ -127,7 +127,7 @@ let clean_results_dir () = let check_captured_empty mode = 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 | Some clean_command -> L.user_warning "@\nNothing to compile. Try running `%s` first.@." clean_command