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;
}
|