xref: /llvm-project/clang/lib/Frontend/SARIFDiagnosticPrinter.cpp (revision 82e893c47c77430ca59f92d7a814a336e3873a35)
1*82e893c4SAbraham Corea Diaz //===------- SARIFDiagnosticPrinter.cpp - Diagnostic Printer---------------===//
2*82e893c4SAbraham Corea Diaz //
3*82e893c4SAbraham Corea Diaz // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*82e893c4SAbraham Corea Diaz // See https://llvm.org/LICENSE.txt for license information.
5*82e893c4SAbraham Corea Diaz // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*82e893c4SAbraham Corea Diaz //
7*82e893c4SAbraham Corea Diaz //===----------------------------------------------------------------------===//
8*82e893c4SAbraham Corea Diaz //
9*82e893c4SAbraham Corea Diaz // This diagnostic client prints out their diagnostic messages in SARIF format.
10*82e893c4SAbraham Corea Diaz //
11*82e893c4SAbraham Corea Diaz //===----------------------------------------------------------------------===//
12*82e893c4SAbraham Corea Diaz 
13*82e893c4SAbraham Corea Diaz #include "clang/Frontend/SARIFDiagnosticPrinter.h"
14*82e893c4SAbraham Corea Diaz #include "clang/Basic/DiagnosticOptions.h"
15*82e893c4SAbraham Corea Diaz #include "clang/Basic/Sarif.h"
16*82e893c4SAbraham Corea Diaz #include "clang/Basic/SourceManager.h"
17*82e893c4SAbraham Corea Diaz #include "clang/Frontend/DiagnosticRenderer.h"
18*82e893c4SAbraham Corea Diaz #include "clang/Frontend/SARIFDiagnostic.h"
19*82e893c4SAbraham Corea Diaz #include "clang/Lex/Lexer.h"
20*82e893c4SAbraham Corea Diaz #include "llvm/ADT/SmallString.h"
21*82e893c4SAbraham Corea Diaz #include "llvm/Support/ErrorHandling.h"
22*82e893c4SAbraham Corea Diaz #include "llvm/Support/JSON.h"
23*82e893c4SAbraham Corea Diaz #include "llvm/Support/raw_ostream.h"
24*82e893c4SAbraham Corea Diaz #include <algorithm>
25*82e893c4SAbraham Corea Diaz 
26*82e893c4SAbraham Corea Diaz namespace clang {
27*82e893c4SAbraham Corea Diaz 
SARIFDiagnosticPrinter(raw_ostream & OS,DiagnosticOptions * Diags)28*82e893c4SAbraham Corea Diaz SARIFDiagnosticPrinter::SARIFDiagnosticPrinter(raw_ostream &OS,
29*82e893c4SAbraham Corea Diaz                                                DiagnosticOptions *Diags)
30*82e893c4SAbraham Corea Diaz     : OS(OS), DiagOpts(Diags) {}
31*82e893c4SAbraham Corea Diaz 
BeginSourceFile(const LangOptions & LO,const Preprocessor * PP)32*82e893c4SAbraham Corea Diaz void SARIFDiagnosticPrinter::BeginSourceFile(const LangOptions &LO,
33*82e893c4SAbraham Corea Diaz                                              const Preprocessor *PP) {
34*82e893c4SAbraham Corea Diaz   // Build the SARIFDiagnostic utility.
35*82e893c4SAbraham Corea Diaz   assert(hasSarifWriter() && "Writer not set!");
36*82e893c4SAbraham Corea Diaz   assert(!SARIFDiag && "SARIFDiagnostic already set.");
37*82e893c4SAbraham Corea Diaz   SARIFDiag = std::make_unique<SARIFDiagnostic>(OS, LO, &*DiagOpts, &*Writer);
38*82e893c4SAbraham Corea Diaz   // Initialize the SARIF object.
39*82e893c4SAbraham Corea Diaz   Writer->createRun("clang", Prefix);
40*82e893c4SAbraham Corea Diaz }
41*82e893c4SAbraham Corea Diaz 
EndSourceFile()42*82e893c4SAbraham Corea Diaz void SARIFDiagnosticPrinter::EndSourceFile() {
43*82e893c4SAbraham Corea Diaz   assert(SARIFDiag && "SARIFDiagnostic has not been set.");
44*82e893c4SAbraham Corea Diaz   Writer->endRun();
45*82e893c4SAbraham Corea Diaz   llvm::json::Value Value(Writer->createDocument());
46*82e893c4SAbraham Corea Diaz   OS << "\n" << Value << "\n\n";
47*82e893c4SAbraham Corea Diaz   OS.flush();
48*82e893c4SAbraham Corea Diaz   SARIFDiag.reset();
49*82e893c4SAbraham Corea Diaz }
50*82e893c4SAbraham Corea Diaz 
HandleDiagnostic(DiagnosticsEngine::Level Level,const Diagnostic & Info)51*82e893c4SAbraham Corea Diaz void SARIFDiagnosticPrinter::HandleDiagnostic(DiagnosticsEngine::Level Level,
52*82e893c4SAbraham Corea Diaz                                               const Diagnostic &Info) {
53*82e893c4SAbraham Corea Diaz   assert(SARIFDiag && "SARIFDiagnostic has not been set.");
54*82e893c4SAbraham Corea Diaz   // Default implementation (Warnings/errors count). Keeps track of the
55*82e893c4SAbraham Corea Diaz   // number of errors.
56*82e893c4SAbraham Corea Diaz   DiagnosticConsumer::HandleDiagnostic(Level, Info);
57*82e893c4SAbraham Corea Diaz 
58*82e893c4SAbraham Corea Diaz   // Render the diagnostic message into a temporary buffer eagerly. We'll use
59*82e893c4SAbraham Corea Diaz   // this later as we add the diagnostic to the SARIF object.
60*82e893c4SAbraham Corea Diaz   SmallString<100> OutStr;
61*82e893c4SAbraham Corea Diaz   Info.FormatDiagnostic(OutStr);
62*82e893c4SAbraham Corea Diaz 
63*82e893c4SAbraham Corea Diaz   llvm::raw_svector_ostream DiagMessageStream(OutStr);
64*82e893c4SAbraham Corea Diaz 
65*82e893c4SAbraham Corea Diaz   // Use a dedicated, simpler path for diagnostics without a valid location.
66*82e893c4SAbraham Corea Diaz   // This is important as if the location is missing, we may be emitting
67*82e893c4SAbraham Corea Diaz   // diagnostics in a context that lacks language options, a source manager, or
68*82e893c4SAbraham Corea Diaz   // other infrastructure necessary when emitting more rich diagnostics.
69*82e893c4SAbraham Corea Diaz   if (Info.getLocation().isInvalid()) {
70*82e893c4SAbraham Corea Diaz     // FIXME: Enable diagnostics without a source manager
71*82e893c4SAbraham Corea Diaz     return;
72*82e893c4SAbraham Corea Diaz   }
73*82e893c4SAbraham Corea Diaz 
74*82e893c4SAbraham Corea Diaz   // Assert that the rest of our infrastructure is setup properly.
75*82e893c4SAbraham Corea Diaz   assert(DiagOpts && "Unexpected diagnostic without options set");
76*82e893c4SAbraham Corea Diaz   assert(Info.hasSourceManager() &&
77*82e893c4SAbraham Corea Diaz          "Unexpected diagnostic with no source manager");
78*82e893c4SAbraham Corea Diaz 
79*82e893c4SAbraham Corea Diaz   SARIFDiag->emitDiagnostic(
80*82e893c4SAbraham Corea Diaz       FullSourceLoc(Info.getLocation(), Info.getSourceManager()), Level,
81*82e893c4SAbraham Corea Diaz       DiagMessageStream.str(), Info.getRanges(), Info.getFixItHints(), &Info);
82*82e893c4SAbraham Corea Diaz }
83*82e893c4SAbraham Corea Diaz } // namespace clang
84