Improve man page for infer explore

Summary:
- `--source-files` was missing.
- The three modes are actually independent, make it clearer and group options by mode.
- Fail if `--procedures` and `--source-files` are used together.

Reviewed By: jeremydubreil

Differential Revision: D15049822

fbshipit-source-id: cc515cb56
master
Mehdi Bouaziz 6 years ago committed by Facebook Github Bot
parent 07d6ab2dd6
commit 4e249b8cc3

@ -4,16 +4,20 @@ NAME
SYNOPSIS
infer explore [options]
infer explore --procedures [options]
infer explore --source-files [options]
DESCRIPTION
Show the list of bugs on the console and explore symbolic program
traces emitted by infer to explain a report. Can also generate an HTML
report from a JSON report.
If --procedures is passed, print information about each procedure
captured by infer.
If --source-files is passed, print information about captured source
files.
Otherwise, show the list of bugs on the console and explore symbolic
program traces emitted by infer to explain a report. Can also generate
an HTML report from a JSON report.
OPTIONS
@ -29,6 +33,10 @@ OPTIONS
Show this manual with all internal options in the INTERNAL OPTIONS
section
--results-dir,-o dir
Write results and internal files in the specified directory
(default: ./infer-out)
EXPLORE BUGS
--html
Activates: Generate html report. (Conversely: --no-html)
@ -41,6 +49,13 @@ OPTIONS
Activates: Show the list of reports and exit (Conversely:
--no-only-show)
--select N
Select bug number N. If omitted, prompt for input.
--no-source-preview
Deactivates: print code excerpts around trace elements
(Conversely: --source-preview)
EXPLORE PROCEDURES
--procedures
Activates: Print functions and methods discovered by infer
(Conversely: --no-procedures)
@ -71,14 +86,7 @@ OPTIONS
Deactivates: Include the source file in which the procedure
definition or declaration was found in the output of --procedures
(Conversely: --procedures-source-file)
--results-dir,-o dir
Write results and internal files in the specified directory
(default: ./infer-out)
--select N
Select bug number N. If omitted, prompt for input.
EXPLORE SOURCE FILES
--source-files
Activates: Print source files discovered by infer (Conversely:
--no-source-files)
@ -109,10 +117,6 @@ OPTIONS
output of --source-files (Conversely:
--no-source-files-type-environment)
--no-source-preview
Deactivates: print code excerpts around trace elements
(Conversely: --source-preview)
ENVIRONMENT
INFER_ARGS, INFERCONFIG, INFER_STRICT_MODE

@ -126,14 +126,17 @@ let explore =
~short_description:"explore the error traces in infer reports"
~synopsis:
{|$(b,infer) $(b,explore) $(i,[options])
$(b,infer) $(b,explore) $(b,--procedures) $(i,[options])|}
$(b,infer) $(b,explore) $(b,--procedures) $(i,[options])
$(b,infer) $(b,explore) $(b,--source-files) $(i,[options])|}
~description:
[ `P
"Show the list of bugs on the console and explore symbolic program traces emitted by \
infer to explain a report. Can also generate an HTML report from a JSON report."
; `P
"If $(b,--procedures) is passed, print information about each procedure captured by \
infer." ]
infer."
; `P "If $(b,--source-files) is passed, print information about captured source files."
; `P
"Otherwise, show the list of bugs on the console and explore symbolic program traces \
emitted by infer to explain a report. Can also generate an HTML report from a JSON \
report." ]
~see_also:InferCommand.[Report; Run]

