1 //===-- DiagnosticManager.h -------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #ifndef lldb_DiagnosticManager_h
11 #define lldb_DiagnosticManager_h
12 
13 #include "lldb/lldb-defines.h"
14 #include "lldb/lldb-types.h"
15 
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   eDiagnosticOriginGo,
28   eDiagnosticOriginSwift,
29   eDiagnosticOriginLLVM
30 };
31 
32 enum DiagnosticSeverity {
33   eDiagnosticSeverityError,
34   eDiagnosticSeverityWarning,
35   eDiagnosticSeverityRemark
36 };
37 
38 const uint32_t LLDB_INVALID_COMPILER_ID = UINT32_MAX;
39 
40 class Diagnostic {
41   friend class DiagnosticManager;
42 
43 public:
getKind()44   DiagnosticOrigin getKind() const { return m_origin; }
45 
classof(const Diagnostic * diag)46   static bool classof(const Diagnostic *diag) {
47     DiagnosticOrigin kind = diag->getKind();
48     switch (kind) {
49     case eDiagnosticOriginUnknown:
50     case eDiagnosticOriginLLDB:
51     case eDiagnosticOriginGo:
52     case eDiagnosticOriginLLVM:
53       return true;
54     case eDiagnosticOriginClang:
55     case eDiagnosticOriginSwift:
56       return false;
57     }
58   }
59 
Diagnostic(llvm::StringRef message,DiagnosticSeverity severity,DiagnosticOrigin origin,uint32_t compiler_id)60   Diagnostic(llvm::StringRef message, DiagnosticSeverity severity,
61              DiagnosticOrigin origin, uint32_t compiler_id)
62       : m_message(message), m_severity(severity), m_origin(origin),
63         m_compiler_id(compiler_id) {}
64 
Diagnostic(const Diagnostic & rhs)65   Diagnostic(const Diagnostic &rhs)
66       : m_message(rhs.m_message), m_severity(rhs.m_severity),
67         m_origin(rhs.m_origin), m_compiler_id(rhs.m_compiler_id) {}
68 
69   virtual ~Diagnostic() = default;
70 
HasFixIts()71   virtual bool HasFixIts() const { return false; }
72 
GetSeverity()73   DiagnosticSeverity GetSeverity() const { return m_severity; }
74 
GetCompilerID()75   uint32_t GetCompilerID() const { return m_compiler_id; }
76 
GetMessage()77   llvm::StringRef GetMessage() const { return m_message; }
78 
79   void AppendMessage(llvm::StringRef message,
80                      bool precede_with_newline = true) {
81     if (precede_with_newline)
82       m_message.push_back('\n');
83     m_message.append(message);
84   }
85 
86 protected:
87   std::string m_message;
88   DiagnosticSeverity m_severity;
89   DiagnosticOrigin m_origin;
90   uint32_t m_compiler_id; // Compiler-specific diagnostic ID
91 };
92 
93 typedef std::vector<Diagnostic *> DiagnosticList;
94 
95 class DiagnosticManager {
96 public:
Clear()97   void Clear() {
98     m_diagnostics.clear();
99     m_fixed_expression.clear();
100   }
101 
102   // The diagnostic manager holds a list of diagnostics, which are owned by the
103   // manager.
Diagnostics()104   const DiagnosticList &Diagnostics() { return m_diagnostics; }
105 
~DiagnosticManager()106   ~DiagnosticManager() {
107     for (Diagnostic *diag : m_diagnostics) {
108       delete diag;
109     }
110   }
111 
HasFixIts()112   bool HasFixIts() {
113     for (Diagnostic *diag : m_diagnostics) {
114       if (diag->HasFixIts())
115         return true;
116     }
117     return false;
118   }
119 
120   void AddDiagnostic(llvm::StringRef message, DiagnosticSeverity severity,
121                      DiagnosticOrigin origin,
122                      uint32_t compiler_id = LLDB_INVALID_COMPILER_ID) {
123     m_diagnostics.push_back(
124         new Diagnostic(message, severity, origin, compiler_id));
125   }
126 
AddDiagnostic(Diagnostic * diagnostic)127   void AddDiagnostic(Diagnostic *diagnostic) {
128     m_diagnostics.push_back(diagnostic);
129   }
130 
131   void CopyDiagnostics(DiagnosticManager &otherDiagnostics);
132 
133   size_t Printf(DiagnosticSeverity severity, const char *format, ...)
134       __attribute__((format(printf, 3, 4)));
135   size_t PutString(DiagnosticSeverity severity, llvm::StringRef str);
136 
AppendMessageToDiagnostic(llvm::StringRef str)137   void AppendMessageToDiagnostic(llvm::StringRef str) {
138     if (!m_diagnostics.empty()) {
139       m_diagnostics.back()->AppendMessage(str);
140     }
141   }
142 
143   // Returns a string containing errors in this format:
144   //
145   // "error: error text\n
146   // warning: warning text\n
147   // remark text\n"
148   std::string GetString(char separator = '\n');
149 
150   void Dump(Log *log);
151 
GetFixedExpression()152   const std::string &GetFixedExpression() { return m_fixed_expression; }
153 
154   // Moves fixed_expression to the internal storage.
SetFixedExpression(std::string fixed_expression)155   void SetFixedExpression(std::string fixed_expression) {
156     m_fixed_expression = std::move(fixed_expression);
157     fixed_expression.clear();
158   }
159 
160 protected:
161   DiagnosticList m_diagnostics;
162   std::string m_fixed_expression;
163 };
164 }
165 
166 #endif /* lldb_DiagnosticManager_h */
167