[Lldb-commits] [lldb] [lldb-dap] Adjust variable display values. (PR #146754)
via lldb-commits
lldb-commits at lists.llvm.org
Wed Jul 2 11:20:22 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lldb
Author: John Harrison (ashgti)
<details>
<summary>Changes</summary>
This corrects a mistake I made when I previously tried to add support for obj-c/swift variables in lldb-dap. This should call into `GetObjectDescription` if there is no summary of the type available and the description is not empty.
I also added a unit test to verify this.
---
Full diff: https://github.com/llvm/llvm-project/pull/146754.diff
5 Files Affected:
- (added) lldb/test/API/tools/lldb-dap/variables/objc/Makefile (+9)
- (added) lldb/test/API/tools/lldb-dap/variables/objc/TestDAP_variables_objc.py (+31)
- (added) lldb/test/API/tools/lldb-dap/variables/objc/main.m (+45)
- (modified) lldb/tools/lldb-dap/JSONUtils.cpp (+12-8)
- (modified) lldb/tools/lldb-dap/JSONUtils.h (+3)
``````````diff
diff --git a/lldb/test/API/tools/lldb-dap/variables/objc/Makefile b/lldb/test/API/tools/lldb-dap/variables/objc/Makefile
new file mode 100644
index 0000000000000..71d7ec417633f
--- /dev/null
+++ b/lldb/test/API/tools/lldb-dap/variables/objc/Makefile
@@ -0,0 +1,9 @@
+OBJC_SOURCES := main.m
+
+CFLAGS_EXTRAS := -w -fobjc-arc
+
+USE_SYSTEM_STDLIB := 1
+
+LD_EXTRAS := -framework Foundation
+
+include Makefile.rules
diff --git a/lldb/test/API/tools/lldb-dap/variables/objc/TestDAP_variables_objc.py b/lldb/test/API/tools/lldb-dap/variables/objc/TestDAP_variables_objc.py
new file mode 100644
index 0000000000000..9dcbed50987b9
--- /dev/null
+++ b/lldb/test/API/tools/lldb-dap/variables/objc/TestDAP_variables_objc.py
@@ -0,0 +1,31 @@
+"""
+Test 'variables' requests for obj-c types.
+"""
+
+import lldbdap_testcase
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+
+
+class TestDAP_variables_objc(lldbdap_testcase.DAPTestCaseBase):
+ @skipUnlessDarwin
+ def test_objc_description(self):
+ """Test that we can get the description of an Objective-C object."""
+ program = self.getBuildArtifact("a.out")
+ self.build_and_launch(
+ program,
+ )
+ source = "main.m"
+ breakpoint_ids = self.set_source_breakpoints(
+ source, [line_number(source, "// breakpoint")]
+ )
+ self.continue_to_breakpoints(breakpoint_ids)
+
+ greeter_var = self.dap_server.get_local_variable(name="greeter")
+ self.assertIsNotNone(greeter_var, "greeter variable should not be None")
+ self.assertEqual(greeter_var["type"], "Greeter *")
+ self.assertEqual(greeter_var["evaluateName"], "greeter")
+ self.assertRegexpMatches(
+ greeter_var["value"], r"<Greeter 0x[0-9A-Fa-f]+ name=Bob debugDescription>"
+ )
+ self.continue_to_exit()
diff --git a/lldb/test/API/tools/lldb-dap/variables/objc/main.m b/lldb/test/API/tools/lldb-dap/variables/objc/main.m
new file mode 100644
index 0000000000000..aeafa0019af8c
--- /dev/null
+++ b/lldb/test/API/tools/lldb-dap/variables/objc/main.m
@@ -0,0 +1,45 @@
+#import <Foundation/Foundation.h>
+
+ at interface Greeter : NSObject
+
+ at property(nonatomic, strong) NSString *name;
+
+- (void)greet:(NSString *)other;
+
+ at end
+
+ at implementation Greeter
+
+- (instancetype)initWithName:(NSString *)name {
+ if ((self = [super init])) {
+ _name = [name copy];
+ }
+ return self;
+}
+
+- (void)greet:(NSString *)other {
+ NSLog(@"Hello %@, from %@", other, _name);
+}
+
+- (NSString *)description {
+ return
+ [NSString stringWithFormat:@"<Greeter %p name=%@>", (void *)self, _name];
+}
+
+- (NSString *)debugDescription {
+ return [NSString stringWithFormat:@"<Greeter %p name=%@ debugDescription>",
+ (void *)self, _name];
+}
+
+ at end
+
+int main(int argc, char *argv[]) {
+ Greeter *greeter = [[Greeter alloc] initWithName:@"Bob"];
+ if (argc > 1) {
+ [greeter greet:@(argv[1])];
+ } else {
+ [greeter greet:@"World"];
+ }
+
+ return 0; // breakpoint
+}
diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp b/lldb/tools/lldb-dap/JSONUtils.cpp
index 08e65ab835a57..a42b4af05d782 100644
--- a/lldb/tools/lldb-dap/JSONUtils.cpp
+++ b/lldb/tools/lldb-dap/JSONUtils.cpp
@@ -836,6 +836,7 @@ VariableDescription::VariableDescription(lldb::SBValue v,
os_display_value << "<error: " << error << ">";
} else {
value = llvm::StringRef(v.GetValue()).str();
+ object_description = llvm::StringRef(v.GetObjectDescription()).str();
summary = llvm::StringRef(v.GetSummary()).str();
if (summary.empty() && auto_variable_summaries)
auto_summary = TryCreateAutoSummary(v);
@@ -843,7 +844,10 @@ VariableDescription::VariableDescription(lldb::SBValue v,
std::optional<std::string> effective_summary =
!summary.empty() ? summary : auto_summary;
- if (!value.empty()) {
+ if (!object_description.empty() &&
+ (!effective_summary || effective_summary->empty())) {
+ os_display_value << object_description;
+ } else if (!value.empty()) {
os_display_value << value;
if (effective_summary)
os_display_value << " " << *effective_summary;
@@ -901,18 +905,18 @@ llvm::json::Object VariableDescription::GetVariableExtensionsJSON() {
std::string VariableDescription::GetResult(llvm::StringRef context) {
// In repl context, the results can be displayed as multiple lines so more
// detailed descriptions can be returned.
- if (context != "repl")
+ if (context != "repl" || !v.IsValid())
return display_value;
- if (!v.IsValid())
- return display_value;
+ // First, try the SBValue::GetObjectDescription(), which may call into
+ // language runtime specific formatters (see ValueObjectPrinter).
+ if (!object_description.empty())
+ return object_description;
- // Try the SBValue::GetDescription(), which may call into language runtime
- // specific formatters (see ValueObjectPrinter).
+ // Fallback to the default description for the value.
lldb::SBStream stream;
v.GetDescription(stream);
- llvm::StringRef description = stream.GetData();
- return description.trim().str();
+ return llvm::StringRef(stream.GetData()).trim().str();
}
bool ValuePointsToCode(lldb::SBValue v) {
diff --git a/lldb/tools/lldb-dap/JSONUtils.h b/lldb/tools/lldb-dap/JSONUtils.h
index fd9a06931ebff..0a660d04d02d8 100644
--- a/lldb/tools/lldb-dap/JSONUtils.h
+++ b/lldb/tools/lldb-dap/JSONUtils.h
@@ -329,6 +329,9 @@ struct VariableDescription {
std::string evaluate_name;
// The output of SBValue.GetValue() if it doesn't fail. It might be empty.
std::string value;
+ // The output of SBValue.GetObjectDescription() if it doesn't fail. It might
+ // be empty.
+ std::string object_description;
// The summary string of this variable. It might be empty.
std::string summary;
// The auto summary if using `enableAutoVariableSummaries`.
``````````
</details>
https://github.com/llvm/llvm-project/pull/146754
More information about the lldb-commits
mailing list