Skip to content

Commit b8d38bb

Browse files
jeffreytan81jeffreytan81
andauthored
Fix dap variable value format issue (#90799)
While adding a UI feature in VSCode to toggle hex/dec in variables view window. I noticed that it does not work after second toggle. Then I noticed that there is a bug that we only explicitly set hex format not reset back to default during further toggle. The new test demonstrates the bug. This PR resets the format back to default if not using hex. One complexity is that, we explicitly set registers value format to AddressInfo, which shouldn't be overridden by default or hex settings. --------- Co-authored-by: jeffreytan81 <[email protected]>
1 parent 2cde0e2 commit b8d38bb

File tree

3 files changed

+69
-16
lines changed

3 files changed

+69
-16
lines changed

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

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,7 @@ def get_completions(self, text, frameId=None):
448448
response = self.request_completions(text, frameId)
449449
return response["body"]["targets"]
450450

451-
def get_scope_variables(self, scope_name, frameIndex=0, threadId=None):
451+
def get_scope_variables(self, scope_name, frameIndex=0, threadId=None, is_hex=None):
452452
stackFrame = self.get_stackFrame(frameIndex=frameIndex, threadId=threadId)
453453
if stackFrame is None:
454454
return []
@@ -462,7 +462,7 @@ def get_scope_variables(self, scope_name, frameIndex=0, threadId=None):
462462
for scope in frame_scopes:
463463
if scope["name"] == scope_name:
464464
varRef = scope["variablesReference"]
465-
variables_response = self.request_variables(varRef)
465+
variables_response = self.request_variables(varRef, is_hex=is_hex)
466466
if variables_response:
467467
if "body" in variables_response:
468468
body = variables_response["body"]
@@ -476,38 +476,42 @@ def get_global_variables(self, frameIndex=0, threadId=None):
476476
"Globals", frameIndex=frameIndex, threadId=threadId
477477
)
478478

479-
def get_local_variables(self, frameIndex=0, threadId=None):
479+
def get_local_variables(self, frameIndex=0, threadId=None, is_hex=None):
480480
return self.get_scope_variables(
481-
"Locals", frameIndex=frameIndex, threadId=threadId
481+
"Locals", frameIndex=frameIndex, threadId=threadId, is_hex=is_hex
482482
)
483483

484484
def get_registers(self, frameIndex=0, threadId=None):
485485
return self.get_scope_variables(
486486
"Registers", frameIndex=frameIndex, threadId=threadId
487487
)
488488

489-
def get_local_variable(self, name, frameIndex=0, threadId=None):
490-
locals = self.get_local_variables(frameIndex=frameIndex, threadId=threadId)
489+
def get_local_variable(self, name, frameIndex=0, threadId=None, is_hex=None):
490+
locals = self.get_local_variables(
491+
frameIndex=frameIndex, threadId=threadId, is_hex=is_hex
492+
)
491493
for local in locals:
492494
if "name" in local and local["name"] == name:
493495
return local
494496
return None
495497

496-
def get_local_variable_value(self, name, frameIndex=0, threadId=None):
498+
def get_local_variable_value(self, name, frameIndex=0, threadId=None, is_hex=None):
497499
variable = self.get_local_variable(
498-
name, frameIndex=frameIndex, threadId=threadId
500+
name, frameIndex=frameIndex, threadId=threadId, is_hex=is_hex
499501
)
500502
if variable and "value" in variable:
501503
return variable["value"]
502504
return None
503505

504-
def get_local_variable_child(self, name, child_name, frameIndex=0, threadId=None):
506+
def get_local_variable_child(
507+
self, name, child_name, frameIndex=0, threadId=None, is_hex=None
508+
):
505509
local = self.get_local_variable(name, frameIndex, threadId)
506510
if local["variablesReference"] == 0:
507511
return None
508-
children = self.request_variables(local["variablesReference"])["body"][
509-
"variables"
510-
]
512+
children = self.request_variables(local["variablesReference"], is_hex=is_hex)[
513+
"body"
514+
]["variables"]
511515
for child in children:
512516
if child["name"] == child_name:
513517
return child
@@ -1035,12 +1039,16 @@ def request_threads(self):
10351039
self.threads = None
10361040
return response
10371041

