Skip to content

Commit c555522

Browse files
authored
[lldb-dap] Migrating 'evaluate' to structured types. (#167720)
Adding structured types for the evaluate request handler. This should be mostly a non-functional change. I did catch some spelling mistakes in our tests ('variable' vs 'variables').
1 parent af6af8e commit c555522

File tree

12 files changed

+461
-254
lines changed

12 files changed

+461
-254
lines changed

lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -978,9 +978,10 @@ def request_evaluate(self, expression, frameIndex=0, threadId=None, context=None
978978
return []
979979
args_dict = {
980980
"expression": expression,
981-
"context": context,
982981
"frameId": stackFrame["id"],
983982
}
983+
if context:
984+
args_dict["context"] = context
984985
command_dict = {
985986
"command": "evaluate",
986987
"type": "request",

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

Lines changed: 151 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,73 @@
11
"""
2-
Test lldb-dap completions request
2+
Test lldb-dap evaluate request
33
"""
44

55
import re
66

77
import lldbdap_testcase
88
from lldbsuite.test.decorators import skipIfWindows
99
from lldbsuite.test.lldbtest import line_number
10+
from typing import TypedDict, Optional
11+
12+
13+
class EvaluateResponseBody(TypedDict, total=False):
14+
result: str
15+
variablesReference: int
16+
type: Optional[str]
17+
memoryReference: Optional[str]
18+
valueLocationReference: Optional[int]
1019

1120

1221
class TestDAP_evaluate(lldbdap_testcase.DAPTestCaseBase):
13-
def assertEvaluate(self, expression, regex):
22+
def assertEvaluate(
23+
self,
24+
expression,
25+
result: str,
26+
want_type="",
27+
want_varref=False,
28+
want_memref=True,
29+
want_locref=False,
30+
):
31+
resp = self.dap_server.request_evaluate(expression, context=self.context)
32+
self.assertTrue(
33+
resp["success"], f"Failed to evaluate expression {expression!r}"
34+
)
35+
body: EvaluateResponseBody = resp["body"]
1436
self.assertRegex(
15-
self.dap_server.request_evaluate(expression, context=self.context)["body"][
16-
"result"
17-
],
18-
regex,
37+
body["result"],
38+
result,
39+
f"Unexpected 'result' for expression {expression!r} in response body {body}",
1940
)
41+
if want_varref:
42+
self.assertNotEqual(
43+
body["variablesReference"],
44+
0,
45+
f"Unexpected 'variablesReference' for expression {expression!r} in response body {body}",
46+
)
47+
else:
48+
self.assertEqual(
49+
body["variablesReference"],
50+
0,
51+
f"Unexpected 'variablesReference' for expression {expression!r} in response body {body}",
52+
)
53+
if want_type:
54+
self.assertEqual(
55+
body["type"],
56+
want_type,
57+
f"Unexpected 'type' for expression {expression!r} in response body {body}",
58+
)
59+
if want_memref:
60+
self.assertIn(
61+
"memoryReference",
62+
body,
63+
f"Unexpected 'memoryReference' for expression {expression!r} in response body {body}",
64+
)
65+
if want_locref:
66+
self.assertIn(
67+
"valueLocationReference",
68+
body,
69+
f"Unexpected 'valueLocationReference' for expression {expression!r} in response body {body}",
70+
)
2071

2172
def assertEvaluateFailure(self, expression):
2273
self.assertNotIn(
@@ -71,29 +122,39 @@ def run_test_evaluate_expressions(
71122
self.continue_to_breakpoint(breakpoint_1)
72123

73124
# Expressions at breakpoint 1, which is in main
74-
self.assertEvaluate("var1", "20")
125+
self.assertEvaluate("var1", "20", want_type="int")
75126
# Empty expression should equate to the previous expression.
76127
if context == "repl":
77128
self.assertEvaluate("", "20")
78129
else:
79130
self.assertEvaluateFailure("")
80-
self.assertEvaluate("var2", "21")
131+
self.assertEvaluate("var2", "21", want_type="int")
81132
if context == "repl":
82-
self.assertEvaluate("", "21")
83-
self.assertEvaluate("", "21")
84-
self.assertEvaluate("static_int", "42")
85-
self.assertEvaluate("non_static_int", "43")
86-
self.assertEvaluate("struct1.foo", "15")
87-
self.assertEvaluate("struct2->foo", "16")
133+
self.assertEvaluate("", "21", want_type="int")
134+
self.assertEvaluate("", "21", want_type="int")
135+
self.assertEvaluate("static_int", "42", want_type="int")
136+
self.assertEvaluate("non_static_int", "43", want_type="int")
137+
self.assertEvaluate("struct1.foo", "15", want_type="int")
138+
self.assertEvaluate("struct2->foo", "16", want_type="int")
88139

89140
if self.isResultExpandedDescription():
90141
self.assertEvaluate(
91142
"struct1",
92143
r"\(my_struct\) (struct1|\$\d+) = \(foo = 15\)",
144+
want_type="my_struct",
145+
want_varref=True,
146+
)
147+
self.assertEvaluate(
148+
"struct2",
149+
r"\(my_struct \*\) (struct2|\$\d+) = 0x.*",
150+
want_type="my_struct *",
151+
want_varref=True,
93152
)
94-
self.assertEvaluate("struct2", r"\(my_struct \*\) (struct2|\$\d+) = 0x.*")
95153
self.assertEvaluate(
96-
"struct3", r"\(my_struct \*\) (struct3|\$\d+) = nullptr"
154+
"struct3",
155+
r"\(my_struct \*\) (struct3|\$\d+) = nullptr",
156+
want_type="my_struct *",
157+
want_varref=True,
97158
)
98159
else:
99160
self.assertEvaluate(
@@ -103,16 +164,22 @@ def run_test_evaluate_expressions(
103164
if enableAutoVariableSummaries
104165
else "my_struct @ 0x"
105166
),
167+
want_varref=True,
168+
)
169+
self.assertEvaluate(
170+
"struct2",
171+
"0x.* {foo:16}" if enableAutoVariableSummaries else "0x.*",
172+
want_varref=True,
173+
want_type="my_struct *",
106174
)
107175
self.assertEvaluate(
108-
"struct2", "0x.* {foo:16}" if enableAutoVariableSummaries else "0x.*"
176+
"struct3", "0x.*0", want_varref=True, want_type="my_struct *"
109177
)
110-
self.assertEvaluate("struct3", "0x.*0")
111178

112179
if context == "repl":
113180
# In the repl context expressions may be interpreted as lldb
114181
# commands since no variables have the same name as the command.
115-
self.assertEvaluate("list", r".*")
182+
self.assertEvaluate("list", r".*", want_memref=False)
116183
else:
117184
self.assertEvaluateFailure("list") # local variable of a_function
118185

@@ -121,10 +188,26 @@ def run_test_evaluate_expressions(
121188
self.assertEvaluateFailure("foo") # member of my_struct
122189

123190
if self.isExpressionParsedExpected():
124-
self.assertEvaluate("a_function", "0x.*a.out`a_function.*")
125-
self.assertEvaluate("a_function(1)", "1")
126-
self.assertEvaluate("var2 + struct1.foo", "36")
127-
self.assertEvaluate("foo_func", "0x.*a.out`foo_func.*")
191+
self.assertEvaluate(
192+
"a_function",
193+
"0x.*a.out`a_function.*",
194+
want_type="int (*)(int)",
195+
want_varref=True,
196+
want_memref=False,
197+
want_locref=True,
198+
)
199+
self.assertEvaluate(
200+
"a_function(1)", "1", want_memref=False, want_type="int"
201+
)
202+
self.assertEvaluate("var2 + struct1.foo", "36", want_memref=False)
203+
self.assertEvaluate(
204+
"foo_func",
205+
"0x.*a.out`foo_func.*",
206+
want_type="int (*)()",
207+
want_varref=True,
208+
want_memref=False,
209+
want_locref=True,
210+
)
128211
self.assertEvaluate("foo_var", "44")
129212
else:
130213
self.assertEvaluateFailure("a_function")
@@ -145,6 +228,8 @@ def run_test_evaluate_expressions(
145228
self.assertEvaluate(
146229
"struct1",
147230
r"\(my_struct\) (struct1|\$\d+) = \(foo = 15\)",
231+
want_type="my_struct",
232+
want_varref=True,
148233
)
149234
else:
150235
self.assertEvaluate(
@@ -154,15 +239,26 @@ def run_test_evaluate_expressions(
154239
if enableAutoVariableSummaries
155240
else "my_struct @ 0x"
156241
),
242+
want_type="my_struct",
243+
want_varref=True,
157244
)
158245
self.assertEvaluate("struct1.foo", "15")
159246
self.assertEvaluate("struct2->foo", "16")
160247

161248
if self.isExpressionParsedExpected():
162-
self.assertEvaluate("a_function", "0x.*a.out`a_function.*")
163-
self.assertEvaluate("a_function(1)", "1")
164-
self.assertEvaluate("var2 + struct1.foo", "17")
165-
self.assertEvaluate("foo_func", "0x.*a.out`foo_func.*")
249+
self.assertEvaluate(
250+
"a_function",
251+
"0x.*a.out`a_function.*",
252+
want_type="int (*)(int)",
253+
want_varref=True,
254+
want_memref=False,
255+
want_locref=True,
256+
)
257+
self.assertEvaluate("a_function(1)", "1", want_memref=False)
258+
self.assertEvaluate("var2 + struct1.foo", "17", want_memref=False)
259+
self.assertEvaluate(
260+
"foo_func", "0x.*a.out`foo_func.*", want_varref=True, want_memref=False
261+
)
166262
self.assertEvaluate("foo_var", "44")
167263
else:
168264
self.assertEvaluateFailure("a_function")
@@ -185,10 +281,18 @@ def run_test_evaluate_expressions(
185281
self.assertEvaluateFailure("var2 + struct1.foo")
186282

187283
if self.isExpressionParsedExpected():
188-
self.assertEvaluate("a_function", "0x.*a.out`a_function.*")
189-
self.assertEvaluate("a_function(1)", "1")
190-
self.assertEvaluate("list + 1", "43")
191-
self.assertEvaluate("foo_func", "0x.*a.out`foo_func.*")
284+
self.assertEvaluate(
285+
"a_function",
286+
"0x.*a.out`a_function.*",
287+
want_varref=True,
288+
want_memref=False,
289+
want_locref=True,
290+
)
291+
self.assertEvaluate("a_function(1)", "1", want_memref=False)
292+
self.assertEvaluate("list + 1", "43", want_memref=False)
293+
self.assertEvaluate(
294+
"foo_func", "0x.*a.out`foo_func.*", want_varref=True, want_memref=False
295+
)
192296
self.assertEvaluate("foo_var", "44")
193297
else:
194298
self.assertEvaluateFailure("a_function")
@@ -199,26 +303,28 @@ def run_test_evaluate_expressions(
199303

200304
# Now we check that values are updated after stepping
201305
self.continue_to_breakpoint(breakpoint_4)
202-
self.assertEvaluate("my_vec", "size=2")
306+
self.assertEvaluate("my_vec", "size=2", want_varref=True)
203307
self.continue_to_breakpoint(breakpoint_5)
204-
self.assertEvaluate("my_vec", "size=3")
308+
self.assertEvaluate("my_vec", "size=3", want_varref=True)
205309

206-
self.assertEvaluate("my_map", "size=2")
310+
self.assertEvaluate("my_map", "size=2", want_varref=True)
207311
self.continue_to_breakpoint(breakpoint_6)
208-
self.assertEvaluate("my_map", "size=3")
312+
self.assertEvaluate("my_map", "size=3", want_varref=True)
209313

210-
self.assertEvaluate("my_bool_vec", "size=1")
314+
self.assertEvaluate("my_bool_vec", "size=1", want_varref=True)
211315
self.continue_to_breakpoint(breakpoint_7)
212-
self.assertEvaluate("my_bool_vec", "size=2")
316+
self.assertEvaluate("my_bool_vec", "size=2", want_varref=True)
213317

214318
self.continue_to_breakpoint(breakpoint_8)
215319
# Test memory read, especially with 'empty' repeat commands.
216320
if context == "repl":
217-
self.assertEvaluate("memory read -c 1 &my_ints", ".* 05 .*\n")
218-
self.assertEvaluate("", ".* 0a .*\n")
219-
self.assertEvaluate("", ".* 0f .*\n")
220-
self.assertEvaluate("", ".* 14 .*\n")
221-
self.assertEvaluate("", ".* 19 .*\n")
321+
self.assertEvaluate(
322+
"memory read -c 1 &my_ints", ".* 05 .*\n", want_memref=False
323+
)
324+
self.assertEvaluate("", ".* 0a .*\n", want_memref=False)
325+
self.assertEvaluate("", ".* 0f .*\n", want_memref=False)
326+
self.assertEvaluate("", ".* 14 .*\n", want_memref=False)
327+
self.assertEvaluate("", ".* 19 .*\n", want_memref=False)
222328

223329
self.continue_to_exit()
224330

@@ -245,4 +351,6 @@ def test_hover_evaluate_expressions(self):
245351
@skipIfWindows
246352
def test_variable_evaluate_expressions(self):
247353
# Tests expression evaluations that are triggered in the variable explorer
248-
self.run_test_evaluate_expressions("variable", enableAutoVariableSummaries=True)
354+
self.run_test_evaluate_expressions(
355+
"variables", enableAutoVariableSummaries=True
356+
)

0 commit comments

Comments
 (0)