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