1038-
def request_variables(self, variablesReference, start=None, count=None):
1042+
def request_variables(
1043+
self, variablesReference, start=None, count=None, is_hex=None
1044+
):
10391045
args_dict = {"variablesReference": variablesReference}
10401046
if start is not None:
10411047
args_dict["start"] = start
10421048
if count is not None:
10431049
args_dict["count"] = count
1050+
if is_hex is not None:
1051+
args_dict["format"] = {"hex": is_hex}
10441052
command_dict = {
10451053
"command": "variables",
10461054
"type": "request",

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

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -754,3 +754,43 @@ def test_darwin_dwarf_missing_obj_with_symbol_ondemand_enabled(self):
754754
"""
755755
initCommands = ["settings set symbols.load-on-demand true"]
756756
self.darwin_dwarf_missing_obj(initCommands)
757+
758+
@no_debug_info_test
759+
@skipIfWindows
760+
@skipIfRemote
761+
def test_value_format(self):
762+
"""
763+
Test that toggle variables value format between decimal and hexical works.
764+
"""
765+
program = self.getBuildArtifact("a.out")
766+
self.build_and_launch(program)
767+
source = "main.cpp"
768+
breakpoint1_line = line_number(source, "// breakpoint 1")
769+
lines = [breakpoint1_line]
770+
771+
breakpoint_ids = self.set_source_breakpoints(source, lines)
772+
self.assertEqual(
773+
len(breakpoint_ids), len(lines), "expect correct number of breakpoints"
774+
)
775+
self.continue_to_breakpoints(breakpoint_ids)
776+
777+
# Verify locals value format decimal
778+
is_hex = False
779+
var_pt_x = self.dap_server.get_local_variable_child("pt", "x", is_hex=is_hex)
780+
self.assertEquals(var_pt_x["value"], "11")
781+
var_pt_y = self.dap_server.get_local_variable_child("pt", "y", is_hex=is_hex)
782+
self.assertEquals(var_pt_y["value"], "22")
783+
784+
# Verify locals value format hexical
785+
is_hex = True
786+
var_pt_x = self.dap_server.get_local_variable_child("pt", "x", is_hex=is_hex)
787+
self.assertEquals(var_pt_x["value"], "0x0000000b")
788+
var_pt_y = self.dap_server.get_local_variable_child("pt", "y", is_hex=is_hex)
789+
self.assertEquals(var_pt_y["value"], "0x00000016")
790+
791+
# Toggle and verify locals value format decimal again
792+
is_hex = False
793+
var_pt_x = self.dap_server.get_local_variable_child("pt", "x", is_hex=is_hex)
794+
self.assertEquals(var_pt_x["value"], "11")
795+
var_pt_y = self.dap_server.get_local_variable_child("pt", "y", is_hex=is_hex)
796+
self.assertEquals(var_pt_y["value"], "22")

lldb/tools/lldb-dap/JSONUtils.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -754,7 +754,6 @@ llvm::json::Value CreateStackFrame(lldb::SBFrame &frame) {
754754
} else {
755755
object.try_emplace("line", 0);
756756
object.try_emplace("column", 0);
757-
object.try_emplace("presentationHint", "subtle");
758757
}
759758

760759
const auto pc = frame.GetPC();
@@ -987,8 +986,14 @@ VariableDescription::VariableDescription(lldb::SBValue v, bool format_hex,
987986
display_type_name =
988987
!raw_display_type_name.empty() ? raw_display_type_name : NO_TYPENAME;
989988

990-
if (format_hex)
991-
v.SetFormat(lldb::eFormatHex);
989+
// Only format hex/default if there is no existing special format.
990+
if (v.GetFormat() == lldb::eFormatDefault ||
991+
v.GetFormat() == lldb::eFormatHex) {
992+
if (format_hex)
993+
v.SetFormat(lldb::eFormatHex);
994+
else
995+
v.SetFormat(lldb::eFormatDefault);
996+
}
992997

993998
llvm::raw_string_ostream os_display_value(display_value);
994999

0 commit comments

Comments
 (0)