print location of errors in infer source code in debug mode

Summary:
public
- add to json reports the location in the ocaml code of assertions raised
  during the analysis
- only add when in debug mode. For this, add a flag to `InferPrint` that is
  passed by the toplevel `infer` whenever `infer -g` is used.

Reviewed By: jeremydubreil

Differential Revision: D2891286

fb-gh-sync-id: ad4577c
master
Jules Villard 9 years ago committed by facebook-github-bot-7
parent 8545a0310e
commit e11395d199

@ -522,6 +522,8 @@ class Infer:
if self.javac.annotations_out is not None: if self.javac.annotations_out is not None:
infer_print_options += [ infer_print_options += [
'-local_config', self.javac.annotations_out] '-local_config', self.javac.annotations_out]
if self.args.debug:
infer_print_options.append('-with_infer_src_loc')
exit_status = subprocess.check_call( exit_status = subprocess.check_call(
infer_print_cmd + infer_print_options infer_print_cmd + infer_print_options
) )

@ -93,6 +93,10 @@ JSON_INDEX_TRACE_DESCRIPTION = 'description'
JSON_INDEX_TRACE_NODE_TAGS = 'node_tags' JSON_INDEX_TRACE_NODE_TAGS = 'node_tags'
JSON_INDEX_TRACE_NODE_TAGS_TAG = 'tags' JSON_INDEX_TRACE_NODE_TAGS_TAG = 'tags'
JSON_INDEX_TRACE_NODE_TAGS_VALUE = 'value' JSON_INDEX_TRACE_NODE_TAGS_VALUE = 'value'
JSON_INDEX_INFER_SOURCE_LOC = 'infer_source_loc'
JSON_INDEX_ISL_FILE = 'file'
JSON_INDEX_ISL_LINE = 'line'
JSON_INDEX_ISL_COLUMN = 'column'
QUALIFIER_TAGS = 'qualifier_tags' QUALIFIER_TAGS = 'qualifier_tags'
BUCKET_TAGS = 'bucket' BUCKET_TAGS = 'bucket'
@ -146,11 +150,20 @@ def text_of_report(report):
line = report[JSON_INDEX_LINE] line = report[JSON_INDEX_LINE]
error_type = report[JSON_INDEX_TYPE] error_type = report[JSON_INDEX_TYPE]
msg = report[JSON_INDEX_QUALIFIER] msg = report[JSON_INDEX_QUALIFIER]
return u'%s:%d: %s: %s\n %s' % ( infer_loc = ''
if JSON_INDEX_INFER_SOURCE_LOC in report:
loc = report[JSON_INDEX_INFER_SOURCE_LOC]
infer_loc = u' (%s:%d:%d)' % (
loc[JSON_INDEX_ISL_FILE],
loc[JSON_INDEX_ISL_LINE],
loc[JSON_INDEX_ISL_COLUMN],
)
return u'%s:%d: %s: %s%s\n %s' % (
filename, filename,
line, line,
kind.lower(), kind.lower(),
error_type, error_type,
infer_loc,
msg, msg,
) )

@ -64,8 +64,16 @@ let empty () = ErrLogHash.create 13
(** type of the function to be passed to iter *) (** type of the function to be passed to iter *)
type iter_fun = type iter_fun =
(int * int) -> Location.t -> Exceptions.err_kind -> bool -> Localise.t -> Localise.error_desc -> (int * int) ->
string -> loc_trace -> Prop.normal Prop.t option -> Exceptions.err_class -> unit Location.t ->
ml_location option ->
Exceptions.err_kind ->
bool ->
Localise.t -> Localise.error_desc -> string ->
loc_trace ->
Prop.normal Prop.t option ->
Exceptions.err_class ->
unit
(** Apply f to nodes and error names *) (** Apply f to nodes and error names *)
let iter (f: iter_fun) (err_log: t) = let iter (f: iter_fun) (err_log: t) =
@ -73,7 +81,7 @@ let iter (f: iter_fun) (err_log: t) =
ErrDataSet.iter ErrDataSet.iter
(fun (node_id_key, section, loc, mloco, ltr, pre_opt, eclass) -> (fun (node_id_key, section, loc, mloco, ltr, pre_opt, eclass) ->
f f
node_id_key loc ekind in_footprint err_name node_id_key loc mloco ekind in_footprint err_name
desc severity ltr pre_opt eclass) desc severity ltr pre_opt eclass)
set) set)
err_log err_log

