xref: /freebsd/contrib/llvm-project/lldb/include/lldb/Expression/DiagnosticManager.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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