xref: /freebsd/contrib/llvm-project/lldb/source/Expression/DiagnosticManager.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
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 
17 using namespace lldb_private;
18 char ExpressionError::ID;
19 
20 /// A std::error_code category for eErrorTypeExpression.
21 class ExpressionCategory : public std::error_category {
name() const22   const char *name() const noexcept override {
23     return "LLDBExpressionCategory";
24   }
message(int __ev) const25   std::string message(int __ev) const override {
26     return toString(static_cast<lldb::ExpressionResults>(__ev));
27   };
28 };
expression_category()29 ExpressionCategory &expression_category() {
30   static ExpressionCategory g_expression_category;
31   return g_expression_category;
32 }
33 
ExpressionError(lldb::ExpressionResults result,std::string msg,std::vector<DiagnosticDetail> details)34 ExpressionError::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 
StringForSeverity(lldb::Severity severity)40 static 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 
message() const53 std::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 
convertToErrorCode() const65 std::error_code ExpressionError::convertToErrorCode() const {
66   return llvm::inconvertibleErrorCode();
67 }
68 
log(llvm::raw_ostream & OS) const69 void ExpressionError::log(llvm::raw_ostream &OS) const { OS << message(); }
70 
Clone() const71 std::unique_ptr<CloneableError> ExpressionError::Clone() const {
72   return std::make_unique<ExpressionError>(
73       (lldb::ExpressionResults)convertToErrorCode().value(), m_message,
74       m_details);
75 }
76 
GetString(char separator)77 std::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 
Dump(Log * log)96 void 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 
GetAsError(lldb::ExpressionResults result,llvm::Twine message) const111 llvm::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 
AddDiagnostic(llvm::StringRef message,lldb::Severity severity,DiagnosticOrigin origin,uint32_t compiler_id)119 void 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 
Printf(lldb::Severity severity,const char * format,...)128 size_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 
PutString(lldb::Severity severity,llvm::StringRef str)142 void DiagnosticManager::PutString(lldb::Severity severity,
143                                   llvm::StringRef str) {
144   if (str.empty())
145     return;
146   AddDiagnostic(str, severity, eDiagnosticOriginLLDB);
147 }
148 
AppendMessage(llvm::StringRef message,bool precede_with_newline)149 void 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