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_DAP_JSONUTILS_H
10#define LLDB_TOOLS_LLDB_DAP_JSONUTILS_H
11
12#include "BreakpointBase.h"
13#include "DAPForward.h"
14#include "lldb/API/SBModule.h"
15#include "llvm/ADT/StringRef.h"
16#include "llvm/Support/JSON.h"
17#include <cstdint>
18#include <optional>
19
20namespace lldb_dap {
21
22/// Emplace a StringRef in a json::Object after enusring that the
23/// string is valid UTF8. If not, first call llvm::json::fixUTF8
24/// before emplacing.
25///
26/// \param[in] obj
27/// A JSON object that we will attempt to emplace the value in
28///
29/// \param[in] key
30/// The key to use when emplacing the value
31///
32/// \param[in] str
33/// The string to emplace
34void EmplaceSafeString(llvm::json::Object &obj, llvm::StringRef key,
35 llvm::StringRef str);
36
37/// Extract simple values as a string.
38///
39/// \param[in] value
40/// A JSON value to extract the string from.
41///
42/// \return
43/// A llvm::StringRef that contains the string value, or an empty
44/// string if \a value isn't a string.
45llvm::StringRef GetAsString(const llvm::json::Value &value);
46
47/// Extract the string value for the specified key from the
48/// specified object.
49///
50/// \param[in] obj
51/// A JSON object that we will attempt to extract the value from
52///
53/// \param[in] key
54/// The key to use when extracting the value
55///
56/// \param[in] defaultValue
57/// The default value to return if the key is not present
58///
59/// \return
60/// A llvm::StringRef that contains the string value for the
61/// specified \a key, or the default value if there is no key that
62/// matches or if the value is not a string.
63llvm::StringRef GetString(const llvm::json::Object &obj, llvm::StringRef key,
64 llvm::StringRef defaultValue = {});
65llvm::StringRef GetString(const llvm::json::Object *obj, llvm::StringRef key,
66 llvm::StringRef defaultValue = {});
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.
81uint64_t GetUnsigned(const llvm::json::Object &obj, llvm::StringRef key,
82 uint64_t fail_value);
83uint64_t GetUnsigned(const llvm::json::Object *obj, llvm::StringRef key,
84 uint64_t fail_value);
85
86/// Extract the boolean value for the specified key from the
87/// specified object.
88///
89/// \param[in] obj
90/// A JSON object that we will attempt to extract the value from
91///
92/// \param[in] key
93/// The key to use when extracting the value
94///
95/// \return
96/// The boolean value for the specified \a key, or \a fail_value
97/// if there is no key that matches or if the value is not a
98/// boolean value of an integer.
99bool GetBoolean(const llvm::json::Object &obj, llvm::StringRef key,
100 bool fail_value);
101bool GetBoolean(const llvm::json::Object *obj, llvm::StringRef key,
102 bool fail_value);
103
104/// Extract the signed integer for the specified key from the
105/// specified object.
106///
107/// \param[in] obj
108/// A JSON object that we will attempt to extract the value from
109///
110/// \param[in] key
111/// The key to use when extracting the value
112///
113/// \return
114/// The signed integer value for the specified \a key, or
115/// \a fail_value if there is no key that matches or if the
116/// value is not an integer.
117int64_t GetSigned(const llvm::json::Object &obj, llvm::StringRef key,
118 int64_t fail_value);
119int64_t GetSigned(const llvm::json::Object *obj, llvm::StringRef key,
120 int64_t fail_value);
121
122/// Check if the specified key exists in the specified object.
123///
124/// \param[in] obj
125/// A JSON object that we will attempt to extract the value from
126///
127/// \param[in] key
128/// The key to check for
129///
130/// \return
131/// \b True if the key exists in the \a obj, \b False otherwise.
132bool ObjectContainsKey(const llvm::json::Object &obj, llvm::StringRef key);
133
134/// Extract an array of strings for the specified key from an object.
135///
136/// String values in the array will be extracted without any quotes
137/// around them. Numbers and Booleans will be converted into
138/// strings. Any NULL, array or objects values in the array will be
139/// ignored.
140///
141/// \param[in] obj
142/// A JSON object that we will attempt to extract the array from
143///
144/// \param[in] key
145/// The key to use when extracting the value
146///
147/// \return
148/// An array of string values for the specified \a key, or
149/// \a fail_value if there is no key that matches or if the
150/// value is not an array or all items in the array are not
151/// strings, numbers or booleans.
152std::vector<std::string> GetStrings(const llvm::json::Object *obj,
153 llvm::StringRef key);
154
155/// Fill a response object given the request object.
156///
157/// The \a response object will get its "type" set to "response",
158/// the "seq" set to zero, "response_seq" set to the "seq" value from
159/// \a request, "command" set to the "command" from \a request,
160/// and "success" set to true.
161///
162/// \param[in] request
163/// The request object received from a call to DAP::ReadJSON().
164///
165/// \param[in,out] response
166/// An empty llvm::json::Object object that will be filled
167/// in as noted in description.
168void FillResponse(const llvm::json::Object &request,
169 llvm::json::Object &response);
170
171/// Converts \a bp to a JSON value and appends the first valid location to the
172/// \a breakpoints array.
173///
174/// \param[in] bp
175/// A LLDB breakpoint object which will get the first valid location
176/// extracted and converted into a JSON object in the \a breakpoints array
177///
178/// \param[in] breakpoints
179/// A JSON array that will get a llvm::json::Value for \a bp
180/// appended to it.
181///
182/// \param[in] request_path
183/// An optional source path to use when creating the "Source" object of this
184/// breakpoint. If not specified, the "Source" object is created from the
185/// breakpoint's address' LineEntry. It is useful to ensure the same source
186/// paths provided by the setBreakpoints request are returned to the IDE.
187///
188/// \param[in] request_line
189/// An optional line to use when creating the "Breakpoint" object to append.
190/// It is used if the breakpoint has no valid locations.
191/// It is useful to ensure the same line
192/// provided by the setBreakpoints request are returned to the IDE as a
193/// fallback.
194void AppendBreakpoint(
195 BreakpointBase *bp, llvm::json::Array &breakpoints,
196 std::optional<llvm::StringRef> request_path = std::nullopt,
197 std::optional<uint32_t> request_line = std::nullopt);
198
199/// Converts breakpoint location to a debug adaptor protocol "Breakpoint".
200///
201/// \param[in] bp
202/// A LLDB breakpoint object to convert into a JSON value
203///
204/// \param[in] request_path
205/// An optional source path to use when creating the "Source" object of this
206/// breakpoint. If not specified, the "Source" object is created from the
207/// breakpoint's address' LineEntry. It is useful to ensure the same source
208/// paths provided by the setBreakpoints request are returned to the IDE.
209///
210/// \param[in] request_line
211/// An optional line to use when creating the resulting "Breakpoint" object.
212/// It is used if the breakpoint has no valid locations.
213/// It is useful to ensure the same line
214/// provided by the setBreakpoints request are returned to the IDE as a
215/// fallback.
216///
217/// \param[in] request_column
218/// An optional column to use when creating the resulting "Breakpoint"
219/// object. It is used if the breakpoint has no valid locations. It is
220/// useful to ensure the same column provided by the setBreakpoints request
221/// are returned to the IDE as a fallback.
222///
223/// \return
224/// A "Breakpoint" JSON object with that follows the formal JSON
225/// definition outlined by Microsoft.
226llvm::json::Value
227CreateBreakpoint(BreakpointBase *bp,
228 std::optional<llvm::StringRef> request_path = std::nullopt,
229 std::optional<uint32_t> request_line = std::nullopt,
230 std::optional<uint32_t> request_column = std::nullopt);
231
232/// Converts a LLDB module to a VS Code DAP module for use in "modules" events.
233///
234/// \param[in] module
235/// A LLDB module object to convert into a JSON value
236///
237/// \return
238/// A "Module" JSON object with that follows the formal JSON
239/// definition outlined by Microsoft.
240llvm::json::Value CreateModule(lldb::SBModule &module);
241
242/// Create a "Event" JSON object using \a event_name as the event name
243///
244/// \param[in] event_name
245/// The string value to use for the "event" key in the JSON object.
246///
247/// \return
248/// A "Event" JSON object with that follows the formal JSON
249/// definition outlined by Microsoft.
250llvm::json::Object CreateEventObject(const llvm::StringRef event_name);
251
252/// Create a "ExceptionBreakpointsFilter" JSON object as described in
253/// the debug adaptor definition.
254///
255/// \param[in] bp
256/// The exception breakpoint object to use
257///
258/// \return
259/// A "ExceptionBreakpointsFilter" JSON object with that follows
260/// the formal JSON definition outlined by Microsoft.
261llvm::json::Value
262CreateExceptionBreakpointFilter(const ExceptionBreakpoint &bp);
263
264/// Create a "Scope" JSON object as described in the debug adaptor definition.
265///
266/// \param[in] name
267/// The value to place into the "name" key
268//
269/// \param[in] variablesReference
270/// The value to place into the "variablesReference" key
271//
272/// \param[in] namedVariables
273/// The value to place into the "namedVariables" key
274//
275/// \param[in] expensive
276/// The value to place into the "expensive" key
277///
278/// \return
279/// A "Scope" JSON object with that follows the formal JSON
280/// definition outlined by Microsoft.
281llvm::json::Value CreateScope(const llvm::StringRef name,
282 int64_t variablesReference,
283 int64_t namedVariables, bool expensive);
284
285/// Create a "Source" JSON object as described in the 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.
294llvm::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.
304llvm::json::Value CreateSource(llvm::StringRef source_path);
305
306/// Create a "StackFrame" object for a LLDB frame object.
307///
308/// This function will fill in the following keys in the returned
309/// object:
310/// "id" - the stack frame ID as an integer
311/// "name" - the function name as a string
312/// "source" - source file information as a "Source" DAP object
313/// "line" - the source file line number as an integer
314/// "column" - the source file column number as an integer
315///
316/// \param[in] frame
317/// The LLDB stack frame to use when populating out the "StackFrame"
318/// object.
319///
320/// \return
321/// A "StackFrame" JSON object with that follows the formal JSON
322/// definition outlined by Microsoft.
323llvm::json::Value CreateStackFrame(lldb::SBFrame &frame);
324
325/// Create a "Thread" object for a LLDB thread object.
326///
327/// This function will fill in the following keys in the returned
328/// object:
329/// "id" - the thread ID as an integer
330/// "name" - the thread name as a string which combines the LLDB
331/// thread index ID along with the string name of the thread
332/// from the OS if it has a name.
333///
334/// \param[in] thread
335/// The LLDB thread to use when populating out the "Thread"
336/// object.
337///
338/// \return
339/// A "Thread" JSON object with that follows the formal JSON
340/// definition outlined by Microsoft.
341llvm::json::Value CreateThread(lldb::SBThread &thread);
342
343/// Create a "StoppedEvent" object for a LLDB thread object.
344///
345/// This function will fill in the following keys in the returned
346/// object's "body" object:
347/// "reason" - With a valid stop reason enumeration string value
348/// that Microsoft specifies
349/// "threadId" - The thread ID as an integer
350/// "description" - a stop description (like "breakpoint 12.3") as a
351/// string
352/// "preserveFocusHint" - a boolean value that states if this thread
353/// should keep the focus in the GUI.
354/// "allThreadsStopped" - set to True to indicate that all threads
355/// stop when any thread stops.
356///
357/// \param[in] thread
358/// The LLDB thread to use when populating out the "StoppedEvent"
359/// object.
360///
361/// \return
362/// A "StoppedEvent" JSON object with that follows the formal JSON
363/// definition outlined by Microsoft.
364llvm::json::Value CreateThreadStopped(lldb::SBThread &thread, uint32_t stop_id);
365
366/// \return
367/// The variable name of \a value or a default placeholder.
368const char *GetNonNullVariableName(lldb::SBValue value);
369
370/// VSCode can't display two variables with the same name, so we need to
371/// distinguish them by using a suffix.
372///
373/// If the source and line information is present, we use it as the suffix.
374/// Otherwise, we fallback to the variable address or register location.
375std::string CreateUniqueVariableNameForDisplay(lldb::SBValue v,
376 bool is_name_duplicated);
377
378/// Helper struct that parses the metadata of an \a lldb::SBValue and produces
379/// a canonical set of properties that can be sent to DAP clients.
380struct VariableDescription {
381 // The error message if SBValue.GetValue() fails.
382 std::optional<std::string> error;
383 // The display description to show on the IDE.
384 std::string display_value;
385 // The display name to show on the IDE.
386 std::string name;
387 // The variable path for this variable.
388 std::string evaluate_name;
389 // The output of SBValue.GetValue() if it doesn't fail. It might be empty.
390 std::string value;
391 // The summary string of this variable. It might be empty.
392 std::string summary;
393 // The auto summary if using `enableAutoVariableSummaries`.
394 std::optional<std::string> auto_summary;
395 // The type of this variable.
396 lldb::SBType type_obj;
397 // The display type name of this variable.
398 std::string display_type_name;
399 /// The SBValue for this variable.
400 lldb::SBValue v;
401
402 VariableDescription(lldb::SBValue v, bool format_hex = false,
403 bool is_name_duplicated = false,
404 std::optional<std::string> custom_name = {});
405
406 /// Create a JSON object that represents these extensions to the DAP variable
407 /// response.
408 llvm::json::Object GetVariableExtensionsJSON();
409
410 /// Returns a description of the value appropriate for the specified context.
411 std::string GetResult(llvm::StringRef context);
412};
413
414/// Create a "Variable" object for a LLDB thread object.
415///
416/// This function will fill in the following keys in the returned
417/// object:
418/// "name" - the name of the variable
419/// "value" - the value of the variable as a string
420/// "type" - the typename of the variable as a string
421/// "id" - a unique identifier for a value in case there are multiple
422/// variables with the same name. Other parts of the DAP
423/// protocol refer to values by name so this can help
424/// disambiguate such cases if a IDE passes this "id" value
425/// back down.
426/// "variablesReference" - Zero if the variable has no children,
427/// non-zero integer otherwise which can be used to expand
428/// the variable.
429/// "evaluateName" - The name of the variable to use in expressions
430/// as a string.
431///
432/// \param[in] v
433/// The LLDB value to use when populating out the "Variable"
434/// object.
435///
436/// \param[in] variablesReference
437/// The variable reference. Zero if this value isn't structured
438/// and has no children, non-zero if it does have children and
439/// might be asked to expand itself.
440///
441/// \param[in] varID
442/// A unique variable identifier to help in properly identifying
443/// variables with the same name. This is an extension to the
444/// VS protocol.
445///
446/// \param[in] format_hex
447/// It set to true the variable will be formatted as hex in
448/// the "value" key value pair for the value of the variable.
449///
450/// \param[in] is_name_duplicated
451/// Whether the same variable name appears multiple times within the same
452/// context (e.g. locals). This can happen due to shadowed variables in
453/// nested blocks.
454///
455/// As VSCode doesn't render two of more variables with the same name, we
456/// apply a suffix to distinguish duplicated variables.
457///
458/// \param[in] custom_name
459/// A provided custom name that is used instead of the SBValue's when
460/// creating the JSON representation.
461///
462/// \return
463/// A "Variable" JSON object with that follows the formal JSON
464/// definition outlined by Microsoft.
465llvm::json::Value CreateVariable(lldb::SBValue v, int64_t variablesReference,
466 int64_t varID, bool format_hex,
467 bool is_name_duplicated = false,
468 std::optional<std::string> custom_name = {});
469
470llvm::json::Value CreateCompileUnit(lldb::SBCompileUnit unit);
471
472/// Create a runInTerminal reverse request object
473///
474/// \param[in] launch_request
475/// The original launch_request object whose fields are used to construct
476/// the reverse request object.
477///
478/// \param[in] debug_adaptor_path
479/// Path to the current debug adaptor. It will be used to delegate the
480/// launch of the target.
481///
482/// \param[in] comm_file
483/// The fifo file used to communicate the with the target launcher.
484///
485/// \param[in] debugger_pid
486/// The PID of the lldb-dap instance that will attach to the target. The
487/// launcher uses it on Linux tell the kernel that it should allow the
488/// debugger process to attach.
489///
490/// \return
491/// A "runInTerminal" JSON object that follows the specification outlined by
492/// Microsoft.
493llvm::json::Object
494CreateRunInTerminalReverseRequest(const llvm::json::Object &launch_request,
495 llvm::StringRef debug_adaptor_path,
496 llvm::StringRef comm_file,
497 lldb::pid_t debugger_pid);
498
499/// Create a "Terminated" JSON object that contains statistics
500///
501/// \return
502/// A body JSON object with debug info and breakpoint info
503llvm::json::Object CreateTerminatedEventObject();
504
505/// Convert a given JSON object to a string.
506std::string JSONToString(const llvm::json::Value &json);
507
508} // namespace lldb_dap
509
510#endif
511

source code of lldb/tools/lldb-dap/JSONUtils.h