1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
|
//===-- DiagnosticManager.cpp ---------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "lldb/Expression/DiagnosticManager.h"
#include "llvm/Support/ErrorHandling.h"
#include "lldb/Utility/ErrorMessages.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/StreamString.h"
using namespace lldb_private;
char ExpressionError::ID;
/// A std::error_code category for eErrorTypeExpression.
class ExpressionCategory : public std::error_category {
const char *name() const noexcept override {
return "LLDBExpressionCategory";
}
std::string message(int __ev) const override {
return toString(static_cast<lldb::ExpressionResults>(__ev));
};
};
ExpressionCategory &expression_category() {
static ExpressionCategory g_expression_category;
return g_expression_category;
}
ExpressionError::ExpressionError(lldb::ExpressionResults result,
std::string msg,
std::vector<DiagnosticDetail> details)
: ErrorInfo(std::error_code(result, expression_category())), m_message(msg),
m_details(details) {}
static llvm::StringRef StringForSeverity(lldb::Severity severity) {
switch (severity) {
// this should be exhaustive
case lldb::eSeverityError:
return "error: ";
case lldb::eSeverityWarning:
return "warning: ";
case lldb::eSeverityInfo:
return "";
}
llvm_unreachable("switch needs another case for lldb::Severity enum");
}
std::string ExpressionError::message() const {
std::string str;
{
llvm::raw_string_ostream os(str);
if (!m_message.empty())
os << m_message << '\n';
for (const auto &detail : m_details)
os << StringForSeverity(detail.severity) << detail.rendered << '\n';
}
return str;
}
std::error_code ExpressionError::convertToErrorCode() const {
return llvm::inconvertibleErrorCode();
}
void ExpressionError::log(llvm::raw_ostream &OS) const { OS << message(); }
std::unique_ptr<CloneableError> ExpressionError::Clone() const {
return std::make_unique<ExpressionError>(
(lldb::ExpressionResults)convertToErrorCode().value(), m_message,
m_details);
}
std::string DiagnosticManager::GetString(char separator) {
std::string str;
llvm::raw_string_ostream stream(str);
for (const auto &diagnostic : Diagnostics()) {
llvm::StringRef severity = StringForSeverity(diagnostic->GetSeverity());
stream << severity;
llvm::StringRef message = diagnostic->GetMessage();
auto severity_pos = message.find(severity);
stream << message.take_front(severity_pos);
if (severity_pos != llvm::StringRef::npos)
stream << message.drop_front(severity_pos + severity.size());
stream << separator;
}
return str;
}
void DiagnosticManager::Dump(Log *log) {
if (!log)
return;
std::string str = GetString();
// We want to remove the last '\n' because log->PutCString will add
// one for us.
if (!str.empty() && str.back() == '\n')
str.pop_back();
log->PutString(str);
}
llvm::Error DiagnosticManager::GetAsError(lldb::ExpressionResults result,
llvm::Twine message) const {
std::vector<DiagnosticDetail> details;
for (const auto &diag : m_diagnostics)
details.push_back(diag->GetDetail());
return llvm::make_error<ExpressionError>(result, message.str(), details);
}
void DiagnosticManager::AddDiagnostic(llvm::StringRef message,
lldb::Severity severity,
DiagnosticOrigin origin,
uint32_t compiler_id) {
m_diagnostics.emplace_back(std::make_unique<Diagnostic>(
origin, compiler_id,
DiagnosticDetail{{}, severity, message.str(), message.str()}));
}
size_t DiagnosticManager::Printf(lldb::Severity severity, const char *format,
...) {
StreamString ss;
va_list args;
va_start(args, format);
size_t result = ss.PrintfVarArg(format, args);
va_end(args);
AddDiagnostic(ss.GetString(), severity, eDiagnosticOriginLLDB);
return result;
}
void DiagnosticManager::PutString(lldb::Severity severity,
llvm::StringRef str) {
if (str.empty())
return;
AddDiagnostic(str, severity, eDiagnosticOriginLLDB);
}
void Diagnostic::AppendMessage(llvm::StringRef message,
bool precede_with_newline) {
if (precede_with_newline) {
m_detail.message.push_back('\n');
m_detail.rendered.push_back('\n');
}
m_detail.message += message;
m_detail.rendered += message;
}
|