Skip to content

Commit a2c0f32

Browse files
walter-erquinigoadrian-prantl
authored andcommitted
[lldb-vscode] Make descriptive summaries and raw child for synthetics configurable (llvm#65687)
"descriptive summaries" should only be used for small to medium binaries because of the performance penalty the cause when completing types. I'm defaulting it to false. Besides that, the "raw child" for synthetics should be optional as well. I'm defaulting it to false. Both options can be set via a launch or attach config, following the pattern of most settings. javascript extension wrappers can set these settings on their own as well. (cherry picked from commit a2a9918)
1 parent 49235a4 commit a2c0f32

File tree

9 files changed

+148
-30
lines changed

9 files changed

+148
-30
lines changed

lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/lldbvscode_testcase.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
from lldbsuite.test.lldbtest import *
21
import os
3-
import vscode
42
import time
53

4+
import vscode
5+
from lldbsuite.test.lldbtest import *
6+
67

78
class VSCodeTestCaseBase(TestBase):
89
NO_DEBUG_INFO_TESTCASE = True
@@ -267,7 +268,7 @@ def disassemble(self, threadId=None, frameIndex=None):
267268

268269
if memoryReference not in self.vscode.disassembled_instructions:
269270
self.vscode.request_disassemble(memoryReference=memoryReference)
270-
271+
271272
return self.vscode.disassembled_instructions[memoryReference]
272273

273274
def attach(
@@ -348,6 +349,8 @@ def launch(
348349
runInTerminal=False,
349350
expectFailure=False,
350351
postRunCommands=None,
352+
enableAutoVariableSummaries=False,
353+
enableSyntheticChildDebugging=False,
351354
):
352355
"""Sending launch request to vscode"""
353356

@@ -384,6 +387,8 @@ def cleanup():
384387
sourceMap=sourceMap,
385388
runInTerminal=runInTerminal,
386389
postRunCommands=postRunCommands,
390+
enableAutoVariableSummaries=enableAutoVariableSummaries,
391+
enableSyntheticChildDebugging=enableSyntheticChildDebugging,
387392
)
388393

389394
if expectFailure:
@@ -418,6 +423,8 @@ def build_and_launch(
418423
disconnectAutomatically=True,
419424
postRunCommands=None,
420425
lldbVSCodeEnv=None,
426+
enableAutoVariableSummaries=False,
427+
enableSyntheticChildDebugging=False,
421428
):
422429
"""Build the default Makefile target, create the VSCode debug adaptor,
423430
and launch the process.
@@ -446,4 +453,6 @@ def build_and_launch(
446453
runInTerminal=runInTerminal,
447454
disconnectAutomatically=disconnectAutomatically,
448455
postRunCommands=postRunCommands,
456+
enableAutoVariableSummaries=enableAutoVariableSummaries,
457+
enableSyntheticChildDebugging=enableSyntheticChildDebugging,
449458
)

lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -648,7 +648,7 @@ def request_disconnect(self, terminateDebuggee=None):
648648
"arguments": args_dict,
649649
}
650650
return self.send_recv(command_dict)
651-
651+
652652
def request_disassemble(self, memoryReference, offset=-50, instructionCount=200, resolveSymbols=True):
653653
args_dict = {
654654
"memoryReference": memoryReference,
@@ -727,6 +727,8 @@ def request_launch(
727727
sourceMap=None,
728728
runInTerminal=False,
729729
postRunCommands=None,
730+
enableAutoVariableSummaries=False,
731+
enableSyntheticChildDebugging=False,
730732
):
731733
args_dict = {"program": program}
732734
if args:
@@ -768,6 +770,8 @@ def request_launch(
768770
args_dict["runInTerminal"] = runInTerminal
769771
if postRunCommands:
770772
args_dict["postRunCommands"] = postRunCommands
773+
args_dict["enableAutoVariableSummaries"] = enableAutoVariableSummaries
774+
args_dict["enableSyntheticChildDebugging"] = enableSyntheticChildDebugging
771775
command_dict = {"command": "launch", "type": "request", "arguments": args_dict}
772776
response = self.send_recv(command_dict)
773777

lldb/test/API/tools/lldb-vscode/evaluate/TestVSCode_evaluate.py

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,17 @@ def assertEvaluateFailure(self, expression):
2828
def isExpressionParsedExpected(self):
2929
return self.context != "hover"
3030

31-
def run_test_evaluate_expressions(self, context=None):
31+
def run_test_evaluate_expressions(
32+
self, context=None, enableAutoVariableSummaries=False
33+
):
3234
"""
3335
Tests the evaluate expression request at different breakpoints
3436
"""
3537
self.context = context
3638
program = self.getBuildArtifact("a.out")
37-
self.build_and_launch(program)
39+
self.build_and_launch(
40+
program, enableAutoVariableSummaries=enableAutoVariableSummaries
41+
)
3842
source = "main.cpp"
3943
self.set_source_breakpoints(
4044
source,
@@ -55,7 +59,9 @@ def run_test_evaluate_expressions(self, context=None):
5559
self.assertEvaluate("var2", "21")
5660
self.assertEvaluate("static_int", "42")
5761
self.assertEvaluate("non_static_int", "43")
58-
self.assertEvaluate("struct1", "{foo:15}")
62+
self.assertEvaluate(
63+
"struct1", "{foo:15}" if enableAutoVariableSummaries else "my_struct @ 0x"
64+
)
5965
self.assertEvaluate("struct1.foo", "15")
6066
self.assertEvaluate("struct2->foo", "16")
6167

@@ -85,7 +91,9 @@ def run_test_evaluate_expressions(self, context=None):
8591
self.assertEvaluate(
8692
"non_static_int", "10"
8793
) # different variable with the same name
88-
self.assertEvaluate("struct1", "{foo:15}")
94+
self.assertEvaluate(
95+
"struct1", "{foo:15}" if enableAutoVariableSummaries else "my_struct @ 0x"
96+
)
8997
self.assertEvaluate("struct1.foo", "15")
9098
self.assertEvaluate("struct2->foo", "16")
9199

@@ -146,22 +154,22 @@ def run_test_evaluate_expressions(self, context=None):
146154
@skipIfRemote
147155
def test_generic_evaluate_expressions(self):
148156
# Tests context-less expression evaluations
149-
self.run_test_evaluate_expressions()
157+
self.run_test_evaluate_expressions(enableAutoVariableSummaries=False)
150158

151159
@skipIfWindows
152160
@skipIfRemote
153161
def test_repl_evaluate_expressions(self):
154162
# Tests expression evaluations that are triggered from the Debug Console
155-
self.run_test_evaluate_expressions("repl")
163+
self.run_test_evaluate_expressions("repl", enableAutoVariableSummaries=True)
156164

157165
@skipIfWindows
158166
@skipIfRemote
159167
def test_watch_evaluate_expressions(self):
160168
# Tests expression evaluations that are triggered from a watch expression
161-
self.run_test_evaluate_expressions("watch")
169+
self.run_test_evaluate_expressions("watch", enableAutoVariableSummaries=False)
162170

163171
@skipIfWindows
164172
@skipIfRemote
165173
def test_hover_evaluate_expressions(self):
166174
# Tests expression evaluations that are triggered when hovering on the editor
167-
self.run_test_evaluate_expressions("hover")
175+
self.run_test_evaluate_expressions("hover", enableAutoVariableSummaries=True)

lldb/test/API/tools/lldb-vscode/variables/TestVSCode_variables.py

Lines changed: 70 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -127,15 +127,17 @@ def darwin_dwarf_missing_obj(self, initCommands):
127127
varref_dict = {}
128128
self.verify_variables(verify_locals, locals, varref_dict)
129129

130-
@skipIfWindows
131-
@skipIfRemote
132-
def test_scopes_variables_setVariable_evaluate(self):
130+
def do_test_scopes_variables_setVariable_evaluate(
131+
self, enableAutoVariableSummaries: bool
132+
):
133133
"""
134134
Tests the "scopes", "variables", "setVariable", and "evaluate"
135135
packets.
136136
"""
137137
program = self.getBuildArtifact("a.out")
138-
self.build_and_launch(program)
138+
self.build_and_launch(
139+
program, enableAutoVariableSummaries=enableAutoVariableSummaries
140+
)
139141
source = "main.cpp"
140142
breakpoint1_line = line_number(source, "// breakpoint 1")
141143
lines = [breakpoint1_line]
@@ -219,12 +221,20 @@ def test_scopes_variables_setVariable_evaluate(self):
219221
},
220222
"pt": {
221223
"equals": {"type": "PointType"},
222-
"startswith": {"result": "{x:11, y:22}"},
224+
"startswith": {
225+
"result": "{x:11, y:22}"
226+
if enableAutoVariableSummaries
227+
else "PointType @ 0x"
228+
},
223229
"hasVariablesReference": True,
224230
},
225231
"pt.buffer": {
226232
"equals": {"type": "int[32]"},
227-
"startswith": {"result": "{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ...}"},
233+
"startswith": {
234+
"result": "{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ...}"
235+
if enableAutoVariableSummaries
236+
else "int[32] @ 0x"
237+
},
228238
"hasVariablesReference": True,
229239
},
230240
"argv": {
@@ -347,13 +357,27 @@ def test_scopes_variables_setVariable_evaluate(self):
347357

348358
@skipIfWindows
349359
@skipIfRemote
350-
def test_scopes_and_evaluate_expansion(self):
360+
def test_scopes_variables_setVariable_evaluate(self):
361+
self.do_test_scopes_variables_setVariable_evaluate(
362+
enableAutoVariableSummaries=False
363+
)
364+
365+
@skipIfWindows
366+
@skipIfRemote
367+
def test_scopes_variables_setVariable_evaluate_with_descriptive_summaries(self):
368+
self.do_test_scopes_variables_setVariable_evaluate(
369+
enableAutoVariableSummaries=True
370+
)
371+
372+
def do_test_scopes_and_evaluate_expansion(self, enableAutoVariableSummaries: bool):
351373
"""
352374
Tests the evaluated expression expands successfully after "scopes" packets
353375
and permanent expressions persist.
354376
"""
355377
program = self.getBuildArtifact("a.out")
356-
self.build_and_launch(program)
378+
self.build_and_launch(
379+
program, enableAutoVariableSummaries=enableAutoVariableSummaries
380+
)
357381
source = "main.cpp"
358382
breakpoint1_line = line_number(source, "// breakpoint 1")
359383
lines = [breakpoint1_line]
@@ -410,7 +434,11 @@ def test_scopes_and_evaluate_expansion(self):
410434
"name": "pt",
411435
"response": {
412436
"equals": {"type": "PointType"},
413-
"startswith": {"result": "{x:11, y:22}"},
437+
"startswith": {
438+
"result": "{x:11, y:22}"
439+
if enableAutoVariableSummaries
440+
else "PointType @ 0x"
441+
},
414442
"missing": ["indexedVariables"],
415443
"hasVariablesReference": True,
416444
},
@@ -487,14 +515,24 @@ def test_scopes_and_evaluate_expansion(self):
487515

488516
@skipIfWindows
489517
@skipIfRemote
490-
def test_indexedVariables(self):
518+
def test_scopes_and_evaluate_expansion(self):
519+
self.do_test_scopes_and_evaluate_expansion(enableAutoVariableSummaries=False)
520+
521+
@skipIfWindows
522+
@skipIfRemote
523+
def test_scopes_and_evaluate_expansion_with_descriptive_summaries(self):
524+
self.do_test_scopes_and_evaluate_expansion(enableAutoVariableSummaries=True)
525+
526+
def do_test_indexedVariables(self, enableSyntheticChildDebugging: bool):
491527
"""
492528
Tests that arrays and lldb.SBValue objects that have synthetic child
493529
providers have "indexedVariables" key/value pairs. This helps the IDE
494530
not to fetch too many children all at once.
495531
"""
496532
program = self.getBuildArtifact("a.out")
497-
self.build_and_launch(program)
533+
self.build_and_launch(
534+
program, enableSyntheticChildDebugging=enableSyntheticChildDebugging
535+
)
498536
source = "main.cpp"
499537
breakpoint1_line = line_number(source, "// breakpoint 4")
500538
lines = [breakpoint1_line]
@@ -507,13 +545,14 @@ def test_indexedVariables(self):
507545

508546
# Verify locals
509547
locals = self.vscode.get_local_variables()
510-
# The vector variables will have one additional entry from the fake
548+
# The vector variables might have one additional entry from the fake
511549
# "[raw]" child.
550+
raw_child_count = 1 if enableSyntheticChildDebugging else 0
512551
verify_locals = {
513552
"small_array": {"equals": {"indexedVariables": 5}},
514553
"large_array": {"equals": {"indexedVariables": 200}},
515-
"small_vector": {"equals": {"indexedVariables": 6}},
516-
"large_vector": {"equals": {"indexedVariables": 201}},
554+
"small_vector": {"equals": {"indexedVariables": 5 + raw_child_count}},
555+
"large_vector": {"equals": {"indexedVariables": 200 + raw_child_count}},
517556
"pt": {"missing": ["indexedVariables"]},
518557
}
519558
self.verify_variables(verify_locals, locals)
@@ -526,12 +565,27 @@ def test_indexedVariables(self):
526565
"[2]": {"equals": {"type": "int", "value": "0"}},
527566
"[3]": {"equals": {"type": "int", "value": "0"}},
528567
"[4]": {"equals": {"type": "int", "value": "0"}},
529-
"[raw]": {"contains": {"type": ["vector"]}},
530568
}
531-
children = self.vscode.request_variables(locals[2]["variablesReference"])["body"]["variables"]
569+
if enableSyntheticChildDebugging:
570+
verify_children["[raw]"] = ({"contains": {"type": ["vector"]}},)
571+
572+
children = self.vscode.request_variables(locals[2]["variablesReference"])[
573+
"body"
574+
]["variables"]
575+
or synthetics configurable (#65687))
532576
self.verify_variables(verify_children, children)
533577

534578

579+
@skipIfWindows
580+
@skipIfRemote
581+
def test_indexedVariables(self):
582+
self.do_test_indexedVariables(enableSyntheticChildDebugging=False)
583+
584+
@skipIfWindows
585+
@skipIfRemote
586+
def test_indexedVariables_with_raw_child_for_synthetics(self):
587+
self.do_test_indexedVariables(enableSyntheticChildDebugging=True)
588+
535589
@skipIfWindows
536590
@skipIfRemote
537591
def test_registers(self):

lldb/tools/lldb-vscode/JSONUtils.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,12 @@ std::vector<std::string> GetStrings(const llvm::json::Object *obj,
137137
/// glance.
138138
static std::optional<std::string>
139139
GetSyntheticSummaryForContainer(lldb::SBValue &v) {
140+
// We gate this feature because it performs GetNumChildren(), which can
141+
// cause performance issues because LLDB needs to complete possibly huge
142+
// types.
143+
if (!g_vsc.enable_auto_variable_summaries)
144+
return std::nullopt;
145+
140146
if (v.TypeIsPointerType() || !v.MightHaveChildren())
141147
return std::nullopt;
142148
/// As this operation can be potentially slow, we limit the total time spent
@@ -191,6 +197,9 @@ GetSyntheticSummaryForContainer(lldb::SBValue &v) {
191197
/// Return whether we should dereference an SBValue in order to generate a more
192198
/// meaningful summary string.
193199
static bool ShouldBeDereferencedForSummary(lldb::SBValue &v) {
200+
if (!g_vsc.enable_auto_variable_summaries)
201+
return false;
202+
194203
if (!v.GetType().IsPointerType() && !v.GetType().IsReferenceType())
195204
return false;
196205

@@ -1137,7 +1146,8 @@ llvm::json::Value CreateVariable(lldb::SBValue v, int64_t variablesReference,
11371146
// We create a "[raw]" fake child for each synthetic type, so we have to
11381147
// account for it when returning indexed variables. We don't need to do this
11391148
// for non-indexed ones.
1140-
int actual_num_children = num_children + (is_synthetic ? 1 : 0);
1149+
bool has_raw_child = is_synthetic && g_vsc.enable_synthetic_child_debugging;
1150+
int actual_num_children = num_children + (has_raw_child ? 1 : 0);
11411151
if (is_array) {
11421152
object.try_emplace("indexedVariables", actual_num_children);
11431153
} else if (num_children > 0) {

lldb/tools/lldb-vscode/VSCode.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ VSCode::VSCode()
4141
{"swift_throw", "Swift Throw", lldb::eLanguageTypeSwift}}),
4242
focus_tid(LLDB_INVALID_THREAD_ID), sent_terminated_event(false),
4343
stop_at_entry(false), is_attach(false),
44+
enable_auto_variable_summaries(false),
45+
enable_synthetic_child_debugging(false),
4446
restarting_process_id(LLDB_INVALID_PROCESS_ID),
4547
configuration_done_sent(false), waiting_for_run_in_terminal(false),
4648
progress_event_reporter(

lldb/tools/lldb-vscode/VSCode.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,8 @@ struct VSCode {
167167
std::atomic<bool> sent_terminated_event;
168168
bool stop_at_entry;
169169
bool is_attach;
170+
bool enable_auto_variable_summaries;
171+
bool enable_synthetic_child_debugging;
170172
// The process event thread normally responds to process exited events by
171173
// shutting down the entire adapter. When we're restarting, we keep the id of
172174
// the old process here so we can detect this case and keep running.

lldb/tools/lldb-vscode/lldb-vscode.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,10 @@ void request_attach(const llvm::json::Object &request) {
645645
std::vector<std::string> postRunCommands =
646646
GetStrings(arguments, "postRunCommands");
647647
const llvm::StringRef debuggerRoot = GetString(arguments, "debuggerRoot");
648+
g_vsc.enable_auto_variable_summaries =
649+
GetBoolean(arguments, "enableAutoVariableSummaries", false);
650+
g_vsc.enable_synthetic_child_debugging =
651+
GetBoolean(arguments, "enableSyntheticChildDebugging", false);
648652

649653
// This is a hack for loading DWARF in .o files on Mac where the .o files
650654
// in the debug map of the main executable have relative paths which require
@@ -1792,6 +1796,10 @@ void request_launch(const llvm::json::Object &request) {
17921796
GetStrings(arguments, "postRunCommands");
17931797
g_vsc.stop_at_entry = GetBoolean(arguments, "stopOnEntry", false);
17941798
const llvm::StringRef debuggerRoot = GetString(arguments, "debuggerRoot");
1799+
g_vsc.enable_auto_variable_summaries =
1800+
GetBoolean(arguments, "enableAutoVariableSummaries", false);
1801+
g_vsc.enable_synthetic_child_debugging =
1802+
GetBoolean(arguments, "enableSyntheticChildDebugging", false);
17951803

17961804
// This is a hack for loading DWARF in .o files on Mac where the .o files
17971805
// in the debug map of the main executable have relative paths which require
@@ -3290,7 +3298,8 @@ void request_variables(const llvm::json::Object &request) {
32903298
// "[raw]" child that can be used to inspect the raw version of a
32913299
// synthetic member. That eliminates the need for the user to go to the
32923300
// debug console and type `frame var <variable> to get these values.
3293-
if (variable.IsSynthetic() && i == num_children)
3301+
if (g_vsc.enable_synthetic_child_debugging && variable.IsSynthetic() &&
3302+
i == num_children)
32943303
addChild(variable.GetNonSyntheticValue(), "[raw]");
32953304
}
32963305
}

0 commit comments

Comments
 (0)