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

StringPtr 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() && script.HasSource()) {
    const String& script_url = String::Handle(script.url());
    intptr_t line, column;
    if (script.GetTokenLocation(token_pos, &line, &column)) {
      const intptr_t token_len = script.GetTokenLength(token_pos);
      if (report_after_token) {
        column += token_len < 0 ? 1 : token_len;
      }
      // Allocate formatted strings in old space as they may be created during
      // optimizing compilation. Those strings are created rarely and should not
      // pollute old space.
      result = String::NewFormatted(
          Heap::kOld, "'%s': %s: line %" Pd " pos %" Pd ": ",
          script_url.ToCString(), message_header, line, column);
      // 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.ptr();
}

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
