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