Skip to content

Commit 6a32432

Browse files
committed
[lldb-dap] Add external terminal support
1 parent 2fe0feb commit 6a32432

File tree

10 files changed

+105
-22
lines changed

10 files changed

+105
-22
lines changed

lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -894,7 +894,8 @@ def request_launch(
894894
disableASLR=False,
895895
disableSTDIO=False,
896896
shellExpandArguments=False,
897-
runInTerminal=False,
897+
runInTerminal=False, # deprecated
898+
console: Optional[str] = None,
898899
enableAutoVariableSummaries=False,
899900
displayExtendedBacktrace=False,
900901
enableSyntheticChildDebugging=False,
@@ -946,6 +947,8 @@ def request_launch(
946947
args_dict["sourceMap"] = sourceMap
947948
if runInTerminal:
948949
args_dict["runInTerminal"] = runInTerminal
950+
if console:
951+
args_dict["console"] = console
949952
if postRunCommands:
950953
args_dict["postRunCommands"] = postRunCommands
951954
if customFrameFormat:

lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,22 +44,39 @@ def test_failing_launch_program(self):
4444
"'{0}' does not exist".format(program), response["body"]["error"]["format"]
4545
)
4646

47-
def test_failing_launch_commands_and_run_in_terminal(self):
47+
def test_failing_launch_commands_and_console(self):
4848
"""
49-
Tests launching with an invalid program.
49+
Tests launching with launch commands in an integrated terminal.
5050
"""
5151
program = self.getBuildArtifact("a.out")
5252
self.create_debug_adapter()
5353
response = self.launch(
54-
program, launchCommands=["a b c"], runInTerminal=True, expectFailure=True
54+
program,
55+
launchCommands=["a b c"],
56+
console="integratedTerminal",
57+
expectFailure=True,
5558
)
5659
self.assertFalse(response["success"])
5760
self.assertTrue(self.get_dict_value(response, ["body", "error", "showUser"]))
5861
self.assertEqual(
59-
"'launchCommands' and 'runInTerminal' are mutually exclusive",
62+
"'launchCommands' and 'console' are mutually exclusive",
6063
self.get_dict_value(response, ["body", "error", "format"]),
6164
)
6265

66+
def test_failing_console(self):
67+
"""
68+
Tests launching in console with an invalid terminal type.
69+
"""
70+
program = self.getBuildArtifact("a.out")
71+
self.create_debug_adapter()
72+
response = self.launch(program, console="invalid", expectFailure=True)
73+
self.assertFalse(response["success"])
74+
self.assertTrue(self.get_dict_value(response, ["body", "error", "showUser"]))
75+
self.assertRegex(
76+
response["body"]["error"]["format"],
77+
r"unexpected value, expected 'internalConsole\', 'integratedTerminal\' or 'externalTerminal\' at arguments.console",
78+
)
79+
6380
@skipIfWindows
6481
def test_termination(self):
6582
"""

lldb/tools/lldb-dap/Handler/LaunchRequestHandler.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,10 @@ namespace lldb_dap {
2323
/// Launch request; value of command field is 'launch'.
2424
Error LaunchRequestHandler::Run(const LaunchRequestArguments &arguments) const {
2525
// Validate that we have a well formed launch request.
26-
if (!arguments.launchCommands.empty() && arguments.runInTerminal)
26+
if (!arguments.launchCommands.empty() &&
27+
arguments.console != protocol::eInternalConsole)
2728
return make_error<DAPError>(
28-
"'launchCommands' and 'runInTerminal' are mutually exclusive");
29+
"'launchCommands' and 'console' are mutually exclusive");
2930

3031
dap.SetConfiguration(arguments.configuration, /*is_attach=*/false);
3132
dap.last_launch_request = arguments;

lldb/tools/lldb-dap/Handler/RequestHandler.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,8 @@ RunInTerminal(DAP &dap, const protocol::LaunchRequestArguments &arguments) {
8080

8181
llvm::json::Object reverse_request = CreateRunInTerminalReverseRequest(
8282
arguments.configuration.program, arguments.args, arguments.env,
83-
arguments.cwd, comm_file.m_path, debugger_pid);
83+
arguments.cwd, comm_file.m_path, debugger_pid,
84+
arguments.console == protocol::eExternalTerminal);
8485
dap.SendReverseRequest<LogFailureResponseHandler>("runInTerminal",
8586
std::move(reverse_request));
8687

@@ -192,7 +193,7 @@ llvm::Error BaseRequestHandler::LaunchProcess(
192193
// about process state changes during the launch.
193194
ScopeSyncMode scope_sync_mode(dap.debugger);
194195

195-
if (arguments.runInTerminal) {
196+
if (arguments.console != protocol::eInternalConsole) {
196197
if (llvm::Error err = RunInTerminal(dap, arguments))
197198
return err;
198199
} else if (launchCommands.empty()) {

lldb/tools/lldb-dap/JSONUtils.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1168,11 +1168,15 @@ llvm::json::Value CreateCompileUnit(lldb::SBCompileUnit &unit) {
11681168
llvm::json::Object CreateRunInTerminalReverseRequest(
11691169
llvm::StringRef program, const std::vector<std::string> &args,
11701170
const llvm::StringMap<std::string> &env, llvm::StringRef cwd,
1171-
llvm::StringRef comm_file, lldb::pid_t debugger_pid) {
1171+
llvm::StringRef comm_file, lldb::pid_t debugger_pid, bool external) {
11721172
llvm::json::Object run_in_terminal_args;
1173-
// This indicates the IDE to open an embedded terminal, instead of opening
1174-
// the terminal in a new window.
1175-
run_in_terminal_args.try_emplace("kind", "integrated");
1173+
if (external)
1174+
// This indicates the IDE to open an external terminal window.
1175+
run_in_terminal_args.try_emplace("kind", "external");
1176+
else
1177+
// This indicates the IDE to open an embedded terminal, instead of opening
1178+
// the terminal in a new window.
1179+
run_in_terminal_args.try_emplace("kind", "integrated");
11761180

11771181
// The program path must be the first entry in the "args" field
11781182
std::vector<std::string> req_args = {DAP::debug_adapter_path.str(),

lldb/tools/lldb-dap/JSONUtils.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -441,13 +441,17 @@ llvm::json::Value CreateCompileUnit(lldb::SBCompileUnit &unit);
441441
/// launcher uses it on Linux tell the kernel that it should allow the
442442
/// debugger process to attach.
443443
///
444+
/// \param[in] external
445+
/// If set to true, the program will run in an external terminal window
446+
/// instead of IDE's integrated terminal.
447+
///
444448
/// \return
445449
/// A "runInTerminal" JSON object that follows the specification outlined by
446450
/// Microsoft.
447451
llvm::json::Object CreateRunInTerminalReverseRequest(
448452
llvm::StringRef program, const std::vector<std::string> &args,
449453
const llvm::StringMap<std::string> &env, llvm::StringRef cwd,
450-
llvm::StringRef comm_file, lldb::pid_t debugger_pid);
454+
llvm::StringRef comm_file, lldb::pid_t debugger_pid, bool external);
451455

452456
/// Create a "Terminated" JSON object that contains statistics
453457
///

lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,37 @@ json::Value toJSON(const BreakpointLocationsResponseBody &BLRB) {
262262
return json::Object{{"breakpoints", BLRB.breakpoints}};
263263
}
264264

265+
bool fromJSON(const json::Value &Params, Console &C, json::Path P) {
266+
auto oldFormatConsole = Params.getAsBoolean();
267+
if (oldFormatConsole) {
268+
if (*oldFormatConsole)
269+
C = eIntegratedTerminal;
270+
else
271+
C = eInternalConsole;
272+
return true;
273+
}
274+
auto newFormatConsole = Params.getAsString();
275+
if (!newFormatConsole) {
276+
P.report("expected a string");
277+
return false;
278+
}
279+
280+
std::optional<Console> console =
281+
StringSwitch<std::optional<Console>>(*newFormatConsole)
282+
.Case("internalConsole", eInternalConsole)
283+
.Case("integratedTerminal", eIntegratedTerminal)
284+
.Case("externalTerminal", eExternalTerminal)
285+
.Default(std::nullopt);
286+
if (!console) {
287+
P.report("unexpected value, expected 'internalConsole', "
288+
"'integratedTerminal' or 'externalTerminal'");
289+
return false;
290+
}
291+
292+
C = *console;
293+
return true;
294+
}
295+
265296
bool fromJSON(const json::Value &Params, LaunchRequestArguments &LRA,
266297
json::Path P) {
267298
json::ObjectMapper O(Params, P);
@@ -273,9 +304,8 @@ bool fromJSON(const json::Value &Params, LaunchRequestArguments &LRA,
273304
O.mapOptional("disableASLR", LRA.disableASLR) &&
274305
O.mapOptional("disableSTDIO", LRA.disableSTDIO) &&
275306
O.mapOptional("shellExpandArguments", LRA.shellExpandArguments) &&
276-
277-
O.mapOptional("runInTerminal", LRA.runInTerminal) &&
278-
parseEnv(Params, LRA.env, P);
307+
O.mapOptional("runInTerminal", LRA.console) &&
308+
O.mapOptional("console", LRA.console) && parseEnv(Params, LRA.env, P);
279309
}
280310

281311
bool fromJSON(const json::Value &Params, AttachRequestArguments &ARA,

lldb/tools/lldb-dap/Protocol/ProtocolRequests.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,12 @@ struct Configuration {
242242
std::string platformName;
243243
};
244244

245+
enum Console : unsigned {
246+
eInternalConsole,
247+
eIntegratedTerminal,
248+
eExternalTerminal
249+
};
250+
245251
/// lldb-dap specific launch arguments.
246252
struct LaunchRequestArguments {
247253
/// Common lldb-dap configuration values for launching/attaching operations.
@@ -290,9 +296,9 @@ struct LaunchRequestArguments {
290296
/// Set whether to shell expand arguments to the process when launching.
291297
bool shellExpandArguments = false;
292298

293-
/// Launch the program inside an integrated terminal in the IDE. Useful for
294-
/// debugging interactive command line programs.
295-
bool runInTerminal = false;
299+
/// Specify where to launch the program: internal console, integrated
300+
/// terminal or external terminal.
301+
Console console = eInternalConsole;
296302

297303
/// @}
298304
};

lldb/tools/lldb-dap/README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,8 @@ contain the following key/value pairs:
235235
| **cwd** | string | | The program working directory.
236236
| **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.
237237
| **stopOnEntry** | boolean | | Whether to stop program immediately after launching.
238-
| **runInTerminal** | boolean | | Launch the program inside an integrated terminal in the IDE. Useful for debugging interactive command line programs.
238+
| **runInTerminal** (deprecated) | boolean | | Launch the program inside an integrated terminal in the IDE. Useful for debugging interactive command line programs.
239+
| **console** | string | | Specify where to launch the program: internal console (`internalConsole`), integrated terminal (`integratedTerminal`) or external terminal (`externalTerminal`).
239240
| **launchCommands** | [string] | | LLDB commands executed to launch the program.
240241

241242
For JSON configurations of `"type": "attach"`, the JSON configuration can contain

lldb/tools/lldb-dap/package.json

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -528,7 +528,23 @@
528528
"runInTerminal": {
529529
"type": "boolean",
530530
"description": "Launch the program inside an integrated terminal in the IDE. Useful for debugging interactive command line programs",
531-
"default": false
531+
"default": false,
532+
"deprecationMessage": "Attribute 'runInTerminal' is deprecated, use 'console' instead."
533+
},
534+
"console": {
535+
"type": "string",
536+
"enum": [
537+
"internalConsole",
538+
"integratedTerminal",
539+
"externalTerminal"
540+
],
541+
"enumDescriptions": [
542+
"Launch the program inside an integrated terminal in the IDE.",
543+
"Launch the program inside an external terminal window.",
544+
"Use Debug Console for output (input is not supported)."
545+
],
546+
"description": "Specify where to launch the program: internal console, integrated terminal or external terminal.",
547+
"default": "internalConsole"
532548
},
533549
"timeout": {
534550
"type": "number",

0 commit comments

Comments
 (0)