// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "gn/err.h"

#include <stddef.h>

#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "gn/filesystem_utils.h"
#include "gn/input_file.h"
#include "gn/parse_tree.h"
#include "gn/standard_out.h"
#include "gn/tokenizer.h"
#include "gn/value.h"

namespace {

std::string GetNthLine(const std::string_view& data, int n) {
  size_t line_off = Tokenizer::ByteOffsetOfNthLine(data, n);
  size_t end = line_off + 1;
  while (end < data.size() && !Tokenizer::IsNewline(data, end))
    end++;
  return std::string(data.substr(line_off, end - line_off));
}

void FillRangeOnLine(const LocationRange& range,
                     int line_number,
                     std::string* line) {
  // Only bother if the range's begin or end overlaps the line. If the entire
  // line is highlighted as a result of this range, it's not very helpful.
  if (range.begin().line_number() != line_number &&
      range.end().line_number() != line_number)
    return;

  // Watch out, the char offsets in the location are 1-based, so we have to
  // subtract 1.
  int begin_char;
  if (range.begin().line_number() < line_number)
    begin_char = 0;
  else
    begin_char = range.begin().column_number() - 1;

  int end_char;
  if (range.end().line_number() > line_number)
    end_char = static_cast<int>(line->size());  // Ending is non-inclusive.
  else
    end_char = range.end().column_number() - 1;

  CHECK(end_char >= begin_char);
  CHECK(begin_char >= 0 && begin_char <= static_cast<int>(line->size()));
  CHECK(end_char >= 0 && end_char <= static_cast<int>(line->size()));
  for (int i = begin_char; i < end_char; i++)
    line->at(i) = '-';
}

// The line length is used to clip the maximum length of the markers we'll
// make if the error spans more than one line (like unterminated literals).
void OutputHighlighedPosition(const Location& location,
                              const Err::RangeList& ranges,
                              size_t line_length) {
  // Make a buffer of the line in spaces.
  std::string highlight;
  highlight.resize(line_length);
  for (size_t i = 0; i < line_length; i++)
    highlight[i] = ' ';

  // Highlight all the ranges on the line.
  for (const auto& range : ranges)
    FillRangeOnLine(range, location.line_number(), &highlight);

  // Allow the marker to be one past the end of the line for marking the end.
  highlight.push_back(' ');
  CHECK(location.column_number() - 1 >= 0 &&
        location.column_number() - 1 < static_cast<int>(highlight.size()));
  highlight[location.column_number() - 1] = '^';

  // Trim unused spaces from end of line.
  while (!highlight.empty() && highlight[highlight.size() - 1] == ' ')
    highlight.resize(highlight.size() - 1);

  highlight += "\n";
  OutputString(highlight, DECORATION_BLUE);
}

}  // namespace

Err::Err() : has_error_(false) {}

Err::Err(const Location& location,
         const std::string& msg,
         const std::string& help)
    : has_error_(true), location_(location), message_(msg), help_text_(help) {}

Err::Err(const LocationRange& range,
         const std::string& msg,
         const std::string& help)
    : has_error_(true),
      location_(range.begin()),
      message_(msg),
      help_text_(help) {
  ranges_.push_back(range);
}

Err::Err(const Token& token, const std::string& msg, const std::string& help)
    : has_error_(true),
      location_(token.location()),
      message_(msg),
      help_text_(help) {
  ranges_.push_back(token.range());
}

Err::Err(const ParseNode* node,
         const std::string& msg,
         const std::string& help_text)
    : has_error_(true), message_(msg), help_text_(help_text) {
  // Node will be null in certain tests.
  if (node) {
    LocationRange range = node->GetRange();
    location_ = range.begin();
    ranges_.push_back(range);
  }
}

Err::Err(const Value& value,
         const std::string msg,
         const std::string& help_text)
    : has_error_(true), message_(msg), help_text_(help_text) {
  if (value.origin()) {
    LocationRange range = value.origin()->GetRange();
    location_ = range.begin();
    ranges_.push_back(range);
  }
}

Err::Err(const Err& other) = default;

Err::~Err() = default;

void Err::PrintToStdout() const {
  InternalPrintToStdout(false, true);
}

void Err::PrintNonfatalToStdout() const {
  InternalPrintToStdout(false, false);
}

void Err::AppendSubErr(const Err& err) {
  sub_errs_.push_back(err);
}

void Err::InternalPrintToStdout(bool is_sub_err, bool is_fatal) const {
  DCHECK(has_error_);

  if (!is_sub_err) {
    if (is_fatal)
      OutputString("ERROR ", DECORATION_RED);
    else
      OutputString("WARNING ", DECORATION_RED);
  }

  // File name and location.
  const InputFile* input_file = location_.file();
  std::string loc_str = location_.Describe(true);
  if (!loc_str.empty()) {
    if (is_sub_err)
      loc_str.insert(0, "See ");
    else
      loc_str.insert(0, "at ");
    if (!toolchain_label_.is_null())
      loc_str += " ";
  }
  std::string toolchain_str;
  if (!toolchain_label_.is_null()) {
    toolchain_str += "(" + toolchain_label_.GetUserVisibleName(false) + ")";
  }
  std::string colon;
  if (!loc_str.empty() || !toolchain_str.empty())
    colon = ": ";
  OutputString(loc_str + toolchain_str + colon + message_ + "\n");

  // Quoted line.
  if (input_file) {
    std::string line =
        GetNthLine(input_file->contents(), location_.line_number());
    if (!base::ContainsOnlyChars(line, base::kWhitespaceASCII)) {
      OutputString(line + "\n", DECORATION_DIM);
      OutputHighlighedPosition(location_, ranges_, line.size());
    }
  }

  // Optional help text.
  if (!help_text_.empty())
    OutputString(help_text_ + "\n");

  // Sub errors.
  for (const auto& sub_err : sub_errs_)
    sub_err.InternalPrintToStdout(true, is_fatal);
}
