#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() {}
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()) {
os << " [" << (level == clang::DiagnosticsEngine::Remark ? "-R" : "-W")
<< opt;
llvm::StringRef optValue = info.getDiags()->getFlagValue();
if (!optValue.empty())
os << "=" << optValue;
os << ']';
}
}
void TextDiagnosticPrinter::printLocForRemarks(
llvm::raw_svector_ostream &diagMessageStream, llvm::StringRef &diagMsg) {
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());
}
if (tokens.size() == 2) {
llvm::SmallString<128> absPath = llvm::sys::path::relative_path(tokens[1]);
llvm::sys::path::remove_filename(absPath);
llvm::sys::path::append(absPath, llvm::sys::path::get_separator());
llvm::sys::path::make_preferred(absPath);
if (diagOpts->ShowColors)
os.changeColor(llvm::raw_ostream::SAVEDCOLOR, true);
os << absPath << tokens[0] << ": ";
}
}
void TextDiagnosticPrinter::HandleDiagnostic(
clang::DiagnosticsEngine::Level level, const clang::Diagnostic &info) {
DiagnosticConsumer::HandleDiagnostic(level, info);
llvm::SmallString<100> outStr;
info.FormatDiagnostic(outStr);
llvm::raw_svector_ostream diagMessageStream(outStr);
printRemarkOption(diagMessageStream, level, info);
if (!prefix.empty())
os << prefix << ": ";
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,
level == clang::DiagnosticsEngine::Note, diagMsg,
diagOpts->ShowColors);
os.flush();
}