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

Provided by KDAB

Privacy Policy
Improve your Profiling and Debugging skills
Find out more

source code of lldb/source/Expression/DiagnosticManager.cpp