/* JSON output for diagnostics
   Copyright (C) 2018 Free Software Foundation, Inc.
   Contributed by David Malcolm <dmalcolm@redhat.com>.

This file is part of GCC.

GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.

GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.  */


#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "diagnostic.h"
#include "json.h"

/* The top-level JSON array of pending diagnostics.  */

static json::array *toplevel_array;

/* The JSON object for the current diagnostic group.  */

static json::object *cur_group;

/* The JSON array for the "children" array within the current diagnostic
   group.  */

static json::array *cur_children_array;

/* Generate a JSON object for LOC.  */

static json::object *
json_from_expanded_location (location_t loc)
{
  expanded_location exploc = expand_location (loc);
  json::object *result = new json::object ();
  result->set ("file", new json::string (exploc.file));
  result->set ("line", new json::number (exploc.line));
  result->set ("column", new json::number (exploc.column));
  return result;
}

/* Generate a JSON object for LOC_RANGE.  */

static json::object *
json_from_location_range (const location_range *loc_range, unsigned range_idx)
{
  location_t caret_loc = get_pure_location (loc_range->m_loc);

  if (caret_loc == UNKNOWN_LOCATION)
    return NULL;

  location_t start_loc = get_start (loc_range->m_loc);
  location_t finish_loc = get_finish (loc_range->m_loc);

  json::object *result = new json::object ();
  result->set ("caret", json_from_expanded_location (caret_loc));
  if (start_loc != caret_loc)
    result->set ("start", json_from_expanded_location (start_loc));
  if (finish_loc != caret_loc)
    result->set ("finish", json_from_expanded_location (finish_loc));

  if (loc_range->m_label)
    {
      label_text text;
      text = loc_range->m_label->get_text (range_idx);
      if (text.m_buffer)
	result->set ("label", new json::string (text.m_buffer));
      text.maybe_free ();
    }

  return result;
}

/* Generate a JSON object for HINT.  */

static json::object *
json_from_fixit_hint (const fixit_hint *hint)
{
  json::object *fixit_obj = new json::object ();

  location_t start_loc = hint->get_start_loc ();
  fixit_obj->set ("start", json_from_expanded_location (start_loc));
  location_t next_loc = hint->get_next_loc ();
  fixit_obj->set ("next", json_from_expanded_location (next_loc));
  fixit_obj->set ("string", new json::string (hint->get_string ()));

  return fixit_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.
   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)
{
  json::object *diag_obj = new json::object ();

  /* Get "kind" of diagnostic.  */
  {
    static const char *const diagnostic_kind_text[] = {
#define DEFINE_DIAGNOSTIC_KIND(K, T, C) (T),
#include "diagnostic.def"
#undef DEFINE_DIAGNOSTIC_KIND
      "must-not-happen"
    };
    /* Lose the trailing ": ".  */
    const char *kind_text = diagnostic_kind_text[diagnostic->kind];
    size_t len = strlen (kind_text);
    gcc_assert (len > 2);
    gcc_assert (kind_text[len - 2] == ':');
    gcc_assert (kind_text[len - 1] == ' ');
    char *rstrip = xstrdup (kind_text);
    rstrip[len - 2] = '\0';
    diag_obj->set ("kind", new json::string (rstrip));
    free (rstrip);
  }

  // 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);

  char *option_text;
  option_text = context->option_name (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 we've already emitted a diagnostic within this auto_diagnostic_group,
     then add diag_obj to its "children" array.  */
  if (cur_group)
    {
      gcc_assert (cur_children_array);
      cur_children_array->append (diag_obj);
    }
  else
    {
      /* Otherwise, make diag_obj be the top-level object within the group;
	 add a "children" array.  */
      toplevel_array->append (diag_obj);
      cur_group = diag_obj;
      cur_children_array = new json::array ();
      diag_obj->set ("children", cur_children_array);
    }

  const rich_location *richloc = diagnostic->richloc;

  json::array *loc_array = new json::array ();
  diag_obj->set ("locations", loc_array);

  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 (loc_range, i);
      if (loc_obj)
	loc_array->append (loc_obj);
    }

  if (richloc->get_num_fixit_hints ())
    {
      json::array *fixit_array = new json::array ();
      diag_obj->set ("fixits", fixit_array);
      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 (hint);
	  fixit_array->append (fixit_obj);
	}
    }

  /* TODO: tree-ish things:
     TODO: functions
     TODO: inlining information
     TODO: macro expansion information.  */
}

/* 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 *)
{
  cur_group = NULL;
  cur_children_array = NULL;
}

/* Callback for final cleanup for JSON output.  */

static void
json_final_cb (diagnostic_context *)
{
  /* Flush the top-level array.  */
  toplevel_array->dump (stderr);
  fprintf (stderr, "\n");
  delete toplevel_array;
  toplevel_array = NULL;
}

/* Set the output format for CONTEXT to FORMAT.  */

void
diagnostic_output_format_init (diagnostic_context *context,
			       enum diagnostics_output_format format)
{
  switch (format)
    {
    default:
      gcc_unreachable ();
    case DIAGNOSTICS_OUTPUT_FORMAT_TEXT:
      /* The default; do nothing.  */
      break;

    case DIAGNOSTICS_OUTPUT_FORMAT_JSON:
      {
	/* 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->final_cb =  json_final_cb;

	/* The option is handled in JSON format, rather than as text.  */
	context->show_option_requested = false;

	/* Don't colorize the text.  */
	pp_show_color (context->printer) = false;
      }
      break;
    }
}
