https://github.com/DrSergei updated 
https://github.com/llvm/llvm-project/pull/146950

>From 112050c1d826ef483b84d1067905ae10aabe31fb Mon Sep 17 00:00:00 2001
From: Druzhkov Sergei <serzhdruz...@gmail.com>
Date: Wed, 2 Jul 2025 23:29:26 +0300
Subject: [PATCH] [lldb-dap] Add external terminal support

---
 .../test/tools/lldb-dap/dap_server.py         |  2 +-
 .../tools/lldb-dap/launch/TestDAP_launch.py   | 16 ++++++++-
 .../lldb-dap/Handler/LaunchRequestHandler.cpp |  2 +-
 .../tools/lldb-dap/Handler/RequestHandler.cpp |  5 +--
 lldb/tools/lldb-dap/JSONUtils.cpp             | 12 ++++---
 lldb/tools/lldb-dap/JSONUtils.h               |  2 +-
 .../lldb-dap/Protocol/ProtocolRequests.cpp    | 34 +++++++++++++++++--
 .../lldb-dap/Protocol/ProtocolRequests.h      |  4 ++-
 lldb/tools/lldb-dap/README.md                 |  1 +
 lldb/tools/lldb-dap/package.json              | 24 +++++++++++--
 10 files changed, 86 insertions(+), 16 deletions(-)

diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py 
b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py
index 0fe36cd4bc71f..d8c1ffa6c00f0 100644
--- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py
+++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py
@@ -890,7 +890,7 @@ def request_launch(
         args: Optional[list[str]] = None,
         cwd: Optional[str] = None,
         env: Optional[dict[str, str]] = None,
-        stopOnEntry=False,
+        stopOnEntry: Union[bool, str] = False,
         disableASLR=False,
         disableSTDIO=False,
         shellExpandArguments=False,
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 ae8142ae4f484..70a3443cf8526 100644
--- a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py
+++ b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py
@@ -46,7 +46,7 @@ def test_failing_launch_program(self):
 
     def test_failing_launch_commands_and_run_in_terminal(self):
         """
-        Tests launching with an invalid program.
+        Tests launching with a launch commands in integrated terminal.
         """
         program = self.getBuildArtifact("a.out")
         self.create_debug_adapter()
@@ -60,6 +60,20 @@ def test_failing_launch_commands_and_run_in_terminal(self):
             self.get_dict_value(response, ["body", "error", "format"]),
         )
 
