1 //===-- CommandReturnObject.cpp -------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "lldb/Interpreter/CommandReturnObject.h"
11 #include "lldb/Utility/DiagnosticsRendering.h"
12 #include "lldb/Utility/Status.h"
13 #include "lldb/Utility/StreamString.h"
16 using namespace lldb_private
;
18 static llvm::raw_ostream
&error(Stream
&strm
) {
19 return llvm::WithColor(strm
.AsRawOstream(), llvm::HighlightColor::Error
,
20 llvm::ColorMode::Enable
)
24 static llvm::raw_ostream
&warning(Stream
&strm
) {
25 return llvm::WithColor(strm
.AsRawOstream(), llvm::HighlightColor::Warning
,
26 llvm::ColorMode::Enable
)
30 static llvm::raw_ostream
¬e(Stream
&strm
) {
31 return llvm::WithColor(strm
.AsRawOstream(), llvm::HighlightColor::Note
,
32 llvm::ColorMode::Enable
)
36 static void DumpStringToStreamWithNewline(Stream
&strm
, const std::string
&s
) {
37 bool add_newline
= false;
39 // We already checked for empty above, now make sure there is a newline in
40 // the error, and if there isn't one, add one.
41 strm
.Write(s
.c_str(), s
.size());
43 const char last_char
= *s
.rbegin();
44 add_newline
= last_char
!= '\n' && last_char
!= '\r';
50 CommandReturnObject::CommandReturnObject(bool colors
)
51 : m_out_stream(colors
), m_err_stream(colors
), m_colors(colors
) {}
53 void CommandReturnObject::AppendErrorWithFormat(const char *format
, ...) {
54 SetStatus(eReturnStatusFailed
);
59 va_start(args
, format
);
61 sstrm
.PrintfVarArg(format
, args
);
64 const std::string
&s
= std::string(sstrm
.GetString());
66 error(GetErrorStream());
67 DumpStringToStreamWithNewline(GetErrorStream(), s
);
71 void CommandReturnObject::AppendMessageWithFormat(const char *format
, ...) {
75 va_start(args
, format
);
77 sstrm
.PrintfVarArg(format
, args
);
80 GetOutputStream() << sstrm
.GetString();
83 void CommandReturnObject::AppendNoteWithFormat(const char *format
, ...) {
87 va_start(args
, format
);
89 sstrm
.PrintfVarArg(format
, args
);
92 note(GetOutputStream()) << sstrm
.GetString();
95 void CommandReturnObject::AppendWarningWithFormat(const char *format
, ...) {
99 va_start(args
, format
);
101 sstrm
.PrintfVarArg(format
, args
);
104 warning(GetErrorStream()) << sstrm
.GetString();
107 void CommandReturnObject::AppendMessage(llvm::StringRef in_string
) {
108 if (in_string
.empty())
110 GetOutputStream() << in_string
.rtrim() << '\n';
113 void CommandReturnObject::AppendNote(llvm::StringRef in_string
) {
114 if (in_string
.empty())
116 note(GetOutputStream()) << in_string
.rtrim() << '\n';
119 void CommandReturnObject::AppendWarning(llvm::StringRef in_string
) {
120 if (in_string
.empty())
122 warning(GetErrorStream()) << in_string
.rtrim() << '\n';
125 void CommandReturnObject::AppendError(llvm::StringRef in_string
) {
126 SetStatus(eReturnStatusFailed
);
127 if (in_string
.empty())
129 // Workaround to deal with already fully formatted compiler diagnostics.
130 llvm::StringRef
msg(in_string
.rtrim());
131 msg
.consume_front("error: ");
132 error(GetErrorStream()) << msg
<< '\n';
135 void CommandReturnObject::SetError(Status error
) {
136 SetError(error
.takeError());
139 void CommandReturnObject::SetError(llvm::Error error
) {
140 // Retrieve any diagnostics.
141 error
= llvm::handleErrors(std::move(error
), [&](DiagnosticError
&error
) {
142 SetStatus(eReturnStatusFailed
);
143 m_diagnostics
= error
.GetDetails();
146 AppendError(llvm::toString(std::move(error
)));
150 std::string
CommandReturnObject::GetInlineDiagnosticString(unsigned indent
) {
151 StreamString
diag_stream(m_colors
);
152 RenderDiagnosticDetails(diag_stream
, indent
, true, m_diagnostics
);
153 // Duplex the diagnostics to the secondary stream (but not inlined).
154 if (auto stream_sp
= m_err_stream
.GetStreamAtIndex(eImmediateStreamIndex
))
155 RenderDiagnosticDetails(*stream_sp
, std::nullopt
, false, m_diagnostics
);
157 return diag_stream
.GetString().str();
160 std::string
CommandReturnObject::GetErrorString(bool with_diagnostics
) {
161 StreamString
stream(m_colors
);
162 if (with_diagnostics
)
163 RenderDiagnosticDetails(stream
, std::nullopt
, false, m_diagnostics
);
165 lldb::StreamSP
stream_sp(m_err_stream
.GetStreamAtIndex(eStreamStringIndex
));
167 stream
<< std::static_pointer_cast
<StreamString
>(stream_sp
)->GetString();
168 return stream
.GetString().str();
171 StructuredData::ObjectSP
CommandReturnObject::GetErrorData() {
172 return Serialize(m_diagnostics
);
175 // Similar to AppendError, but do not prepend 'Status: ' to message, and don't
176 // append "\n" to the end of it.
178 void CommandReturnObject::AppendRawError(llvm::StringRef in_string
) {
179 SetStatus(eReturnStatusFailed
);
180 assert(!in_string
.empty() && "Expected a non-empty error message");
181 GetErrorStream() << in_string
;
184 void CommandReturnObject::SetStatus(ReturnStatus status
) { m_status
= status
; }
186 ReturnStatus
CommandReturnObject::GetStatus() const { return m_status
; }
188 bool CommandReturnObject::Succeeded() const {
189 return m_status
<= eReturnStatusSuccessContinuingResult
;
192 bool CommandReturnObject::HasResult() const {
193 return (m_status
== eReturnStatusSuccessFinishResult
||
194 m_status
== eReturnStatusSuccessContinuingResult
);
197 void CommandReturnObject::Clear() {
198 lldb::StreamSP stream_sp
;
199 stream_sp
= m_out_stream
.GetStreamAtIndex(eStreamStringIndex
);
201 static_cast<StreamString
*>(stream_sp
.get())->Clear();
202 stream_sp
= m_err_stream
.GetStreamAtIndex(eStreamStringIndex
);
204 static_cast<StreamString
*>(stream_sp
.get())->Clear();
205 m_diagnostics
.clear();
206 m_status
= eReturnStatusStarted
;
207 m_did_change_process_state
= false;
208 m_suppress_immediate_output
= false;
209 m_interactive
= true;
212 bool CommandReturnObject::GetDidChangeProcessState() const {
213 return m_did_change_process_state
;
216 void CommandReturnObject::SetDidChangeProcessState(bool b
) {
217 m_did_change_process_state
= b
;
220 bool CommandReturnObject::GetInteractive() const { return m_interactive
; }
222 void CommandReturnObject::SetInteractive(bool b
) { m_interactive
= b
; }
224 bool CommandReturnObject::GetSuppressImmediateOutput() const {
225 return m_suppress_immediate_output
;
228 void CommandReturnObject::SetSuppressImmediateOutput(bool b
) {
229 m_suppress_immediate_output
= b
;