diff options
author | David Malcolm <dmalcolm@redhat.com> | 2023-12-06 12:35:44 -0500 |
---|---|---|
committer | David Malcolm <dmalcolm@redhat.com> | 2023-12-06 12:35:44 -0500 |
commit | 3bd8241a1f19827586cbed7832a24f44ff3e22ac (patch) | |
tree | 5d30aa8826b5c856b8fd973286f095a85d7bfd4f /gcc/diagnostic-format-json.cc | |
parent | 8fc4e6c397e1ce64bec6f9fed148950821cc79e7 (diff) | |
download | gcc-3bd8241a1f19827586cbed7832a24f44ff3e22ac.zip gcc-3bd8241a1f19827586cbed7832a24f44ff3e22ac.tar.gz gcc-3bd8241a1f19827586cbed7832a24f44ff3e22ac.tar.bz2 |
diagnostics: prettify JSON output formats
Previously our JSON output emitted the JSON all on one line, with
no indentation to show the structure of the values.
Although it's easy to reformat such output (e.g. with
"python -m json.tool"), I've found it's a pain to need to do so
e.g. my text editor sometimes hangs when opening a multimegabyte
json file all on one line. Similarly diff-ing is easier if the
json is already formatted.
This patch add whitespace to json output to show the structure.
It turned out to be fairly easy to implement using pretty_printer's
existing indentation machinery.
The patch uses this formatting for the various JSON-based diagnostic
output formats.
For example, with this patch, the output from
fdiagnostics-format=json-stderr looks like:
[{"kind": "warning",
"message": "stack-based buffer overflow",
"option": "-Wanalyzer-out-of-bounds",
"option_url": "https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-out-of-bounds",
"children": [{"kind": "note",
"message": "write of 350 bytes to beyond the end of ‘buf’",
"locations": [{"caret": {"file": "../../src/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-19.c",
"line": 20,
"display-column": 3,
"byte-column": 3,
"column": 3},
"finish": {"file": "../../src/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-19.c",
"line": 20,
"display-column": 27,
"byte-column": 27,
"column": 27}}],
"escape-source": false},
{"kind": "note",
"message": "valid subscripts for ‘buf’ are ‘[0]’ to ‘[99]’",
"locations": [{"caret": {"file": "../../src/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-19.c",
"line": 20,
"display-column": 3,
"byte-column": 3,
"column": 3},
"finish": {"file": "../../src/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-19.c",
"line": 20,
"display-column": 27,
"byte-column": 27,
"column": 27}}],
"escape-source": false}],
"column-origin": 1,
...snip...]
I was able to update almost all of our DejaGnu test cases for JSON to
handle this format tweak, and IMHO it improved the readability of these
test cases, but a couple were more awkward. Hence I added
-fno-diagnostics-json-formatting as an option to disable this
formatting.
The formatting does not affect the output of -fsave-optimization-record
or the JSON output from gcov (but this could be enabled if desirable).
gcc/analyzer/ChangeLog:
* engine.cc (dump_analyzer_json): Use
flag_diagnostics_json_formatting.
gcc/ChangeLog:
* common.opt (fdiagnostics-json-formatting): New.
* diagnostic-format-json.cc: Add "formatted" boolean
to json_output_format and subclasses, and to the
diagnostic_output_format_init_json_* functions. Use it when
printing JSON.
* diagnostic-format-sarif.cc: Likewise for sarif_builder,
sarif_output_format, and the various
diagnostic_output_format_init_sarif_* functions.
* diagnostic.cc (diagnostic_output_format_init): Add
"json_formatting" boolean and pass on to the various cases.
* diagnostic.h (diagnostic_output_format_init): Add
"json_formatted" param.
(diagnostic_output_format_init_json_stderr): Add "formatted" param
(diagnostic_output_format_init_json_file): Likewise.
(diagnostic_output_format_init_sarif_stderr): Likewise.
(diagnostic_output_format_init_sarif_file): Likewise.
(diagnostic_output_format_init_sarif_stream): Likewise.
* doc/invoke.texi (-fdiagnostics-format=json): Remove discussion
about JSON output needing formatting.
(-fno-diagnostics-json-formatting): Add.
* gcc.cc (driver_handle_option): Use
opts->x_flag_diagnostics_json_formatting.
* gcov.cc (generate_results): Pass "false" for new formatting
option when printing json.
* json.cc (value::dump): Add new "formatted" param.
(object::print): Likewise, using it to add whitespace to format
the JSON output.
(array::print): Likewise.
(float_number::print): Add new "formatted" param.
(integer_number::print): Likewise.
(string::print): Likewise.
(literal::print): Likewise.
(selftest::assert_print_eq): Add "formatted" param.
(ASSERT_PRINT_EQ): Add "FORMATTED" param.
(selftest::test_writing_objects): Test both formatted and
unformatted printing.
(selftest::test_writing_arrays): Likewise.
(selftest::test_writing_float_numbers): Update for new param of
ASSERT_PRINT_EQ.
(selftest::test_writing_integer_numbers): Likewise.
(selftest::test_writing_strings): Likewise.
(selftest::test_writing_literals): Likewise.
(selftest::test_formatting): New.
(selftest::json_cc_tests): Call it.
* json.h (value::print): Add "formatted" param.
(value::dump): Likewise.
(object::print): Likewise.
(array::print): Likewise.
(float_number::print): Likewise.
(integer_number::print): Likewise.
(string::print): Likewise.
(literal::print): Likewise.
* optinfo-emit-json.cc (optrecord_json_writer::write): Pass
"false" for new formatting option when printing json.
(selftest::test_building_json_from_dump_calls): Likewise.
* opts.cc (common_handle_option): Use
opts->x_flag_diagnostics_json_formatting.
gcc/testsuite/ChangeLog:
* c-c++-common/diagnostic-format-json-1.c: Update expected JSON
output to reflect whitespace.
* c-c++-common/diagnostic-format-json-2.c: Likewise.
* c-c++-common/diagnostic-format-json-3.c: Likewise.
* c-c++-common/diagnostic-format-json-4.c: Likewise.
* c-c++-common/diagnostic-format-json-5.c: Likewise.
* c-c++-common/diagnostic-format-json-stderr-1.c: Likewise.
* g++.dg/pr90462.C: Add -fno-diagnostics-json-formatting.
* gcc.dg/analyzer/malloc-sarif-1.c: Likewise.
* gcc.dg/plugin/diagnostic-test-paths-3.c: Update expected JSON
output to reflect whitespace.
* gfortran.dg/diagnostic-format-json-1.F90: Likewise.
* gfortran.dg/diagnostic-format-json-2.F90: Likewise.
* gfortran.dg/diagnostic-format-json-3.F90: Likewise.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
Diffstat (limited to 'gcc/diagnostic-format-json.cc')
-rw-r--r-- | gcc/diagnostic-format-json.cc | 26 |
1 files changed, 18 insertions, 8 deletions
diff --git a/gcc/diagnostic-format-json.cc b/gcc/diagnostic-format-json.cc index 418db74..c013192 100644 --- a/gcc/diagnostic-format-json.cc +++ b/gcc/diagnostic-format-json.cc @@ -56,11 +56,13 @@ public: } protected: - json_output_format (diagnostic_context &context) + json_output_format (diagnostic_context &context, + bool formatted) : diagnostic_output_format (context), m_toplevel_array (new json::array ()), m_cur_group (nullptr), - m_cur_children_array (nullptr) + m_cur_children_array (nullptr), + m_formatted (formatted) { } @@ -68,7 +70,7 @@ protected: void flush_to_file (FILE *outf) { - m_toplevel_array->dump (outf); + m_toplevel_array->dump (outf, m_formatted); fprintf (outf, "\n"); delete m_toplevel_array; m_toplevel_array = nullptr; @@ -84,6 +86,8 @@ private: /* The JSON array for the "children" array within the current diagnostic group. */ json::array *m_cur_children_array; + + bool m_formatted; }; /* Generate a JSON object for LOC. */ @@ -301,8 +305,9 @@ json_output_format::on_end_diagnostic (const diagnostic_info &diagnostic, class json_stderr_output_format : public json_output_format { public: - json_stderr_output_format (diagnostic_context &context) - : json_output_format (context) + json_stderr_output_format (diagnostic_context &context, + bool formatted) + : json_output_format (context, formatted) { } ~json_stderr_output_format () @@ -315,8 +320,9 @@ class json_file_output_format : public json_output_format { public: json_file_output_format (diagnostic_context &context, + bool formatted, const char *base_file_name) - : json_output_format (context), + : json_output_format (context, formatted), m_base_file_name (xstrdup (base_file_name)) { } @@ -367,10 +373,12 @@ diagnostic_output_format_init_json (diagnostic_context *context) /* Populate CONTEXT in preparation for JSON output to stderr. */ void -diagnostic_output_format_init_json_stderr (diagnostic_context *context) +diagnostic_output_format_init_json_stderr (diagnostic_context *context, + bool formatted) { diagnostic_output_format_init_json (context); - context->set_output_format (new json_stderr_output_format (*context)); + context->set_output_format (new json_stderr_output_format (*context, + formatted)); } /* Populate CONTEXT in preparation for JSON output to a file named @@ -378,10 +386,12 @@ diagnostic_output_format_init_json_stderr (diagnostic_context *context) void diagnostic_output_format_init_json_file (diagnostic_context *context, + bool formatted, const char *base_file_name) { diagnostic_output_format_init_json (context); context->set_output_format (new json_file_output_format (*context, + formatted, base_file_name)); } |