1 //===-- JSONUtils.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_TOOLS_LLDB_VSCODE_JSONUTILS_H 10 #define LLDB_TOOLS_LLDB_VSCODE_JSONUTILS_H 11 12 #include <stdint.h> 13 #include "llvm/ADT/StringRef.h" 14 #include "llvm/Support/JSON.h" 15 #include "VSCodeForward.h" 16 17 namespace lldb_vscode { 18 19 /// Emplace a StringRef in a json::Object after enusring that the 20 /// string is valid UTF8. If not, first call llvm::json::fixUTF8 21 /// before emplacing. 22 /// 23 /// \param[in] obj 24 /// A JSON object that we will attempt to emplace the value in 25 /// 26 /// \param[in] key 27 /// The key to use when emplacing the value 28 /// 29 /// \param[in] str 30 /// The string to emplace 31 void EmplaceSafeString(llvm::json::Object &obj, llvm::StringRef key, 32 llvm::StringRef str); 33 34 /// Extract simple values as a string. 35 /// 36 /// \param[in] value 37 /// A JSON value to extract the string from. 38 /// 39 /// \return 40 /// A llvm::StringRef that contains the string value, or an empty 41 /// string if \a value isn't a string. 42 llvm::StringRef GetAsString(const llvm::json::Value &value); 43 44 /// Extract the string value for the specified key from the 45 /// specified object. 46 /// 47 /// \param[in] obj 48 /// A JSON object that we will attempt to extract the value from 49 /// 50 /// \param[in] key 51 /// The key to use when extracting the value 52 /// 53 /// \return 54 /// A llvm::StringRef that contains the string value for the 55 /// specified \a key, or an empty string if there is no key that 56 /// matches or if the value is not a string. 57 llvm::StringRef GetString(const llvm::json::Object &obj, llvm::StringRef key); 58 llvm::StringRef GetString(const llvm::json::Object *obj, llvm::StringRef key); 59 60 /// Extract the unsigned integer value for the specified key from 61 /// the specified object. 62 /// 63 /// \param[in] obj 64 /// A JSON object that we will attempt to extract the value from 65 /// 66 /// \param[in] key 67 /// The key to use when extracting the value 68 /// 69 /// \return 70 /// The unsigned integer value for the specified \a key, or 71 /// \a fail_value if there is no key that matches or if the 72 /// value is not an integer. 73 uint64_t GetUnsigned(const llvm::json::Object &obj, llvm::StringRef key, 74 uint64_t fail_value); 75 uint64_t GetUnsigned(const llvm::json::Object *obj, llvm::StringRef key, 76 uint64_t fail_value); 77 78 /// Extract the boolean value for the specified key from the 79 /// specified object. 80 /// 81 /// \param[in] obj 82 /// A JSON object that we will attempt to extract the value from 83 /// 84 /// \param[in] key 85 /// The key to use when extracting the value 86 /// 87 /// \return 88 /// The boolean value for the specified \a key, or \a fail_value 89 /// if there is no key that matches or if the value is not a 90 /// boolean value of an integer. 91 bool GetBoolean(const llvm::json::Object &obj, llvm::StringRef key, 92 bool fail_value); 93 bool GetBoolean(const llvm::json::Object *obj, llvm::StringRef key, 94 bool fail_value); 95 96 /// Extract the signed integer for the specified key from the 97 /// specified object. 98 /// 99 /// \param[in] obj 100 /// A JSON object that we will attempt to extract the value from 101 /// 102 /// \param[in] key 103 /// The key to use when extracting the value 104 /// 105 /// \return 106 /// The signed integer value for the specified \a key, or 107 /// \a fail_value if there is no key that matches or if the 108 /// value is not an integer. 109 int64_t GetSigned(const llvm::json::Object &obj, llvm::StringRef key, 110 int64_t fail_value); 111 int64_t GetSigned(const llvm::json::Object *obj, llvm::StringRef key, 112 int64_t fail_value); 113 114 /// Check if the specified key exists in the specified object. 115 /// 116 /// \param[in] obj 117 /// A JSON object that we will attempt to extract the value from 118 /// 119 /// \param[in] key 120 /// The key to check for 121 /// 122 /// \return 123 /// \b True if the key exists in the \a obj, \b False otherwise. 124 bool ObjectContainsKey(const llvm::json::Object &obj, llvm::StringRef key); 125 126 /// Extract an array of strings for the specified key from an object. 127 /// 128 /// String values in the array will be extracted without any quotes 129 /// around them. Numbers and Booleans will be converted into 130 /// strings. Any NULL, array or objects values in the array will be 131 /// ignored. 132 /// 133 /// \param[in] obj 134 /// A JSON object that we will attempt to extract the array from 135 /// 136 /// \param[in] key 137 /// The key to use when extracting the value 138 /// 139 /// \return 140 /// An array of string values for the specified \a key, or 141 /// \a fail_value if there is no key that matches or if the 142 /// value is not an array or all items in the array are not 143 /// strings, numbers or booleans. 144 std::vector<std::string> GetStrings(const llvm::json::Object *obj, 145 llvm::StringRef key); 146 147 /// Fill a response object given the request object. 148 /// 149 /// The \a response object will get its "type" set to "response", 150 /// the "seq" set to zero, "response_seq" set to the "seq" value from 151 /// \a request, "command" set to the "command" from \a request, 152 /// and "success" set to true. 153 /// 154 /// \param[in] request 155 /// The request object received from a call to VSCode::ReadJSON(). 156 /// 157 /// \param[in,out] response 158 /// An empty llvm::json::Object object that will be filled 159 /// in as noted in description. 160 void FillResponse(const llvm::json::Object &request, 161 llvm::json::Object &response); 162 163 /// Emplace the string value from an SBValue into the supplied object 164 /// using \a key as the key that will contain the value. 165 /// 166 /// The value is what we will display in VS Code. Some SBValue objects 167 /// can have a value and/or a summary. If a value has both, we 168 /// combine the value and the summary into one string. If we only have a 169 /// value or summary, then that is considered the value. If there is 170 /// no value and no summary then the value is the type name followed by 171 /// the address of the type if it has an address. 172 /// 173 /// 174 /// \param[in] v 175 /// A lldb::SBValue object to extract the string value from 176 /// 177 /// 178 /// \param[in] object 179 /// The object to place the value object into 180 /// 181 /// 182 /// \param[in] key 183 /// The key name to use when inserting the value object we create 184 void SetValueForKey(lldb::SBValue &v, llvm::json::Object &object, 185 llvm::StringRef key); 186 187 /// Converts \a bp to a JSON value and appends the first valid location to the 188 /// \a breakpoints array. 189 /// 190 /// \param[in] bp 191 /// A LLDB breakpoint object which will get the first valid location 192 /// extracted and converted into a JSON object in the \a breakpoints array 193 /// 194 /// \param[in] breakpoints 195 /// A JSON array that will get a llvm::json::Value for \a bp 196 /// appended to it. 197 /// 198 /// \param[in] request_path 199 /// An optional source path to use when creating the "Source" object of this 200 /// breakpoint. If not specified, the "Source" object is created from the 201 /// breakpoint's address' LineEntry. It is useful to ensure the same source 202 /// paths provided by the setBreakpoints request are returned to the IDE. 203 /// 204 /// \param[in] request_line 205 /// An optional line to use when creating the "Breakpoint" object to append. 206 /// It is used if the breakpoint has no valid locations. 207 /// It is useful to ensure the same line 208 /// provided by the setBreakpoints request are returned to the IDE as a 209 /// fallback. 210 void AppendBreakpoint(lldb::SBBreakpoint &bp, llvm::json::Array &breakpoints, 211 llvm::Optional<llvm::StringRef> request_path = llvm::None, 212 llvm::Optional<uint32_t> request_line = llvm::None); 213 214 /// Converts breakpoint location to a Visual Studio Code "Breakpoint" 215 /// 216 /// \param[in] bp 217 /// A LLDB breakpoint object to convert into a JSON value 218 /// 219 /// \param[in] request_path 220 /// An optional source path to use when creating the "Source" object of this 221 /// breakpoint. If not specified, the "Source" object is created from the 222 /// breakpoint's address' LineEntry. It is useful to ensure the same source 223 /// paths provided by the setBreakpoints request are returned to the IDE. 224 /// 225 /// \param[in] request_line 226 /// An optional line to use when creating the resulting "Breakpoint" object. 227 /// It is used if the breakpoint has no valid locations. 228 /// It is useful to ensure the same line 229 /// provided by the setBreakpoints request are returned to the IDE as a 230 /// fallback. 231 /// 232 /// \return 233 /// A "Breakpoint" JSON object with that follows the formal JSON 234 /// definition outlined by Microsoft. 235 llvm::json::Value 236 CreateBreakpoint(lldb::SBBreakpoint &bp, 237 llvm::Optional<llvm::StringRef> request_path = llvm::None, 238 llvm::Optional<uint32_t> request_line = llvm::None); 239 240 /// Create a "Event" JSON object using \a event_name as the event name 241 /// 242 /// \param[in] event_name 243 /// The string value to use for the "event" key in the JSON object. 244 /// 245 /// \return 246 /// A "Event" JSON object with that follows the formal JSON 247 /// definition outlined by Microsoft. 248 llvm::json::Object CreateEventObject(const llvm::StringRef event_name); 249 250 /// Create a "ExceptionBreakpointsFilter" JSON object as described in 251 /// the Visual Studio Code debug adaptor definition. 252 /// 253 /// \param[in] bp 254 /// The exception breakpoint object to use 255 /// 256 /// \return 257 /// A "ExceptionBreakpointsFilter" JSON object with that follows 258 /// the formal JSON definition outlined by Microsoft. 259 llvm::json::Value 260 CreateExceptionBreakpointFilter(const ExceptionBreakpoint &bp); 261 262 /// Create a "Scope" JSON object as described in the Visual Studio Code 263 /// debug adaptor definition. 264 /// 265 /// \param[in] name 266 /// The value to place into the "name" key 267 // 268 /// \param[in] variablesReference 269 /// The value to place into the "variablesReference" key 270 // 271 /// \param[in] namedVariables 272 /// The value to place into the "namedVariables" key 273 // 274 /// \param[in] expensive 275 /// The value to place into the "expensive" key 276 /// 277 /// \return 278 /// A "Scope" JSON object with that follows the formal JSON 279 /// definition outlined by Microsoft. 280 llvm::json::Value CreateScope(const llvm::StringRef name, 281 int64_t variablesReference, 282 int64_t namedVariables, bool expensive); 283 284 /// Create a "Source" JSON object as described in the Visual Studio Code 285 /// debug adaptor definition. 286 /// 287 /// \param[in] line_entry 288 /// The LLDB line table to use when populating out the "Source" 289 /// object 290 /// 291 /// \return 292 /// A "Source" JSON object with that follows the formal JSON 293 /// definition outlined by Microsoft. 294 llvm::json::Value CreateSource(lldb::SBLineEntry &line_entry); 295 296 /// Create a "Source" object for a given source path. 297 /// 298 /// \param[in] source_path 299 /// The path to the source to use when creating the "Source" object. 300 /// 301 /// \return 302 /// A "Source" JSON object that follows the formal JSON 303 /// definition outlined by Microsoft. 304 llvm::json::Value CreateSource(llvm::StringRef source_path); 305 306 /// Create a "Source" object for a given frame. 307 /// 308 /// When there is no source file information for a stack frame, we will 309 /// create disassembly for a function and store a permanent 310 /// "sourceReference" that contains the textual disassembly for a 311 /// function along with address to line information. The "Source" object 312 /// that is created will contain a "sourceReference" that the VSCode 313 /// protocol can later fetch as text in order to display disassembly. 314 /// The PC will be extracted from the frame and the disassembly line 315 /// within the source referred to by "sourceReference" will be filled 316 /// in. 317 /// 318 /// \param[in] frame 319 /// The LLDB stack frame to use when populating out the "Source" 320 /// object. 321 /// 322 /// \param[out] disasm_line 323 /// The line within the "sourceReference" file that the PC from 324 /// \a frame matches. 325 /// 326 /// \return 327 /// A "Source" JSON object with that follows the formal JSON 328 /// definition outlined by Microsoft. 329 llvm::json::Value CreateSource(lldb::SBFrame &frame, int64_t &disasm_line); 330 331 /// Create a "StackFrame" object for a LLDB frame object. 332 /// 333 /// This function will fill in the following keys in the returned 334 /// object: 335 /// "id" - the stack frame ID as an integer 336 /// "name" - the function name as a string 337 /// "source" - source file information as a "Source" VSCode object 338 /// "line" - the source file line number as an integer 339 /// "column" - the source file column number as an integer 340 /// 341 /// \param[in] frame 342 /// The LLDB stack frame to use when populating out the "StackFrame" 343 /// object. 344 /// 345 /// \return 346 /// A "StackFrame" JSON object with that follows the formal JSON 347 /// definition outlined by Microsoft. 348 llvm::json::Value CreateStackFrame(lldb::SBFrame &frame); 349 350 /// Create a "Thread" object for a LLDB thread object. 351 /// 352 /// This function will fill in the following keys in the returned 353 /// object: 354 /// "id" - the thread ID as an integer 355 /// "name" - the thread name as a string which combines the LLDB 356 /// thread index ID along with the string name of the thread 357 /// from the OS if it has a name. 358 /// 359 /// \param[in] thread 360 /// The LLDB thread to use when populating out the "Thread" 361 /// object. 362 /// 363 /// \return 364 /// A "Thread" JSON object with that follows the formal JSON 365 /// definition outlined by Microsoft. 366 llvm::json::Value CreateThread(lldb::SBThread &thread); 367 368 /// Create a "StoppedEvent" object for a LLDB thread object. 369 /// 370 /// This function will fill in the following keys in the returned 371 /// object's "body" object: 372 /// "reason" - With a valid stop reason enumeration string value 373 /// that Microsoft specifies 374 /// "threadId" - The thread ID as an integer 375 /// "description" - a stop description (like "breakpoint 12.3") as a 376 /// string 377 /// "preserveFocusHint" - a boolean value that states if this thread 378 /// should keep the focus in the GUI. 379 /// "allThreadsStopped" - set to True to indicate that all threads 380 /// stop when any thread stops. 381 /// 382 /// \param[in] thread 383 /// The LLDB thread to use when populating out the "StoppedEvent" 384 /// object. 385 /// 386 /// \return 387 /// A "StoppedEvent" JSON object with that follows the formal JSON 388 /// definition outlined by Microsoft. 389 llvm::json::Value CreateThreadStopped(lldb::SBThread &thread, uint32_t stop_id); 390 391 /// Create a "Variable" object for a LLDB thread object. 392 /// 393 /// This function will fill in the following keys in the returned 394 /// object: 395 /// "name" - the name of the variable 396 /// "value" - the value of the variable as a string 397 /// "type" - the typename of the variable as a string 398 /// "id" - a unique identifier for a value in case there are multiple 399 /// variables with the same name. Other parts of the VSCode 400 /// protocol refer to values by name so this can help 401 /// disambiguate such cases if a IDE passes this "id" value 402 /// back down. 403 /// "variablesReference" - Zero if the variable has no children, 404 /// non-zero integer otherwise which can be used to expand 405 /// the variable. 406 /// "evaluateName" - The name of the variable to use in expressions 407 /// as a string. 408 /// 409 /// \param[in] v 410 /// The LLDB value to use when populating out the "Variable" 411 /// object. 412 /// 413 /// \param[in] variablesReference 414 /// The variable reference. Zero if this value isn't structured 415 /// and has no children, non-zero if it does have children and 416 /// might be asked to expand itself. 417 /// 418 /// \param[in] varID 419 /// A unique variable identifier to help in properly identifying 420 /// variables with the same name. This is an extension to the 421 /// VS protocol. 422 /// 423 /// \param[in] format_hex 424 /// It set to true the variable will be formatted as hex in 425 /// the "value" key value pair for the value of the variable. 426 /// 427 /// \return 428 /// A "Variable" JSON object with that follows the formal JSON 429 /// definition outlined by Microsoft. 430 llvm::json::Value CreateVariable(lldb::SBValue v, int64_t variablesReference, 431 int64_t varID, bool format_hex); 432 433 } // namespace lldb_vscode 434 435 #endif 436