158 lines · cpp
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-exception6//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(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 exhaustive43 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(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 (lldb::ExpressionResults)convertToErrorCode().value(), m_message,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 auto severity_pos = message.find(severity);87 stream << message.take_front(severity_pos);88 89 if (severity_pos != llvm::StringRef::npos)90 stream << message.drop_front(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 add103 // 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(diag->GetDetail());116 return llvm::make_error<ExpressionError>(result, message.str(), 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(std::make_unique<Diagnostic>(124 origin, compiler_id,125 DiagnosticDetail{{}, severity, message.str(), 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(ss.GetString(), severity, 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(str, severity, 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('\n');153 m_detail.rendered.push_back('\n');154 }155 m_detail.message += message;156 m_detail.rendered += message;157}158