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