Path: blob/main/contrib/llvm-project/clang/lib/Frontend/SARIFDiagnosticPrinter.cpp
35233 views
//===------- SARIFDiagnosticPrinter.cpp - Diagnostic Printer---------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This diagnostic client prints out their diagnostic messages in SARIF format.9//10//===----------------------------------------------------------------------===//1112#include "clang/Frontend/SARIFDiagnosticPrinter.h"13#include "clang/Basic/DiagnosticOptions.h"14#include "clang/Basic/Sarif.h"15#include "clang/Basic/SourceManager.h"16#include "clang/Frontend/DiagnosticRenderer.h"17#include "clang/Frontend/SARIFDiagnostic.h"18#include "clang/Lex/Lexer.h"19#include "llvm/ADT/SmallString.h"20#include "llvm/Support/ErrorHandling.h"21#include "llvm/Support/JSON.h"22#include "llvm/Support/raw_ostream.h"23#include <algorithm>2425namespace clang {2627SARIFDiagnosticPrinter::SARIFDiagnosticPrinter(raw_ostream &OS,28DiagnosticOptions *Diags)29: OS(OS), DiagOpts(Diags) {}3031void SARIFDiagnosticPrinter::BeginSourceFile(const LangOptions &LO,32const Preprocessor *PP) {33// Build the SARIFDiagnostic utility.34assert(hasSarifWriter() && "Writer not set!");35assert(!SARIFDiag && "SARIFDiagnostic already set.");36SARIFDiag = std::make_unique<SARIFDiagnostic>(OS, LO, &*DiagOpts, &*Writer);37// Initialize the SARIF object.38Writer->createRun("clang", Prefix);39}4041void SARIFDiagnosticPrinter::EndSourceFile() {42assert(SARIFDiag && "SARIFDiagnostic has not been set.");43Writer->endRun();44llvm::json::Value Value(Writer->createDocument());45OS << "\n" << Value << "\n\n";46OS.flush();47SARIFDiag.reset();48}4950void SARIFDiagnosticPrinter::HandleDiagnostic(DiagnosticsEngine::Level Level,51const Diagnostic &Info) {52assert(SARIFDiag && "SARIFDiagnostic has not been set.");53// Default implementation (Warnings/errors count). Keeps track of the54// number of errors.55DiagnosticConsumer::HandleDiagnostic(Level, Info);5657// Render the diagnostic message into a temporary buffer eagerly. We'll use58// this later as we add the diagnostic to the SARIF object.59SmallString<100> OutStr;60Info.FormatDiagnostic(OutStr);6162llvm::raw_svector_ostream DiagMessageStream(OutStr);6364// Use a dedicated, simpler path for diagnostics without a valid location.65// This is important as if the location is missing, we may be emitting66// diagnostics in a context that lacks language options, a source manager, or67// other infrastructure necessary when emitting more rich diagnostics.68if (Info.getLocation().isInvalid()) {69// FIXME: Enable diagnostics without a source manager70return;71}7273// Assert that the rest of our infrastructure is setup properly.74assert(DiagOpts && "Unexpected diagnostic without options set");75assert(Info.hasSourceManager() &&76"Unexpected diagnostic with no source manager");7778SARIFDiag->emitDiagnostic(79FullSourceLoc(Info.getLocation(), Info.getSourceManager()), Level,80DiagMessageStream.str(), Info.getRanges(), Info.getFixItHints(), &Info);81}82} // namespace clang838485