+    def test_failing_run_in_terminal(self):
+        """
+        Tests launching in terminal.
+        """
+        program = self.getBuildArtifact("a.out")
+        self.create_debug_adapter()
+        response = self.launch(program, runInTerminal="invalid", 
expectFailure=True)
+        self.assertFalse(response["success"])
+        self.assertTrue(self.get_dict_value(response, ["body", "error", 
"showUser"]))
+        self.assertRegex(
+            response["body"]["error"]["format"],
+            r"unexpected value, expected 'console', 'integrated' or 'external' 
at arguments.runInTerminal",
+        )
+
     @skipIfWindows
     def test_termination(self):
         """
diff --git a/lldb/tools/lldb-dap/Handler/LaunchRequestHandler.cpp 
b/lldb/tools/lldb-dap/Handler/LaunchRequestHandler.cpp
index 1d7b4b7009462..907d93021cd76 100644
--- a/lldb/tools/lldb-dap/Handler/LaunchRequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/LaunchRequestHandler.cpp
@@ -23,7 +23,7 @@ namespace lldb_dap {
 /// Launch request; value of command field is 'launch'.
 Error LaunchRequestHandler::Run(const LaunchRequestArguments &arguments) const 
{
   // Validate that we have a well formed launch request.
-  if (!arguments.launchCommands.empty() && arguments.runInTerminal)
+  if (!arguments.launchCommands.empty() && arguments.terminal)
     return make_error<DAPError>(
         "'launchCommands' and 'runInTerminal' are mutually exclusive");
 
diff --git a/lldb/tools/lldb-dap/Handler/RequestHandler.cpp 
b/lldb/tools/lldb-dap/Handler/RequestHandler.cpp
index 93bc80a38e29d..d2227cfffa18a 100644
--- a/lldb/tools/lldb-dap/Handler/RequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/RequestHandler.cpp
@@ -80,7 +80,8 @@ RunInTerminal(DAP &dap, const 
protocol::LaunchRequestArguments &arguments) {
 
   llvm::json::Object reverse_request = CreateRunInTerminalReverseRequest(
       arguments.configuration.program, arguments.args, arguments.env,
-      arguments.cwd, comm_file.m_path, debugger_pid);
+      arguments.cwd, comm_file.m_path, debugger_pid,
+      arguments.terminal == protocol::eExternal);
   dap.SendReverseRequest<LogFailureResponseHandler>("runInTerminal",
                                                     
std::move(reverse_request));
 
@@ -192,7 +193,7 @@ llvm::Error BaseRequestHandler::LaunchProcess(
     // about process state changes during the launch.
     ScopeSyncMode scope_sync_mode(dap.debugger);
 
-    if (arguments.runInTerminal) {
+    if (arguments.terminal) {
       if (llvm::Error err = RunInTerminal(dap, arguments))
         return err;
     } else if (launchCommands.empty()) {
diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp 
b/lldb/tools/lldb-dap/JSONUtils.cpp
index 08e65ab835a57..08e3e504689e7 100644
--- a/lldb/tools/lldb-dap/JSONUtils.cpp
+++ b/lldb/tools/lldb-dap/JSONUtils.cpp
@@ -1168,11 +1168,15 @@ llvm::json::Value CreateCompileUnit(lldb::SBCompileUnit 
&unit) {
 llvm::json::Object CreateRunInTerminalReverseRequest(
     llvm::StringRef program, const std::vector<std::string> &args,
     const llvm::StringMap<std::string> &env, llvm::StringRef cwd,
-    llvm::StringRef comm_file, lldb::pid_t debugger_pid) {
+    llvm::StringRef comm_file, lldb::pid_t debugger_pid, bool external) {
   llvm::json::Object run_in_terminal_args;
-  // This indicates the IDE to open an embedded terminal, instead of opening
-  // the terminal in a new window.
-  run_in_terminal_args.try_emplace("kind", "integrated");
+  if (external)
+    // This indicates the IDE to open an external terminal window.
+    run_in_terminal_args.try_emplace("kind", "external");
+  else
+    // This indicates the IDE to open an embedded terminal, instead of opening
+    // the terminal in a new window.
+    run_in_terminal_args.try_emplace("kind", "integrated");
 
   // The program path must be the first entry in the "args" field
   std::vector<std::string> req_args = {DAP::debug_adapter_path.str(),
diff --git a/lldb/tools/lldb-dap/JSONUtils.h b/lldb/tools/lldb-dap/JSONUtils.h
index fd9a06931ebff..4a8feab741e4b 100644
--- a/lldb/tools/lldb-dap/JSONUtils.h
+++ b/lldb/tools/lldb-dap/JSONUtils.h
@@ -447,7 +447,7 @@ llvm::json::Value CreateCompileUnit(lldb::SBCompileUnit 
&unit);
 llvm::json::Object CreateRunInTerminalReverseRequest(
     llvm::StringRef program, const std::vector<std::string> &args,
     const llvm::StringMap<std::string> &env, llvm::StringRef cwd,
-    llvm::StringRef comm_file, lldb::pid_t debugger_pid);
+    llvm::StringRef comm_file, lldb::pid_t debugger_pid, bool external);
 
 /// Create a "Terminated" JSON object that contains statistics
 ///
diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp 
b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp
index 9bd84a6c898f9..f55efd185f9f6 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp
@@ -262,6 +262,37 @@ json::Value toJSON(const BreakpointLocationsResponseBody 
&BLRB) {
   return json::Object{{"breakpoints", BLRB.breakpoints}};
 }
 
+bool fromJSON(const json::Value &Params, Terminal &T, json::Path P) {
+  auto oldFormatTerminal = Params.getAsBoolean();
+  if (oldFormatTerminal) {
+    if (*oldFormatTerminal)
+      T = eIntegrated;
+    else
+      T = eConsole;
+    return true;
+  }
+  auto newFormatTerminal = Params.getAsString();
+  if (!newFormatTerminal) {
+    P.report("expected a string");
+    return false;
+  }
+
+  std::optional<Terminal> terminal =
+      StringSwitch<std::optional<Terminal>>(*newFormatTerminal)
+          .Case("console", eConsole)
+          .Case("integrated", eIntegrated)
+          .Case("external", eExternal)
+          .Default(std::nullopt);
+  if (!terminal) {
+    P.report(
+        "unexpected value, expected 'console', 'integrated' or 'external'");
+    return false;
+  }
+
+  T = *terminal;
+  return true;
+}
+
 bool fromJSON(const json::Value &Params, LaunchRequestArguments &LRA,
               json::Path P) {
   json::ObjectMapper O(Params, P);
@@ -273,8 +304,7 @@ bool fromJSON(const json::Value &Params, 
LaunchRequestArguments &LRA,
          O.mapOptional("disableASLR", LRA.disableASLR) &&
          O.mapOptional("disableSTDIO", LRA.disableSTDIO) &&
          O.mapOptional("shellExpandArguments", LRA.shellExpandArguments) &&
-
-         O.mapOptional("runInTerminal", LRA.runInTerminal) &&
+         O.mapOptional("runInTerminal", LRA.terminal) &&
          parseEnv(Params, LRA.env, P);
 }
 
diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h 
b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h
index d4b816c72679b..2e72f50c63afe 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h
@@ -242,6 +242,8 @@ struct Configuration {
   std::string platformName;
 };
 
+enum Terminal : unsigned { eConsole, eIntegrated, eExternal };
+
 /// lldb-dap specific launch arguments.
 struct LaunchRequestArguments {
   /// Common lldb-dap configuration values for launching/attaching operations.
@@ -292,7 +294,7 @@ struct LaunchRequestArguments {
 
   /// Launch the program inside an integrated terminal in the IDE. Useful for
   /// debugging interactive command line programs.
-  bool runInTerminal = false;
+  Terminal terminal = eConsole;
 
   /// @}
 };
diff --git a/lldb/tools/lldb-dap/README.md b/lldb/tools/lldb-dap/README.md
index 18bfa9d518b98..61d2cc06f99eb 100644
--- a/lldb/tools/lldb-dap/README.md
+++ b/lldb/tools/lldb-dap/README.md
@@ -236,6 +236,7 @@ contain the following key/value pairs:
 | **env**                           | dictionary  |     | Environment 
variables to set when launching the program. The format of each environment 
variable string is "VAR=VALUE" for environment variables with values or just 
"VAR" for environment variables with no values.
 | **stopOnEntry**                   | boolean     |     | Whether to stop 
program immediately after launching.
 | **runInTerminal**                 | boolean     |     | Launch the program 
inside an integrated terminal in the IDE. Useful for debugging interactive 
command line programs.
+| **runInTerminal**                 | string      |     | Specifies where 
program should be launch: `integrated` for an integrated terminal in the IDE, 
`external` for external terminal window or `console` (default) for IDE debug 
console.
 | **launchCommands**                | [string]    |     | LLDB commands 
executed to launch the program.
 
 For JSON configurations of `"type": "attach"`, the JSON configuration can 
contain
diff --git a/lldb/tools/lldb-dap/package.json b/lldb/tools/lldb-dap/package.json
index b150dee792c34..cf5712261d051 100644
--- a/lldb/tools/lldb-dap/package.json
+++ b/lldb/tools/lldb-dap/package.json
@@ -526,9 +526,27 @@
                 "default": []
               },
               "runInTerminal": {
-                "type": "boolean",
-                "description": "Launch the program inside an integrated 
terminal in the IDE. Useful for debugging interactive command line programs",
-                "default": false
+                "anyOf": [
+                  {
+                    "type": "boolean",
+                    "description": "Launch the program inside an integrated 
terminal in the IDE. Useful for debugging interactive command line programs",
+                    "default": false
+                  },
+                  {
+                    "type": "string",
+                    "enum": [
+                      "console",
+                      "integrated",
+                      "external"
+                    ],
+                    "enumDescriptions": [
+                      "Launch the program inside an integrated terminal in the 
IDE.",
+                      "Launch the program inside an external terminal window.",
+                      "Use Debug Console for output (input is not supported)."
+                    ],
+                    "default": "console"
+                  }
+                ]
               },
               "timeout": {
                 "type": "number",

_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to