diff options
Diffstat (limited to 'gcc/diagnostic-format-json.cc')
-rw-r--r-- | gcc/diagnostic-format-json.cc | 230 |
1 files changed, 121 insertions, 109 deletions
diff --git a/gcc/diagnostic-format-json.cc b/gcc/diagnostic-format-json.cc index 539b98b..346abb3 100644 --- a/gcc/diagnostic-format-json.cc +++ b/gcc/diagnostic-format-json.cc @@ -28,18 +28,63 @@ along with GCC; see the file COPYING3. If not see #include "json.h" #include "selftest.h" -/* The top-level JSON array of pending diagnostics. */ +/* Subclass of diagnostic_output_format for JSON output. */ -static json::array *toplevel_array; +class json_output_format : public diagnostic_output_format +{ +public: + void on_begin_group () final override + { + /* No-op. */ + } + void on_end_group () final override + { + m_cur_group = nullptr; + m_cur_children_array = nullptr; + } + void + on_begin_diagnostic (diagnostic_info *) final override + { + /* No-op. */ + } + void + on_end_diagnostic (diagnostic_info *diagnostic, + diagnostic_t orig_diag_kind) final override; + void on_diagram (const diagnostic_diagram &) final override + { + /* No-op. */ + } -/* The JSON object for the current diagnostic group. */ +protected: + json_output_format (diagnostic_context &context) + : diagnostic_output_format (context), + m_toplevel_array (new json::array ()), + m_cur_group (nullptr), + m_cur_children_array (nullptr) + { + } -static json::object *cur_group; + /* Flush the top-level array to OUTF. */ + void + flush_to_file (FILE *outf) + { + m_toplevel_array->dump (outf); + fprintf (outf, "\n"); + delete m_toplevel_array; + m_toplevel_array = nullptr; + } + +private: + /* The top-level JSON array of pending diagnostics. */ + json::array *m_toplevel_array; -/* The JSON array for the "children" array within the current diagnostic - group. */ + /* The JSON object for the current diagnostic group. */ + json::object *m_cur_group; -static json::array *cur_children_array; + /* The JSON array for the "children" array within the current diagnostic + group. */ + json::array *m_cur_children_array; +}; /* Generate a JSON object for LOC. */ @@ -139,20 +184,13 @@ json_from_metadata (const diagnostic_metadata *metadata) return metadata_obj; } -/* No-op implementation of "begin_diagnostic" for JSON output. */ - -static void -json_begin_diagnostic (diagnostic_context *, diagnostic_info *) -{ -} - -/* Implementation of "end_diagnostic" for JSON output. +/* Implementation of "on_end_diagnostic" vfunc for JSON output. Generate a JSON object for DIAGNOSTIC, and store for output within current diagnostic group. */ -static void -json_end_diagnostic (diagnostic_context *context, diagnostic_info *diagnostic, - diagnostic_t orig_diag_kind) +void +json_output_format::on_end_diagnostic (diagnostic_info *diagnostic, + diagnostic_t orig_diag_kind) { json::object *diag_obj = new json::object (); @@ -178,22 +216,22 @@ json_end_diagnostic (diagnostic_context *context, diagnostic_info *diagnostic, // FIXME: encoding of the message (json::string requires UTF-8) diag_obj->set ("message", - new json::string (pp_formatted_text (context->printer))); - pp_clear_output_area (context->printer); + new json::string (pp_formatted_text (m_context.printer))); + pp_clear_output_area (m_context.printer); char *option_text; - option_text = context->option_name (context, diagnostic->option_index, - orig_diag_kind, diagnostic->kind); + option_text = m_context.option_name (&m_context, diagnostic->option_index, + orig_diag_kind, diagnostic->kind); if (option_text) { diag_obj->set ("option", new json::string (option_text)); free (option_text); } - if (context->get_option_url) + if (m_context.get_option_url) { - char *option_url = context->get_option_url (context, - diagnostic->option_index); + char *option_url = m_context.get_option_url (&m_context, + diagnostic->option_index); if (option_url) { diag_obj->set ("option_url", new json::string (option_url)); @@ -203,21 +241,21 @@ json_end_diagnostic (diagnostic_context *context, diagnostic_info *diagnostic, /* If we've already emitted a diagnostic within this auto_diagnostic_group, then add diag_obj to its "children" array. */ - if (cur_group) + if (m_cur_group) { - gcc_assert (cur_children_array); - cur_children_array->append (diag_obj); + gcc_assert (m_cur_children_array); + m_cur_children_array->append (diag_obj); } else { /* Otherwise, make diag_obj be the top-level object within the group; add a "children" array and record the column origin. */ - toplevel_array->append (diag_obj); - cur_group = diag_obj; - cur_children_array = new json::array (); - diag_obj->set ("children", cur_children_array); + m_toplevel_array->append (diag_obj); + m_cur_group = diag_obj; + m_cur_children_array = new json::array (); + diag_obj->set ("children", m_cur_children_array); diag_obj->set ("column-origin", - new json::integer_number (context->column_origin)); + new json::integer_number (m_context.column_origin)); } const rich_location *richloc = diagnostic->richloc; @@ -228,7 +266,8 @@ json_end_diagnostic (diagnostic_context *context, diagnostic_info *diagnostic, for (unsigned int i = 0; i < richloc->get_num_locations (); i++) { const location_range *loc_range = richloc->get_range (i); - json::object *loc_obj = json_from_location_range (context, loc_range, i); + json::object *loc_obj + = json_from_location_range (&m_context, loc_range, i); if (loc_obj) loc_array->append (loc_obj); } @@ -240,7 +279,7 @@ json_end_diagnostic (diagnostic_context *context, diagnostic_info *diagnostic, for (unsigned int i = 0; i < richloc->get_num_fixit_hints (); i++) { const fixit_hint *hint = richloc->get_fixit_hint (i); - json::object *fixit_obj = json_from_fixit_hint (context, hint); + json::object *fixit_obj = json_from_fixit_hint (&m_context, hint); fixit_array->append (fixit_obj); } } @@ -257,9 +296,9 @@ json_end_diagnostic (diagnostic_context *context, diagnostic_info *diagnostic, } const diagnostic_path *path = richloc->get_path (); - if (path && context->make_json_for_path) + if (path && m_context.make_json_for_path) { - json::value *path_value = context->make_json_for_path (context, path); + json::value *path_value = m_context.make_json_for_path (&m_context, path); diag_obj->set ("path", path_value); } @@ -267,71 +306,51 @@ json_end_diagnostic (diagnostic_context *context, diagnostic_info *diagnostic, new json::literal (richloc->escape_on_output_p ())); } -/* No-op implementation of "begin_group_cb" for JSON output. */ - -static void -json_begin_group (diagnostic_context *) -{ -} - -/* Implementation of "end_group_cb" for JSON output. */ - -static void -json_end_group (diagnostic_context *) +class json_stderr_output_format : public json_output_format { - cur_group = NULL; - cur_children_array = NULL; -} - -/* Flush the top-level array to OUTF. */ - -static void -json_flush_to_file (FILE *outf) -{ - toplevel_array->dump (outf); - fprintf (outf, "\n"); - delete toplevel_array; - toplevel_array = NULL; -} - -/* Callback for final cleanup for JSON output to stderr. */ - -static void -json_stderr_final_cb (diagnostic_context *) -{ - json_flush_to_file (stderr); -} - -static char *json_output_base_file_name; - -/* Callback for final cleanup for JSON output to a file. */ +public: + json_stderr_output_format (diagnostic_context &context) + : json_output_format (context) + { + } + ~json_stderr_output_format () + { + flush_to_file (stderr); + } +}; -static void -json_file_final_cb (diagnostic_context *) +class json_file_output_format : public json_output_format { - char *filename = concat (json_output_base_file_name, ".gcc.json", NULL); - FILE *outf = fopen (filename, "w"); - if (!outf) - { - const char *errstr = xstrerror (errno); - fnotice (stderr, "error: unable to open '%s' for writing: %s\n", - filename, errstr); - free (filename); - return; - } - json_flush_to_file (outf); - fclose (outf); - free (filename); -} +public: + json_file_output_format (diagnostic_context &context, + const char *base_file_name) + : json_output_format (context), + m_base_file_name (xstrdup (base_file_name)) + { + } -/* Callback for diagnostic_context::m_diagrams.m_emission_cb. */ + ~json_file_output_format () + { + char *filename = concat (m_base_file_name, ".gcc.json", NULL); + free (m_base_file_name); + m_base_file_name = nullptr; + FILE *outf = fopen (filename, "w"); + if (!outf) + { + const char *errstr = xstrerror (errno); + fnotice (stderr, "error: unable to open '%s' for writing: %s\n", + filename, errstr); + free (filename); + return; + } + flush_to_file (outf); + fclose (outf); + free (filename); + } -static void -json_emit_diagram (diagnostic_context *, - const diagnostic_diagram &) -{ - /* No-op. */ -} +private: + char *m_base_file_name; +}; /* Populate CONTEXT in preparation for JSON output (either to stderr, or to a file). */ @@ -339,17 +358,8 @@ json_emit_diagram (diagnostic_context *, static void diagnostic_output_format_init_json (diagnostic_context *context) { - /* Set up top-level JSON array. */ - if (toplevel_array == NULL) - toplevel_array = new json::array (); - /* Override callbacks. */ - context->begin_diagnostic = json_begin_diagnostic; - context->end_diagnostic = json_end_diagnostic; - context->begin_group_cb = json_begin_group; - context->end_group_cb = json_end_group; context->print_path = NULL; /* handled in json_end_diagnostic. */ - context->m_diagrams.m_emission_cb = json_emit_diagram; /* The metadata is handled in JSON format, rather than as text. */ context->show_cwe = false; @@ -368,7 +378,8 @@ void diagnostic_output_format_init_json_stderr (diagnostic_context *context) { diagnostic_output_format_init_json (context); - context->final_cb = json_stderr_final_cb; + delete context->m_output_format; + context->m_output_format = new json_stderr_output_format (*context); } /* Populate CONTEXT in preparation for JSON output to a file named @@ -379,8 +390,9 @@ diagnostic_output_format_init_json_file (diagnostic_context *context, const char *base_file_name) { diagnostic_output_format_init_json (context); - context->final_cb = json_file_final_cb; - json_output_base_file_name = xstrdup (base_file_name); + delete context->m_output_format; + context->m_output_format = new json_file_output_format (*context, + base_file_name); } #if CHECKING_P |