[Lldb-commits] [lldb] [lldb][lldb-dap] fix repeating commands in repl mode (PR #135008)

Ebuka Ezike via lldb-commits lldb-commits at lists.llvm.org
Wed Apr 16 12:41:27 PDT 2025


https://github.com/da-viper updated https://github.com/llvm/llvm-project/pull/135008

>From 296019edb5edba4a21e040feb154b1ef83f1e64d Mon Sep 17 00:00:00 2001
From: Ebuka Ezike <yerimyah1 at gmail.com>
Date: Wed, 9 Apr 2025 14:35:09 +0100
Subject: [PATCH 1/5] [lldb][lldb-dap] fix repeating commands in repl mode

Fixes #131589
Add a new option to the RunCommands* functions to control the echoing of commands
---
 .../lldb-dap/evaluate/TestDAP_evaluate.py     |  2 +-
 .../tools/lldb-dap/launch/TestDAP_launch.py   |  4 +--
 .../repl-mode/TestDAP_repl_mode_detection.py  | 11 +++---
 lldb/tools/lldb-dap/DAP.cpp                   |  6 ++--
 lldb/tools/lldb-dap/DAP.h                     |  3 +-
 .../Handler/EvaluateRequestHandler.cpp        |  3 +-
 lldb/tools/lldb-dap/LLDBUtils.cpp             | 35 ++++++++++++++-----
 lldb/tools/lldb-dap/LLDBUtils.h               | 19 +++++++---
 8 files changed, 54 insertions(+), 29 deletions(-)

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 251d77d79d080..e2f843bd337a6 100644
--- a/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py
+++ b/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py
@@ -101,7 +101,7 @@ def run_test_evaluate_expressions(
         if context == "repl":
             # In the repl context expressions may be interpreted as lldb
             # commands since no variables have the same name as the command.
-            self.assertEvaluate("list", r"\(lldb\) list\n.*")
+            self.assertEvaluate("list", r".*")
         else:
             self.assertEvaluateFailure("list")  # local variable of a_function
 
diff --git a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py
index 64c99019a1c9b..eceba2f8a13cb 100644
--- a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py
+++ b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py
@@ -522,11 +522,9 @@ def test_version(self):
         )
         version_eval_output = version_eval_response["body"]["result"]
 
-        # The first line is the prompt line like "(lldb) version", so we skip it.
-        version_eval_output_without_prompt_line = version_eval_output.splitlines()[1:]
         version_string = self.dap_server.get_initialize_value("$__lldb_version")
         self.assertEqual(
-            version_eval_output_without_prompt_line,
+            version_eval_output.splitlines(),
             version_string.splitlines(),
             "version string does not match",
         )
diff --git a/lldb/test/API/tools/lldb-dap/repl-mode/TestDAP_repl_mode_detection.py b/lldb/test/API/tools/lldb-dap/repl-mode/TestDAP_repl_mode_detection.py
index 7c77fc8541b93..09ca725ee8883 100644
--- a/lldb/test/API/tools/lldb-dap/repl-mode/TestDAP_repl_mode_detection.py
+++ b/lldb/test/API/tools/lldb-dap/repl-mode/TestDAP_repl_mode_detection.py
@@ -28,15 +28,12 @@ def test_completions(self):
 
         self.set_source_breakpoints(source, [breakpoint1_line, breakpoint2_line])
 
-        self.assertEvaluate(
-            "`command regex user_command s/^$/platform/", r"\(lldb\) command regex"
-        )
-        self.assertEvaluate(
-            "`command alias alias_command platform", r"\(lldb\) command alias"
-        )
+        # the result of the commands should return the empty string.
+        self.assertEvaluate("`command regex user_command s/^$/platform/", r"^$")
+        self.assertEvaluate("`command alias alias_command platform", r"^$")
         self.assertEvaluate(
             "`command alias alias_command_with_arg platform select --sysroot %1 remote-linux",
-            r"\(lldb\) command alias",
+            r"^$",
         )
 
         self.continue_to_next_stop()
diff --git a/lldb/tools/lldb-dap/DAP.cpp b/lldb/tools/lldb-dap/DAP.cpp
index 9361ba968e9c2..03b9dc7135ef7 100644
--- a/lldb/tools/lldb-dap/DAP.cpp
+++ b/lldb/tools/lldb-dap/DAP.cpp
@@ -561,10 +561,12 @@ ReplMode DAP::DetectReplMode(lldb::SBFrame frame, std::string &expression,
 }
 
 bool DAP::RunLLDBCommands(llvm::StringRef prefix,
-                          llvm::ArrayRef<std::string> commands) {
+                          llvm::ArrayRef<std::string> commands,
+                          bool echo_commands) {
   bool required_command_failed = false;
   std::string output =
-      ::RunLLDBCommands(debugger, prefix, commands, required_command_failed);
+      ::RunLLDBCommands(debugger, prefix, commands, required_command_failed,
+                        /*parse_command_directives*/ true, echo_commands);
   SendOutput(OutputType::Console, output);
   return !required_command_failed;
 }
diff --git a/lldb/tools/lldb-dap/DAP.h b/lldb/tools/lldb-dap/DAP.h
index fc43d988f3a09..cb3431cc87fd1 100644
--- a/lldb/tools/lldb-dap/DAP.h
+++ b/lldb/tools/lldb-dap/DAP.h
@@ -290,7 +290,8 @@ struct DAP {
   ///   \b false if a fatal error was found while executing these commands,
   ///   according to the rules of \a LLDBUtils::RunLLDBCommands.
   bool RunLLDBCommands(llvm::StringRef prefix,
-                       llvm::ArrayRef<std::string> commands);
+                       llvm::ArrayRef<std::string> commands,
+                       bool echo_commands = true);
 
   llvm::Error RunAttachCommands(llvm::ArrayRef<std::string> attach_commands);
   llvm::Error RunLaunchCommands(llvm::ArrayRef<std::string> launch_commands);
diff --git a/lldb/tools/lldb-dap/Handler/EvaluateRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/EvaluateRequestHandler.cpp
index 8ed09fa2a931a..cd7b367d41d20 100644
--- a/lldb/tools/lldb-dap/Handler/EvaluateRequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/EvaluateRequestHandler.cpp
@@ -164,7 +164,8 @@ void EvaluateRequestHandler::operator()(
       dap.focus_tid = frame.GetThread().GetThreadID();
     }
     auto result = RunLLDBCommandsVerbatim(dap.debugger, llvm::StringRef(),
-                                          {std::string(expression)});
+                                          {std::string(expression)},
+                                          /*echo_commands*/ false);
     EmplaceSafeString(body, "result", result);
     body.try_emplace("variablesReference", (int64_t)0);
   } else {
diff --git a/lldb/tools/lldb-dap/LLDBUtils.cpp b/lldb/tools/lldb-dap/LLDBUtils.cpp
index a27beff0b030d..393cd7c43e34e 100644
--- a/lldb/tools/lldb-dap/LLDBUtils.cpp
+++ b/lldb/tools/lldb-dap/LLDBUtils.cpp
@@ -17,12 +17,24 @@ namespace lldb_dap {
 
 bool RunLLDBCommands(lldb::SBDebugger &debugger, llvm::StringRef prefix,
                      const llvm::ArrayRef<std::string> &commands,
-                     llvm::raw_ostream &strm, bool parse_command_directives) {
+                     llvm::raw_ostream &strm, bool parse_command_directives,
+                     bool echo_commands) {
   if (commands.empty())
     return true;
 
   bool did_print_prefix = false;
 
+  // Get the default prompt from settings.
+  std::string prompt_string = "(lldb) ";
+  if (const lldb::SBStructuredData prompt = debugger.GetSetting("prompt")) {
+    const size_t prompt_length = prompt.GetStringValue(nullptr, 0);
+
+    if (prompt_length != 0) {
+      prompt_string.resize(prompt_length + 1);
+      prompt.GetStringValue(prompt_string.data(), prompt_string.length());
+    }
+  }
+
   lldb::SBCommandInterpreter interp = debugger.GetCommandInterpreter();
   for (llvm::StringRef command : commands) {
     lldb::SBCommandReturnObject result;
@@ -60,7 +72,10 @@ bool RunLLDBCommands(lldb::SBDebugger &debugger, llvm::StringRef prefix,
         strm << prefix << "\n";
         did_print_prefix = true;
       }
-      strm << "(lldb) " << command << "\n";
+
+      if (echo_commands)
+        strm << prompt_string.c_str() << command << '\n';
+
       auto output_len = result.GetOutputSize();
       if (output_len) {
         const char *output = result.GetOutput();
@@ -81,21 +96,23 @@ bool RunLLDBCommands(lldb::SBDebugger &debugger, llvm::StringRef prefix,
 std::string RunLLDBCommands(lldb::SBDebugger &debugger, llvm::StringRef prefix,
                             const llvm::ArrayRef<std::string> &commands,
                             bool &required_command_failed,
-                            bool parse_command_directives) {
+                            bool parse_command_directives, bool echo_commands) {
   required_command_failed = false;
   std::string s;
   llvm::raw_string_ostream strm(s);
-  required_command_failed = !RunLLDBCommands(debugger, prefix, commands, strm,
-                                             parse_command_directives);
+  required_command_failed =
+      !RunLLDBCommands(debugger, prefix, commands, strm,
+                       parse_command_directives, echo_commands);
   return s;
 }
 
-std::string
-RunLLDBCommandsVerbatim(lldb::SBDebugger &debugger, llvm::StringRef prefix,
-                        const llvm::ArrayRef<std::string> &commands) {
+std::string RunLLDBCommandsVerbatim(lldb::SBDebugger &debugger,
+                                    llvm::StringRef prefix,
+                                    const llvm::ArrayRef<std::string> &commands,
+                                    bool echo_commands) {
   bool required_command_failed = false;
   return RunLLDBCommands(debugger, prefix, commands, required_command_failed,
-                         /*parse_command_directives=*/false);
+                         /*parse_command_directives=*/false, echo_commands);
 }
 
 bool ThreadHasStopReason(lldb::SBThread &thread) {
diff --git a/lldb/tools/lldb-dap/LLDBUtils.h b/lldb/tools/lldb-dap/LLDBUtils.h
index 2c57847303cb3..d526ed431fff3 100644
--- a/lldb/tools/lldb-dap/LLDBUtils.h
+++ b/lldb/tools/lldb-dap/LLDBUtils.h
@@ -51,12 +51,16 @@ namespace lldb_dap {
 ///     If \b false, then command prefixes like \b ! or \b ? are not parsed and
 ///     each command is executed verbatim.
 ///
+/// \param[in] echo_commands
+///     If \b true, the command are echoed to the stream.
+///
 /// \return
 ///     \b true, unless a command prefixed with \b ! fails and parsing of
 ///     command directives is enabled.
 bool RunLLDBCommands(lldb::SBDebugger &debugger, llvm::StringRef prefix,
                      const llvm::ArrayRef<std::string> &commands,
-                     llvm::raw_ostream &strm, bool parse_command_directives);
+                     llvm::raw_ostream &strm, bool parse_command_directives,
+                     bool echo_commands);
 
 /// Run a list of LLDB commands in the LLDB command interpreter.
 ///
@@ -81,18 +85,23 @@ bool RunLLDBCommands(lldb::SBDebugger &debugger, llvm::StringRef prefix,
 ///     If \b false, then command prefixes like \b ! or \b ? are not parsed and
 ///     each command is executed verbatim.
 ///
+/// \param[in] echo_commands
+///     If \b true, the command are echoed to the stream.
+///
 /// \return
 ///     A std::string that contains the prefix and all commands and
 ///     command output.
 std::string RunLLDBCommands(lldb::SBDebugger &debugger, llvm::StringRef prefix,
                             const llvm::ArrayRef<std::string> &commands,
                             bool &required_command_failed,
-                            bool parse_command_directives = true);
+                            bool parse_command_directives = true,
+                            bool echo_commands = true);
 
 /// Similar to the method above, but without parsing command directives.
-std::string
-RunLLDBCommandsVerbatim(lldb::SBDebugger &debugger, llvm::StringRef prefix,
-                        const llvm::ArrayRef<std::string> &commands);
+std::string RunLLDBCommandsVerbatim(lldb::SBDebugger &debugger,
+                                    llvm::StringRef prefix,
+                                    const llvm::ArrayRef<std::string> &commands,
+                                    bool echo_commands);
 
 /// Check if a thread has a stop reason.
 ///

>From 4f97db30a4c74a2e5efe75e4200b70a016fef6e1 Mon Sep 17 00:00:00 2001
From: Ebuka Ezike <yerimyah1 at gmail.com>
Date: Fri, 11 Apr 2025 10:11:27 +0100
Subject: [PATCH 2/5] [lldb][lldb-dap] update review requests

---
 lldb/tools/lldb-dap/DAP.cpp       |  9 ++++-----
 lldb/tools/lldb-dap/DAP.h         |  3 +--
 lldb/tools/lldb-dap/LLDBUtils.cpp | 21 +++++++++++++--------
 3 files changed, 18 insertions(+), 15 deletions(-)

diff --git a/lldb/tools/lldb-dap/DAP.cpp b/lldb/tools/lldb-dap/DAP.cpp
index 03b9dc7135ef7..e6712990c0ec6 100644
--- a/lldb/tools/lldb-dap/DAP.cpp
+++ b/lldb/tools/lldb-dap/DAP.cpp
@@ -561,12 +561,11 @@ ReplMode DAP::DetectReplMode(lldb::SBFrame frame, std::string &expression,
 }
 
 bool DAP::RunLLDBCommands(llvm::StringRef prefix,
-                          llvm::ArrayRef<std::string> commands,
-                          bool echo_commands) {
+                          llvm::ArrayRef<std::string> commands) {
   bool required_command_failed = false;
-  std::string output =
-      ::RunLLDBCommands(debugger, prefix, commands, required_command_failed,
-                        /*parse_command_directives*/ true, echo_commands);
+  std::string output = ::RunLLDBCommands(
+      debugger, prefix, commands, required_command_failed,
+      /*parse_command_directives*/ true, /*echo_commands*/ true);
   SendOutput(OutputType::Console, output);
   return !required_command_failed;
 }
diff --git a/lldb/tools/lldb-dap/DAP.h b/lldb/tools/lldb-dap/DAP.h
index cb3431cc87fd1..fc43d988f3a09 100644
--- a/lldb/tools/lldb-dap/DAP.h
+++ b/lldb/tools/lldb-dap/DAP.h
@@ -290,8 +290,7 @@ struct DAP {
   ///   \b false if a fatal error was found while executing these commands,
   ///   according to the rules of \a LLDBUtils::RunLLDBCommands.
   bool RunLLDBCommands(llvm::StringRef prefix,
-                       llvm::ArrayRef<std::string> commands,
-                       bool echo_commands = true);
+                       llvm::ArrayRef<std::string> commands);
 
   llvm::Error RunAttachCommands(llvm::ArrayRef<std::string> attach_commands);
   llvm::Error RunLaunchCommands(llvm::ArrayRef<std::string> launch_commands);
diff --git a/lldb/tools/lldb-dap/LLDBUtils.cpp b/lldb/tools/lldb-dap/LLDBUtils.cpp
index 393cd7c43e34e..5b76b67b128fb 100644
--- a/lldb/tools/lldb-dap/LLDBUtils.cpp
+++ b/lldb/tools/lldb-dap/LLDBUtils.cpp
@@ -24,14 +24,19 @@ bool RunLLDBCommands(lldb::SBDebugger &debugger, llvm::StringRef prefix,
 
   bool did_print_prefix = false;
 
-  // Get the default prompt from settings.
-  std::string prompt_string = "(lldb) ";
-  if (const lldb::SBStructuredData prompt = debugger.GetSetting("prompt")) {
-    const size_t prompt_length = prompt.GetStringValue(nullptr, 0);
-
-    if (prompt_length != 0) {
-      prompt_string.resize(prompt_length + 1);
-      prompt.GetStringValue(prompt_string.data(), prompt_string.length());
+  // We only need the prompt when echoing commands.
+  std::string prompt_string;
+  if (echo_commands) {
+    prompt_string = "(lldb) ";
+
+    // Get the current prompt from settings.
+    if (const lldb::SBStructuredData prompt = debugger.GetSetting("prompt")) {
+      const size_t prompt_length = prompt.GetStringValue(nullptr, 0);
+
+      if (prompt_length != 0) {
+        prompt_string.resize(prompt_length + 1);
+        prompt.GetStringValue(prompt_string.data(), prompt_string.length());
+      }
     }
   }
 

>From 300b722c51471b7a71f1c28b8a08b35a54521a95 Mon Sep 17 00:00:00 2001
From: Ebuka Ezike <yerimyah1 at gmail.com>
Date: Tue, 15 Apr 2025 13:05:45 +0100
Subject: [PATCH 3/5] [lldb] set echo commands to false by default

Signed-off-by: Ebuka Ezike <yerimyah1 at gmail.com>
---
 lldb/tools/lldb-dap/LLDBUtils.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lldb/tools/lldb-dap/LLDBUtils.h b/lldb/tools/lldb-dap/LLDBUtils.h
index d526ed431fff3..9afe285fc4ed5 100644
--- a/lldb/tools/lldb-dap/LLDBUtils.h
+++ b/lldb/tools/lldb-dap/LLDBUtils.h
@@ -95,7 +95,7 @@ std::string RunLLDBCommands(lldb::SBDebugger &debugger, llvm::StringRef prefix,
                             const llvm::ArrayRef<std::string> &commands,
                             bool &required_command_failed,
                             bool parse_command_directives = true,
-                            bool echo_commands = true);
+                            bool echo_commands = false);
 
 /// Similar to the method above, but without parsing command directives.
 std::string RunLLDBCommandsVerbatim(lldb::SBDebugger &debugger,

>From 304f55fdfe8f48fb60cfa1699149a9b3bc36e97a Mon Sep 17 00:00:00 2001
From: Ebuka Ezike <yerimyah1 at gmail.com>
Date: Wed, 16 Apr 2025 20:41:03 +0100
Subject: [PATCH 4/5] Update
 lldb/test/API/tools/lldb-dap/repl-mode/TestDAP_repl_mode_detection.py

Co-authored-by: Walter Erquinigo <a20012251 at gmail.com>
---
 .../API/tools/lldb-dap/repl-mode/TestDAP_repl_mode_detection.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lldb/test/API/tools/lldb-dap/repl-mode/TestDAP_repl_mode_detection.py b/lldb/test/API/tools/lldb-dap/repl-mode/TestDAP_repl_mode_detection.py
index 09ca725ee8883..c6f59949d668e 100644
--- a/lldb/test/API/tools/lldb-dap/repl-mode/TestDAP_repl_mode_detection.py
+++ b/lldb/test/API/tools/lldb-dap/repl-mode/TestDAP_repl_mode_detection.py
@@ -28,7 +28,7 @@ def test_completions(self):
 
         self.set_source_breakpoints(source, [breakpoint1_line, breakpoint2_line])
 
-        # the result of the commands should return the empty string.
+        # The result of the commands should return the empty string.
         self.assertEvaluate("`command regex user_command s/^$/platform/", r"^$")
         self.assertEvaluate("`command alias alias_command platform", r"^$")
         self.assertEvaluate(

>From f63a2dd573192fcdc823e64ad412bea1fc85bb3b Mon Sep 17 00:00:00 2001
From: Ebuka Ezike <yerimyah1 at gmail.com>
Date: Wed, 16 Apr 2025 20:41:17 +0100
Subject: [PATCH 5/5] Update
 lldb/tools/lldb-dap/Handler/EvaluateRequestHandler.cpp

Co-authored-by: Walter Erquinigo <a20012251 at gmail.com>
---
 lldb/tools/lldb-dap/Handler/EvaluateRequestHandler.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lldb/tools/lldb-dap/Handler/EvaluateRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/EvaluateRequestHandler.cpp
index cd7b367d41d20..88f730313c9bc 100644
--- a/lldb/tools/lldb-dap/Handler/EvaluateRequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/EvaluateRequestHandler.cpp
@@ -165,7 +165,7 @@ void EvaluateRequestHandler::operator()(
     }
     auto result = RunLLDBCommandsVerbatim(dap.debugger, llvm::StringRef(),
                                           {std::string(expression)},
-                                          /*echo_commands*/ false);
+                                          /*echo_commands=*/ false);
     EmplaceSafeString(body, "result", result);
     body.try_emplace("variablesReference", (int64_t)0);
   } else {



More information about the lldb-commits mailing list