//===- AccumulatingDiagnosticConsumer.h - Collect Text Diagnostics C++ -*-===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2020 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// // // This file defines the AccumulatingDiagnosticConsumer class, which collects // all emitted diagnostics into an externally-owned collection. // //===----------------------------------------------------------------------===// #ifndef SWIFT_ACCUMULATINGDIAGNOSTICCONSUMER_H #define SWIFT_ACCUMULATINGDIAGNOSTICCONSUMER_H #include "swift/AST/DiagnosticConsumer.h" #include "swift/Basic/DiagnosticOptions.h" #include "swift/Basic/LLVM.h" #include #include namespace swift { /// Diagnostic consumer that simply collects all emitted diagnostics into the provided /// collection. class AccumulatingFileDiagnosticConsumer : public DiagnosticConsumer { std::vector &Diagnostics; public: AccumulatingFileDiagnosticConsumer(std::vector &DiagBuffer) : Diagnostics(DiagBuffer) {} private: void handleDiagnostic(SourceManager &SM, const DiagnosticInfo &Info) override { addDiagnostic(SM, Info); for (auto ChildInfo : Info.ChildDiagnosticInfo) { addDiagnostic(SM, *ChildInfo); } } // TODO: Support Swift-style diagnostic formatting void addDiagnostic(SourceManager &SM, const DiagnosticInfo &Info) { // Determine what kind of diagnostic we're emitting. llvm::SourceMgr::DiagKind SMKind; switch (Info.Kind) { case DiagnosticKind::Error: SMKind = llvm::SourceMgr::DK_Error; break; case DiagnosticKind::Warning: SMKind = llvm::SourceMgr::DK_Warning; break; case DiagnosticKind::Note: SMKind = llvm::SourceMgr::DK_Note; break; case DiagnosticKind::Remark: SMKind = llvm::SourceMgr::DK_Remark; break; } // Translate ranges. SmallVector Ranges; for (auto R : Info.Ranges) Ranges.push_back(getRawRange(SM, R)); // Translate fix-its. SmallVector FixIts; for (DiagnosticInfo::FixIt F : Info.FixIts) FixIts.push_back(getRawFixIt(SM, F)); // Actually substitute the diagnostic arguments into the diagnostic text. llvm::SmallString<256> Text; { llvm::raw_svector_ostream Out(Text); DiagnosticEngine::formatDiagnosticText(Out, Info.FormatString, Info.FormatArgs); } const llvm::SourceMgr &rawSM = SM.getLLVMSourceMgr(); auto Msg = SM.GetMessage(Info.Loc, SMKind, Text, Ranges, FixIts); std::string result; llvm::raw_string_ostream os(result); rawSM.PrintMessage(os, Msg, false); os.flush(); Diagnostics.push_back(result); } }; } #endif