1212#include " lldb/lldb-defines.h"
1313#include " lldb/lldb-types.h"
1414
15+ #include " lldb/Utility/FileSpec.h"
16+ #include " lldb/Utility/Status.h"
17+
1518#include " llvm/ADT/STLExtras.h"
1619#include " llvm/ADT/StringRef.h"
1720
2023
2124namespace lldb_private {
2225
26+ // / A compiler-independent representation of a Diagnostic. Expression
27+ // / evaluation failures often have more than one diagnostic that a UI
28+ // / layer might want to render differently, for example to colorize
29+ // / it.
30+ // /
31+ // / Running example:
32+ // / (lldb) expr 1+foo
33+ // / error: <user expression 0>:1:3: use of undeclared identifier 'foo'
34+ // / 1+foo
35+ // / ^
36+ struct DiagnosticDetail {
37+ struct SourceLocation {
38+ FileSpec file;
39+ unsigned line = 0 ;
40+ uint16_t column = 0 ;
41+ uint16_t length = 0 ;
42+ bool in_user_input = false ;
43+ };
44+ // / Contains {{}, 1, 3, 3, true} in the example above.
45+ std::optional<SourceLocation> source_location;
46+ // / Contains eSeverityError in the example above.
47+ lldb::Severity severity = lldb::eSeverityInfo;
48+ // / Contains "use of undeclared identifier 'x'" in the example above.
49+ std::string message;
50+ // / Contains the fully rendered error message.
51+ std::string rendered;
52+ };
53+
54+ // / An llvm::Error used to communicate diagnostics in Status. Multiple
55+ // / diagnostics may be chained in an llvm::ErrorList.
56+ class ExpressionError
57+ : public llvm::ErrorInfo<ExpressionError, ExpressionErrorBase> {
58+ std::string m_message;
59+ std::vector<DiagnosticDetail> m_details;
60+
61+ public:
62+ static char ID;
63+ using llvm::ErrorInfo<ExpressionError, ExpressionErrorBase>::ErrorInfo;
64+ ExpressionError (lldb::ExpressionResults result, std::string msg,
65+ std::vector<DiagnosticDetail> details = {});
66+ std::string message () const override ;
67+ llvm::ArrayRef<DiagnosticDetail> GetDetail () const { return m_details; }
68+ std::error_code convertToErrorCode () const override ;
69+ void log (llvm::raw_ostream &OS) const override ;
70+ std::unique_ptr<CloneableError> Clone () const override ;
71+ };
72+
2373enum DiagnosticOrigin {
2474 eDiagnosticOriginUnknown = 0 ,
2575 eDiagnosticOriginLLDB,
@@ -49,37 +99,28 @@ class Diagnostic {
4999 }
50100 }
51101
52- Diagnostic (llvm::StringRef message, lldb::Severity severity,
53- DiagnosticOrigin origin, uint32_t compiler_id)
54- : m_message(message), m_severity(severity), m_origin(origin),
55- m_compiler_id (compiler_id) {}
56-
57- Diagnostic (const Diagnostic &rhs)
58- : m_message(rhs.m_message), m_severity(rhs.m_severity),
59- m_origin(rhs.m_origin), m_compiler_id(rhs.m_compiler_id) {}
102+ Diagnostic (DiagnosticOrigin origin, uint32_t compiler_id,
103+ DiagnosticDetail detail)
104+ : m_origin(origin), m_compiler_id(compiler_id), m_detail(detail) {}
60105
61106 virtual ~Diagnostic () = default ;
62107
63108 virtual bool HasFixIts () const { return false ; }
64109
65- lldb::Severity GetSeverity () const { return m_severity ; }
110+ lldb::Severity GetSeverity () const { return m_detail. severity ; }
66111
67112 uint32_t GetCompilerID () const { return m_compiler_id; }
68113
69- llvm::StringRef GetMessage () const { return m_message; }
114+ llvm::StringRef GetMessage () const { return m_detail.message ; }
115+ const DiagnosticDetail &GetDetail () const { return m_detail; }
70116
71- void AppendMessage (llvm::StringRef message,
72- bool precede_with_newline = true ) {
73- if (precede_with_newline)
74- m_message.push_back (' \n ' );
75- m_message += message;
76- }
117+ void AppendMessage (llvm::StringRef message, bool precede_with_newline = true );
77118
78119protected:
79- std::string m_message;
80- lldb::Severity m_severity;
81120 DiagnosticOrigin m_origin;
82- uint32_t m_compiler_id; // Compiler-specific diagnostic ID
121+ // / Compiler-specific diagnostic ID.
122+ uint32_t m_compiler_id;
123+ DiagnosticDetail m_detail;
83124};
84125
85126typedef std::vector<std::unique_ptr<Diagnostic>> DiagnosticList;
@@ -102,10 +143,7 @@ class DiagnosticManager {
102143
103144 void AddDiagnostic (llvm::StringRef message, lldb::Severity severity,
104145 DiagnosticOrigin origin,
105- uint32_t compiler_id = LLDB_INVALID_COMPILER_ID) {
106- m_diagnostics.emplace_back (
107- std::make_unique<Diagnostic>(message, severity, origin, compiler_id));
108- }
146+ uint32_t compiler_id = LLDB_INVALID_COMPILER_ID);
109147
110148 void AddDiagnostic (std::unique_ptr<Diagnostic> diagnostic) {
111149 if (diagnostic)
@@ -130,6 +168,11 @@ class DiagnosticManager {
130168 m_diagnostics.back ()->AppendMessage (str);
131169 }
132170
171+ // / Copies the diagnostics into an llvm::Error{List}.
172+ // / The first diagnostic wraps \c result.
173+ llvm::Error GetAsError (lldb::ExpressionResults result,
174+ llvm::Twine message = {}) const ;
175+
133176 // Returns a string containing errors in this format:
134177 //
135178 // "error: error text\n
0 commit comments