From ebbc202342a8e1431f9516d7067070651e49abb3 Mon Sep 17 00:00:00 2001 From: Jules Villard Date: Fri, 11 Aug 2017 11:07:55 -0700 Subject: [PATCH] [help] in infer --help, show in which manual each option can be found Summary: This gives additional information to users. For instance: ``` --biabduction Activates: the separation logic based bi-abduction analysis using the checkers framework (Conversely: --no-biabduction) This option is relevant to infer-analyze(1). ``` Reviewed By: sblackshear Differential Revision: D5583197 fbshipit-source-id: 2960b90 --- infer/src/backend/clusterMakefile.ml | 2 +- infer/src/base/CommandDoc.ml | 36 +++-------------- infer/src/base/CommandDoc.mli | 8 ---- infer/src/base/CommandLineOption.ml | 60 ++++++++++++++++++++++++++-- infer/src/base/CommandLineOption.mli | 8 ++++ infer/src/base/Config.ml | 4 +- infer/src/integration/Maven.ml | 2 +- 7 files changed, 75 insertions(+), 45 deletions(-) diff --git a/infer/src/backend/clusterMakefile.ml b/infer/src/backend/clusterMakefile.ml index 72b211538..18542f6ec 100644 --- a/infer/src/backend/clusterMakefile.ml +++ b/infer/src/backend/clusterMakefile.ml @@ -27,7 +27,7 @@ let pp_prolog fmt clusters = |> String.concat ~sep:" " |> escape in F.fprintf fmt "INFERANALYZE = '%s' --no-report --results-dir '%s' %s@\n@\n" - (Config.bin_dir ^/ CommandDoc.exe_name_of_command CLOpt.Analyze) + (Config.bin_dir ^/ CLOpt.exe_name_of_command CLOpt.Analyze) (escape Config.results_dir) compilation_dbs_cmd ; F.fprintf fmt "CLUSTERS=" ; List.iteri ~f:(fun i _ -> F.fprintf fmt "%a " Cluster.pp_cluster_name (i + 1)) clusters ; diff --git a/infer/src/base/CommandDoc.ml b/infer/src/base/CommandDoc.ml index cc2a75481..16ea5a457 100644 --- a/infer/src/base/CommandDoc.ml +++ b/infer/src/base/CommandDoc.ml @@ -13,39 +13,16 @@ type data = {name: string; command_doc: CLOpt.command_doc} let inferconfig_env_var = "INFERCONFIG" -let infer_exe_name = "infer" - (** Name of the infer configuration file *) let inferconfig_file = ".inferconfig" -let command_to_name = - let open CLOpt in - [ (Analyze, "analyze") - ; (Capture, "capture") - ; (Compile, "compile") - ; (Diff, "diff") - ; (Explore, "explore") - ; (Report, "report") - ; (ReportDiff, "reportdiff") - ; (Run, "run") ] - -let name_of_command = List.Assoc.find_exn ~equal:CLOpt.equal_command command_to_name - -let exe_name_of_command_name name = Printf.sprintf "%s-%s" infer_exe_name name - -let exe_name_of_command cmd = name_of_command cmd |> exe_name_of_command_name - -let command_of_exe_name exe_name = - List.find_map command_to_name ~f:(fun (cmd, name) -> - if String.equal exe_name (exe_name_of_command_name name) then Some cmd else None ) - let mk_command_doc ~see_also:see_also_commands ?environment:environment_opt ?files:files_opt ~synopsis = let section = 1 in let see_also = let exe_names = List.map see_also_commands ~f:(fun cmd -> - let exe = exe_name_of_command cmd in + let exe = CLOpt.exe_name_of_command cmd in Printf.sprintf "$(b,%s)(%d)" (Cmdliner.Manpage.escape exe) section ) in [`P (String.concat ~sep:", " exe_names)] @@ -160,14 +137,13 @@ $(b,infer) $(i,[options])|} [ `P "Infer is a static analyzer. Given a collection of source files written in Java or in languages of the C family, and a command to build them, infer produces a list of potential issues." ; `P - "Infer consists of a collection of tools referenced in the $(i,SEE ALSO) section of this manual. See their respective manuals for more information about each." + "Infer consists of a collection of tools referenced in the $(i,SEE ALSO) section of this manual. See their respective manuals for more information." ; `P - "If a compilation command is specified via the $(b,--) option or one of the $(b,--clang-compilation-database[-escaped]) options, $(b,infer) behaves as $(b,infer-run)(1). Otherwise, $(b,infer) behaves as $(b,infer-analyze)(1)." + "When run without a subcommand, and if a compilation command is specified via the $(b,--) option or one of the $(b,--clang-compilation-database[-escaped]) options, then $(b,infer) behaves as $(b,infer-run)(1). Otherwise, $(b,infer) behaves as $(b,infer-analyze)(1)." ] ~options: (`Prepend - [ `P - "Every infer command accepts the arguments from all the other infer commands. The same option may affect and thus be list in the manual of several commands." + [ `P "Every infer command accepts the arguments from all the other infer commands." ; `P (Printf.sprintf "Options are read from the $(b,%s) file, then from the $(b,%s) environment variable, then from the command line. Options in $(b,%s) take precedence over options in $(b,%s), and options passed on the command line take precedence over options in $(b,%s). See the $(i,%s) and $(i,%s) sections of this manual for more information." @@ -270,8 +246,8 @@ $(b,infer) $(b,analyze) $(i,[options])|} ] let command_to_data = let mk cmd mk_doc = - let name = name_of_command cmd in - let command_doc = mk_doc (exe_name_of_command cmd) in + let name = CLOpt.name_of_command cmd in + let command_doc = mk_doc (CLOpt.exe_name_of_command cmd) in (cmd, {name; command_doc}) in let open CLOpt in diff --git a/infer/src/base/CommandDoc.mli b/infer/src/base/CommandDoc.mli index f6c5a24fa..8ec4a70d0 100644 --- a/infer/src/base/CommandDoc.mli +++ b/infer/src/base/CommandDoc.mli @@ -12,18 +12,10 @@ module CLOpt = CommandLineOption type data = {name: string; command_doc: CLOpt.command_doc} -val infer_exe_name : string - val inferconfig_env_var : string val inferconfig_file : string -val name_of_command : CLOpt.command -> string - -val exe_name_of_command : CLOpt.command -> string - -val command_of_exe_name : string -> CLOpt.command option - val infer : CLOpt.command_doc val data_of_command : CLOpt.command -> data diff --git a/infer/src/base/CommandLineOption.ml b/infer/src/base/CommandLineOption.ml index 736f24257..08fa2cfa7 100644 --- a/infer/src/base/CommandLineOption.ml +++ b/infer/src/base/CommandLineOption.ml @@ -98,7 +98,30 @@ type command = let equal_command = [%compare.equal : command] -let all_commands = [Analyze; Capture; Clang; Compile; Diff; Explore; Report; ReportDiff; Run] +let infer_exe_name = "infer" + +let command_to_name = + [ (Analyze, "analyze") + ; (Capture, "capture") + ; (Clang, "clang") + ; (Compile, "compile") + ; (Diff, "diff") + ; (Explore, "explore") + ; (Report, "report") + ; (ReportDiff, "reportdiff") + ; (Run, "run") ] + +let all_commands = List.map ~f:fst command_to_name + +let name_of_command = List.Assoc.find_exn ~equal:equal_command command_to_name + +let exe_name_of_command_name name = Printf.sprintf "%s-%s" infer_exe_name name + +let exe_name_of_command cmd = name_of_command cmd |> exe_name_of_command_name + +let command_of_exe_name exe_name = + List.find_map command_to_name ~f:(fun (cmd, name) -> + if String.equal exe_name (exe_name_of_command_name name) then Some cmd else None ) type command_doc = { title: Cmdliner.Manpage.title @@ -207,8 +230,39 @@ let add parse_mode sections desc = in List.iter sections ~f:add_to_section ; if List.is_empty sections then hidden_descs_list := desc :: !hidden_descs_list - else visible_descs_list := desc :: !visible_descs_list ; - () + else + let desc_infer = + if String.equal "" desc.doc then desc + else + let oxford_comma l = + let rec aux acc l = + match (l, acc) with + | [], _ + -> assert false + | [x], [] + -> x + | [x; y], [] + -> Printf.sprintf "%s and %s" x y + | [x; y], acc + -> Printf.sprintf "%s, %s, and %s" (String.concat ~sep:", " (List.rev acc)) x y + | x :: tl, acc + -> aux (x :: acc) tl + in + aux [] l + in + (* in the help of `infer` itself, show in which specific commands the option is used *) + let commands = + List.map ~f:fst sections |> List.sort ~cmp:compare_command + |> List.remove_consecutive_duplicates ~equal:equal_command + |> List.map ~f:(fun cmd -> + let exe = exe_name_of_command cmd in + Printf.sprintf "$(b,%s)(1)" (Cmdliner.Manpage.escape exe) ) + |> oxford_comma + in + {desc with doc= Printf.sprintf "%s\nSee also %s." desc.doc commands} + in + visible_descs_list := desc_infer :: !visible_descs_list ; + () let deprecate_desc parse_mode ~long ~short ~deprecated desc = let warn () = diff --git a/infer/src/base/CommandLineOption.mli b/infer/src/base/CommandLineOption.mli index b4cdb287b..0a3bbb273 100644 --- a/infer/src/base/CommandLineOption.mli +++ b/infer/src/base/CommandLineOption.mli @@ -44,6 +44,14 @@ val equal_command : command -> command -> bool val all_commands : command list +val infer_exe_name : string + +val name_of_command : command -> string + +val exe_name_of_command : command -> string + +val command_of_exe_name : string -> command option + val is_originator : bool val init_work_dir : string diff --git a/infer/src/base/Config.ml b/infer/src/base/Config.ml index 08d5cb2a3..fa068c6fc 100644 --- a/infer/src/base/Config.ml +++ b/infer/src/base/Config.ml @@ -351,7 +351,7 @@ let initial_command = (* Sys.executable_name tries to do clever things which we must avoid, use argv[0] instead *) let exe_basename = Filename.basename Sys.argv.(0) in let is_clang = List.mem ~equal:String.equal clang_exe_aliases in - match CommandDoc.command_of_exe_name exe_basename with + match CLOpt.command_of_exe_name exe_basename with | Some _ as command -> command | None when is_clang exe_basename @@ -429,7 +429,7 @@ let exe_usage = | Some CLOpt.Clang -> None (* users cannot see this *) | Some command - -> Some (CommandDoc.name_of_command command) + -> Some (CLOpt.name_of_command command) | None -> None in diff --git a/infer/src/integration/Maven.ml b/infer/src/integration/Maven.ml index c7f905d1c..284879ab2 100644 --- a/infer/src/integration/Maven.ml +++ b/infer/src/integration/Maven.ml @@ -34,7 +34,7 @@ let infer_profile = |} - infer_profile_name (Config.bin_dir ^/ CommandDoc.infer_exe_name)) ) + infer_profile_name (Config.bin_dir ^/ CLOpt.infer_exe_name)) ) let pom_worklist = ref [CLOpt.init_work_dir]