LLDB mainline
DiagnosticManager.cpp
Go to the documentation of this file.
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
10
11#include "llvm/Support/ErrorHandling.h"
12
14#include "lldb/Utility/Log.h"
16
17using namespace lldb_private;
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(static_cast<lldb::ExpressionResults>(__ev));
27 };
28};
30 static ExpressionCategory g_expression_category;
31 return g_expression_category;
32}
33
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
44 return "error: ";
46 return "warning: ";
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(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>(
74 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(diagnostic->GetSeverity());
83 stream << severity;
84
85 llvm::StringRef message = diagnostic->GetMessage();
86 std::string searchable_message = message.lower();
87 auto severity_pos = message.find(severity);
88 stream << message.take_front(severity_pos);
89
90 if (severity_pos != llvm::StringRef::npos)
91 stream << message.drop_front(severity_pos + severity.size());
92 stream << separator;
93 }
94 return str;
95}
96
98 if (!log)
99 return;
100
101 std::string str = GetString();
102
103 // We want to remove the last '\n' because log->PutCString will add
104 // one for us.
105
106 if (!str.empty() && str.back() == '\n')
107 str.pop_back();
108
109 log->PutString(str);
110}
111
113 llvm::Twine message) const {
114 std::vector<DiagnosticDetail> details;
115 for (const auto &diag : m_diagnostics)
116 details.push_back(diag->GetDetail());
117 return llvm::make_error<ExpressionError>(result, message.str(), details);
118}
119
120void DiagnosticManager::AddDiagnostic(llvm::StringRef message,
121 lldb::Severity severity,
122 DiagnosticOrigin origin,
123 uint32_t compiler_id) {
124 m_diagnostics.emplace_back(std::make_unique<Diagnostic>(
125 origin, compiler_id,
126 DiagnosticDetail{{}, severity, message.str(), message.str()}));
127}
128
129size_t DiagnosticManager::Printf(lldb::Severity severity, const char *format,
130 ...) {
131 StreamString ss;
132
133 va_list args;
134 va_start(args, format);
135 size_t result = ss.PrintfVarArg(format, args);
136 va_end(args);
137
139
140 return result;
141}
142
144 llvm::StringRef str) {
145 if (str.empty())
146 return;
147 AddDiagnostic(str, severity, eDiagnosticOriginLLDB);
148}
149
150void Diagnostic::AppendMessage(llvm::StringRef message,
151 bool precede_with_newline) {
152 if (precede_with_newline) {
153 m_detail.message.push_back('\n');
154 m_detail.rendered.push_back('\n');
155 }
156 m_detail.message += message;
157 m_detail.rendered += message;
158}
static llvm::StringRef StringForSeverity(lldb::Severity severity)
ExpressionCategory & expression_category()
A std::error_code category for eErrorTypeExpression.
const char * name() const noexcept override
std::string message(int __ev) const override
size_t void PutString(lldb::Severity severity, llvm::StringRef str)
llvm::Error GetAsError(lldb::ExpressionResults result, llvm::Twine message={}) const
Returns an ExpressionError with arg as error code.
std::string GetString(char separator='\n')
const DiagnosticList & Diagnostics()
void AddDiagnostic(llvm::StringRef message, lldb::Severity severity, DiagnosticOrigin origin, uint32_t compiler_id=LLDB_INVALID_COMPILER_ID)
size_t Printf(lldb::Severity severity, const char *format,...) __attribute__((format(printf
void AppendMessage(llvm::StringRef message, bool precede_with_newline=true)
std::vector< DiagnosticDetail > m_details
void log(llvm::raw_ostream &OS) const override
std::unique_ptr< CloneableError > Clone() const override
ExpressionError(lldb::ExpressionResults result, std::string msg, std::vector< DiagnosticDetail > details={})
std::error_code convertToErrorCode() const override
std::string message() const override
void PutString(llvm::StringRef str)
Definition: Log.cpp:147
llvm::StringRef GetString() const
size_t size_t PrintfVarArg(const char *format, va_list args)
Definition: Stream.cpp:143
A class that represents a running process on the host machine.
const char * toString(AppleArm64ExceptionClass EC)
Severity
Used for expressing severity in logs and diagnostics.
ExpressionResults
The results of expression evaluation.
A compiler-independent representation of an lldb_private::Diagnostic.
std::string rendered
Contains the fully rendered error message, without "error: ", but including the source context.
std::string message
Contains "use of undeclared identifier 'foo'" in the example above.