//===--- TextDiagnosticPrinter.cpp - Diagnostic Printer -------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This diagnostic client prints out their diagnostic messages.
//
//===----------------------------------------------------------------------===//
//
// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
//
//===----------------------------------------------------------------------===//

#include "flang/Frontend/TextDiagnosticPrinter.h"
#include "flang/Frontend/TextDiagnostic.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"

using namespace Fortran::frontend;

TextDiagnosticPrinter::TextDiagnosticPrinter(raw_ostream &diagOs,
                                             clang::DiagnosticOptions *diags)
    : os(diagOs), diagOpts(diags) {}

TextDiagnosticPrinter::~TextDiagnosticPrinter() {}

// For remarks only, print the remark option and pass name that was used to a
// raw_ostream. This also supports warnings from invalid remark arguments
// provided.
static void printRemarkOption(llvm::raw_ostream &os,
                              clang::DiagnosticsEngine::Level level,
                              const clang::Diagnostic &info) {
  llvm::StringRef opt =
      clang::DiagnosticIDs::getWarningOptionForDiag(info.getID());
  if (!opt.empty()) {
    // We still need to check if the level is a Remark since, an unknown option
    // warning could be printed i.e. [-Wunknown-warning-option]
    os << " [" << (level == clang::DiagnosticsEngine::Remark ? "-R" : "-W")
       << opt;
    llvm::StringRef optValue = info.getDiags()->getFlagValue();
    if (!optValue.empty())
      os << "=" << optValue;
    os << ']';
  }
}

// For remarks only, if we are receiving a message of this format
// [file location with line and column];;[path to file];;[the remark message]
// then print the absolute file path, line and column number.
void TextDiagnosticPrinter::printLocForRemarks(
    llvm::raw_svector_ostream &diagMessageStream, llvm::StringRef &diagMsg) {
  // split incoming string to get the absolute path and filename in the
  // case we are receiving optimization remarks from BackendRemarkConsumer
  diagMsg = diagMessageStream.str();
  llvm::StringRef delimiter = ";;";

  size_t pos = 0;
  llvm::SmallVector<llvm::StringRef> tokens;
  while ((pos = diagMsg.find(delimiter)) != std::string::npos) {
    tokens.push_back(diagMsg.substr(0, pos));
    diagMsg = diagMsg.drop_front(pos + delimiter.size());
  }

  // tokens will always be of size 2 in the case of optimization
  // remark message received
  if (tokens.size() == 2) {
    // Extract absolute path
    llvm::SmallString<128> absPath = llvm::sys::path::relative_path(tokens[1]);
    llvm::sys::path::remove_filename(absPath);
    // Add the last separator before the file name
    llvm::sys::path::append(absPath, llvm::sys::path::get_separator());
    llvm::sys::path::make_preferred(absPath);

    // Used for changing only the bold attribute
    if (diagOpts->ShowColors)
      os.changeColor(llvm::raw_ostream::SAVEDCOLOR, true);

    // Print path, file name, line and column
    os << absPath << tokens[0] << ": ";
  }
}

void TextDiagnosticPrinter::HandleDiagnostic(
    clang::DiagnosticsEngine::Level level, const clang::Diagnostic &info) {
  // Default implementation (Warnings/errors count).
  DiagnosticConsumer::HandleDiagnostic(level, info);

  // Render the diagnostic message into a temporary buffer eagerly. We'll use
  // this later as we print out the diagnostic to the terminal.
  llvm::SmallString<100> outStr;
  info.FormatDiagnostic(outStr);

  llvm::raw_svector_ostream diagMessageStream(outStr);
  printRemarkOption(diagMessageStream, level, info);

  if (!prefix.empty())
    os << prefix << ": ";

  // We only emit diagnostics in contexts that lack valid source locations.
  assert(!info.getLocation().isValid() &&
         "Diagnostics with valid source location are not supported");

  llvm::StringRef diagMsg;
  printLocForRemarks(diagMessageStream, diagMsg);

  Fortran::frontend::TextDiagnostic::printDiagnosticLevel(os, level,
                                                          diagOpts->ShowColors);
  Fortran::frontend::TextDiagnostic::printDiagnosticMessage(
      os,
      /*IsSupplemental=*/level == clang::DiagnosticsEngine::Note, diagMsg,
      diagOpts->ShowColors);

  os.flush();
}
