================
@@ -11,37 +11,113 @@
//===----------------------------------------------------------------------===//
#include "clang/Frontend/SARIFDiagnosticPrinter.h"
+#include "clang/Basic/DiagnosticDriver.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/Sarif.h"
#include "clang/Frontend/DiagnosticRenderer.h"
#include "clang/Frontend/SARIFDiagnostic.h"
#include "clang/Lex/Lexer.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/JSON.h"
#include "llvm/Support/raw_ostream.h"
namespace clang {
-SARIFDiagnosticPrinter::SARIFDiagnosticPrinter(raw_ostream &OS,
+SARIFDiagnosticPrinter::SARIFDiagnosticPrinter(llvm::StringRef FilePath,
DiagnosticOptions &DiagOpts)
- : OS(OS), DiagOpts(DiagOpts) {}
+ : FilePath(FilePath), DiagOpts(DiagOpts) {}
+
+std::unique_ptr<SARIFDiagnosticPrinter>
+SARIFDiagnosticPrinter::create(ArrayRef<std::pair<StringRef, StringRef>>
Config,
+ DiagnosticOptions &DiagOpts,
+ DiagnosticsEngine &Diags) {
+ std::optional<std::string> FilePath;
+ SarifVersion Version = SarifDocumentWriter::getDefaultVersion();
+
+ for (const auto &Pair : Config) {
+ if (Pair.first == "file") {
+ FilePath = Pair.second;
+ } else if (Pair.first == "version") {
+ auto SupportedVersions = SarifDocumentWriter::getSupportedVersions();
+ auto FoundVersion =
+ std::find_if(SupportedVersions.begin(), SupportedVersions.end(),
+ [=](const SarifVersion &V) {
+ return V.CommandLineVersion == Pair.second;
+ });
+ if (FoundVersion != SupportedVersions.end()) {
+ Version = *FoundVersion;
+ } else {
+ SmallString<64> SupportedList;
+ bool First = true;
+ for (const auto &V : SupportedVersions) {
+ if (First) {
+ First = false;
+ } else {
+ SupportedList.append(", ");
+ }
+ SupportedList.append("'");
+ SupportedList.append(V.CommandLineVersion);
+ SupportedList.append("'");
+ }
+ Diags.Report(SourceLocation(), diag::err_invalid_sarif_version)
+ << Pair.second << SupportedList;
+ }
+ } else {
+ Diags.Report(SourceLocation(), diag::err_diagnostic_output_unknown_key)
+ << "sarif" << Pair.second;
+ }
+ }
+
+ if (!FilePath) {
+ // We should probably have a default here based on the input file name or
+ // the output object file name, but I'm not sure how to get that
information
+ // here.
+ Diags.Report(SourceLocation(), diag::err_missing_sarif_file_name);
+ return {};
+ }
+
+ return std::make_unique<SARIFDiagnosticPrinter>(*FilePath, DiagOpts);
+}
void SARIFDiagnosticPrinter::BeginSourceFile(const LangOptions &LO,
const Preprocessor *PP) {
// Build the SARIFDiagnostic utility.
+ if (!hasSarifWriter() && PP) {
+ // Use the SourceManager from the preproces`sor.
+ setSarifWriter(
+ std::make_unique<SarifDocumentWriter>(PP->getSourceManager()));
+ }
assert(hasSarifWriter() && "Writer not set!");
assert(!SARIFDiag && "SARIFDiagnostic already set.");
- SARIFDiag = std::make_unique<SARIFDiagnostic>(OS, LO, DiagOpts, &*Writer);
+ SARIFDiag = std::make_unique<SARIFDiagnostic>(LO, DiagOpts, &*Writer);
// Initialize the SARIF object.
- Writer->createRun("clang", Prefix);
+ Writer->createRun("clang", Prefix, getClangFullVersion());
}
void SARIFDiagnosticPrinter::EndSourceFile() {
assert(SARIFDiag && "SARIFDiagnostic has not been set.");
Writer->endRun();
llvm::json::Value Value(Writer->createDocument());
- OS << llvm::formatv("\n{0:2}\n\n", Value);
- OS.flush();
+ if (FilePath.empty()) {
+ // Write to console.
+ llvm::errs() << llvm::formatv("\n{0:2}\n\n", Value);
+ llvm::errs().flush();
+ } else {
+ // Write to file.
+ std::error_code EC;
+ llvm::raw_fd_ostream OS(FilePath, EC, llvm::sys::fs::OF_TextWithCRLF);
----------------
AaronBallman wrote:
Is there a reason the CRLF behavior is needed on all platforms? I would have
assumed we'd want the default line endings (but I wasn't sure if SARIF required
CRLF or something).
https://github.com/llvm/llvm-project/pull/185201
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits