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