// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "vm/report.h"

#include "vm/code_patcher.h"
#include "vm/exceptions.h"
#include "vm/flags.h"
#include "vm/longjump.h"
#include "vm/object.h"
#include "vm/stack_frame.h"
#include "vm/symbols.h"

namespace dart {

DEFINE_FLAG(bool, silent_warnings, false, "Silence warnings.");
DEFINE_FLAG(bool, warning_as_error, false, "Treat warnings as errors.");

RawString* Report::PrependSnippet(Kind kind,
                                  const Script& script,
                                  TokenPosition token_pos,
                                  bool report_after_token,
                                  const String& message) {
  const char* message_header;
  switch (kind) {
    case kWarning:
      message_header = "warning";
      break;
    case kError:
      message_header = "error";
      break;
    case kBailout:
      message_header = "bailout";
      break;
    default:
      message_header = "";
      UNREACHABLE();
  }
  String& result = String::Handle();
  if (!script.IsNull() && !String::Handle(script.Source()).IsNull()) {
    const String& script_url = String::Handle(script.url());
    if (token_pos.IsReal()) {
      intptr_t line, column, token_len;
      script.GetTokenLocation(token_pos, &line, &column, &token_len);
      if (report_after_token) {
        column += token_len;
      }
      // Only report the line position if we have the original source. We still
      // need to get a valid column so that we can report the ^ mark below the
      // snippet.
      // Allocate formatted strings in old space as they may be created during
      // optimizing compilation. Those strings are created rarely and should not
      // polute old space.
      if (script.HasSource()) {
        result = String::NewFormatted(
            Heap::kOld, "'%s': %s: line %" Pd " pos %" Pd ": ",
            script_url.ToCString(), message_header, line, column);
      } else {
        result =
            String::NewFormatted(Heap::kOld, "'%s': %s: line %" Pd ": ",
                                 script_url.ToCString(), message_header, line);
      }
      // Append the formatted error or warning message.
      const Array& strs = Array::Handle(Array::New(6, Heap::kOld));
      strs.SetAt(0, result);
      strs.SetAt(1, message);
      // Append the source line.
      const String& script_line =
          String::Handle(script.GetLine(line, Heap::kOld));
      ASSERT(!script_line.IsNull());
      strs.SetAt(2, Symbols::NewLine());
      strs.SetAt(3, script_line);
      strs.SetAt(4, Symbols::NewLine());
      // Append the column marker.
      const String& column_line = String::Handle(String::NewFormatted(
          Heap::kOld, "%*s\n", static_cast<int>(column), "^"));
      strs.SetAt(5, column_line);
      result = String::ConcatAll(strs, Heap::kOld);
    } else {
      // Token position is unknown.
      result = String::NewFormatted(
          Heap::kOld, "'%s': %s: ", script_url.ToCString(), message_header);
      result = String::Concat(result, message, Heap::kOld);
    }
  } else {
    // Script is unknown.
    // Append the formatted error or warning message.
    result = String::NewFormatted(Heap::kOld, "%s: ", message_header);
    result = String::Concat(result, message, Heap::kOld);
  }
  return result.raw();
}

void Report::LongJump(const Error& error) {
  Thread::Current()->long_jump_base()->Jump(1, error);
  UNREACHABLE();
}

void Report::LongJumpF(const Error& prev_error,
                       const Script& script,
                       TokenPosition token_pos,
                       const char* format,
                       ...) {
  va_list args;
  va_start(args, format);
  LongJumpV(prev_error, script, token_pos, format, args);
  va_end(args);
  UNREACHABLE();
}

void Report::LongJumpV(const Error& prev_error,
                       const Script& script,
                       TokenPosition token_pos,
                       const char* format,
                       va_list args) {
  // If an isolate is being killed a [UnwindError] will be propagated up the
  // stack. In such a case we cannot wrap the unwind error in a new
  // [LanguageError]. Instead we simply continue propagating the [UnwindError]
  // upwards.
  if (prev_error.IsUnwindError()) {
    LongJump(prev_error);
    UNREACHABLE();
  }
  const Error& error = Error::Handle(LanguageError::NewFormattedV(
      prev_error, script, token_pos, Report::AtLocation, kError, Heap::kOld,
      format, args));
  LongJump(error);
  UNREACHABLE();
}

void Report::MessageF(Kind kind,
                      const Script& script,
                      TokenPosition token_pos,
                      bool report_after_token,
                      const char* format,
                      ...) {
  va_list args;
  va_start(args, format);
  MessageV(kind, script, token_pos, report_after_token, format, args);
  va_end(args);
}

void Report::MessageV(Kind kind,
                      const Script& script,
                      TokenPosition token_pos,
                      bool report_after_token,
                      const char* format,
                      va_list args) {
  if (kind < kError) {
    // Reporting a warning.
    if (FLAG_silent_warnings) {
      return;
    }
    if (!FLAG_warning_as_error) {
      const String& msg = String::Handle(String::NewFormattedV(format, args));
      const String& snippet_msg = String::Handle(
          PrependSnippet(kind, script, token_pos, report_after_token, msg));
      OS::PrintErr("%s", snippet_msg.ToCString());
      return;
    }
  }
  // Reporting an error (or a warning as error).
  const Error& error = Error::Handle(LanguageError::NewFormattedV(
      Error::Handle(),  // No previous error.
      script, token_pos, report_after_token, kind, Heap::kOld, format, args));
  LongJump(error);
  UNREACHABLE();
}

}  // namespace dart
