1 //===-- CommandReturnObject.h -----------------------------------*- C++ -*-===// 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 #ifndef LLDB_INTERPRETER_COMMANDRETURNOBJECT_H 10 #define LLDB_INTERPRETER_COMMANDRETURNOBJECT_H 11 12 #include "lldb/Host/StreamFile.h" 13 #include "lldb/Utility/DiagnosticsRendering.h" 14 #include "lldb/Utility/StreamString.h" 15 #include "lldb/Utility/StreamTee.h" 16 #include "lldb/Utility/StructuredData.h" 17 #include "lldb/ValueObject/ValueObjectList.h" 18 #include "lldb/lldb-private.h" 19 20 #include "llvm/ADT/StringRef.h" 21 #include "llvm/Support/Error.h" 22 #include "llvm/Support/FormatVariadic.h" 23 #include "llvm/Support/WithColor.h" 24 25 #include <memory> 26 27 namespace lldb_private { 28 29 class CommandReturnObject { 30 public: 31 CommandReturnObject(bool colors); 32 33 ~CommandReturnObject() = default; 34 35 /// Get the command as the user typed it. Empty string if commands were run on 36 /// behalf of lldb. GetCommand()37 const std::string &GetCommand() const { return m_command; } 38 SetCommand(std::string command)39 void SetCommand(std::string command) { m_command = std::move(command); } 40 41 /// Format any inline diagnostics with an indentation of \c indent. 42 std::string GetInlineDiagnosticString(unsigned indent) const; 43 GetOutputString()44 llvm::StringRef GetOutputString() const { 45 lldb::StreamSP stream_sp(m_out_stream.GetStreamAtIndex(eStreamStringIndex)); 46 if (stream_sp) 47 return std::static_pointer_cast<StreamString>(stream_sp)->GetString(); 48 return llvm::StringRef(); 49 } 50 51 /// Return the errors as a string. 52 /// 53 /// If \c with_diagnostics is true, all diagnostics are also 54 /// rendered into the string. Otherwise the expectation is that they 55 /// are fetched with \ref GetInlineDiagnosticString(). 56 std::string GetErrorString(bool with_diagnostics = true) const; 57 StructuredData::ObjectSP GetErrorData(); 58 GetOutputStream()59 Stream &GetOutputStream() { 60 // Make sure we at least have our normal string stream output stream 61 lldb::StreamSP stream_sp(m_out_stream.GetStreamAtIndex(eStreamStringIndex)); 62 if (!stream_sp) { 63 stream_sp = std::make_shared<StreamString>(); 64 m_out_stream.SetStreamAtIndex(eStreamStringIndex, stream_sp); 65 } 66 return m_out_stream; 67 } 68 GetErrorStream()69 Stream &GetErrorStream() { 70 // Make sure we at least have our normal string stream output stream 71 lldb::StreamSP stream_sp(m_err_stream.GetStreamAtIndex(eStreamStringIndex)); 72 if (!stream_sp) { 73 stream_sp = std::make_shared<StreamString>(); 74 m_err_stream.SetStreamAtIndex(eStreamStringIndex, stream_sp); 75 } 76 return m_err_stream; 77 } 78 SetImmediateOutputFile(lldb::FileSP file_sp)79 void SetImmediateOutputFile(lldb::FileSP file_sp) { 80 if (m_suppress_immediate_output) 81 return; 82 lldb::StreamSP stream_sp(new StreamFile(file_sp)); 83 m_out_stream.SetStreamAtIndex(eImmediateStreamIndex, stream_sp); 84 } 85 SetImmediateErrorFile(lldb::FileSP file_sp)86 void SetImmediateErrorFile(lldb::FileSP file_sp) { 87 if (m_suppress_immediate_output) 88 return; 89 lldb::StreamSP stream_sp(new StreamFile(file_sp)); 90 m_err_stream.SetStreamAtIndex(eImmediateStreamIndex, stream_sp); 91 } 92 SetImmediateOutputStream(const lldb::StreamSP & stream_sp)93 void SetImmediateOutputStream(const lldb::StreamSP &stream_sp) { 94 if (m_suppress_immediate_output) 95 return; 96 m_out_stream.SetStreamAtIndex(eImmediateStreamIndex, stream_sp); 97 } 98 SetImmediateErrorStream(const lldb::StreamSP & stream_sp)99 void SetImmediateErrorStream(const lldb::StreamSP &stream_sp) { 100 if (m_suppress_immediate_output) 101 return; 102 m_err_stream.SetStreamAtIndex(eImmediateStreamIndex, stream_sp); 103 } 104 GetImmediateOutputStream()105 lldb::StreamSP GetImmediateOutputStream() const { 106 return m_out_stream.GetStreamAtIndex(eImmediateStreamIndex); 107 } 108 GetImmediateErrorStream()109 lldb::StreamSP GetImmediateErrorStream() const { 110 return m_err_stream.GetStreamAtIndex(eImmediateStreamIndex); 111 } 112 113 void Clear(); 114 115 void AppendMessage(llvm::StringRef in_string); 116 117 void AppendMessageWithFormat(const char *format, ...) 118 __attribute__((format(printf, 2, 3))); 119 120 void AppendNote(llvm::StringRef in_string); 121 122 void AppendNoteWithFormat(const char *format, ...) 123 __attribute__((format(printf, 2, 3))); 124 125 void AppendWarning(llvm::StringRef in_string); 126 127 void AppendWarningWithFormat(const char *format, ...) 128 __attribute__((format(printf, 2, 3))); 129 130 void AppendError(llvm::StringRef in_string); 131 132 void AppendRawError(llvm::StringRef in_string); 133 134 void AppendErrorWithFormat(const char *format, ...) 135 __attribute__((format(printf, 2, 3))); 136 137 template <typename... Args> AppendMessageWithFormatv(const char * format,Args &&...args)138 void AppendMessageWithFormatv(const char *format, Args &&...args) { 139 AppendMessage(llvm::formatv(format, std::forward<Args>(args)...).str()); 140 } 141 142 template <typename... Args> AppendNoteWithFormatv(const char * format,Args &&...args)143 void AppendNoteWithFormatv(const char *format, Args &&...args) { 144 AppendNote(llvm::formatv(format, std::forward<Args>(args)...).str()); 145 } 146 147 template <typename... Args> AppendWarningWithFormatv(const char * format,Args &&...args)148 void AppendWarningWithFormatv(const char *format, Args &&...args) { 149 AppendWarning(llvm::formatv(format, std::forward<Args>(args)...).str()); 150 } 151 152 template <typename... Args> AppendErrorWithFormatv(const char * format,Args &&...args)153 void AppendErrorWithFormatv(const char *format, Args &&...args) { 154 AppendError(llvm::formatv(format, std::forward<Args>(args)...).str()); 155 } 156 157 void SetError(Status error); 158 159 void SetError(llvm::Error error); 160 SetDiagnosticIndent(std::optional<uint16_t> indent)161 void SetDiagnosticIndent(std::optional<uint16_t> indent) { 162 m_diagnostic_indent = indent; 163 } 164 GetDiagnosticIndent()165 std::optional<uint16_t> GetDiagnosticIndent() const { 166 return m_diagnostic_indent; 167 } 168 GetValueObjectList()169 const ValueObjectList &GetValueObjectList() const { return m_value_objects; } 170 GetValueObjectList()171 ValueObjectList &GetValueObjectList() { return m_value_objects; } 172 173 lldb::ReturnStatus GetStatus() const; 174 175 void SetStatus(lldb::ReturnStatus status); 176 177 bool Succeeded() const; 178 179 bool HasResult() const; 180 181 bool GetDidChangeProcessState() const; 182 183 void SetDidChangeProcessState(bool b); 184 185 bool GetInteractive() const; 186 187 void SetInteractive(bool b); 188 189 bool GetSuppressImmediateOutput() const; 190 191 void SetSuppressImmediateOutput(bool b); 192 193 private: 194 enum { eStreamStringIndex = 0, eImmediateStreamIndex = 1 }; 195 196 std::string m_command; 197 198 StreamTee m_out_stream; 199 StreamTee m_err_stream; 200 std::vector<DiagnosticDetail> m_diagnostics; 201 std::optional<uint16_t> m_diagnostic_indent; 202 203 lldb::ReturnStatus m_status = lldb::eReturnStatusStarted; 204 205 /// An optionally empty list of values produced by this command. 206 ValueObjectList m_value_objects; 207 208 bool m_did_change_process_state = false; 209 bool m_suppress_immediate_output = false; 210 211 /// If true, then the input handle from the debugger will be hooked up. 212 bool m_interactive = true; 213 bool m_colors; 214 }; 215 216 } // namespace lldb_private 217 218 #endif // LLDB_INTERPRETER_COMMANDRETURNOBJECT_H 219