diff --git a/infer/src/backend/InferPrint.re b/infer/src/backend/InferPrint.re index 5d690786d..4d382f859 100644 --- a/infer/src/backend/InferPrint.re +++ b/infer/src/backend/InferPrint.re @@ -524,10 +524,10 @@ let module IssuesJson = { ltr eclass visibility => { - let source_file = + let (source_file, procedure_start_line) = switch proc_loc_opt { - | Some proc_loc => proc_loc.Location.file - | None => loc.Location.file + | Some proc_loc => (proc_loc.Location.file, proc_loc.Location.line) + | None => (loc.Location.file, loc.Location.line) }; let file_opt = make_cpp_models_path_relative source_file; if ( @@ -557,6 +557,7 @@ let module IssuesJson = { column: loc.Location.col, procedure: Procname.to_string procname, procedure_id, + procedure_start_line, file, bug_trace: loc_trace_to_jsonbug_record ltr ekind, key: node_key, @@ -628,6 +629,20 @@ let module IssuesTests = { }; }; +let pp_tests_of_report fmt report => { + let pp_row jsonbug => + Jsonbug_t.( + F.fprintf + fmt + "%s, %s, %d, %s@." + jsonbug.file + jsonbug.procedure + (jsonbug.line - jsonbug.procedure_start_line) + jsonbug.bug_type + ); + IList.iter pp_row report +}; + let module IssuesTxt = { /** Write bug report in text format */ @@ -646,6 +661,21 @@ let module IssuesTxt = { }; }; +let pp_text_of_report fmt report => { + let pp_row jsonbug => + Jsonbug_t.( + F.fprintf + fmt + "%s:%d: %s: %s %s@\n" + jsonbug.file + jsonbug.line + jsonbug.kind + jsonbug.bug_type + jsonbug.qualifier + ); + IList.iter pp_row report +}; + let module IssuesXml = { let xml_issues_id = ref 0; let loc_trace_to_xml linereader ltr => { @@ -1187,6 +1217,31 @@ let pp_summary_by_report_kind IList.iter pp_summary_by_report_kind formats_by_report_kind }; +let pp_json_report_by_report_kind formats_by_report_kind fname => + switch (read_file fname) { + | Some report_lines => + let pp_json_issues format_list report => { + let pp_json_issue (format_kind, outf) => + switch format_kind { + | Tests => pp_tests_of_report outf.fmt report + | Text => pp_text_of_report outf.fmt report + | Json => failwith "Printing issues from json does not support json output" + | Csv => failwith "Printing issues from json does not support csv output" + | Xml => failwith "Printing issues from json does not support xml output" + | Latex => failwith "Printing issues from json does not support latex output" + }; + IList.iter pp_json_issue format_list + }; + let report = Jsonbug_j.report_of_string (String.concat "\n" report_lines); + let pp_report_by_report_kind (report_kind, format_list) => + switch (report_kind, format_list) { + | (Issues, [_, ..._]) => pp_json_issues format_list report + | _ => () + }; + IList.iter pp_report_by_report_kind formats_by_report_kind + | None => failwithf "Error reading %s. Does the file exist?" fname + }; + let pp_lint_issues_by_report_kind formats_by_report_kind error_filter linereader procname error_log => { let pp_summary_by_report_kind (report_kind, format_list) => switch (report_kind, format_list) { @@ -1428,7 +1483,6 @@ let finalize_and_close_files format_list_by_kind stats pdflatex => { }; let pp_summary_and_issues formats_by_report_kind => { - init_files formats_by_report_kind; let pdflatex fname => ignore (Sys.command ("pdflatex " ^ fname)); let stats = Stats.create (); let linereader = Printer.LineReader.create (); @@ -1455,6 +1509,14 @@ let pp_summary_and_issues formats_by_report_kind => { finalize_and_close_files formats_by_report_kind stats pdflatex }; +let print_issues formats_by_report_kind => { + init_files formats_by_report_kind; + switch Config.from_json_report { + | Some fname => pp_json_report_by_report_kind formats_by_report_kind fname + | None => pp_summary_and_issues formats_by_report_kind + } +}; + let main report_csv::report_csv report_json::report_json => { let formats_by_report_kind = [ (Issues, init_issues_format_list report_csv report_json), @@ -1465,6 +1527,5 @@ let main report_csv::report_csv report_json::report_json => { ]; register_perf_stats_report (); handle_source_file_copy_option (); - /* print issues */ - pp_summary_and_issues formats_by_report_kind + print_issues formats_by_report_kind }; diff --git a/infer/src/backend/jsonbug.atd b/infer/src/backend/jsonbug.atd index 2e538ef46..0af0f3075 100644 --- a/infer/src/backend/jsonbug.atd +++ b/infer/src/backend/jsonbug.atd @@ -29,6 +29,7 @@ type jsonbug = { column: int; procedure : string; procedure_id : string; + procedure_start_line : int; file : string; bug_trace : json_trace_item list; key : int; diff --git a/infer/src/base/Config.ml b/infer/src/base/Config.ml index 8b257539b..d8cc82644 100644 --- a/infer/src/base/Config.ml +++ b/infer/src/base/Config.ml @@ -899,6 +899,13 @@ and flavors = "Buck integration using Buck flavors (clang only), eg `infer --flavors -- buck build \ //foo:bar#infer`" +and from_json_report = + CLOpt.mk_path_opt ~long:"from-json-report" + ~exes:CLOpt.[Print] + ~meta:"report.json" + "Load analysis results from a report file (default is to load the results from the specs \ + files generated by the analysis)." + and frontend_debug = CLOpt.mk_bool ~long:"frontend-debug" ~short:"fd" "Emit debug info to *.o.astlog and a script *.o.sh that replays the command used to run clang \ @@ -1437,6 +1444,7 @@ and fcp_syntax_only = !fcp_syntax_only and filter_paths = !filter_paths and filtering = !filtering and flavors = !flavors +and from_json_report = !from_json_report and frontend_debug = !frontend_debug and frontend_stats = !frontend_stats and headers = !headers diff --git a/infer/src/base/Config.mli b/infer/src/base/Config.mli index 40100755f..ebacb5c7a 100644 --- a/infer/src/base/Config.mli +++ b/infer/src/base/Config.mli @@ -193,6 +193,7 @@ val fcp_syntax_only : bool val filter_paths : bool val filtering : bool val flavors : bool +val from_json_report : string option val frontend_debug : bool val frontend_tests : bool val frontend_stats : bool