@ -14,6 +14,14 @@ let is_past_limit limit =
match limit with None -> fun _ -> false | Some limit -> fun n -> n > = limit
match limit with None -> fun _ -> false | Some limit -> fun n -> n > = limit
let has_trace { Jsonbug_t . bug_trace ; _ } = not ( List . is_empty bug_trace )
let with_file_fmt file ~ f =
Utils . with_file_out file ~ f : ( fun outc ->
let fmt = F . formatter_of_out_channel outc in
f fmt ; F . pp_print_flush fmt () )
let pp_trace_item ~ show_source_context fmt
let pp_trace_item ~ show_source_context fmt
Jsonbug_t . { level ; filename ; line_number ; column_number ; description } =
Jsonbug_t . { level ; filename ; line_number ; column_number ; description } =
let pp_col_number fmt c = if c > = 0 then F . fprintf fmt " :%d " c in
let pp_col_number fmt c = if c > = 0 then F . fprintf fmt " :%d " c in
@ -23,15 +31,15 @@ let pp_trace_item ~show_source_context fmt
{ Jsonbug_t . file = filename ; lnum = line_number ; cnum = column_number ; enum = - 1 }
{ Jsonbug_t . file = filename ; lnum = line_number ; cnum = column_number ; enum = - 1 }
let show _issue_with_trace ~ show_source_context ~ max_nested_level
let pp _issue_with_trace ~ show_source_context ~ max_nested_level fmt
( n_issue , ( issue : Jsonbug_t . jsonbug ) ) =
( n_issue , ( issue : Jsonbug_t . jsonbug ) ) =
L. resul t " #%d@ \n %a@ \n " n_issue TextReport . pp_jsonbug issue ;
F. fprintf fm t " #%d@ \n %a@ \n " n_issue TextReport . pp_jsonbug issue ;
if List . is_empty issue . bug_trace then L. resul t " @ \n Empty trace@ \n %! "
if List . is_empty issue . bug_trace then F. fprintf fm t " @ \n Empty trace@ \n %! "
else
else
List . iter issue . bug_trace ~ f : ( fun trace_item ->
List . iter issue . bug_trace ~ f : ( fun trace_item ->
(* subtract 1 to get inclusive limits on the nesting level *)
(* subtract 1 to get inclusive limits on the nesting level *)
if not ( is_past_limit max_nested_level ( trace_item . Jsonbug_t . level - 1 ) ) then
if not ( is_past_limit max_nested_level ( trace_item . Jsonbug_t . level - 1 ) ) then
L. resul t " @ \n %a " ( pp_trace_item ~ show_source_context ) trace_item )
F. fprintf fm t " @ \n %a " ( pp_trace_item ~ show_source_context ) trace_item )
let user_select_issue ~ selector_limit report =
let user_select_issue ~ selector_limit report =
@ -62,9 +70,11 @@ let user_select_issue ~selector_limit report =
( n , List . nth_exn report n )
( n , List . nth_exn report n )
let read_report report_json = Atdgen_runtime . Util . Json . from_file Jsonbug_j . read_report report_json
let explore ~ selector_limit ~ report_txt : _ ~ report_json ~ show_source_context ~ selected
let explore ~ selector_limit ~ report_txt : _ ~ report_json ~ show_source_context ~ selected
~ max_nested_level =
~ max_nested_level =
let report = Atdgen_runtime . Util . Json . from_file Jsonbug_j . read_report report_json in
let report = read_report report_json in
let issue_to_display =
let issue_to_display =
match ( selected , report ) with
match ( selected , report ) with
| Some n , _ -> (
| Some n , _ -> (
@ -87,7 +97,51 @@ let explore ~selector_limit ~report_txt:_ ~report_json ~show_source_context ~sel
(* user prompt *)
(* user prompt *)
Some ( user_select_issue ~ selector_limit report )
Some ( user_select_issue ~ selector_limit report )
in
in
Option . iter issue_to_display
Option . iter issue_to_display ~ f : ( fun issue ->
~ f :
L . result " @ \n %a " ( pp_issue_with_trace ~ show_source_context ~ max_nested_level ) issue )
( L . result " @ \n " ;
show_issue_with_trace ~ show_source_context ~ max_nested_level )
let trace_path_of_bug_number ~ traces_dir i = traces_dir ^/ Printf . sprintf " bug_%d.txt " i
let pp_html_index ~ traces_dir fmt report =
let pp_issue_entry fmt issue_i =
let pp_trace_uri fmt ( i , ( issue : Jsonbug_t . jsonbug ) ) =
if has_trace issue then
F . fprintf fmt " <a href= \" %s \" >trace</a> " ( trace_path_of_bug_number ~ traces_dir i )
else F . pp_print_string fmt " no trace "
in
F . fprintf fmt " <li>%a (%a)</li> " TextReport . pp_jsonbug ( snd issue_i ) pp_trace_uri issue_i
in
let pp_issues_list fmt report =
F . fprintf fmt " <ol start= \" 0 \" >@ \n " ;
List . iteri report ~ f : ( fun i issue -> pp_issue_entry fmt ( i , issue ) ) ;
F . fprintf fmt " @ \n </ol> "
in
F . fprintf fmt
{ | < html >
< head >
< title > Infer found % d issues < / title >
< / head >
< body >
< h2 > List of issues found < / h2 >
% a
< / body >
< / html > | }
( List . length report ) pp_issues_list report
let gen_html_report ~ show_source_context ~ max_nested_level ~ report_json ~ report_html_dir =
(* delete previous report if present *)
Utils . rmtree report_html_dir ;
Utils . create_dir report_html_dir ;
let traces_dir = " traces " in
Utils . create_dir ( report_html_dir ^/ traces_dir ) ;
let report = read_report report_json in
List . iteri report ~ f : ( fun i issue ->
if has_trace issue then
let file = report_html_dir ^/ trace_path_of_bug_number ~ traces_dir i in
with_file_fmt file ~ f : ( fun fmt ->
pp_issue_with_trace ~ show_source_context ~ max_nested_level fmt ( i , issue ) ) ) ;
let report_html = report_html_dir ^/ " index.html " in
with_file_fmt report_html ~ f : ( fun fmt -> pp_html_index ~ traces_dir fmt report ) ;
L . result " Saved HTML report in '%s'@. " report_html