[Lldb-commits] [lldb] [lldb-dap] Add external terminal support (PR #146950)
via lldb-commits
lldb-commits at lists.llvm.org
Thu Jul 3 12:35:13 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lldb
Author: None (DrSergei)
<details>
<summary>Changes</summary>
Popular debugger extensions, such as cpptools (`externalConsole` option) and codelldb (`terminal` option), support launching program in external console. This patch change behavior of `runInTerminal` option similar to codellb, but save old behavior if boolean value was set.
---
Full diff: https://github.com/llvm/llvm-project/pull/146950.diff
10 Files Affected:
- (modified) lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py (+1-1)
- (modified) lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py (+17-1)
- (modified) lldb/tools/lldb-dap/Handler/LaunchRequestHandler.cpp (+1-1)
- (modified) lldb/tools/lldb-dap/Handler/RequestHandler.cpp (+3-2)
- (modified) lldb/tools/lldb-dap/JSONUtils.cpp (+8-4)
- (modified) lldb/tools/lldb-dap/JSONUtils.h (+1-1)
- (modified) lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp (+32-2)
- (modified) lldb/tools/lldb-dap/Protocol/ProtocolRequests.h (+3-1)
- (modified) lldb/tools/lldb-dap/README.md (+1)
- (modified) lldb/tools/lldb-dap/package.json (+21-3)
``````````diff
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..e8cb64dc9cf4e 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,22 @@ 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",
``````````
</details>
https://github.com/llvm/llvm-project/pull/146950
More information about the lldb-commits
mailing list