@ -201,6 +201,12 @@ let manual_clang = "CLANG OPTIONS"
let manual_clang_linters = "CLANG LINTERS OPTIONS"
let manual_explore_bugs = "EXPLORE BUGS"
let manual_explore_procedures = "EXPLORE PROCEDURES"
let manual_explore_source_files = "EXPLORE SOURCE FILES"
let manual_generic = Cmdliner.Manpage.s_options
let manual_hoisting = "HOISTING OPTIONS"
@ -1427,7 +1433,7 @@ and help_format =
and html =
CLOpt.mk_bool ~long:"html"
~in_help:InferCommand.[(Explore, manual_generic)]
~in_help:InferCommand.[(Explore, manual_explore_bugs)]
"Generate html report."
@ -1608,7 +1614,7 @@ and margin =
and max_nesting =
CLOpt.mk_int_opt ~long:"max-nesting"
~in_help:InferCommand.[(Explore, manual_generic)]
~in_help:InferCommand.[(Explore, manual_explore_bugs)]
"Level of nested procedure calls to show. Trace elements beyond the maximum nesting level are \
skipped. If omitted, all levels are shown."
@ -1678,7 +1684,7 @@ and only_footprint =
and only_show =
CLOpt.mk_bool ~long:"only-show"
~in_help:InferCommand.[(Explore, manual_generic)]
~in_help:InferCommand.[(Explore, manual_explore_bugs)]
"Show the list of reports and exit"
@ -1763,19 +1769,19 @@ and print_using_diff =
and procedures =
CLOpt.mk_bool ~long:"procedures"
~in_help:InferCommand.[(Explore, manual_generic)]
~in_help:InferCommand.[(Explore, manual_explore_procedures)]
"Print functions and methods discovered by infer"
and procedures_attributes =
CLOpt.mk_bool ~long:"procedures-attributes"
~in_help:InferCommand.[(Explore, manual_generic)]
~in_help:InferCommand.[(Explore, manual_explore_procedures)]
"Print the attributes of each procedure in the output of $(b,--procedures)"
and procedures_definedness =
CLOpt.mk_bool ~long:"procedures-definedness" ~default:true
~in_help:InferCommand.[(Explore, manual_generic)]
~in_help:InferCommand.[(Explore, manual_explore_procedures)]
"Include procedures definedness in the output of $(b,--procedures), i.e. whether the \
procedure definition was found, or only the procedure declaration, or the procedure is an \
auto-generated Objective-C accessor"
@ -1783,7 +1789,7 @@ and procedures_definedness =
and procedures_filter =
CLOpt.mk_string_opt ~long:"procedures-filter" ~meta:"filter"
~in_help:InferCommand.[(Explore, manual_generic)]
~in_help:InferCommand.[(Explore, manual_explore_procedures)]
"With $(b,--procedures), only print functions and methods (procedures) matching the specified \
$(i,filter). A procedure filter is of the form $(i,path_pattern:procedure_name). Patterns \
are interpreted as OCaml Str regular expressions. For instance, to keep only methods named \
@ -1792,7 +1798,7 @@ and procedures_filter =
and procedures_name =
CLOpt.mk_bool ~long:"procedures-name"
~in_help:InferCommand.[(Explore, manual_generic)]
~in_help:InferCommand.[(Explore, manual_explore_procedures)]
"Include procedures names in the output of $(b,--procedures)"
@ -1805,7 +1811,7 @@ and procedures_per_process =
and procedures_source_file =
CLOpt.mk_bool ~long:"procedures-source-file" ~default:true
~in_help:InferCommand.[(Explore, manual_generic)]
~in_help:InferCommand.[(Explore, manual_explore_procedures)]
"Include the source file in which the procedure definition or declaration was found in the \
output of $(b,--procedures)"
@ -1987,7 +1993,7 @@ and seconds_per_iteration =
and select =
CLOpt.mk_int_opt ~long:"select" ~meta:"N"
~in_help:InferCommand.[(Explore, manual_generic)]
~in_help:InferCommand.[(Explore, manual_explore_bugs)]
"Select bug number $(i,N). If omitted, prompt for input."
@ -2025,19 +2031,19 @@ and skip_translation_headers =
and source_preview =
CLOpt.mk_bool ~long:"source-preview" ~default:true
~in_help:InferCommand.[(Explore, manual_generic)]
~in_help:InferCommand.[(Explore, manual_explore_bugs)]
"print code excerpts around trace elements"
and source_files =
CLOpt.mk_bool ~long:"source-files"
~in_help:InferCommand.[(Explore, manual_generic)]
~in_help:InferCommand.[(Explore, manual_explore_source_files)]
"Print source files discovered by infer"
and source_files_cfg =
CLOpt.mk_bool ~long:"source-files-cfg"
~in_help:InferCommand.[(Explore, manual_generic)]
~in_help:InferCommand.[(Explore, manual_explore_source_files)]
(Printf.sprintf
"Output a dotty file in infer-out/%s for each source file in the output of \
$(b,--source-files)"
@ -2046,7 +2052,7 @@ and source_files_cfg =
and source_files_filter =
CLOpt.mk_string_opt ~long:"source-files-filter" ~meta:"filter"
~in_help:InferCommand.[(Explore, manual_generic)]
~in_help:InferCommand.[(Explore, manual_explore_source_files)]
"With $(b,--source-files), only print source files matching the specified $(i,filter). The \
filter is a pattern that should match the file path. Patterns are interpreted as OCaml Str \
regular expressions."
@ -2054,19 +2060,19 @@ and source_files_filter =
and source_files_type_environment =
CLOpt.mk_bool ~long:"source-files-type-environment"
~in_help:InferCommand.[(Explore, manual_generic)]
~in_help:InferCommand.[(Explore, manual_explore_source_files)]
"Print the type environment of each source file in the output of $(b,--source-files)"
and source_files_procedure_names =
CLOpt.mk_bool ~long:"source-files-procedure-names"
~in_help:InferCommand.[(Explore, manual_generic)]
~in_help:InferCommand.[(Explore, manual_explore_source_files)]
"Print the names of procedure of each source file in the output of $(b,--source-files)"
and source_files_freshly_captured =
CLOpt.mk_bool ~long:"source-files-freshly-captured"
~in_help:InferCommand.[(Explore, manual_generic)]
~in_help:InferCommand.[(Explore, manual_explore_source_files)]
"Print whether the source file has been captured in the most recent capture phase in the \
output of $(b,--source-files)."

@ -145,53 +145,57 @@ let () =
~previous_costs:Config.costs_previous
| Diff ->
Diff.diff (Lazy.force Driver.mode_from_command_line)
| Explore when Config.procedures ->
L.result "%a"
Config.(
Procedures.pp_all
~filter:(Lazy.force Filtering.procedures_filter)
~proc_name:procedures_name ~attr_kind:procedures_definedness
~source_file:procedures_source_file ~proc_attributes:procedures_attributes)
()
| Explore when Config.source_files ->
let filter = Lazy.force Filtering.source_files_filter in
L.result "%a"
(SourceFiles.pp_all ~filter ~type_environment:Config.source_files_type_environment
~procedure_names:Config.source_files_procedure_names
~freshly_captured:Config.source_files_freshly_captured)
() ;
if Config.source_files_cfg then (
let source_files = SourceFiles.get_all ~filter () in
List.iter source_files ~f:(fun source_file ->
(* create directory in captured/ *)
DB.Results_dir.init ~debug:true source_file ;
(* collect the CFGs for all the procedures in [source_file] *)
let proc_names = SourceFiles.proc_names_of_source source_file in
let cfgs = Typ.Procname.Hash.create (List.length proc_names) in
List.iter proc_names ~f:(fun proc_name ->
Procdesc.load proc_name
|> Option.iter ~f:(fun cfg -> Typ.Procname.Hash.add cfgs proc_name cfg) ) ;
(* emit the dotty file in captured/... *)
Dotty.print_icfg_dotty source_file cfgs ) ;
L.result "CFGs written in %s/*/%s@." Config.captured_dir Config.dotty_output )
| Explore ->
let if_some key opt args =
match opt with None -> args | Some arg -> key :: string_of_int arg :: args
in
let if_true key opt args = if not opt then args else key :: args in
let if_false key opt args = if opt then args else key :: args in
let args =
if_some "--max-level" Config.max_nesting
@@ if_true "--only-show" Config.only_show
@@ if_false "--no-source" Config.source_preview
@@ if_true "--html" Config.html
@@ if_some "--select" Config.select ["-o"; Config.results_dir]
in
let prog = Config.lib_dir ^/ "python" ^/ "inferTraceBugs" in
if is_error (Unix.waitpid (Unix.fork_exec ~prog ~argv:(prog :: args) ())) then
L.external_error
"** Error running the reporting script:@\n** %s %s@\n** See error above@." prog
(String.concat ~sep:" " args)
| Explore -> (
match (Config.procedures, Config.source_files) with
| true, false ->
L.result "%a"
Config.(
Procedures.pp_all
~filter:(Lazy.force Filtering.procedures_filter)
~proc_name:procedures_name ~attr_kind:procedures_definedness
~source_file:procedures_source_file ~proc_attributes:procedures_attributes)
()
| false, true ->
let filter = Lazy.force Filtering.source_files_filter in
L.result "%a"
(SourceFiles.pp_all ~filter ~type_environment:Config.source_files_type_environment
~procedure_names:Config.source_files_procedure_names
~freshly_captured:Config.source_files_freshly_captured)
() ;
if Config.source_files_cfg then (
let source_files = SourceFiles.get_all ~filter () in
List.iter source_files ~f:(fun source_file ->
(* create directory in captured/ *)
DB.Results_dir.init ~debug:true source_file ;
(* collect the CFGs for all the procedures in [source_file] *)
let proc_names = SourceFiles.proc_names_of_source source_file in
let cfgs = Typ.Procname.Hash.create (List.length proc_names) in
List.iter proc_names ~f:(fun proc_name ->
Procdesc.load proc_name
|> Option.iter ~f:(fun cfg -> Typ.Procname.Hash.add cfgs proc_name cfg) ) ;
(* emit the dotty file in captured/... *)
Dotty.print_icfg_dotty source_file cfgs ) ;
L.result "CFGs written in %s/*/%s@." Config.captured_dir Config.dotty_output )
| false, false ->
let if_some key opt args =
match opt with None -> args | Some arg -> key :: string_of_int arg :: args
in
let if_true key opt args = if not opt then args else key :: args in
let if_false key opt args = if opt then args else key :: args in
let args =
if_some "--max-level" Config.max_nesting
@@ if_true "--only-show" Config.only_show
@@ if_false "--no-source" Config.source_preview
@@ if_true "--html" Config.html
@@ if_some "--select" Config.select ["-o"; Config.results_dir]
in
let prog = Config.lib_dir ^/ "python" ^/ "inferTraceBugs" in
if is_error (Unix.waitpid (Unix.fork_exec ~prog ~argv:(prog :: args) ())) then
L.external_error
"** Error running the reporting script:@\n** %s %s@\n** See error above@." prog
(String.concat ~sep:" " args)
| true, true ->
L.user_error "Options --procedures and --source-files cannot be used together.@\n" )
| Events ->
EventLogger.dump () ) ;
(* to make sure the exitcode=0 case is logged, explicitly invoke exit *)

Loading…
Cancel
Save