Skip to content

Commit 79c4948

Browse files
ashgtijustinfargnoli
authored andcommitted
[lldb-dap] Updating VariableDescription to use GetDescription() as a fallback. (llvm#77026)
When generating a `display_value` for a variable the current approach calls `SBValue::GetValue()` and `SBValue::GetSummary()` to generate a `display_value` for the `SBValue`. However, there are cases where both of these return an empty string and the fallback is to print a pointer and type name instead (e.g. `FooBarType @ 0x00321`). For swift types, lldb includes a langauge runtime plugin that can generate a description of the object but this is only used with `SBValue::GetDescription()`. For example: ``` $ lldb swift-binary ... stop at breakpoint ... lldb> script >>> event = lldb.frame.GetValueForVariablePath("event") >>> print("Value", event.GetValue()) Value None >>> print("Summary", event.GetSummary()) Summary None >>> print("Description", event) # __str__ calls SBValue::GetDescription() Description (main.Event) event = (name = "Greetings", time = 2024-01-04 23:38:06 UTC) ``` With this change, if GetValue and GetSummary return empty then we try `SBValue::GetDescription()` as a fallback before using the previous logic of printing `<type> @ <addr>`.
1 parent 6fb4ee2 commit 79c4948

File tree

6 files changed

+202
-66
lines changed

6 files changed

+202
-66
lines changed

lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py

+47-14
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
Test lldb-dap completions request
33
"""
44

5+
import re
56

67
import lldbdap_testcase
78
import dap_server
@@ -10,7 +11,7 @@
1011
from lldbsuite.test.lldbtest import *
1112

1213

13-
class TestDAP_variables(lldbdap_testcase.DAPTestCaseBase):
14+
class TestDAP_evaluate(lldbdap_testcase.DAPTestCaseBase):
1415
def assertEvaluate(self, expression, regex):
1516
self.assertRegexpMatches(
1617
self.dap_server.request_evaluate(expression, context=self.context)["body"][
@@ -25,6 +26,9 @@ def assertEvaluateFailure(self, expression):
2526
self.dap_server.request_evaluate(expression, context=self.context)["body"],
2627
)
2728

29+
def isResultExpandedDescription(self):
30+
return self.context == "repl" or self.context == "hover"
31+
2832
def isExpressionParsedExpected(self):
2933
return self.context != "hover"
3034

@@ -59,16 +63,30 @@ def run_test_evaluate_expressions(
5963
self.assertEvaluate("var2", "21")
6064
self.assertEvaluate("static_int", "42")
6165
self.assertEvaluate("non_static_int", "43")
62-
self.assertEvaluate(
63-
"struct1", "{foo:15}" if enableAutoVariableSummaries else "my_struct @ 0x"
64-
)
65-
self.assertEvaluate(
66-
"struct2", "0x.* {foo:16}" if enableAutoVariableSummaries else "0x.*"
67-
)
68-
self.assertEvaluate("struct3", "0x.*0")
6966
self.assertEvaluate("struct1.foo", "15")
7067
self.assertEvaluate("struct2->foo", "16")
7168

69+
if self.isResultExpandedDescription():
70+
self.assertEvaluate(
71+
"struct1",
72+
r"\(my_struct\) (struct1|\$\d+) = \(foo = 15\)",
73+
)
74+
self.assertEvaluate("struct2", r"\(my_struct \*\) (struct2|\$\d+) = 0x.*")
75+
self.assertEvaluate(
76+
"struct3", r"\(my_struct \*\) (struct3|\$\d+) = nullptr"
77+
)
78+
else:
79+
self.assertEvaluate(
80+
"struct1",
81+
re.escape("{foo:15}")
82+
if enableAutoVariableSummaries
83+
else "my_struct @ 0x",
84+
)
85+
self.assertEvaluate(
86+
"struct2", "0x.* {foo:16}" if enableAutoVariableSummaries else "0x.*"
87+
)
88+
self.assertEvaluate("struct3", "0x.*0")
89+
7290
self.assertEvaluateFailure("var") # local variable of a_function
7391
self.assertEvaluateFailure("my_struct") # type name
7492
self.assertEvaluateFailure("int") # type name
@@ -95,9 +113,18 @@ def run_test_evaluate_expressions(
95113
self.assertEvaluate(
96114
"non_static_int", "10"
97115
) # different variable with the same name
98-
self.assertEvaluate(
99-
"struct1", "{foo:15}" if enableAutoVariableSummaries else "my_struct @ 0x"
100-
)
116+
if self.isResultExpandedDescription():
117+
self.assertEvaluate(
118+
"struct1",
119+
r"\(my_struct\) (struct1|\$\d+) = \(foo = 15\)",
120+
)
121+
else:
122+
self.assertEvaluate(
123+
"struct1",
124+
re.escape("{foo:15}")
125+
if enableAutoVariableSummaries
126+
else "my_struct @ 0x",
127+
)
101128
self.assertEvaluate("struct1.foo", "15")
102129
self.assertEvaluate("struct2->foo", "16")
103130

@@ -164,16 +191,22 @@ def test_generic_evaluate_expressions(self):
164191
@skipIfRemote
165192
def test_repl_evaluate_expressions(self):
166193
# Tests expression evaluations that are triggered from the Debug Console
167-
self.run_test_evaluate_expressions("repl", enableAutoVariableSummaries=True)
194+
self.run_test_evaluate_expressions("repl", enableAutoVariableSummaries=False)
168195

169196
@skipIfWindows
170197
@skipIfRemote
171198
def test_watch_evaluate_expressions(self):
172199
# Tests expression evaluations that are triggered from a watch expression
173-
self.run_test_evaluate_expressions("watch", enableAutoVariableSummaries=False)
200+
self.run_test_evaluate_expressions("watch", enableAutoVariableSummaries=True)
174201

175202
@skipIfWindows
176203
@skipIfRemote
177204
def test_hover_evaluate_expressions(self):
178205
# Tests expression evaluations that are triggered when hovering on the editor
179-
self.run_test_evaluate_expressions("hover", enableAutoVariableSummaries=True)
206+
self.run_test_evaluate_expressions("hover", enableAutoVariableSummaries=False)
207+
208+
@skipIfWindows
209+
@skipIfRemote
210+
def test_variable_evaluate_expressions(self):
211+
# Tests expression evaluations that are triggered in the variable explorer
212+
self.run_test_evaluate_expressions("variable", enableAutoVariableSummaries=True)

lldb/test/API/tools/lldb-dap/variables/TestDAP_variables.py

+112-37
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,18 @@ def verify_values(self, verify_dict, actual, varref_dict=None, expression=None):
3939
startswith = actual_value.startswith(verify_value)
4040
self.assertTrue(
4141
startswith,
42-
('"%s" value "%s" doesn\'t start with' ' "%s")')
42+
('"%s" value "%s" doesn\'t start with "%s")')
43+
% (key, actual_value, verify_value),
44+
)
45+
if "matches" in verify_dict:
46+
verify = verify_dict["matches"]
47+
for key in verify:
48+
verify_value = verify[key]
49+
actual_value = actual[key]
50+
self.assertRegex(
51+
actual_value,
52+
verify_value,
53+
('"%s" value "%s" doesn\'t match pattern "%s")')
4354
% (key, actual_value, verify_value),
4455
)
4556
if "contains" in verify_dict:
@@ -150,7 +161,7 @@ def do_test_scopes_variables_setVariable_evaluate(
150161
self.continue_to_breakpoints(breakpoint_ids)
151162
locals = self.dap_server.get_local_variables()
152163
globals = self.dap_server.get_global_variables()
153-
buffer_children = make_buffer_verify_dict(0, 32)
164+
buffer_children = make_buffer_verify_dict(0, 16)
154165
verify_locals = {
155166
"argc": {
156167
"equals": {
@@ -243,18 +254,18 @@ def do_test_scopes_variables_setVariable_evaluate(
243254
"pt": {
244255
"equals": {"type": "PointType"},
245256
"startswith": {
246-
"result": "{x:11, y:22}"
257+
"result": "{x:11, y:22, buffer:{...}}"
247258
if enableAutoVariableSummaries
248259
else "PointType @ 0x"
249260
},
250261
"hasVariablesReference": True,
251262
},
252263
"pt.buffer": {
253-
"equals": {"type": "int[32]"},
264+
"equals": {"type": "int[16]"},
254265
"startswith": {
255266
"result": "{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ...}"
256267
if enableAutoVariableSummaries
257-
else "int[32] @ 0x"
268+
else "int[16] @ 0x"
258269
},
259270
"hasVariablesReference": True,
260271
},
@@ -440,7 +451,7 @@ def do_test_scopes_and_evaluate_expansion(self, enableAutoVariableSummaries: boo
440451
},
441452
"buffer": {
442453
"children": buffer_children,
443-
"equals": {"indexedVariables": 32},
454+
"equals": {"indexedVariables": 16},
444455
},
445456
},
446457
},
@@ -455,15 +466,85 @@ def do_test_scopes_and_evaluate_expansion(self, enableAutoVariableSummaries: boo
455466
# the other temporary (from other UI).
456467
expandable_expression = {
457468
"name": "pt",
458-
"response": {
459-
"equals": {"type": "PointType"},
460-
"startswith": {
461-
"result": "{x:11, y:22}"
462-
if enableAutoVariableSummaries
463-
else "PointType @ 0x"
469+
"context": {
470+
"repl": {
471+
"equals": {"type": "PointType"},
472+
"equals": {
473+
"result": """(PointType) $0 = {
474+
x = 11
475+
y = 22
476+
buffer = {
477+
[0] = 0
478+
[1] = 1
479+
[2] = 2
480+
[3] = 3
481+
[4] = 4
482+
[5] = 5
483+
[6] = 6
484+
[7] = 7
485+
[8] = 8
486+
[9] = 9
487+
[10] = 10
488+
[11] = 11
489+
[12] = 12
490+
[13] = 13
491+
[14] = 14
492+
[15] = 15
493+
}
494+
}"""
495+
},
496+
"missing": ["indexedVariables"],
497+
"hasVariablesReference": True,
498+
},
499+
"hover": {
500+
"equals": {"type": "PointType"},
501+
"equals": {
502+
"result": """(PointType) pt = {
503+
x = 11
504+
y = 22
505+
buffer = {
506+
[0] = 0
507+
[1] = 1
508+
[2] = 2
509+
[3] = 3
510+
[4] = 4
511+
[5] = 5
512+
[6] = 6
513+
[7] = 7
514+
[8] = 8
515+
[9] = 9
516+
[10] = 10
517+
[11] = 11
518+
[12] = 12
519+
[13] = 13
520+
[14] = 14
521+
[15] = 15
522+
}
523+
}"""
524+
},
525+
"missing": ["indexedVariables"],
526+
"hasVariablesReference": True,
527+
},
528+
"watch": {
529+
"equals": {"type": "PointType"},
530+
"startswith": {
531+
"result": "{x:11, y:22, buffer:{...}}"
532+
if enableAutoVariableSummaries
533+
else "PointType @ 0x"
534+
},
535+
"missing": ["indexedVariables"],
536+
"hasVariablesReference": True,
537+
},
538+
"variables": {
539+
"equals": {"type": "PointType"},
540+
"startswith": {
541+
"result": "{x:11, y:22, buffer:{...}}"
542+
if enableAutoVariableSummaries
543+
else "PointType @ 0x"
544+
},
545+
"missing": ["indexedVariables"],
546+
"hasVariablesReference": True,
464547
},
465-
"missing": ["indexedVariables"],
466-
"hasVariablesReference": True,
467548
},
468549
"children": {
469550
"x": {"equals": {"type": "int", "value": "11"}},
@@ -472,35 +553,29 @@ def do_test_scopes_and_evaluate_expansion(self, enableAutoVariableSummaries: boo
472553
},
473554
}
474555

475-
# Evaluate from permanent UI.
476-
permanent_expr_varref_dict = {}
477-
response = self.dap_server.request_evaluate(
478-
expandable_expression["name"], frameIndex=0, threadId=None, context="repl"
479-
)
480-
self.verify_values(
481-
expandable_expression["response"],
482-
response["body"],
483-
permanent_expr_varref_dict,
484-
expandable_expression["name"],
485-
)
486-
487-
# Evaluate from temporary UI.
488-
temporary_expr_varref_dict = {}
489-
response = self.dap_server.request_evaluate(expandable_expression["name"])
490-
self.verify_values(
491-
expandable_expression["response"],
492-
response["body"],
493-
temporary_expr_varref_dict,
494-
expandable_expression["name"],
495-
)
556+
# Evaluate from known contexts.
557+
expr_varref_dict = {}
558+
for context, verify_dict in expandable_expression["context"].items():
559+
response = self.dap_server.request_evaluate(
560+
expandable_expression["name"],
561+
frameIndex=0,
562+
threadId=None,
563+
context=context,
564+
)
565+
self.verify_values(
566+
verify_dict,
567+
response["body"],
568+
expr_varref_dict,
569+
expandable_expression["name"],
570+
)
496571

497572
# Evaluate locals again.
498573
locals = self.dap_server.get_local_variables()
499574
self.verify_variables(verify_locals, locals)
500575

501576
# Verify the evaluated expressions before second locals evaluation
502577
# can be expanded.
503-
var_ref = temporary_expr_varref_dict[expandable_expression["name"]]
578+
var_ref = expr_varref_dict[expandable_expression["name"]]
504579
response = self.dap_server.request_variables(var_ref)
505580
self.verify_variables(
506581
expandable_expression["children"], response["body"]["variables"]
@@ -516,7 +591,7 @@ def do_test_scopes_and_evaluate_expansion(self, enableAutoVariableSummaries: boo
516591
)
517592
self.continue_to_breakpoints(breakpoint_ids)
518593

519-
var_ref = permanent_expr_varref_dict[expandable_expression["name"]]
594+
var_ref = expr_varref_dict[expandable_expression["name"]]
520595
response = self.dap_server.request_variables(var_ref)
521596
self.verify_variables(
522597
expandable_expression["children"], response["body"]["variables"]

lldb/test/API/tools/lldb-dap/variables/main.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
#define BUFFER_SIZE 32
2+
#define BUFFER_SIZE 16
33
struct PointType {
44
int x;
55
int y;

0 commit comments

Comments
 (0)