1 //===-- DiagnosticManager.h -------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLDB_EXPRESSION_DIAGNOSTICMANAGER_H 10 #define LLDB_EXPRESSION_DIAGNOSTICMANAGER_H 11 12 #include "lldb/lldb-defines.h" 13 #include "lldb/lldb-types.h" 14 15 #include "llvm/ADT/STLExtras.h" 16 #include "llvm/ADT/StringRef.h" 17 18 #include <string> 19 #include <vector> 20 21 namespace lldb_private { 22 23 enum DiagnosticOrigin { 24 eDiagnosticOriginUnknown = 0, 25 eDiagnosticOriginLLDB, 26 eDiagnosticOriginClang, 27 eDiagnosticOriginSwift, 28 eDiagnosticOriginLLVM 29 }; 30 31 const uint32_t LLDB_INVALID_COMPILER_ID = UINT32_MAX; 32 33 class Diagnostic { 34 friend class DiagnosticManager; 35 36 public: getKind()37 DiagnosticOrigin getKind() const { return m_origin; } 38 classof(const Diagnostic * diag)39 static bool classof(const Diagnostic *diag) { 40 DiagnosticOrigin kind = diag->getKind(); 41 switch (kind) { 42 case eDiagnosticOriginUnknown: 43 case eDiagnosticOriginLLDB: 44 case eDiagnosticOriginLLVM: 45 return true; 46 case eDiagnosticOriginClang: 47 case eDiagnosticOriginSwift: 48 return false; 49 } 50 } 51 Diagnostic(llvm::StringRef message,lldb::Severity severity,DiagnosticOrigin origin,uint32_t compiler_id)52 Diagnostic(llvm::StringRef message, lldb::Severity severity, 53 DiagnosticOrigin origin, uint32_t compiler_id) 54 : m_message(message), m_severity(severity), m_origin(origin), 55 m_compiler_id(compiler_id) {} 56 Diagnostic(const Diagnostic & rhs)57 Diagnostic(const Diagnostic &rhs) 58 : m_message(rhs.m_message), m_severity(rhs.m_severity), 59 m_origin(rhs.m_origin), m_compiler_id(rhs.m_compiler_id) {} 60 61 virtual ~Diagnostic() = default; 62 HasFixIts()63 virtual bool HasFixIts() const { return false; } 64 GetSeverity()65 lldb::Severity GetSeverity() const { return m_severity; } 66 GetCompilerID()67 uint32_t GetCompilerID() const { return m_compiler_id; } 68 GetMessage()69 llvm::StringRef GetMessage() const { return m_message; } 70 71 void AppendMessage(llvm::StringRef message, 72 bool precede_with_newline = true) { 73 if (precede_with_newline) 74 m_message.push_back('\n'); 75 m_message += message; 76 } 77 78 protected: 79 std::string m_message; 80 lldb::Severity m_severity; 81 DiagnosticOrigin m_origin; 82 uint32_t m_compiler_id; // Compiler-specific diagnostic ID 83 }; 84 85 typedef std::vector<std::unique_ptr<Diagnostic>> DiagnosticList; 86 87 class DiagnosticManager { 88 public: Clear()89 void Clear() { 90 m_diagnostics.clear(); 91 m_fixed_expression.clear(); 92 } 93 Diagnostics()94 const DiagnosticList &Diagnostics() { return m_diagnostics; } 95 HasFixIts()96 bool HasFixIts() const { 97 return llvm::any_of(m_diagnostics, 98 [](const std::unique_ptr<Diagnostic> &diag) { 99 return diag->HasFixIts(); 100 }); 101 } 102 103 void AddDiagnostic(llvm::StringRef message, lldb::Severity severity, 104 DiagnosticOrigin origin, 105 uint32_t compiler_id = LLDB_INVALID_COMPILER_ID) { 106 m_diagnostics.emplace_back( 107 std::make_unique<Diagnostic>(message, severity, origin, compiler_id)); 108 } 109 AddDiagnostic(std::unique_ptr<Diagnostic> diagnostic)110 void AddDiagnostic(std::unique_ptr<Diagnostic> diagnostic) { 111 if (diagnostic) 112 m_diagnostics.push_back(std::move(diagnostic)); 113 } 114 115 /// Moves over the contents of a second diagnostic manager over. Leaves other 116 /// diagnostic manager in an empty state. Consume(DiagnosticManager && other)117 void Consume(DiagnosticManager &&other) { 118 std::move(other.m_diagnostics.begin(), other.m_diagnostics.end(), 119 std::back_inserter(m_diagnostics)); 120 m_fixed_expression = std::move(other.m_fixed_expression); 121 other.Clear(); 122 } 123 124 size_t Printf(lldb::Severity severity, const char *format, ...) 125 __attribute__((format(printf, 3, 4))); 126 void PutString(lldb::Severity severity, llvm::StringRef str); 127 AppendMessageToDiagnostic(llvm::StringRef str)128 void AppendMessageToDiagnostic(llvm::StringRef str) { 129 if (!m_diagnostics.empty()) 130 m_diagnostics.back()->AppendMessage(str); 131 } 132 133 // Returns a string containing errors in this format: 134 // 135 // "error: error text\n 136 // warning: warning text\n 137 // remark text\n" 138 std::string GetString(char separator = '\n'); 139 140 void Dump(Log *log); 141 GetFixedExpression()142 const std::string &GetFixedExpression() { return m_fixed_expression; } 143 144 // Moves fixed_expression to the internal storage. SetFixedExpression(std::string fixed_expression)145 void SetFixedExpression(std::string fixed_expression) { 146 m_fixed_expression = std::move(fixed_expression); 147 } 148 149 protected: 150 DiagnosticList m_diagnostics; 151 std::string m_fixed_expression; 152 }; 153 } 154 155 #endif // LLDB_EXPRESSION_DIAGNOSTICMANAGER_H 156