https://github.com/DrSergei updated https://github.com/llvm/llvm-project/pull/170644
>From a16f50d7da57310c8b473f3d88c8caeeed454407 Mon Sep 17 00:00:00 2001 From: Druzhkov Sergei <[email protected]> Date: Thu, 4 Dec 2025 14:31:36 +0300 Subject: [PATCH 1/5] [lldb-dap] Add clipboard context support --- lldb/include/lldb/API/SBValue.h | 2 +- lldb/source/API/SBValue.cpp | 7 +++- .../lldb-dap/evaluate/TestDAP_evaluate.py | 36 +++++++++++++++++++ lldb/tools/lldb-dap/Handler/RequestHandler.h | 3 +- lldb/tools/lldb-dap/JSONUtils.cpp | 9 ++--- 5 files changed, 50 insertions(+), 7 deletions(-) diff --git a/lldb/include/lldb/API/SBValue.h b/lldb/include/lldb/API/SBValue.h index 0f788ff602b70..91fa78b206cf2 100644 --- a/lldb/include/lldb/API/SBValue.h +++ b/lldb/include/lldb/API/SBValue.h @@ -318,7 +318,7 @@ class LLDB_API SBValue { lldb::SBValue Persist(); - bool GetDescription(lldb::SBStream &description); + bool GetDescription(lldb::SBStream &description, bool short_mode = false); bool GetExpressionPath(lldb::SBStream &description); diff --git a/lldb/source/API/SBValue.cpp b/lldb/source/API/SBValue.cpp index e300ecee3f8ac..5ff6f4dc301ea 100644 --- a/lldb/source/API/SBValue.cpp +++ b/lldb/source/API/SBValue.cpp @@ -1259,7 +1259,7 @@ lldb::SBValue SBValue::EvaluateExpression(const char *expr, return result; } -bool SBValue::GetDescription(SBStream &description) { +bool SBValue::GetDescription(SBStream &description, bool short_mode) { LLDB_INSTRUMENT_VA(this, description); Stream &strm = description.ref(); @@ -1270,6 +1270,11 @@ bool SBValue::GetDescription(SBStream &description) { DumpValueObjectOptions options; options.SetUseDynamicType(m_opaque_sp->GetUseDynamic()); options.SetUseSyntheticValue(m_opaque_sp->GetUseSynthetic()); + if (short_mode) { + options.SetAllowOnelinerMode(true); + options.SetHideRootName(true); + options.SetHideRootType(true); + } if (llvm::Error error = value_sp->Dump(strm, options)) { strm << "error: " << toString(std::move(error)); return false; diff --git a/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py b/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py index 95ad0f06d9a06..4562435cc82b3 100644 --- a/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py +++ b/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py @@ -81,6 +81,9 @@ def assertEvaluateFailure(self, expression): def isResultExpandedDescription(self): return self.context == "repl" + def isResultShortDescription(self): + return self.context == "clipboard" + def isExpressionParsedExpected(self): return self.context != "hover" @@ -165,6 +168,25 @@ def run_test_evaluate_expressions( want_type="my_struct *", want_varref=True, ) + elif self.isResultShortDescription(): + self.assertEvaluate( + "struct1", + "(foo = 15)", + want_type="my_struct", + want_varref=True, + ) + self.assertEvaluate( + "struct2", + r"0x.*", + want_type="my_struct *", + want_varref=True, + ) + self.assertEvaluate( + "struct3", + "nullptr", + want_type="my_struct *", + want_varref=True, + ) else: self.assertEvaluate( "struct1", @@ -236,6 +258,13 @@ def run_test_evaluate_expressions( want_type="my_struct", want_varref=True, ) + elif self.isResultShortDescription(): + self.assertEvaluate( + "struct1", + "(foo = 15)", + want_type="my_struct", + want_varref=True, + ) else: self.assertEvaluate( "struct1", @@ -355,3 +384,10 @@ def test_variable_evaluate_expressions(self): self.run_test_evaluate_expressions( "variables", enableAutoVariableSummaries=True ) + + @skipIfWindows + def test_variable_evaluate_expressions(self): + # Tests expression evaluations that are triggered when value copied in editor + self.run_test_evaluate_expressions( + "clipboard", enableAutoVariableSummaries=False + ) diff --git a/lldb/tools/lldb-dap/Handler/RequestHandler.h b/lldb/tools/lldb-dap/Handler/RequestHandler.h index 1e3d66ed3f795..3e8104f750ce6 100644 --- a/lldb/tools/lldb-dap/Handler/RequestHandler.h +++ b/lldb/tools/lldb-dap/Handler/RequestHandler.h @@ -293,7 +293,8 @@ class EvaluateRequestHandler llvm::Expected<protocol::EvaluateResponseBody> Run(const protocol::EvaluateArguments &) const override; FeatureSet GetSupportedFeatures() const override { - return {protocol::eAdapterFeatureEvaluateForHovers}; + return {protocol::eAdapterFeatureEvaluateForHovers, + protocol::eAdapterFeatureClipboardContext}; } }; diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp b/lldb/tools/lldb-dap/JSONUtils.cpp index 9a2142cd847ab..3915543dd74c4 100644 --- a/lldb/tools/lldb-dap/JSONUtils.cpp +++ b/lldb/tools/lldb-dap/JSONUtils.cpp @@ -662,9 +662,10 @@ VariableDescription::VariableDescription( } std::string VariableDescription::GetResult(protocol::EvaluateContext context) { - // In repl context, the results can be displayed as multiple lines so more - // detailed descriptions can be returned. - if (context != protocol::eEvaluateContextRepl) + // In repl and clipboard contexts, the results can be displayed as multiple + // lines so more detailed descriptions can be returned. + if (context != protocol::eEvaluateContextRepl && + context != protocol::eEvaluateContextClipboard) return display_value; if (!val.IsValid()) @@ -673,7 +674,7 @@ std::string VariableDescription::GetResult(protocol::EvaluateContext context) { // Try the SBValue::GetDescription(), which may call into language runtime // specific formatters (see ValueObjectPrinter). lldb::SBStream stream; - val.GetDescription(stream); + val.GetDescription(stream, context == protocol::eEvaluateContextClipboard); llvm::StringRef description = stream.GetData(); return description.trim().str(); } >From a46dbfb301c80e839f2f9310aa84d008aff57e06 Mon Sep 17 00:00:00 2001 From: Druzhkov Sergei <[email protected]> Date: Fri, 5 Dec 2025 12:56:29 +0300 Subject: [PATCH 2/5] Add description level and update tests --- lldb/include/lldb/API/SBValue.h | 5 +- lldb/source/API/SBValue.cpp | 17 ++-- .../lldb-dap/evaluate/TestDAP_evaluate.py | 88 +++++++++++++++++-- lldb/tools/lldb-dap/JSONUtils.cpp | 5 +- 4 files changed, 101 insertions(+), 14 deletions(-) diff --git a/lldb/include/lldb/API/SBValue.h b/lldb/include/lldb/API/SBValue.h index 91fa78b206cf2..b87b3274efdaf 100644 --- a/lldb/include/lldb/API/SBValue.h +++ b/lldb/include/lldb/API/SBValue.h @@ -12,6 +12,7 @@ #include "lldb/API/SBData.h" #include "lldb/API/SBDefines.h" #include "lldb/API/SBType.h" +#include "lldb/lldb-enumerations.h" class ValueImpl; class ValueLocker; @@ -318,7 +319,9 @@ class LLDB_API SBValue { lldb::SBValue Persist(); - bool GetDescription(lldb::SBStream &description, bool short_mode = false); + bool GetDescription( + lldb::SBStream &description, + lldb::DescriptionLevel description_level = eDescriptionLevelFull); bool GetExpressionPath(lldb::SBStream &description); diff --git a/lldb/source/API/SBValue.cpp b/lldb/source/API/SBValue.cpp index 5ff6f4dc301ea..7a208023bc19f 100644 --- a/lldb/source/API/SBValue.cpp +++ b/lldb/source/API/SBValue.cpp @@ -45,6 +45,7 @@ #include "lldb/API/SBProcess.h" #include "lldb/API/SBTarget.h" #include "lldb/API/SBThread.h" +#include "lldb/lldb-enumerations.h" #include <memory> @@ -1259,8 +1260,9 @@ lldb::SBValue SBValue::EvaluateExpression(const char *expr, return result; } -bool SBValue::GetDescription(SBStream &description, bool short_mode) { - LLDB_INSTRUMENT_VA(this, description); +bool SBValue::GetDescription(SBStream &description, + lldb::DescriptionLevel description_level) { + LLDB_INSTRUMENT_VA(this, description, description_level); Stream &strm = description.ref(); @@ -1268,12 +1270,17 @@ bool SBValue::GetDescription(SBStream &description, bool short_mode) { lldb::ValueObjectSP value_sp(GetSP(locker)); if (value_sp) { DumpValueObjectOptions options; - options.SetUseDynamicType(m_opaque_sp->GetUseDynamic()); - options.SetUseSyntheticValue(m_opaque_sp->GetUseSynthetic()); - if (short_mode) { + if (description_level != eDescriptionLevelInitial) { + options.SetUseDynamicType(m_opaque_sp->GetUseDynamic()); + options.SetUseSyntheticValue(m_opaque_sp->GetUseSynthetic()); + } + if (description_level == eDescriptionLevelBrief) { options.SetAllowOnelinerMode(true); options.SetHideRootName(true); options.SetHideRootType(true); + } else if (description_level == eDescriptionLevelVerbose) { + options.SetShowTypes(true); + options.SetShowLocation(true); } if (llvm::Error error = value_sp->Dump(strm, options)) { strm << "error: " << toString(std::move(error)); diff --git a/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py b/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py index 4562435cc82b3..7e0077f5887d1 100644 --- a/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py +++ b/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py @@ -333,17 +333,91 @@ def run_test_evaluate_expressions( # Now we check that values are updated after stepping self.continue_to_breakpoint(breakpoint_4) - self.assertEvaluate("my_vec", "size=2", want_varref=True) + if self.isResultExpandedDescription(): + self.assertEvaluate( + "my_vec", + r"\(std::vector<int>\) \$\d+ = size=2 {\n \[0\] = 1\n \[1\] = 2\n}", + want_varref=True, + ) + elif self.isResultShortDescription(): + self.assertEvaluate( + "my_vec", r"size=2 {\n \[0\] = 1\n \[1\] = 2\n}", want_varref=True + ) + else: + self.assertEvaluate("my_vec", "size=2", want_varref=True) self.continue_to_breakpoint(breakpoint_5) - self.assertEvaluate("my_vec", "size=3", want_varref=True) + if self.isResultExpandedDescription(): + self.assertEvaluate( + "my_vec", + r"\(std::vector<int>\) \$\d+ = size=3 {\n \[0\] = 1\n \[1\] = 2\n \[2\] = 3\n}", + want_varref=True, + ) + elif self.isResultShortDescription(): + self.assertEvaluate( + "my_vec", + r"size=3 {\n \[0\] = 1\n \[1\] = 2\n \[2\] = 3\n}", + want_varref=True, + ) + else: + self.assertEvaluate("my_vec", "size=3", want_varref=True) - self.assertEvaluate("my_map", "size=2", want_varref=True) + if self.isResultExpandedDescription(): + self.assertEvaluate( + "my_map", + r"\(std::map<int, int>\) \$\d+ = size=2 {\n \[0\] = \(first = 1, second = 2\)\n \[1\] = \(first = 2, second = 3\)\n}", + want_varref=True, + ) + elif self.isResultShortDescription(): + self.assertEvaluate( + "my_map", + r"size=2 {\n \[0\] = \(first = 1, second = 2\)\n \[1\] = \(first = 2, second = 3\)\n}", + want_varref=True, + ) + else: + self.assertEvaluate("my_map", "size=2", want_varref=True) self.continue_to_breakpoint(breakpoint_6) - self.assertEvaluate("my_map", "size=3", want_varref=True) + if self.isResultExpandedDescription(): + self.assertEvaluate( + "my_map", + r"\(std::map<int, int>\) \$\d+ = size=3 {\n \[0\] = \(first = 1, second = 2\)\n \[1\] = \(first = 2, second = 3\)\n \[2\] = \(first = 3, second = 4\)\n}", + want_varref=True, + ) + elif self.isResultShortDescription(): + self.assertEvaluate( + "my_map", + r"size=3 {\n \[0\] = \(first = 1, second = 2\)\n \[1\] = \(first = 2, second = 3\)\n \[2\] = \(first = 3, second = 4\)\n}", + want_varref=True, + ) + else: + self.assertEvaluate("my_map", "size=3", want_varref=True) - self.assertEvaluate("my_bool_vec", "size=1", want_varref=True) + if self.isResultExpandedDescription(): + self.assertEvaluate( + "my_bool_vec", + r"\(std::vector<bool>\) \$\d+ = size=1 {\n \[0\] = true\n}", + want_varref=True, + ) + elif self.isResultShortDescription(): + self.assertEvaluate( + "my_bool_vec", r"size=1 {\n \[0\] = true\n}", want_varref=True + ) + else: + self.assertEvaluate("my_bool_vec", "size=1", want_varref=True) self.continue_to_breakpoint(breakpoint_7) - self.assertEvaluate("my_bool_vec", "size=2", want_varref=True) + if self.isResultExpandedDescription(): + self.assertEvaluate( + "my_bool_vec", + r"\(std::vector<bool>\) \$\d+ = size=2 {\n \[0\] = true\n \[1\] = false\n}", + want_varref=True, + ) + elif self.isResultShortDescription(): + self.assertEvaluate( + "my_bool_vec", + r"size=2 {\n \[0\] = true\n \[1\] = false\n}", + want_varref=True, + ) + else: + self.assertEvaluate("my_bool_vec", "size=2", want_varref=True) self.continue_to_breakpoint(breakpoint_8) # Test memory read, especially with 'empty' repeat commands. @@ -386,7 +460,7 @@ def test_variable_evaluate_expressions(self): ) @skipIfWindows - def test_variable_evaluate_expressions(self): + def test_clipboard_evaluate_expressions(self): # Tests expression evaluations that are triggered when value copied in editor self.run_test_evaluate_expressions( "clipboard", enableAutoVariableSummaries=False diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp b/lldb/tools/lldb-dap/JSONUtils.cpp index 3915543dd74c4..8851af65d1c4f 100644 --- a/lldb/tools/lldb-dap/JSONUtils.cpp +++ b/lldb/tools/lldb-dap/JSONUtils.cpp @@ -674,7 +674,10 @@ std::string VariableDescription::GetResult(protocol::EvaluateContext context) { // Try the SBValue::GetDescription(), which may call into language runtime // specific formatters (see ValueObjectPrinter). lldb::SBStream stream; - val.GetDescription(stream, context == protocol::eEvaluateContextClipboard); + if (context == protocol::eEvaluateContextRepl) + val.GetDescription(stream, lldb::eDescriptionLevelFull); + else + val.GetDescription(stream, lldb::eDescriptionLevelBrief); llvm::StringRef description = stream.GetData(); return description.trim().str(); } >From 797a428485cd25f88b7bcd0f7b297a211ecd1a1c Mon Sep 17 00:00:00 2001 From: Druzhkov Sergei <[email protected]> Date: Fri, 5 Dec 2025 16:54:23 +0300 Subject: [PATCH 3/5] Add array test --- .../lldb-dap/evaluate/TestDAP_evaluate.py | 19 +++++++++++++++++++ .../test/API/tools/lldb-dap/evaluate/main.cpp | 1 + 2 files changed, 20 insertions(+) diff --git a/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py b/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py index 7e0077f5887d1..58ec6e0fd9e76 100644 --- a/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py +++ b/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py @@ -430,6 +430,25 @@ def run_test_evaluate_expressions( self.assertEvaluate("", ".* 14 .*\n", want_memref=False) self.assertEvaluate("", ".* 19 .*\n", want_memref=False) + if self.isResultExpandedDescription(): + self.assertEvaluate( + "my_longs", + r"\(long\[3\]\) \$\d+ = \(\[0\] = 5, \[1\] = 6, \[2\] = 7\)", + want_varref=True, + ) + elif self.isResultShortDescription(): + self.assertEvaluate( + "my_longs", + r"\(\[0\] = 5, \[1\] = 6, \[2\] = 7\)", + want_varref=True, + ) + else: + self.assertEvaluate( + "my_longs", + "{5, 6, 7}" if enableAutoVariableSummaries else r"long\[3\] @ 0x", + want_varref=True, + ) + self.continue_to_exit() @skipIfWindows diff --git a/lldb/test/API/tools/lldb-dap/evaluate/main.cpp b/lldb/test/API/tools/lldb-dap/evaluate/main.cpp index 1c3d258114b1f..112726677637c 100644 --- a/lldb/test/API/tools/lldb-dap/evaluate/main.cpp +++ b/lldb/test/API/tools/lldb-dap/evaluate/main.cpp @@ -47,5 +47,6 @@ int main(int argc, char const *argv[]) { my_bool_vec.push_back(true); // breakpoint 7 uint8_t my_ints[] = {5, 10, 15, 20, 25, 30}; + long my_longs[] = {5, 6, 7}; return 0; // breakpoint 8 } >From 8ee5ffe4719932715f0b62dd861a6ce9d9088b71 Mon Sep 17 00:00:00 2001 From: Druzhkov Sergei <[email protected]> Date: Fri, 5 Dec 2025 21:19:27 +0300 Subject: [PATCH 4/5] Fix review comments --- lldb/include/lldb/API/SBValue.h | 8 ++++---- lldb/source/API/SBValue.cpp | 5 +++++ .../tools/lldb-dap/evaluate/TestDAP_evaluate.py | 15 +-------------- 3 files changed, 10 insertions(+), 18 deletions(-) diff --git a/lldb/include/lldb/API/SBValue.h b/lldb/include/lldb/API/SBValue.h index b87b3274efdaf..dead11fba19fe 100644 --- a/lldb/include/lldb/API/SBValue.h +++ b/lldb/include/lldb/API/SBValue.h @@ -12,7 +12,6 @@ #include "lldb/API/SBData.h" #include "lldb/API/SBDefines.h" #include "lldb/API/SBType.h" -#include "lldb/lldb-enumerations.h" class ValueImpl; class ValueLocker; @@ -319,9 +318,10 @@ class LLDB_API SBValue { lldb::SBValue Persist(); - bool GetDescription( - lldb::SBStream &description, - lldb::DescriptionLevel description_level = eDescriptionLevelFull); + bool GetDescription(lldb::SBStream &description); + + bool GetDescription(lldb::SBStream &description, + lldb::DescriptionLevel description_level); bool GetExpressionPath(lldb::SBStream &description); diff --git a/lldb/source/API/SBValue.cpp b/lldb/source/API/SBValue.cpp index 7a208023bc19f..67ef407ed3f9c 100644 --- a/lldb/source/API/SBValue.cpp +++ b/lldb/source/API/SBValue.cpp @@ -1260,6 +1260,11 @@ lldb::SBValue SBValue::EvaluateExpression(const char *expr, return result; } +bool SBValue::GetDescription(SBStream &description) { + LLDB_INSTRUMENT_VA(this, description); + return GetDescription(description, eDescriptionLevelFull); +} + bool SBValue::GetDescription(SBStream &description, lldb::DescriptionLevel description_level) { LLDB_INSTRUMENT_VA(this, description, description_level); diff --git a/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py b/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py index 58ec6e0fd9e76..2aa2d51acfaeb 100644 --- a/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py +++ b/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py @@ -376,20 +376,7 @@ def run_test_evaluate_expressions( else: self.assertEvaluate("my_map", "size=2", want_varref=True) self.continue_to_breakpoint(breakpoint_6) - if self.isResultExpandedDescription(): - self.assertEvaluate( - "my_map", - r"\(std::map<int, int>\) \$\d+ = size=3 {\n \[0\] = \(first = 1, second = 2\)\n \[1\] = \(first = 2, second = 3\)\n \[2\] = \(first = 3, second = 4\)\n}", - want_varref=True, - ) - elif self.isResultShortDescription(): - self.assertEvaluate( - "my_map", - r"size=3 {\n \[0\] = \(first = 1, second = 2\)\n \[1\] = \(first = 2, second = 3\)\n \[2\] = \(first = 3, second = 4\)\n}", - want_varref=True, - ) - else: - self.assertEvaluate("my_map", "size=3", want_varref=True) + self.assertEvaluate("my_map", "size=3", want_varref=True) if self.isResultExpandedDescription(): self.assertEvaluate( >From e623235a9a6047cee162af0a7f2c2adefd412821 Mon Sep 17 00:00:00 2001 From: Sergei Druzhkov <[email protected]> Date: Tue, 6 Jan 2026 16:22:41 +0300 Subject: [PATCH 5/5] Fix test --- lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py b/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py index 2aa2d51acfaeb..bc08462cfcba9 100644 --- a/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py +++ b/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py @@ -432,7 +432,7 @@ def run_test_evaluate_expressions( else: self.assertEvaluate( "my_longs", - "{5, 6, 7}" if enableAutoVariableSummaries else r"long\[3\] @ 0x", + "{5, 6, 7}" if enableAutoVariableSummaries else r"long\[3\]", want_varref=True, ) _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
