diff --git a/infer/lib/python/inferTraceBugs b/infer/lib/python/inferTraceBugs index 07f9f094c..f07c2c093 100755 --- a/infer/lib/python/inferTraceBugs +++ b/infer/lib/python/inferTraceBugs @@ -81,12 +81,14 @@ class Tracer(object): return report_line = node[issues.JSON_INDEX_TRACE_LINE] + report_col = node[issues.JSON_INDEX_TRACE_COLUMN] fname = node[issues.JSON_INDEX_TRACE_FILENAME] self.indenter.newline() - self.indenter.add('%s:%d: %s' % ( + self.indenter.add('%s:%d:%d: %s' % ( fname, report_line, + report_col, node[issues.JSON_INDEX_TRACE_DESCRIPTION], )) self.indenter.newline() @@ -96,9 +98,13 @@ class Tracer(object): mode = colorize.TERMINAL_FORMATTER if self.args.html: mode = colorize.PLAIN_FORMATTER + empty_desc = len(node[issues.JSON_INDEX_TRACE_DESCRIPTION]) == 0 self.indenter.add(source.build_source_context(fname, mode, - report_line)) + report_line, + report_col, + empty_desc + )) self.indenter.indent_pop() self.indenter.newline() diff --git a/infer/lib/python/inferlib/issues.py b/infer/lib/python/inferlib/issues.py index 6360a102e..ec6f6bd0a 100644 --- a/infer/lib/python/inferlib/issues.py +++ b/infer/lib/python/inferlib/issues.py @@ -52,6 +52,7 @@ JSON_INDEX_TRACE = 'bug_trace' JSON_INDEX_TRACE_LEVEL = 'level' JSON_INDEX_TRACE_FILENAME = 'filename' JSON_INDEX_TRACE_LINE = 'line_number' +JSON_INDEX_TRACE_COLUMN = 'column_number' JSON_INDEX_TRACE_DESCRIPTION = 'description' JSON_INDEX_TRACEVIEW_ID = 'traceview_id' JSON_INDEX_VISIBILITY = 'visibility' @@ -110,6 +111,8 @@ def _text_of_report_list(project_root, reports, bugs_txt_path, limit=None, os.path.join(project_root, filename), formatter, line, + 1, + True ) indenter = source.Indenter() \ .indent_push() \ diff --git a/infer/lib/python/inferlib/source.py b/infer/lib/python/inferlib/source.py index 1c6c79649..b2d4ce00f 100644 --- a/infer/lib/python/inferlib/source.py +++ b/infer/lib/python/inferlib/source.py @@ -60,8 +60,10 @@ class Indenter(unicode): return utils.encode(unicode(self)) -def build_source_context(source_name, mode, report_line): +def build_source_context(source_name, mode, report_line, + report_col, empty_desc): start_line = max(1, report_line - SOURCE_CONTEXT) + start_col = max(0, report_col) # could go beyond last line, checked in the loop end_line = report_line + SOURCE_CONTEXT @@ -91,10 +93,20 @@ def build_source_context(source_name, mode, report_line): num = colorize.color((str(line_number) + '.').zfill(n_length), colorize.DIM, mode) caret = ' ' - if line_number == report_line: + do_mark_column = (line_number == report_line and + start_col > 1 and not empty_desc) + + # mark the line if we are not also marking the column + if line_number == report_line and not do_mark_column: caret = colorize.color('> ', - colorize.HEADER, mode) + colorize.BLUE + colorize.BRIGHT, mode) s += '%s %s%s\n' % (num, caret, line) + # mark the column position + if do_mark_column: + pad = ' ' * (3 + n_length + start_col) + s += pad + colorize.color('^', + colorize.BLUE + colorize.BRIGHT, + mode) + '\n' line_number += 1 return s diff --git a/infer/src/backend/InferPrint.re b/infer/src/backend/InferPrint.re index 2f9dbc3b0..18087236f 100644 --- a/infer/src/backend/InferPrint.re +++ b/infer/src/backend/InferPrint.re @@ -126,6 +126,7 @@ let loc_trace_to_jsonbug_record trace_list ekind => Jsonbug_j.level: trace_item.Errlog.lt_level, filename: SourceFile.to_string trace_item.Errlog.lt_loc.Location.file, line_number: trace_item.Errlog.lt_loc.Location.line, + column_number: trace_item.Errlog.lt_loc.Location.col, description: trace_item.Errlog.lt_description, node_tags: List.concat_map f::tag_value_records_of_node_tag trace_item.Errlog.lt_node_tags }; diff --git a/infer/src/backend/jsonbug.atd b/infer/src/backend/jsonbug.atd index 12cd3cf22..e6a859590 100644 --- a/infer/src/backend/jsonbug.atd +++ b/infer/src/backend/jsonbug.atd @@ -7,6 +7,7 @@ type json_trace_item = { level : int; filename : string; line_number : int; + column_number : int; description : string; node_tags : tag_value_record list; } diff --git a/infer/src/backend/paths.ml b/infer/src/backend/paths.ml index c3c74779f..14163b9c8 100644 --- a/infer/src/backend/paths.ml +++ b/infer/src/backend/paths.ml @@ -472,16 +472,20 @@ end = struct trace := Errlog.make_trace_element level curr_loc descr node_tags :: !trace | Procdesc.Node.Prune_node (is_true_branch, if_kind, _) -> let descr = match is_true_branch, if_kind with - | true, Sil.Ik_if -> "Taking true branch" - | false, Sil.Ik_if -> "Taking false branch" + | true, Sil.Ik_if -> + "Taking true branch" + | false, Sil.Ik_if -> + "Taking false branch" | true, (Sil.Ik_for | Sil.Ik_while | Sil.Ik_dowhile) -> "Loop condition is true. Entering loop body" | false, (Sil.Ik_for | Sil.Ik_while | Sil.Ik_dowhile) -> "Loop condition is false. Leaving loop" | true, Sil.Ik_switch -> "Switch condition is true. Entering switch case" | false, Sil.Ik_switch -> "Switch condition is false. Skipping switch case" - | true, (Sil.Ik_bexp | Sil.Ik_land_lor) -> "Condition is true" - | false, (Sil.Ik_bexp | Sil.Ik_land_lor) -> "Condition is false" in + | true, (Sil.Ik_bexp | Sil.Ik_land_lor) -> + "Condition is true" + | false, (Sil.Ik_bexp | Sil.Ik_land_lor) -> + "Condition is false" in let node_tags = [Errlog.Condition is_true_branch] in trace := Errlog.make_trace_element level curr_loc descr node_tags :: !trace | Procdesc.Node.Exit_node pname ->