================
@@ -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

Reply via email to