@ -9,6 +9,8 @@
(** Module for error logs. *) (** Module for error logs. *)
open Utils
(** Element of a loc trace *) (** Element of a loc trace *)
type loc_trace_elem = { type loc_trace_elem = {
lt_level : int; (** nesting level of procedure calls *) lt_level : int; (** nesting level of procedure calls *)
@ -28,8 +30,16 @@ val empty : unit -> t
(** type of the function to be passed to iter *) (** type of the function to be passed to iter *)
type iter_fun = type iter_fun =
(int * int) -> Location.t -> Exceptions.err_kind -> bool -> Localise.t -> Localise.error_desc -> (int * int) ->
string -> loc_trace -> Prop.normal Prop.t option -> Exceptions.err_class -> unit Location.t ->
ml_location option ->
Exceptions.err_kind ->
bool ->
Localise.t -> Localise.error_desc -> string ->
loc_trace ->
Prop.normal Prop.t option ->
Exceptions.err_class ->
unit
(** Apply f to nodes and error names *) (** Apply f to nodes and error names *)
val iter : iter_fun -> t -> unit val iter : iter_fun -> t -> unit

@ -64,6 +64,9 @@ let precondition_stats = ref false
(** name of the file to load analysis results from *) (** name of the file to load analysis results from *)
let load_analysis_results = ref None let load_analysis_results = ref None
(** If true then include Infer source code locations in json reports *)
let reports_include_ml_loc = ref false
(** name of the file to load save results to *) (** name of the file to load save results to *)
let save_analysis_results = ref None let save_analysis_results = ref None
@ -114,6 +117,8 @@ let arg_desc =
"Path to the .inferconfig file"; "Path to the .inferconfig file";
"-local_config", Arg.String (fun s -> Inferconfig.local_config := Some s), Some "Path", "-local_config", Arg.String (fun s -> Inferconfig.local_config := Some s), Some "Path",
"Path to local config file"; "Path to local config file";
"-with_infer_src_loc", Arg.Set reports_include_ml_loc, None,
"include the location (in the Infer source code) from where reports are generated";
] in ] in
Arg.create_options_desc false "Options" desc in Arg.create_options_desc false "Options" desc in
let reserved_arg = let reserved_arg =
@ -414,7 +419,7 @@ module BugsCsv = struct
let pp_bugs error_filter fname fmt summary = let pp_bugs error_filter fname fmt summary =
let pp x = F.fprintf fmt x in let pp x = F.fprintf fmt x in
let err_log = summary.Specs.attributes.ProcAttributes.err_log in let err_log = summary.Specs.attributes.ProcAttributes.err_log in
let pp_row (node_id, node_key) loc ekind in_footprint error_name error_desc severity ltr pre_opt eclass = let pp_row (node_id, node_key) loc ml_loc_opt ekind in_footprint error_name error_desc severity ltr pre_opt eclass =
if in_footprint && error_filter error_desc error_name then if in_footprint && error_filter error_desc error_name then
let err_desc_string = error_desc_to_csv_string error_desc in let err_desc_string = error_desc_to_csv_string error_desc in
let err_advice_string = error_advice_to_csv_string error_desc in let err_advice_string = error_advice_to_csv_string error_desc in
@ -463,13 +468,17 @@ module BugsJson = struct
let pp_bugs error_filter fname fmt summary = let pp_bugs error_filter fname fmt summary =
let pp x = F.fprintf fmt x in let pp x = F.fprintf fmt x in
let err_log = summary.Specs.attributes.ProcAttributes.err_log in let err_log = summary.Specs.attributes.ProcAttributes.err_log in
let pp_row (node_id, node_key) loc ekind in_footprint error_name error_desc severity ltr pre_opt eclass = let pp_row (node_id, node_key) loc ml_loc_opt ekind in_footprint error_name error_desc severity ltr pre_opt eclass =
if in_footprint && error_filter error_desc error_name then if in_footprint && error_filter error_desc error_name then
let kind = Exceptions.err_kind_string ekind in let kind = Exceptions.err_kind_string ekind in
let bug_type = Localise.to_string error_name in let bug_type = Localise.to_string error_name in
let procedure_id = Procname.to_filename (Specs.get_proc_name summary) in let procedure_id = Procname.to_filename (Specs.get_proc_name summary) in
let file = let file =
DB.source_file_to_string summary.Specs.attributes.ProcAttributes.loc.Location.file in DB.source_file_to_string summary.Specs.attributes.ProcAttributes.loc.Location.file in
let json_mloc = match ml_loc_opt with
| Some (file, line, column) when !reports_include_ml_loc ->
Some Jsonbug_j.{ file; line; column }
| _ -> None in
let bug = { let bug = {
bug_class = Exceptions.err_class_string eclass; bug_class = Exceptions.err_class_string eclass;
kind = kind; kind = kind;
@ -485,6 +494,7 @@ module BugsJson = struct
qualifier_tags = error_desc_to_qualifier_tags_records error_desc; qualifier_tags = error_desc_to_qualifier_tags_records error_desc;
hash = get_bug_hash kind bug_type procedure_id file node_key error_desc; hash = get_bug_hash kind bug_type procedure_id file node_key error_desc;
dotty = error_desc_to_dotty_string error_desc; dotty = error_desc_to_dotty_string error_desc;
infer_source_loc = json_mloc;
} in } in
if not !is_first_item then pp "," else is_first_item := false; if not !is_first_item then pp "," else is_first_item := false;
pp "%s@?" (string_of_jsonbug bug) in pp "%s@?" (string_of_jsonbug bug) in
@ -495,7 +505,7 @@ module BugsTxt = struct
(** Write bug report in text format *) (** Write bug report in text format *)
let pp_bugs error_filter fname fmt summary = let pp_bugs error_filter fname fmt summary =
let err_log = summary.Specs.attributes.ProcAttributes.err_log in let err_log = summary.Specs.attributes.ProcAttributes.err_log in
let pp_row (node_id, node_key) loc ekind in_footprint error_name error_desc severity ltr pre_opt eclass = let pp_row (node_id, node_key) loc ml_loc_opt ekind in_footprint error_name error_desc severity ltr pre_opt eclass =
if in_footprint && error_filter error_desc error_name then if in_footprint && error_filter error_desc error_name then
Exceptions.pp_err (node_id, node_key) loc ekind error_name error_desc None fmt () in Exceptions.pp_err (node_id, node_key) loc ekind error_name error_desc None fmt () in
Errlog.iter pp_row err_log Errlog.iter pp_row err_log
@ -535,7 +545,7 @@ module BugsXml = struct
(** print bugs from summary in xml *) (** print bugs from summary in xml *)
let pp_bugs error_filter linereader fmt summary = let pp_bugs error_filter linereader fmt summary =
let err_log = summary.Specs.attributes.ProcAttributes.err_log in let err_log = summary.Specs.attributes.ProcAttributes.err_log in
let do_row (node_id, node_key) loc ekind in_footprint error_name error_desc severity ltr pre_opt eclass = let do_row (node_id, node_key) loc ml_loc_opt ekind in_footprint error_name error_desc severity ltr pre_opt eclass =
if in_footprint && error_filter error_desc error_name then if in_footprint && error_filter error_desc error_name then
let err_desc_string = error_desc_to_xml_string error_desc in let err_desc_string = error_desc_to_xml_string error_desc in
let precondition_tree () = match pre_opt with let precondition_tree () = match pre_opt with
@ -729,7 +739,7 @@ module Stats = struct
let process_err_log error_filter linereader err_log stats = let process_err_log error_filter linereader err_log stats =
let found_errors = ref false in let found_errors = ref false in
let process_row (node_id, node_key) loc ekind in_footprint error_name error_desc severity ltr pre_opt eclass = let process_row (node_id, node_key) loc ml_loc_opt ekind in_footprint error_name error_desc severity ltr pre_opt eclass =
let type_str = Localise.to_string error_name in let type_str = Localise.to_string error_name in
if in_footprint && error_filter error_desc error_name if in_footprint && error_filter error_desc error_name
then match ekind with then match ekind with

