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
25namespace lldb_private {
26
27/// An llvm::Error used to communicate diagnostics in Status. Multiple
28/// diagnostics may be chained in an llvm::ErrorList.
29class ExpressionError
30 : public llvm::ErrorInfo<ExpressionError, DiagnosticError> {
31 std::string m_message;
32 std::vector<DiagnosticDetail> m_details;
33
34public:
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;
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
48enum DiagnosticOrigin {
49 eDiagnosticOriginUnknown = 0,
50 eDiagnosticOriginLLDB,
51 eDiagnosticOriginClang,
52 eDiagnosticOriginSwift,
53 eDiagnosticOriginLLVM
54};
55
56const uint32_t LLDB_INVALID_COMPILER_ID = UINT32_MAX;
57
58class Diagnostic {
59 friend class DiagnosticManager;
60
61public:
62 DiagnosticOrigin getKind() const { return m_origin; }
63
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
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
83 virtual bool HasFixIts() const { return false; }
84
85 lldb::Severity GetSeverity() const { return m_detail.severity; }
86
87 uint32_t GetCompilerID() const { return m_compiler_id; }
88
89 llvm::StringRef GetMessage() const { return m_detail.message; }
90 const DiagnosticDetail &GetDetail() const { return m_detail; }
91
92 void AppendMessage(llvm::StringRef message, bool precede_with_newline = true);
93
94protected:
95 DiagnosticOrigin m_origin;
96 /// Compiler-specific diagnostic ID.
97 uint32_t m_compiler_id;
98 DiagnosticDetail m_detail;
99};
100
101typedef std::vector<std::unique_ptr<Diagnostic>> DiagnosticList;
102
103class DiagnosticManager {
104public:
105 void Clear() {
106 m_diagnostics.clear();
107 m_fixed_expression.clear();
108 }
109
110 const DiagnosticList &Diagnostics() const { return m_diagnostics; }
111 DiagnosticList &Diagnostics() { return m_diagnostics; }
112
113 bool HasFixIts() const {
114 return llvm::any_of(Range: m_diagnostics,
115 P: [](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
124 void AddDiagnostic(std::unique_ptr<Diagnostic> diagnostic) {
125 if (diagnostic)
126 m_diagnostics.push_back(x: 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.
131 void Consume(DiagnosticManager &&other) {
132 std::move(first: other.m_diagnostics.begin(), last: other.m_diagnostics.end(),
133 result: std::back_inserter(x&: 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
142 void AppendMessageToDiagnostic(llvm::StringRef str) {
143 if (!m_diagnostics.empty())
144 m_diagnostics.back()->AppendMessage(message: 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
160 const std::string &GetFixedExpression() { return m_fixed_expression; }
161
162 // Moves fixed_expression to the internal storage.
163 void SetFixedExpression(std::string fixed_expression) {
164 m_fixed_expression = std::move(fixed_expression);
165 }
166
167protected:
168 DiagnosticList m_diagnostics;
169 std::string m_fixed_expression;
170};
171}
172
173#endif // LLDB_EXPRESSION_DIAGNOSTICMANAGER_H
174

source code of lldb/include/lldb/Expression/DiagnosticManager.h