xref: /freebsd/contrib/llvm-project/lldb/include/lldb/Expression/DiagnosticManager.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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 "lldb/Utility/DiagnosticsRendering.h"
16 #include "lldb/Utility/FileSpec.h"
17 #include "lldb/Utility/Status.h"
18 
19 #include "llvm/ADT/STLExtras.h"
20 #include "llvm/ADT/StringRef.h"
21 
22 #include <string>
23 #include <vector>
24 
25 namespace lldb_private {
26 
27 /// An llvm::Error used to communicate diagnostics in Status. Multiple
28 /// diagnostics may be chained in an llvm::ErrorList.
29 class ExpressionError
30     : public llvm::ErrorInfo<ExpressionError, DiagnosticError> {
31   std::string m_message;
32   std::vector<DiagnosticDetail> m_details;
33 
34 public:
35   static char ID;
36   using llvm::ErrorInfo<ExpressionError, DiagnosticError>::ErrorInfo;
37   ExpressionError(lldb::ExpressionResults result, std::string msg,
38                   std::vector<DiagnosticDetail> details = {});
39   std::string message() const override;
GetDetails()40   llvm::ArrayRef<DiagnosticDetail> GetDetails() const override {
41     return m_details;
42   }
43   std::error_code convertToErrorCode() const override;
44   void log(llvm::raw_ostream &OS) const override;
45   std::unique_ptr<CloneableError> Clone() const override;
46 };
47 
48 enum DiagnosticOrigin {
49   eDiagnosticOriginUnknown = 0,
50   eDiagnosticOriginLLDB,
51   eDiagnosticOriginClang,
52   eDiagnosticOriginSwift,
53   eDiagnosticOriginLLVM
54 };
55 
56 const uint32_t LLDB_INVALID_COMPILER_ID = UINT32_MAX;
57 
58 class Diagnostic {
59   friend class DiagnosticManager;
60 
61 public:
getKind()62   DiagnosticOrigin getKind() const { return m_origin; }
63 
classof(const Diagnostic * diag)64   static bool classof(const Diagnostic *diag) {
65     DiagnosticOrigin kind = diag->getKind();
66     switch (kind) {
67     case eDiagnosticOriginUnknown:
68     case eDiagnosticOriginLLDB:
69     case eDiagnosticOriginLLVM:
70       return true;
71     case eDiagnosticOriginClang:
72     case eDiagnosticOriginSwift:
73       return false;
74     }
75   }
76 
Diagnostic(DiagnosticOrigin origin,uint32_t compiler_id,DiagnosticDetail detail)77   Diagnostic(DiagnosticOrigin origin, uint32_t compiler_id,
78              DiagnosticDetail detail)
79       : m_origin(origin), m_compiler_id(compiler_id), m_detail(detail) {}
80 
81   virtual ~Diagnostic() = default;
82 
HasFixIts()83   virtual bool HasFixIts() const { return false; }
84 
GetSeverity()85   lldb::Severity GetSeverity() const { return m_detail.severity; }
86 
GetCompilerID()87   uint32_t GetCompilerID() const { return m_compiler_id; }
88 
GetMessage()89   llvm::StringRef GetMessage() const { return m_detail.message; }
GetDetail()90   const DiagnosticDetail &GetDetail() const { return m_detail; }
91 
92   void AppendMessage(llvm::StringRef message, bool precede_with_newline = true);
93 
94 protected:
95   DiagnosticOrigin m_origin;
96   /// Compiler-specific diagnostic ID.
97   uint32_t m_compiler_id;
98   DiagnosticDetail m_detail;
99 };
100 
101 typedef std::vector<std::unique_ptr<Diagnostic>> DiagnosticList;
102 
103 class DiagnosticManager {
104 public:
Clear()105   void Clear() {
106     m_diagnostics.clear();
107     m_fixed_expression.clear();
108   }
109 
Diagnostics()110   const DiagnosticList &Diagnostics() const { return m_diagnostics; }
Diagnostics()111   DiagnosticList &Diagnostics() { return m_diagnostics; }
112 
HasFixIts()113   bool HasFixIts() const {
114     return llvm::any_of(m_diagnostics,
115                         [](const std::unique_ptr<Diagnostic> &diag) {
116                           return diag->HasFixIts();
117                         });
118   }
119 
120   void AddDiagnostic(llvm::StringRef message, lldb::Severity severity,
121                      DiagnosticOrigin origin,
122                      uint32_t compiler_id = LLDB_INVALID_COMPILER_ID);
123 
AddDiagnostic(std::unique_ptr<Diagnostic> diagnostic)124   void AddDiagnostic(std::unique_ptr<Diagnostic> diagnostic) {
125     if (diagnostic)
126       m_diagnostics.push_back(std::move(diagnostic));
127   }
128 
129   /// Moves over the contents of a second diagnostic manager over. Leaves other
130   /// diagnostic manager in an empty state.
Consume(DiagnosticManager && other)131   void Consume(DiagnosticManager &&other) {
132     std::move(other.m_diagnostics.begin(), other.m_diagnostics.end(),
133               std::back_inserter(m_diagnostics));
134     m_fixed_expression = std::move(other.m_fixed_expression);
135     other.Clear();
136   }
137 
138   size_t Printf(lldb::Severity severity, const char *format, ...)
139       __attribute__((format(printf, 3, 4)));
140   void PutString(lldb::Severity severity, llvm::StringRef str);
141 
AppendMessageToDiagnostic(llvm::StringRef str)142   void AppendMessageToDiagnostic(llvm::StringRef str) {
143     if (!m_diagnostics.empty())
144       m_diagnostics.back()->AppendMessage(str);
145   }
146 
147   /// Returns an \ref ExpressionError with \c arg as error code.
148   llvm::Error GetAsError(lldb::ExpressionResults result,
149                          llvm::Twine message = {}) const;
150 
151   // Returns a string containing errors in this format:
152   //
153   // "error: error text\n
154   // warning: warning text\n
155   // remark text\n"
156   std::string GetString(char separator = '\n');
157 
158   void Dump(Log *log);
159 
GetFixedExpression()160   const std::string &GetFixedExpression() { return m_fixed_expression; }
161 
162   // Moves fixed_expression to the internal storage.
SetFixedExpression(std::string fixed_expression)163   void SetFixedExpression(std::string fixed_expression) {
164     m_fixed_expression = std::move(fixed_expression);
165   }
166 
167 protected:
168   DiagnosticList m_diagnostics;
169   std::string m_fixed_expression;
170 };
171 }
172 
173 #endif // LLDB_EXPRESSION_DIAGNOSTICMANAGER_H
174