@ -1,33 +1,40 @@
type tag_value_record = { type tag_value_record = {
tag : string; tag : string;
value : string; value : string;
} }
type json_trace_item = { type json_trace_item = {
level : int; level : int;
filename : string; filename : string;
line_number : int; line_number : int;
description : string; description : string;
node_tags : tag_value_record list; node_tags : tag_value_record list;
}
type loc = {
file: string;
line: int;
column: int;
} }
type jsonbug = { type jsonbug = {
bug_class : string; bug_class : string;
kind : string; kind : string;
bug_type : string; bug_type : string;
qualifier : string; qualifier : string;
severity : string; severity : string;
line: int; line: int;
procedure : string; procedure : string;
procedure_id : string; procedure_id : string;
file : string; file : string;
bug_trace : json_trace_item list; bug_trace : json_trace_item list;
key : int; key : int;
qualifier_tags : tag_value_record list; qualifier_tags : tag_value_record list;
hash : int; hash : int;
dotty : string; dotty : string;
?infer_source_loc: loc option;
} }
type json_trace = { type json_trace = {
trace : json_trace_item list; trace : json_trace_item list;
} }

@ -290,9 +290,8 @@ let proc_write_log whole_seconds cfg pname =
(** Creare a hash table mapping line numbers to the set of errors occurring on that line *) (** Creare a hash table mapping line numbers to the set of errors occurring on that line *)
let create_errors_per_line err_log = let create_errors_per_line err_log =
let err_per_line = Hashtbl.create 17 in let err_per_line = Hashtbl.create 17 in
let add_err node_id_key loc ekind in_footprint err_name desc severity ltr pre_opt eclass = let add_err node_id_key loc ml_loc_opt ekind in_footprint err_name desc severity ltr pre_opt eclass =
let err_str = Localise.to_string err_name ^ " " ^ (pp_to_string Localise.pp_error_desc desc) in let err_str = Localise.to_string err_name ^ " " ^ (pp_to_string Localise.pp_error_desc desc) in
(* if in_footprint then *)
try try
let set = Hashtbl.find err_per_line loc.Location.line in let set = Hashtbl.find err_per_line loc.Location.line in
Hashtbl.replace err_per_line loc.Location.line (StringSet.add err_str set) Hashtbl.replace err_per_line loc.Location.line (StringSet.add err_str set)

Loading…
Cancel
Save