Skip to content

[lldb-dap] Updating VariableDescription to use GetDescription() as a fallback. #77026

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 47 additions & 14 deletions lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
Test lldb-dap completions request
"""

import re

import lldbdap_testcase
import dap_server
Expand All @@ -10,7 +11,7 @@
from lldbsuite.test.lldbtest import *


class TestDAP_variables(lldbdap_testcase.DAPTestCaseBase):
class TestDAP_evaluate(lldbdap_testcase.DAPTestCaseBase):
def assertEvaluate(self, expression, regex):
self.assertRegexpMatches(
self.dap_server.request_evaluate(expression, context=self.context)["body"][
Expand All @@ -25,6 +26,9 @@ def assertEvaluateFailure(self, expression):
self.dap_server.request_evaluate(expression, context=self.context)["body"],
)

def isResultExpandedDescription(self):
return self.context == "repl" or self.context == "hover"

def isExpressionParsedExpected(self):
return self.context != "hover"

Expand Down Expand Up @@ -59,16 +63,30 @@ def run_test_evaluate_expressions(
self.assertEvaluate("var2", "21")
self.assertEvaluate("static_int", "42")
self.assertEvaluate("non_static_int", "43")
self.assertEvaluate(
"struct1", "{foo:15}" if enableAutoVariableSummaries else "my_struct @ 0x"
)
self.assertEvaluate(
"struct2", "0x.* {foo:16}" if enableAutoVariableSummaries else "0x.*"
)
self.assertEvaluate("struct3", "0x.*0")
self.assertEvaluate("struct1.foo", "15")
self.assertEvaluate("struct2->foo", "16")

if self.isResultExpandedDescription():
self.assertEvaluate(
"struct1",
r"\(my_struct\) (struct1|\$\d+) = \(foo = 15\)",
)
self.assertEvaluate("struct2", r"\(my_struct \*\) (struct2|\$\d+) = 0x.*")
self.assertEvaluate(
"struct3", r"\(my_struct \*\) (struct3|\$\d+) = nullptr"
)
else:
self.assertEvaluate(
"struct1",
re.escape("{foo:15}")
if enableAutoVariableSummaries
else "my_struct @ 0x",
)
self.assertEvaluate(
"struct2", "0x.* {foo:16}" if enableAutoVariableSummaries else "0x.*"
)
self.assertEvaluate("struct3", "0x.*0")

self.assertEvaluateFailure("var") # local variable of a_function
self.assertEvaluateFailure("my_struct") # type name
self.assertEvaluateFailure("int") # type name
Expand All @@ -95,9 +113,18 @@ def run_test_evaluate_expressions(
self.assertEvaluate(
"non_static_int", "10"
) # different variable with the same name
self.assertEvaluate(
"struct1", "{foo:15}" if enableAutoVariableSummaries else "my_struct @ 0x"
)
if self.isResultExpandedDescription():
self.assertEvaluate(
"struct1",
r"\(my_struct\) (struct1|\$\d+) = \(foo = 15\)",
)
else:
self.assertEvaluate(
"struct1",
re.escape("{foo:15}")
if enableAutoVariableSummaries
else "my_struct @ 0x",
)
self.assertEvaluate("struct1.foo", "15")
self.assertEvaluate("struct2->foo", "16")

Expand Down Expand Up @@ -164,16 +191,22 @@ def test_generic_evaluate_expressions(self):
@skipIfRemote
def test_repl_evaluate_expressions(self):
# Tests expression evaluations that are triggered from the Debug Console
self.run_test_evaluate_expressions("repl", enableAutoVariableSummaries=True)
self.run_test_evaluate_expressions("repl", enableAutoVariableSummaries=False)

@skipIfWindows
@skipIfRemote
def test_watch_evaluate_expressions(self):
# Tests expression evaluations that are triggered from a watch expression
self.run_test_evaluate_expressions("watch", enableAutoVariableSummaries=False)
self.run_test_evaluate_expressions("watch", enableAutoVariableSummaries=True)

@skipIfWindows
@skipIfRemote
def test_hover_evaluate_expressions(self):
# Tests expression evaluations that are triggered when hovering on the editor
self.run_test_evaluate_expressions("hover", enableAutoVariableSummaries=True)
self.run_test_evaluate_expressions("hover", enableAutoVariableSummaries=False)

@skipIfWindows
@skipIfRemote
def test_variable_evaluate_expressions(self):
# Tests expression evaluations that are triggered in the variable explorer
self.run_test_evaluate_expressions("variable", enableAutoVariableSummaries=True)
149 changes: 112 additions & 37 deletions lldb/test/API/tools/lldb-dap/variables/TestDAP_variables.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,18 @@ def verify_values(self, verify_dict, actual, varref_dict=None, expression=None):
startswith = actual_value.startswith(verify_value)
self.assertTrue(
startswith,
('"%s" value "%s" doesn\'t start with' ' "%s")')
('"%s" value "%s" doesn\'t start with "%s")')
% (key, actual_value, verify_value),
)
if "matches" in verify_dict:
verify = verify_dict["matches"]
for key in verify:
verify_value = verify[key]
actual_value = actual[key]
self.assertRegex(
actual_value,
verify_value,
('"%s" value "%s" doesn\'t match pattern "%s")')
% (key, actual_value, verify_value),
)
if "contains" in verify_dict:
Expand Down Expand Up @@ -150,7 +161,7 @@ def do_test_scopes_variables_setVariable_evaluate(
self.continue_to_breakpoints(breakpoint_ids)
locals = self.dap_server.get_local_variables()
globals = self.dap_server.get_global_variables()
buffer_children = make_buffer_verify_dict(0, 32)
buffer_children = make_buffer_verify_dict(0, 16)
verify_locals = {
"argc": {
"equals": {
Expand Down Expand Up @@ -243,18 +254,18 @@ def do_test_scopes_variables_setVariable_evaluate(
"pt": {
"equals": {"type": "PointType"},
"startswith": {
"result": "{x:11, y:22}"
"result": "{x:11, y:22, buffer:{...}}"
if enableAutoVariableSummaries
else "PointType @ 0x"
},
"hasVariablesReference": True,
},
"pt.buffer": {
"equals": {"type": "int[32]"},
"equals": {"type": "int[16]"},
"startswith": {
"result": "{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ...}"
if enableAutoVariableSummaries
else "int[32] @ 0x"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

out of curiosity, how is this rendered in the variables tab on VSCode? Something I tried to achieve with auto summaries is to use a single line for readability, so I'd like to know how this looks like in the UI

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the UI it will look like in the variable view:
Screenshot 2024-01-09 at 11 36 21 AM

Hover in the variable view:
Screenshot 2024-01-09 at 11 36 30 AM

Debug Console:
Screenshot 2024-01-09 at 11 47 52 AM

Debug Console Hover:
Screenshot 2024-01-09 at 11 48 02 AM

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quite an interesting coincidence that it looks nice when the children are expanded.

else "int[16] @ 0x"
},
"hasVariablesReference": True,
},
Expand Down Expand Up @@ -440,7 +451,7 @@ def do_test_scopes_and_evaluate_expansion(self, enableAutoVariableSummaries: boo
},
"buffer": {
"children": buffer_children,
"equals": {"indexedVariables": 32},
"equals": {"indexedVariables": 16},
},
},
},
Expand All @@ -455,15 +466,85 @@ def do_test_scopes_and_evaluate_expansion(self, enableAutoVariableSummaries: boo
# the other temporary (from other UI).
expandable_expression = {
"name": "pt",
"response": {
"equals": {"type": "PointType"},
"startswith": {
"result": "{x:11, y:22}"
if enableAutoVariableSummaries
else "PointType @ 0x"
"context": {
"repl": {
"equals": {"type": "PointType"},
"equals": {
"result": """(PointType) $0 = {
x = 11
y = 22
buffer = {
[0] = 0
[1] = 1
[2] = 2
[3] = 3
[4] = 4
[5] = 5
[6] = 6
[7] = 7
[8] = 8
[9] = 9
[10] = 10
[11] = 11
[12] = 12
[13] = 13
[14] = 14
[15] = 15
}
}"""
},
"missing": ["indexedVariables"],
"hasVariablesReference": True,
},
"hover": {
"equals": {"type": "PointType"},
"equals": {
"result": """(PointType) pt = {
x = 11
y = 22
buffer = {
[0] = 0
[1] = 1
[2] = 2
[3] = 3
[4] = 4
[5] = 5
[6] = 6
[7] = 7
[8] = 8
[9] = 9
[10] = 10
[11] = 11
[12] = 12
[13] = 13
[14] = 14
[15] = 15
}
}"""
},
"missing": ["indexedVariables"],
"hasVariablesReference": True,
},
"watch": {
"equals": {"type": "PointType"},
"startswith": {
"result": "{x:11, y:22, buffer:{...}}"
if enableAutoVariableSummaries
else "PointType @ 0x"
},
"missing": ["indexedVariables"],
"hasVariablesReference": True,
},
"variables": {
"equals": {"type": "PointType"},
"startswith": {
"result": "{x:11, y:22, buffer:{...}}"
if enableAutoVariableSummaries
else "PointType @ 0x"
},
"missing": ["indexedVariables"],
"hasVariablesReference": True,
},
"missing": ["indexedVariables"],
"hasVariablesReference": True,
},
"children": {
"x": {"equals": {"type": "int", "value": "11"}},
Expand All @@ -472,35 +553,29 @@ def do_test_scopes_and_evaluate_expansion(self, enableAutoVariableSummaries: boo
},
}

# Evaluate from permanent UI.
permanent_expr_varref_dict = {}
response = self.dap_server.request_evaluate(
expandable_expression["name"], frameIndex=0, threadId=None, context="repl"
)
self.verify_values(
expandable_expression["response"],
response["body"],
permanent_expr_varref_dict,
expandable_expression["name"],
)

# Evaluate from temporary UI.
temporary_expr_varref_dict = {}
response = self.dap_server.request_evaluate(expandable_expression["name"])
self.verify_values(
expandable_expression["response"],
response["body"],
temporary_expr_varref_dict,
expandable_expression["name"],
)
# Evaluate from known contexts.
expr_varref_dict = {}
for context, verify_dict in expandable_expression["context"].items():
response = self.dap_server.request_evaluate(
expandable_expression["name"],
frameIndex=0,
threadId=None,
context=context,
)
self.verify_values(
verify_dict,
response["body"],
expr_varref_dict,
expandable_expression["name"],
)

# Evaluate locals again.
locals = self.dap_server.get_local_variables()
self.verify_variables(verify_locals, locals)

# Verify the evaluated expressions before second locals evaluation
# can be expanded.
var_ref = temporary_expr_varref_dict[expandable_expression["name"]]
var_ref = expr_varref_dict[expandable_expression["name"]]
response = self.dap_server.request_variables(var_ref)
self.verify_variables(
expandable_expression["children"], response["body"]["variables"]
Expand All @@ -516,7 +591,7 @@ def do_test_scopes_and_evaluate_expansion(self, enableAutoVariableSummaries: boo
)
self.continue_to_breakpoints(breakpoint_ids)

var_ref = permanent_expr_varref_dict[expandable_expression["name"]]
var_ref = expr_varref_dict[expandable_expression["name"]]
response = self.dap_server.request_variables(var_ref)
self.verify_variables(
expandable_expression["children"], response["body"]["variables"]
Expand Down
2 changes: 1 addition & 1 deletion lldb/test/API/tools/lldb-dap/variables/main.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

#define BUFFER_SIZE 32
#define BUFFER_SIZE 16
struct PointType {
int x;
int y;
Expand Down
Loading