[Lldb-commits] [lldb] [lldb-dap] Migrating DAP 'initialize' to new typed RequestHandler. (PR #133007)
John Harrison via lldb-commits
lldb-commits at lists.llvm.org
Thu Mar 27 09:22:17 PDT 2025
https://github.com/ashgti updated https://github.com/llvm/llvm-project/pull/133007
>From b6850bfee90229c8da5ffa5359023c682b574954 Mon Sep 17 00:00:00 2001
From: John Harrison <harjohn at google.com>
Date: Tue, 25 Mar 2025 14:58:03 -0700
Subject: [PATCH 1/6] [lldb-dap] Migrating DAP 'initialize' to new typed
RequestHandler.
This adds new types and helpers to support the 'initialize' request with the new typed RequestHandler. While working on this I found there were a few cases where we incorrectly treated initialize arguments as capabilities. The new `lldb_dap::protocol::InitializeRequestArguments` and `lldb_dap::protocol::Capabilities` uncovered the inconsistencies.
---
.../test/tools/lldb-dap/dap_server.py | 5 +-
.../tools/lldb-dap/launch/TestDAP_launch.py | 3 +-
lldb/tools/lldb-dap/DAP.cpp | 145 ++++++++--
lldb/tools/lldb-dap/DAP.h | 6 +-
.../Handler/InitializeRequestHandler.cpp | 162 ++---------
.../tools/lldb-dap/Handler/RequestHandler.cpp | 1 +
lldb/tools/lldb-dap/Handler/RequestHandler.h | 89 +++---
lldb/tools/lldb-dap/JSONUtils.cpp | 34 +--
lldb/tools/lldb-dap/JSONUtils.h | 3 +-
.../lldb-dap/Protocol/ProtocolRequests.cpp | 52 ++++
.../lldb-dap/Protocol/ProtocolRequests.h | 69 +++++
.../tools/lldb-dap/Protocol/ProtocolTypes.cpp | 199 ++++++++++++++
lldb/tools/lldb-dap/Protocol/ProtocolTypes.h | 255 ++++++++++++++++++
13 files changed, 800 insertions(+), 223 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 359ac718138b2..01ef4b68f2653 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
@@ -776,7 +776,8 @@ def request_initialize(self, sourceInitFile):
"supportsVariablePaging": True,
"supportsVariableType": True,
"supportsStartDebuggingRequest": True,
- "sourceInitFile": sourceInitFile,
+ "supportsProgressReporting": True,
+ "$__lldb_sourceInitFile": sourceInitFile,
},
}
response = self.send_recv(command_dict)
@@ -1261,7 +1262,7 @@ def launch(cls, /, executable, env=None, log_file=None, connection=None):
expected_prefix = "Listening for: "
out = process.stdout.readline().decode()
if not out.startswith(expected_prefix):
- self.process.kill()
+ process.kill()
raise ValueError(
"lldb-dap failed to print listening address, expected '{}', got '{}'".format(
expected_prefix, out
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 0c92e5bff07c6..64c99019a1c9b 100644
--- a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py
+++ b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py
@@ -524,8 +524,7 @@ def test_version(self):
# 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:]
- lldb_json = self.dap_server.get_initialize_value("__lldb")
- version_string = lldb_json["version"]
+ version_string = self.dap_server.get_initialize_value("$__lldb_version")
self.assertEqual(
version_eval_output_without_prompt_line,
version_string.splitlines(),
diff --git a/lldb/tools/lldb-dap/DAP.cpp b/lldb/tools/lldb-dap/DAP.cpp
index 65de0488729e5..0da8ce43f73c4 100644
--- a/lldb/tools/lldb-dap/DAP.cpp
+++ b/lldb/tools/lldb-dap/DAP.cpp
@@ -14,6 +14,7 @@
#include "LLDBUtils.h"
#include "OutputRedirector.h"
#include "Protocol/ProtocolBase.h"
+#include "Protocol/ProtocolTypes.h"
#include "Transport.h"
#include "lldb/API/SBBreakpoint.h"
#include "lldb/API/SBCommandInterpreter.h"
@@ -1144,31 +1145,137 @@ lldb::SBValue Variables::FindVariable(uint64_t variablesReference,
return variable;
}
-llvm::StringMap<bool> DAP::GetCapabilities() {
- llvm::StringMap<bool> capabilities;
+static void mergeCapabilities(protocol::Capabilities &into,
+ const protocol::Capabilities &from) {
+ if (from.supportsConfigurationDoneRequest)
+ into.supportsConfigurationDoneRequest =
+ *from.supportsConfigurationDoneRequest;
+ if (from.supportsFunctionBreakpoints)
+ into.supportsFunctionBreakpoints = *from.supportsFunctionBreakpoints;
+ if (from.supportsConditionalBreakpoints)
+ into.supportsConditionalBreakpoints = *from.supportsConditionalBreakpoints;
+ if (from.supportsHitConditionalBreakpoints)
+ into.supportsHitConditionalBreakpoints =
+ *from.supportsHitConditionalBreakpoints;
+ if (from.supportsEvaluateForHovers)
+ into.supportsEvaluateForHovers = *from.supportsEvaluateForHovers;
+ if (from.exceptionBreakpointFilters)
+ into.exceptionBreakpointFilters = *from.exceptionBreakpointFilters;
+ if (from.supportsStepBack)
+ into.supportsStepBack = *from.supportsStepBack;
+ if (from.supportsSetVariable)
+ into.supportsSetVariable = *from.supportsSetVariable;
+ if (from.supportsRestartFrame)
+ into.supportsRestartFrame = *from.supportsRestartFrame;
+ if (from.supportsGotoTargetsRequest)
+ into.supportsGotoTargetsRequest = *from.supportsGotoTargetsRequest;
+ if (from.supportsStepInTargetsRequest)
+ into.supportsStepInTargetsRequest = *from.supportsStepInTargetsRequest;
+ if (from.supportsCompletionsRequest)
+ into.supportsCompletionsRequest = *from.supportsCompletionsRequest;
+ if (from.completionTriggerCharacters)
+ into.completionTriggerCharacters = *from.completionTriggerCharacters;
+ if (from.supportsModulesRequest)
+ into.supportsModulesRequest = *from.supportsModulesRequest;
+ if (from.additionalModuleColumns)
+ into.additionalModuleColumns = *from.additionalModuleColumns;
+ if (from.supportedChecksumAlgorithms)
+ into.supportedChecksumAlgorithms = *from.supportedChecksumAlgorithms;
+ if (from.supportsRestartRequest)
+ into.supportsRestartRequest = *from.supportsRestartRequest;
+ if (from.supportsExceptionOptions)
+ into.supportsExceptionOptions = *from.supportsExceptionOptions;
+ if (from.supportsValueFormattingOptions)
+ into.supportsValueFormattingOptions = *from.supportsValueFormattingOptions;
+ if (from.supportsExceptionInfoRequest)
+ into.supportsExceptionInfoRequest = *from.supportsExceptionInfoRequest;
+ if (from.supportTerminateDebuggee)
+ into.supportTerminateDebuggee = *from.supportTerminateDebuggee;
+ if (from.supportSuspendDebuggee)
+ into.supportSuspendDebuggee = *from.supportSuspendDebuggee;
+ if (from.supportsDelayedStackTraceLoading)
+ into.supportsDelayedStackTraceLoading =
+ *from.supportsDelayedStackTraceLoading;
+ if (from.supportsLoadedSourcesRequest)
+ into.supportsLoadedSourcesRequest = *from.supportsLoadedSourcesRequest;
+ if (from.supportsLogPoints)
+ into.supportsLogPoints = *from.supportsLogPoints;
+ if (from.supportsTerminateThreadsRequest)
+ into.supportsTerminateThreadsRequest =
+ *from.supportsTerminateThreadsRequest;
+ if (from.supportsSetExpression)
+ into.supportsSetExpression = *from.supportsSetExpression;
+ if (from.supportsTerminateRequest)
+ into.supportsTerminateRequest = *from.supportsTerminateRequest;
+ if (from.supportsDataBreakpoints)
+ into.supportsDataBreakpoints = *from.supportsDataBreakpoints;
+ if (from.supportsReadMemoryRequest)
+ into.supportsReadMemoryRequest = *from.supportsReadMemoryRequest;
+ if (from.supportsWriteMemoryRequest)
+ into.supportsWriteMemoryRequest = *from.supportsWriteMemoryRequest;
+ if (from.supportsDisassembleRequest)
+ into.supportsDisassembleRequest = *from.supportsDisassembleRequest;
+ if (from.supportsCancelRequest)
+ into.supportsCancelRequest = *from.supportsCancelRequest;
+ if (from.supportsBreakpointLocationsRequest)
+ into.supportsBreakpointLocationsRequest =
+ *from.supportsBreakpointLocationsRequest;
+ if (from.supportsClipboardContext)
+ into.supportsClipboardContext = *from.supportsClipboardContext;
+ if (from.supportsSteppingGranularity)
+ into.supportsSteppingGranularity = *from.supportsSteppingGranularity;
+ if (from.supportsInstructionBreakpoints)
+ into.supportsInstructionBreakpoints = *from.supportsInstructionBreakpoints;
+ if (from.supportsExceptionFilterOptions)
+ into.supportsExceptionFilterOptions = *from.supportsExceptionFilterOptions;
+ if (from.supportsSingleThreadExecutionRequests)
+ into.supportsSingleThreadExecutionRequests =
+ *from.supportsSingleThreadExecutionRequests;
+ if (from.supportsDataBreakpointBytes)
+ into.supportsDataBreakpointBytes = *from.supportsDataBreakpointBytes;
+ if (from.breakpointModes)
+ into.breakpointModes = *from.breakpointModes;
+ if (from.supportsANSIStyling)
+ into.supportsANSIStyling = *from.supportsANSIStyling;
+}
+
+protocol::Capabilities DAP::GetCapabilities() {
+ protocol::Capabilities capabilities;
// Supported capabilities.
- capabilities["supportTerminateDebuggee"] = true;
- capabilities["supportsDataBreakpoints"] = true;
- capabilities["supportsDelayedStackTraceLoading"] = true;
- capabilities["supportsEvaluateForHovers"] = true;
- capabilities["supportsExceptionOptions"] = true;
- capabilities["supportsLogPoints"] = true;
- capabilities["supportsProgressReporting"] = true;
- capabilities["supportsSteppingGranularity"] = true;
- capabilities["supportsValueFormattingOptions"] = true;
+ capabilities.supportTerminateDebuggee = true;
+ capabilities.supportsDataBreakpoints = true;
+ capabilities.supportsDelayedStackTraceLoading = true;
+ capabilities.supportsEvaluateForHovers = true;
+ capabilities.supportsExceptionOptions = true;
+ capabilities.supportsLogPoints = true;
+ capabilities.supportsSteppingGranularity = true;
+ capabilities.supportsValueFormattingOptions = true;
// Unsupported capabilities.
- capabilities["supportsGotoTargetsRequest"] = false;
- capabilities["supportsLoadedSourcesRequest"] = false;
- capabilities["supportsRestartFrame"] = false;
- capabilities["supportsStepBack"] = false;
+ capabilities.supportsGotoTargetsRequest = false;
+ capabilities.supportsLoadedSourcesRequest = false;
+ capabilities.supportsRestartFrame = false;
+ capabilities.supportsStepBack = false;
// Capabilities associated with specific requests.
- for (auto &kv : request_handlers) {
- for (auto &request_kv : kv.second->GetCapabilities())
- capabilities[request_kv.getKey()] = request_kv.getValue();
- }
+ for (auto &kv : request_handlers)
+ mergeCapabilities(capabilities, kv.second->GetCapabilities());
+
+ // Available filters or options for the setExceptionBreakpoints request.
+ std::vector<protocol::ExceptionBreakpointsFilter> filters;
+ for (const auto &exc_bp : *exception_breakpoints)
+ filters.emplace_back(CreateExceptionBreakpointFilter(exc_bp));
+ capabilities.exceptionBreakpointFilters = std::move(filters);
+
+ std::vector<std::string> completion_characters;
+ completion_characters.emplace_back(".");
+ completion_characters.emplace_back(" ");
+ completion_characters.emplace_back("\t");
+ capabilities.completionTriggerCharacters = std::move(completion_characters);
+
+ // Put in non-DAP specification lldb specific information.
+ capabilities.lldbVersion = debugger.GetVersionString();
return capabilities;
}
diff --git a/lldb/tools/lldb-dap/DAP.h b/lldb/tools/lldb-dap/DAP.h
index 4b4d471161137..2f23e5a116bc3 100644
--- a/lldb/tools/lldb-dap/DAP.h
+++ b/lldb/tools/lldb-dap/DAP.h
@@ -16,6 +16,7 @@
#include "OutputRedirector.h"
#include "ProgressEvent.h"
#include "Protocol/ProtocolBase.h"
+#include "Protocol/ProtocolTypes.h"
#include "SourceBreakpoint.h"
#include "Transport.h"
#include "lldb/API/SBBroadcaster.h"
@@ -180,6 +181,7 @@ struct DAP {
bool enable_auto_variable_summaries;
bool enable_synthetic_child_debugging;
bool display_extended_backtrace;
+ bool supports_run_in_terminal_request;
// The process event thread normally responds to process exited events by
// shutting down the entire adapter. When we're restarting, we keep the id of
// the old process here so we can detect this case and keep running.
@@ -363,8 +365,8 @@ struct DAP {
request_handlers[Handler::GetCommand()] = std::make_unique<Handler>(*this);
}
- /// Return a key-value list of capabilities.
- llvm::StringMap<bool> GetCapabilities();
+ /// The set of capablities supported by this adapter.
+ protocol::Capabilities GetCapabilities();
/// Debuggee will continue from stopped state.
void WillContinue() { variables.Clear(); }
diff --git a/lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp
index a8fe0d6ffce8b..b85424975a0fc 100644
--- a/lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp
@@ -9,6 +9,7 @@
#include "DAP.h"
#include "EventHelper.h"
#include "JSONUtils.h"
+#include "Protocol/ProtocolRequests.h"
#include "RequestHandler.h"
#include "lldb/API/SBEvent.h"
#include "lldb/API/SBListener.h"
@@ -229,118 +230,29 @@ static void EventThreadFunction(DAP &dap) {
}
}
-// "InitializeRequest": {
-// "allOf": [ { "$ref": "#/definitions/Request" }, {
-// "type": "object",
-// "description": "Initialize request; value of command field is
-// 'initialize'.",
-// "properties": {
-// "command": {
-// "type": "string",
-// "enum": [ "initialize" ]
-// },
-// "arguments": {
-// "$ref": "#/definitions/InitializeRequestArguments"
-// }
-// },
-// "required": [ "command", "arguments" ]
-// }]
-// },
-// "InitializeRequestArguments": {
-// "type": "object",
-// "description": "Arguments for 'initialize' request.",
-// "properties": {
-// "clientID": {
-// "type": "string",
-// "description": "The ID of the (frontend) client using this adapter."
-// },
-// "adapterID": {
-// "type": "string",
-// "description": "The ID of the debug adapter."
-// },
-// "locale": {
-// "type": "string",
-// "description": "The ISO-639 locale of the (frontend) client using
-// this adapter, e.g. en-US or de-CH."
-// },
-// "linesStartAt1": {
-// "type": "boolean",
-// "description": "If true all line numbers are 1-based (default)."
-// },
-// "columnsStartAt1": {
-// "type": "boolean",
-// "description": "If true all column numbers are 1-based (default)."
-// },
-// "pathFormat": {
-// "type": "string",
-// "_enum": [ "path", "uri" ],
-// "description": "Determines in what format paths are specified. The
-// default is 'path', which is the native format."
-// },
-// "supportsVariableType": {
-// "type": "boolean",
-// "description": "Client supports the optional type attribute for
-// variables."
-// },
-// "supportsVariablePaging": {
-// "type": "boolean",
-// "description": "Client supports the paging of variables."
-// },
-// "supportsRunInTerminalRequest": {
-// "type": "boolean",
-// "description": "Client supports the runInTerminal request."
-// }
-// },
-// "required": [ "adapterID" ]
-// },
-// "InitializeResponse": {
-// "allOf": [ { "$ref": "#/definitions/Response" }, {
-// "type": "object",
-// "description": "Response to 'initialize' request.",
-// "properties": {
-// "body": {
-// "$ref": "#/definitions/Capabilities",
-// "description": "The capabilities of this debug adapter."
-// }
-// }
-// }]
-// }
-void InitializeRequestHandler::operator()(
- const llvm::json::Object &request) const {
- llvm::json::Object response;
- FillResponse(request, response);
- llvm::json::Object body;
-
- const auto *arguments = request.getObject("arguments");
- // sourceInitFile option is not from formal DAP specification. It is only
- // used by unit tests to prevent sourcing .lldbinit files from environment
- // which may affect the outcome of tests.
- bool source_init_file =
- GetBoolean(arguments, "sourceInitFile").value_or(true);
-
+/// Initialize request; value of command field is 'initialize'.
+llvm::Expected<protocol::InitializeResponseBody> InitializeRequestHandler::Run(
+ const protocol::InitializeRequestArguments &arguments) const {
// Do not source init files until in/out/err are configured.
dap.debugger = lldb::SBDebugger::Create(false);
dap.debugger.SetInputFile(dap.in);
- auto out_fd = dap.out.GetWriteFileDescriptor();
- if (llvm::Error err = out_fd.takeError()) {
- response["success"] = false;
- EmplaceSafeString(response, "message", llvm::toString(std::move(err)));
- dap.SendJSON(llvm::json::Value(std::move(response)));
- return;
- }
+
+ llvm::Expected<int> out_fd = dap.out.GetWriteFileDescriptor();
+ if (!out_fd)
+ return out_fd.takeError();
dap.debugger.SetOutputFile(lldb::SBFile(*out_fd, "w", false));
- auto err_fd = dap.err.GetWriteFileDescriptor();
- if (llvm::Error err = err_fd.takeError()) {
- response["success"] = false;
- EmplaceSafeString(response, "message", llvm::toString(std::move(err)));
- dap.SendJSON(llvm::json::Value(std::move(response)));
- return;
- }
+
+ llvm::Expected<int> err_fd = dap.err.GetWriteFileDescriptor();
+ if (!err_fd)
+ return err_fd.takeError();
dap.debugger.SetErrorFile(lldb::SBFile(*err_fd, "w", false));
auto interp = dap.debugger.GetCommandInterpreter();
- if (source_init_file) {
+ // sourceInitFile option is not from formal DAP specification. It is only
+ // used by unit tests to prevent sourcing .lldbinit files from environment
+ // which may affect the outcome of tests.
+ if (arguments.sourceInitFile.value_or(true)) {
dap.debugger.SkipLLDBInitFiles(false);
dap.debugger.SkipAppInitFiles(false);
lldb::SBCommandReturnObject init;
@@ -348,59 +260,35 @@ void InitializeRequestHandler::operator()(
interp.SourceInitFileInHomeDirectory(init);
}
- if (llvm::Error err = dap.RunPreInitCommands()) {
- response["success"] = false;
- EmplaceSafeString(response, "message", llvm::toString(std::move(err)));
- dap.SendJSON(llvm::json::Value(std::move(response)));
- return;
- }
+ if (llvm::Error err = dap.RunPreInitCommands())
+ return err;
dap.PopulateExceptionBreakpoints();
auto cmd = dap.debugger.GetCommandInterpreter().AddMultiwordCommand(
"lldb-dap", "Commands for managing lldb-dap.");
- if (GetBoolean(arguments, "supportsStartDebuggingRequest").value_or(false)) {
+ if (arguments.supportsStartDebuggingRequest.value_or(false)) {
cmd.AddCommand(
"start-debugging", new StartDebuggingRequestHandler(dap),
"Sends a startDebugging request from the debug adapter to the client "
"to start a child debug session of the same type as the caller.");
}
+ dap.supports_run_in_terminal_request =
+ arguments.supportsRunInTerminalRequest.value_or(false);
cmd.AddCommand(
"repl-mode", new ReplModeRequestHandler(dap),
"Get or set the repl behavior of lldb-dap evaluation requests.");
cmd.AddCommand("send-event", new SendEventRequestHandler(dap),
"Sends an DAP event to the client.");
- dap.progress_event_thread =
- std::thread(ProgressEventThreadFunction, std::ref(dap));
+ if (arguments.supportsProgressReporting)
+ dap.progress_event_thread =
+ std::thread(ProgressEventThreadFunction, std::ref(dap));
// Start our event thread so we can receive events from the debugger, target,
// process and more.
dap.event_thread = std::thread(EventThreadFunction, std::ref(dap));
- llvm::StringMap<bool> capabilities = dap.GetCapabilities();
- for (auto &kv : capabilities)
- body.try_emplace(kv.getKey(), kv.getValue());
-
- // Available filters or options for the setExceptionBreakpoints request.
- llvm::json::Array filters;
- for (const auto &exc_bp : *dap.exception_breakpoints)
- filters.emplace_back(CreateExceptionBreakpointFilter(exc_bp));
- body.try_emplace("exceptionBreakpointFilters", std::move(filters));
-
- llvm::json::Array completion_characters;
- completion_characters.emplace_back(".");
- completion_characters.emplace_back(" ");
- completion_characters.emplace_back("\t");
- body.try_emplace("completionTriggerCharacters",
- std::move(completion_characters));
-
- // Put in non-DAP specification lldb specific information.
- llvm::json::Object lldb_json;
- lldb_json.try_emplace("version", dap.debugger.GetVersionString());
- body.try_emplace("__lldb", std::move(lldb_json));
-
- response.try_emplace("body", std::move(body));
- dap.SendJSON(llvm::json::Value(std::move(response)));
+ return dap.GetCapabilities();
}
} // namespace lldb_dap
diff --git a/lldb/tools/lldb-dap/Handler/RequestHandler.cpp b/lldb/tools/lldb-dap/Handler/RequestHandler.cpp
index 60c82649938d6..d2a0da420739e 100644
--- a/lldb/tools/lldb-dap/Handler/RequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/RequestHandler.cpp
@@ -201,6 +201,7 @@ BaseRequestHandler::LaunchProcess(const llvm::json::Object &request) const {
const auto timeout_seconds =
GetInteger<uint64_t>(arguments, "timeout").value_or(30);
+ // FIXME: Check dap.supports_run_in_terminal_request.
if (GetBoolean(arguments, "runInTerminal").value_or(false)) {
if (llvm::Error err = RunInTerminal(dap, request, timeout_seconds))
error.SetErrorString(llvm::toString(std::move(err)).c_str());
diff --git a/lldb/tools/lldb-dap/Handler/RequestHandler.h b/lldb/tools/lldb-dap/Handler/RequestHandler.h
index 8971b02fcb92e..ba854c9884cde 100644
--- a/lldb/tools/lldb-dap/Handler/RequestHandler.h
+++ b/lldb/tools/lldb-dap/Handler/RequestHandler.h
@@ -14,6 +14,7 @@
#include "DAPLog.h"
#include "Protocol/ProtocolBase.h"
#include "Protocol/ProtocolRequests.h"
+#include "Protocol/ProtocolTypes.h"
#include "lldb/API/SBError.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Error.h"
@@ -47,7 +48,7 @@ class BaseRequestHandler {
virtual void operator()(const protocol::Request &request) const = 0;
- virtual llvm::StringMap<bool> GetCapabilities() const { return {}; }
+ virtual protocol::Capabilities GetCapabilities() const { return {}; }
protected:
/// Helpers used by multiple request handlers.
@@ -175,8 +176,10 @@ class BreakpointLocationsRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "breakpointLocations"; }
- llvm::StringMap<bool> GetCapabilities() const override {
- return {{"supportsBreakpointLocationsRequest", true}};
+ protocol::Capabilities GetCapabilities() const override {
+ protocol::Capabilities capabilities;
+ capabilities.supportsBreakpointLocationsRequest = true;
+ return capabilities;
}
void operator()(const llvm::json::Object &request) const override;
};
@@ -185,8 +188,10 @@ class CompletionsRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "completions"; }
- llvm::StringMap<bool> GetCapabilities() const override {
- return {{"supportsCompletionsRequest", true}};
+ protocol::Capabilities GetCapabilities() const override {
+ protocol::Capabilities capabilities;
+ capabilities.supportsCompletionsRequest = true;
+ return capabilities;
}
void operator()(const llvm::json::Object &request) const override;
};
@@ -202,8 +207,10 @@ class ConfigurationDoneRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "configurationDone"; }
- llvm::StringMap<bool> GetCapabilities() const override {
- return {{"supportsConfigurationDoneRequest", true}};
+ protocol::Capabilities GetCapabilities() const override {
+ protocol::Capabilities capabilities;
+ capabilities.supportsConfigurationDoneRequest = true;
+ return capabilities;
}
void operator()(const llvm::json::Object &request) const override;
};
@@ -229,20 +236,22 @@ class ExceptionInfoRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "exceptionInfo"; }
- llvm::StringMap<bool> GetCapabilities() const override {
- return {{"supportsExceptionInfoRequest", true}};
+ protocol::Capabilities GetCapabilities() const override {
+ protocol::Capabilities capabilities;
+ capabilities.supportsExceptionInfoRequest = true;
+ return capabilities;
}
void operator()(const llvm::json::Object &request) const override;
};
-class InitializeRequestHandler : public LegacyRequestHandler {
+class InitializeRequestHandler
+ : public RequestHandler<protocol::InitializeRequestArguments,
+ protocol::InitializeResponseBody> {
public:
- using LegacyRequestHandler::LegacyRequestHandler;
+ using RequestHandler::RequestHandler;
static llvm::StringLiteral GetCommand() { return "initialize"; }
- llvm::StringMap<bool> GetCapabilities() const override {
- return {{"supportsRunInTerminalRequest", true}};
- }
- void operator()(const llvm::json::Object &request) const override;
+ llvm::Expected<protocol::InitializeResponseBody>
+ Run(const protocol::InitializeRequestArguments &args) const override;
};
class LaunchRequestHandler : public LegacyRequestHandler {
@@ -256,8 +265,10 @@ class RestartRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "restart"; }
- llvm::StringMap<bool> GetCapabilities() const override {
- return {{"supportsRestartRequest", true}};
+ protocol::Capabilities GetCapabilities() const override {
+ protocol::Capabilities capabilities;
+ capabilities.supportsRestartRequest = true;
+ return capabilities;
}
void operator()(const llvm::json::Object &request) const override;
};
@@ -280,8 +291,10 @@ class StepInTargetsRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "stepInTargets"; }
- llvm::StringMap<bool> GetCapabilities() const override {
- return {{"supportsStepInTargetsRequest", true}};
+ protocol::Capabilities GetCapabilities() const override {
+ protocol::Capabilities capabilities;
+ capabilities.supportsStepInTargetsRequest = true;
+ return capabilities;
}
void operator()(const llvm::json::Object &request) const override;
};
@@ -297,9 +310,11 @@ class SetBreakpointsRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "setBreakpoints"; }
- llvm::StringMap<bool> GetCapabilities() const override {
- return {{"supportsConditionalBreakpoints", true},
- {"supportsHitConditionalBreakpoints", true}};
+ protocol::Capabilities GetCapabilities() const override {
+ protocol::Capabilities capabilities;
+ capabilities.supportsConditionalBreakpoints = true;
+ capabilities.supportsHitConditionalBreakpoints = true;
+ return capabilities;
}
void operator()(const llvm::json::Object &request) const override;
};
@@ -315,8 +330,10 @@ class SetFunctionBreakpointsRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "setFunctionBreakpoints"; }
- llvm::StringMap<bool> GetCapabilities() const override {
- return {{"supportsFunctionBreakpoints", true}};
+ protocol::Capabilities GetCapabilities() const override {
+ protocol::Capabilities capabilities;
+ capabilities.supportsFunctionBreakpoints = true;
+ return capabilities;
}
void operator()(const llvm::json::Object &request) const override;
};
@@ -355,8 +372,10 @@ class ModulesRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "modules"; }
- llvm::StringMap<bool> GetCapabilities() const override {
- return {{"supportsModulesRequest", true}};
+ protocol::Capabilities GetCapabilities() const override {
+ protocol::Capabilities capabilities;
+ capabilities.supportsModulesRequest = true;
+ return capabilities;
}
void operator()(const llvm::json::Object &request) const override;
};
@@ -379,8 +398,10 @@ class SetVariableRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "setVariable"; }
- llvm::StringMap<bool> GetCapabilities() const override {
- return {{"supportsSetVariable", true}};
+ protocol::Capabilities GetCapabilities() const override {
+ protocol::Capabilities capabilities;
+ capabilities.supportsSetVariable = true;
+ return capabilities;
}
void operator()(const llvm::json::Object &request) const override;
};
@@ -427,8 +448,10 @@ class DisassembleRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "disassemble"; }
- llvm::StringMap<bool> GetCapabilities() const override {
- return {{"supportsDisassembleRequest", true}};
+ protocol::Capabilities GetCapabilities() const override {
+ protocol::Capabilities capabilities;
+ capabilities.supportsDisassembleRequest = true;
+ return capabilities;
}
void operator()(const llvm::json::Object &request) const override;
};
@@ -437,8 +460,10 @@ class ReadMemoryRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "readMemory"; }
- llvm::StringMap<bool> GetCapabilities() const override {
- return {{"supportsReadMemoryRequest", true}};
+ protocol::Capabilities GetCapabilities() const override {
+ protocol::Capabilities capabilities;
+ capabilities.supportsReadMemoryRequest = true;
+ return capabilities;
}
void operator()(const llvm::json::Object &request) const override;
};
diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp b/lldb/tools/lldb-dap/JSONUtils.cpp
index ea942c5d65934..9773b91a35a45 100644
--- a/lldb/tools/lldb-dap/JSONUtils.cpp
+++ b/lldb/tools/lldb-dap/JSONUtils.cpp
@@ -557,35 +557,13 @@ llvm::json::Object CreateEventObject(const llvm::StringRef event_name) {
return event;
}
-// "ExceptionBreakpointsFilter": {
-// "type": "object",
-// "description": "An ExceptionBreakpointsFilter is shown in the UI as an
-// option for configuring how exceptions are dealt with.",
-// "properties": {
-// "filter": {
-// "type": "string",
-// "description": "The internal ID of the filter. This value is passed
-// to the setExceptionBreakpoints request."
-// },
-// "label": {
-// "type": "string",
-// "description": "The name of the filter. This will be shown in the UI."
-// },
-// "default": {
-// "type": "boolean",
-// "description": "Initial value of the filter. If not specified a value
-// 'false' is assumed."
-// }
-// },
-// "required": [ "filter", "label" ]
-// }
-llvm::json::Value
+protocol::ExceptionBreakpointsFilter
CreateExceptionBreakpointFilter(const ExceptionBreakpoint &bp) {
- llvm::json::Object object;
- EmplaceSafeString(object, "filter", bp.filter);
- EmplaceSafeString(object, "label", bp.label);
- object.try_emplace("default", bp.default_value);
- return llvm::json::Value(std::move(object));
+ protocol::ExceptionBreakpointsFilter filter;
+ filter.filter = bp.filter;
+ filter.label = bp.label;
+ filter.defaultState = bp.default_value;
+ return filter;
}
// "Source": {
diff --git a/lldb/tools/lldb-dap/JSONUtils.h b/lldb/tools/lldb-dap/JSONUtils.h
index a8858020f7d85..5d403d39a76d4 100644
--- a/lldb/tools/lldb-dap/JSONUtils.h
+++ b/lldb/tools/lldb-dap/JSONUtils.h
@@ -10,6 +10,7 @@
#define LLDB_TOOLS_LLDB_DAP_JSONUTILS_H
#include "DAPForward.h"
+#include "Protocol/ProtocolTypes.h"
#include "lldb/API/SBCompileUnit.h"
#include "lldb/API/SBFileSpec.h"
#include "lldb/API/SBFormat.h"
@@ -289,7 +290,7 @@ llvm::json::Object CreateEventObject(const llvm::StringRef event_name);
/// \return
/// A "ExceptionBreakpointsFilter" JSON object with that follows
/// the formal JSON definition outlined by Microsoft.
-llvm::json::Value
+protocol::ExceptionBreakpointsFilter
CreateExceptionBreakpointFilter(const ExceptionBreakpoint &bp);
/// Create a "Scope" JSON object as described in the debug adapter definition.
diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp
index 5cc5429227439..16d54b1184f1d 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp
@@ -23,6 +23,58 @@ bool fromJSON(const json::Value &Params, DisconnectArguments &DA,
O.mapOptional("suspendDebuggee", DA.suspendDebuggee);
}
+bool fromJSON(const llvm::json::Value &Params,
+ InitializeRequestArguments::PathFormat &PF, llvm::json::Path P) {
+ auto rawPathFormat = Params.getAsString();
+ if (!rawPathFormat) {
+ P.report("expected a string");
+ return false;
+ }
+
+ std::optional<InitializeRequestArguments::PathFormat> pathFormat =
+ StringSwitch<std::optional<InitializeRequestArguments::PathFormat>>(
+ *rawPathFormat)
+ .Case("path", InitializeRequestArguments::PathFormat::path)
+ .Case("uri", InitializeRequestArguments::PathFormat::uri)
+ .Default(std::nullopt);
+ if (!pathFormat) {
+ P.report("unexpected value, expected 'path' or 'uri'");
+ return false;
+ }
+
+ PF = *pathFormat;
+ return true;
+}
+
+bool fromJSON(const llvm::json::Value &Params, InitializeRequestArguments &IRA,
+ llvm::json::Path P) {
+ json::ObjectMapper O(Params, P);
+ return O && O.mapOptional("adatperID", IRA.adatperID) &&
+ O.mapOptional("clientID", IRA.clientID) &&
+ O.mapOptional("clientName", IRA.clientName) &&
+ O.mapOptional("locale", IRA.locale) &&
+ O.mapOptional("linesStartAt1", IRA.linesStartAt1) &&
+ O.mapOptional("columnsStartAt1", IRA.columnsStartAt1) &&
+ O.mapOptional("pathFormat", IRA.pathFormat) &&
+ O.mapOptional("supportsVariableType", IRA.supportsVariableType) &&
+ O.mapOptional("supportsVariablePaging", IRA.supportsVariablePaging) &&
+ O.mapOptional("supportsRunInTerminalRequest",
+ IRA.supportsRunInTerminalRequest) &&
+ O.mapOptional("supportsMemoryReferences",
+ IRA.supportsMemoryReferences) &&
+ O.mapOptional("supportsProgressReporting",
+ IRA.supportsProgressReporting) &&
+ O.mapOptional("supportsInvalidatedEvent",
+ IRA.supportsInvalidatedEvent) &&
+ O.mapOptional("supportsMemoryEvent", IRA.supportsMemoryEvent) &&
+ O.mapOptional("supportsArgsCanBeInterpretedByShell",
+ IRA.supportsArgsCanBeInterpretedByShell) &&
+ O.mapOptional("supportsStartDebuggingRequest",
+ IRA.supportsStartDebuggingRequest) &&
+ O.mapOptional("supportsANSIStyling", IRA.supportsANSIStyling) &&
+ O.mapOptional("$__lldb_sourceInitFile", IRA.sourceInitFile);
+}
+
bool fromJSON(const json::Value &Params, SourceArguments &SA, json::Path P) {
json::ObjectMapper O(Params, P);
return O && O.mapOptional("source", SA.source) &&
diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h
index 5dc4a589178d2..beb573515df62 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h
@@ -54,6 +54,75 @@ bool fromJSON(const llvm::json::Value &, DisconnectArguments &,
/// body field is required.
using DisconnectResponse = VoidResponse;
+/// Arguments for `initialize` request.
+struct InitializeRequestArguments {
+ /// The ID of the debug adapter.
+ std::string adatperID;
+
+ /// The ID of the client using this adapter.
+ std::optional<std::string> clientID;
+
+ /// The human-readable name of the client using this adapter.
+ std::optional<std::string> clientName;
+
+ /// The ISO-639 locale of the client using this adapter, e.g. en-US or de-CH.
+ std::optional<std::string> locale;
+
+ /// If true all line numbers are 1-based (default).
+ std::optional<bool> linesStartAt1;
+
+ /// If true all column numbers are 1-based (default).
+ std::optional<bool> columnsStartAt1;
+
+ enum class PathFormat { path, uri };
+
+ /// Determines in what format paths are specified. The default is `path`,
+ /// which is the native format.
+ std::optional<PathFormat> pathFormat = PathFormat::path;
+
+ /// Client supports the `type` attribute for variables.
+ std::optional<bool> supportsVariableType;
+
+ /// Client supports the paging of variables.
+ std::optional<bool> supportsVariablePaging;
+
+ /// Client supports the `runInTerminal` request.
+ std::optional<bool> supportsRunInTerminalRequest;
+
+ /// Client supports memory references.
+ std::optional<bool> supportsMemoryReferences;
+
+ /// Client supports progress reporting.
+ std::optional<bool> supportsProgressReporting;
+
+ /// Client supports the `invalidated` event.
+ std::optional<bool> supportsInvalidatedEvent;
+
+ /// Client supports the `memory` event.
+ std::optional<bool> supportsMemoryEvent;
+
+ /// Client supports the `argsCanBeInterpretedByShell` attribute on the
+ /// `runInTerminal` request.
+ std::optional<bool> supportsArgsCanBeInterpretedByShell;
+
+ /// Client supports the `startDebugging` request.
+ std::optional<bool> supportsStartDebuggingRequest;
+
+ /// The client will interpret ANSI escape sequences in the display of
+ /// `OutputEvent.output` and `Variable.value` fields when
+ /// `Capabilities.supportsANSIStyling` is also enabled.
+ std::optional<bool> supportsANSIStyling;
+
+ /// lldb-dap Extensions
+ /// Source init files when initializing lldb::SBDebugger.
+ std::optional<bool> sourceInitFile;
+};
+bool fromJSON(const llvm::json::Value &, InitializeRequestArguments &,
+ llvm::json::Path);
+
+/// Response to `initialize` request. The capabilities of this debug adapter.
+using InitializeResponseBody = std::optional<Capabilities>;
+
/// Arguments for `source` request.
struct SourceArguments {
/// Specifies the source content to load. Either `source.path` or
diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp
index efb5c3abe32bf..d81d4bc801538 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp
@@ -44,4 +44,203 @@ bool fromJSON(const json::Value &Params, Source &S, json::Path P) {
O.mapOptional("sourceReference", S.sourceReference);
}
+json::Value toJSON(const ExceptionBreakpointsFilter &EBF) {
+ json::Object result{{"filter", EBF.filter}, {"label", EBF.label}};
+
+ if (EBF.description)
+ result.insert({"description", *EBF.description});
+ if (EBF.defaultState)
+ result.insert({"defaultState", *EBF.defaultState});
+ if (EBF.supportsCondition)
+ result.insert({"supportsCondition", *EBF.supportsCondition});
+ if (EBF.conditionDescription)
+ result.insert({"conditionDescription", *EBF.conditionDescription});
+
+ return result;
+}
+
+json::Value toJSON(const ColumnDescriptor::Type &T) {
+ switch (T) {
+ case ColumnDescriptor::Type::String:
+ return "string";
+ case ColumnDescriptor::Type::Number:
+ return "number";
+ case ColumnDescriptor::Type::Boolean:
+ return "boolean";
+ case ColumnDescriptor::Type::Timestamp:
+ return "unixTimestampUTC";
+ }
+}
+
+json::Value toJSON(const ColumnDescriptor &CD) {
+ json::Object result{{"attributeName", CD.attributeName}, {"label", CD.label}};
+
+ if (CD.format)
+ result.insert({"format", *CD.format});
+ if (CD.type)
+ result.insert({"type", *CD.type});
+ if (CD.width)
+ result.insert({"width", *CD.width});
+
+ return result;
+}
+
+json::Value toJSON(const ChecksumAlgorithm &CA) {
+ switch (CA) {
+ case ChecksumAlgorithm::md5:
+ return "MD5";
+ case ChecksumAlgorithm::sha1:
+ return "SHA1";
+ case ChecksumAlgorithm::sha256:
+ return "SHA256";
+ case ChecksumAlgorithm::timestamp:
+ return "timestamp";
+ }
+}
+
+json::Value toJSON(const BreakpointModeApplicability &BMA) {
+ switch (BMA) {
+ case BreakpointModeApplicability::source:
+ return "source";
+ case BreakpointModeApplicability::exception:
+ return "exception";
+ case BreakpointModeApplicability::data:
+ return "data";
+ case BreakpointModeApplicability::instruction:
+ return "instruction";
+ }
+}
+
+json::Value toJSON(const BreakpointMode &BM) {
+ json::Object result{
+ {"mode", BM.mode},
+ {"label", BM.label},
+ {"appliesTo", BM.appliesTo},
+ };
+
+ if (BM.description)
+ result.insert({"description", *BM.description});
+
+ return result;
+}
+
+json::Value toJSON(const Capabilities &C) {
+ json::Object result;
+
+ if (C.supportsConfigurationDoneRequest && *C.supportsConfigurationDoneRequest)
+ result.insert({"supportsConfigurationDoneRequest",
+ *C.supportsConfigurationDoneRequest});
+ if (C.supportsFunctionBreakpoints && *C.supportsFunctionBreakpoints)
+ result.insert(
+ {"supportsFunctionBreakpoints", *C.supportsFunctionBreakpoints});
+ if (C.supportsConditionalBreakpoints && *C.supportsConditionalBreakpoints)
+ result.insert(
+ {"supportsConditionalBreakpoints", *C.supportsConditionalBreakpoints});
+ if (C.supportsHitConditionalBreakpoints &&
+ *C.supportsHitConditionalBreakpoints)
+ result.insert({"supportsHitConditionalBreakpoints",
+ *C.supportsHitConditionalBreakpoints});
+ if (C.supportsEvaluateForHovers && *C.supportsEvaluateForHovers)
+ result.insert({"supportsEvaluateForHovers", *C.supportsEvaluateForHovers});
+ if (C.exceptionBreakpointFilters && !C.exceptionBreakpointFilters->empty())
+ result.insert(
+ {"exceptionBreakpointFilters", *C.exceptionBreakpointFilters});
+ if (C.supportsStepBack && *C.supportsStepBack)
+ result.insert({"supportsStepBack", *C.supportsStepBack});
+ if (C.supportsSetVariable && *C.supportsSetVariable)
+ result.insert({"supportsSetVariable", *C.supportsSetVariable});
+ if (C.supportsRestartFrame && *C.supportsRestartFrame)
+ result.insert({"supportsRestartFrame", *C.supportsRestartFrame});
+ if (C.supportsGotoTargetsRequest && *C.supportsGotoTargetsRequest)
+ result.insert(
+ {"supportsGotoTargetsRequest", *C.supportsGotoTargetsRequest});
+ if (C.supportsStepInTargetsRequest && *C.supportsStepInTargetsRequest)
+ result.insert(
+ {"supportsStepInTargetsRequest", *C.supportsStepInTargetsRequest});
+ if (C.supportsCompletionsRequest && *C.supportsCompletionsRequest)
+ result.insert(
+ {"supportsCompletionsRequest", *C.supportsCompletionsRequest});
+ if (C.completionTriggerCharacters && !C.completionTriggerCharacters->empty())
+ result.insert(
+ {"completionTriggerCharacters", *C.completionTriggerCharacters});
+ if (C.supportsModulesRequest && *C.supportsModulesRequest)
+ result.insert({"supportsModulesRequest", *C.supportsModulesRequest});
+ if (C.additionalModuleColumns && !C.additionalModuleColumns->empty())
+ result.insert({"additionalModuleColumns", *C.additionalModuleColumns});
+ if (C.supportedChecksumAlgorithms && !C.supportedChecksumAlgorithms->empty())
+ result.insert(
+ {"supportedChecksumAlgorithms", *C.supportedChecksumAlgorithms});
+ if (C.supportsRestartRequest && *C.supportsRestartRequest)
+ result.insert({"supportsRestartRequest", *C.supportsRestartRequest});
+ if (C.supportsExceptionOptions && *C.supportsExceptionOptions)
+ result.insert({"supportsExceptionOptions", *C.supportsExceptionOptions});
+ if (C.supportsValueFormattingOptions && *C.supportsValueFormattingOptions)
+ result.insert(
+ {"supportsValueFormattingOptions", *C.supportsValueFormattingOptions});
+ if (C.supportsExceptionInfoRequest && *C.supportsExceptionInfoRequest)
+ result.insert(
+ {"supportsExceptionInfoRequest", *C.supportsExceptionInfoRequest});
+ if (C.supportTerminateDebuggee && *C.supportTerminateDebuggee)
+ result.insert({"supportTerminateDebuggee", *C.supportTerminateDebuggee});
+ if (C.supportSuspendDebuggee && *C.supportSuspendDebuggee)
+ result.insert({"supportSuspendDebuggee", *C.supportSuspendDebuggee});
+ if (C.supportsDelayedStackTraceLoading && *C.supportsDelayedStackTraceLoading)
+ result.insert({"supportsDelayedStackTraceLoading",
+ *C.supportsDelayedStackTraceLoading});
+ if (C.supportsLoadedSourcesRequest && *C.supportsLoadedSourcesRequest)
+ result.insert(
+ {"supportsLoadedSourcesRequest", *C.supportsLoadedSourcesRequest});
+ if (C.supportsLogPoints && *C.supportsLogPoints)
+ result.insert({"supportsLogPoints", *C.supportsLogPoints});
+ if (C.supportsTerminateThreadsRequest && *C.supportsTerminateThreadsRequest)
+ result.insert({"supportsTerminateThreadsRequest",
+ *C.supportsTerminateThreadsRequest});
+ if (C.supportsSetExpression && *C.supportsSetExpression)
+ result.insert({"supportsSetExpression", *C.supportsSetExpression});
+ if (C.supportsTerminateRequest && *C.supportsTerminateRequest)
+ result.insert({"supportsTerminateRequest", *C.supportsTerminateRequest});
+ if (C.supportsDataBreakpoints && *C.supportsDataBreakpoints)
+ result.insert({"supportsDataBreakpoints", *C.supportsDataBreakpoints});
+ if (C.supportsReadMemoryRequest && *C.supportsReadMemoryRequest)
+ result.insert({"supportsReadMemoryRequest", *C.supportsReadMemoryRequest});
+ if (C.supportsWriteMemoryRequest && *C.supportsWriteMemoryRequest)
+ result.insert(
+ {"supportsWriteMemoryRequest", *C.supportsWriteMemoryRequest});
+ if (C.supportsDisassembleRequest && *C.supportsDisassembleRequest)
+ result.insert(
+ {"supportsDisassembleRequest", *C.supportsDisassembleRequest});
+ if (C.supportsCancelRequest && *C.supportsCancelRequest)
+ result.insert({"supportsCancelRequest", *C.supportsCancelRequest});
+ if (C.supportsBreakpointLocationsRequest &&
+ *C.supportsBreakpointLocationsRequest)
+ result.insert({"supportsBreakpointLocationsRequest",
+ *C.supportsBreakpointLocationsRequest});
+ if (C.supportsClipboardContext && *C.supportsClipboardContext)
+ result.insert({"supportsClipboardContext", *C.supportsClipboardContext});
+ if (C.supportsSteppingGranularity && *C.supportsSteppingGranularity)
+ result.insert(
+ {"supportsSteppingGranularity", *C.supportsSteppingGranularity});
+ if (C.supportsInstructionBreakpoints && *C.supportsInstructionBreakpoints)
+ result.insert(
+ {"supportsInstructionBreakpoints", *C.supportsInstructionBreakpoints});
+ if (C.supportsExceptionFilterOptions && *C.supportsExceptionFilterOptions)
+ result.insert(
+ {"supportsExceptionFilterOptions", *C.supportsExceptionFilterOptions});
+ if (C.supportsSingleThreadExecutionRequests &&
+ *C.supportsSingleThreadExecutionRequests)
+ result.insert({"supportsSingleThreadExecutionRequests",
+ *C.supportsSingleThreadExecutionRequests});
+ if (C.supportsDataBreakpointBytes && *C.supportsDataBreakpointBytes)
+ result.insert(
+ {"supportsDataBreakpointBytes", *C.supportsDataBreakpointBytes});
+ if (C.breakpointModes && !C.breakpointModes->empty())
+ result.insert({"breakpointModes", *C.breakpointModes});
+ if (C.supportsANSIStyling && *C.supportsANSIStyling)
+ result.insert({"supportsANSIStyling", *C.supportsANSIStyling});
+ if (C.lldbVersion && !C.lldbVersion->empty())
+ result.insert({"$__lldb_version", *C.lldbVersion});
+
+ return result;
+}
+
} // namespace lldb_dap::protocol
diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h
index b54d76cb29a77..9a58e83b39ad1 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h
@@ -27,6 +27,261 @@
namespace lldb_dap::protocol {
+/// An `ExceptionBreakpointsFilter` is shown in the UI as an filter option for
+/// configuring how exceptions are dealt with.
+struct ExceptionBreakpointsFilter {
+ /// The internal ID of the filter option. This value is passed to the
+ /// `setExceptionBreakpoints` request.
+ std::string filter;
+
+ /// The name of the filter option. This is shown in the UI.
+ std::string label;
+
+ /// A help text providing additional information about the exception filter.
+ /// This string is typically shown as a hover and can be translated.
+ std::optional<std::string> description;
+
+ /// Initial value of the filter option. If not specified a value false is
+ /// assumed.
+ std::optional<bool> defaultState;
+
+ /// Controls whether a condition can be specified for this filter option. If
+ /// false or missing, a condition can not be set.
+ std::optional<bool> supportsCondition;
+
+ /// A help text providing information about the condition. This string is
+ /// shown as the placeholder text for a text box and can be translated.
+ std::optional<std::string> conditionDescription;
+};
+llvm::json::Value toJSON(const ExceptionBreakpointsFilter &);
+
+/// A ColumnDescriptor specifies what module attribute to show in a column of
+/// the modules view, how to format it, and what the column’s label should be.
+///
+/// It is only used if the underlying UI actually supports this level of
+/// customization.
+struct ColumnDescriptor {
+ /// Name of the attribute rendered in this column.
+ std::string attributeName;
+
+ /// Header UI label of column.
+ std::string label;
+
+ /// Format to use for the rendered values in this column. TBD how the format
+ /// strings looks like.
+ std::optional<std::string> format;
+
+ enum class Type { String, Number, Boolean, Timestamp };
+
+ /// Datatype of values in this column. Defaults to `string` if not specified.
+ /// Values: 'string', 'number', 'boolean', 'unixTimestampUTC'.
+ std::optional<Type> type;
+
+ /// Width of this column in characters (hint only).
+ std::optional<int> width;
+};
+llvm::json::Value toJSON(const ColumnDescriptor &);
+
+/// Names of checksum algorithms that may be supported by a debug adapter.
+/// Values: ‘MD5’, ‘SHA1’, ‘SHA256’, ‘timestamp’.
+enum class ChecksumAlgorithm { md5, sha1, sha256, timestamp };
+llvm::json::Value toJSON(const ChecksumAlgorithm &);
+
+/// Describes one or more type of breakpoint a BreakpointMode applies to. This
+/// is a non-exhaustive enumeration and may expand as future breakpoint types
+/// are added.
+enum class BreakpointModeApplicability {
+ /// In `SourceBreakpoint`'s.
+ source,
+ /// In exception breakpoints applied in the `ExceptionFilterOptions`.
+ exception,
+ /// In data breakpoints requested in the `DataBreakpointInfo` request.
+ data,
+ /// In `InstructionBreakpoint`'s.
+ instruction
+};
+llvm::json::Value toJSON(const BreakpointModeApplicability &);
+
+/// A `BreakpointMode` is provided as a option when setting breakpoints on
+/// sources or instructions.
+struct BreakpointMode {
+ /// The internal ID of the mode. This value is passed to the `setBreakpoints`
+ /// request.
+ std::string mode;
+
+ /// The name of the breakpoint mode. This is shown in the UI.
+ std::string label;
+
+ /// A help text providing additional information about the breakpoint mode.
+ /// This string is typically shown as a hover and can be translated.
+ std::optional<std::string> description;
+
+ /// Describes one or more type of breakpoint this mode applies to.
+ std::vector<BreakpointModeApplicability> appliesTo;
+};
+llvm::json::Value toJSON(const BreakpointMode &);
+
+/// Information about the capabilities of a debug adapter.
+struct Capabilities {
+ /// The debug adapter supports the `configurationDone` request.
+ std::optional<bool> supportsConfigurationDoneRequest;
+
+ /// The debug adapter supports function breakpoints.
+ std::optional<bool> supportsFunctionBreakpoints;
+
+ /// The debug adapter supports conditional breakpoints.
+ std::optional<bool> supportsConditionalBreakpoints;
+
+ /// The debug adapter supports breakpoints that break execution after a
+ /// specified number of hits.
+ std::optional<bool> supportsHitConditionalBreakpoints;
+
+ /// The debug adapter supports a (side effect free) `evaluate` request for
+ /// data hovers.
+ std::optional<bool> supportsEvaluateForHovers;
+
+ /// Available exception filter options for the `setExceptionBreakpoints`
+ /// request.
+ std::optional<std::vector<ExceptionBreakpointsFilter>>
+ exceptionBreakpointFilters;
+
+ /// The debug adapter supports stepping back via the `stepBack` and
+ /// `reverseContinue` requests.
+ std::optional<bool> supportsStepBack;
+
+ /// The debug adapter supports setting a variable to a value.
+ std::optional<bool> supportsSetVariable;
+
+ /// The debug adapter supports restarting a frame.
+ std::optional<bool> supportsRestartFrame;
+
+ /// The debug adapter supports the `gotoTargets` request.
+ std::optional<bool> supportsGotoTargetsRequest;
+
+ /// The debug adapter supports the `stepInTargets` request.
+ std::optional<bool> supportsStepInTargetsRequest;
+
+ /// The debug adapter supports the `completions` request.
+ std::optional<bool> supportsCompletionsRequest;
+
+ /// The set of characters that should trigger completion in a REPL. If not
+ /// specified, the UI should assume the `.` character.
+ std::optional<std::vector<std::string>> completionTriggerCharacters;
+
+ /// The debug adapter supports the `modules` request.
+ std::optional<bool> supportsModulesRequest;
+
+ /// The set of additional module information exposed by the debug adapter.
+ std::optional<std::vector<ColumnDescriptor>> additionalModuleColumns;
+
+ /// Checksum algorithms supported by the debug adapter.
+ std::optional<std::vector<ChecksumAlgorithm>> supportedChecksumAlgorithms;
+
+ /// The debug adapter supports the `restart` request. In this case a client
+ /// should not implement `restart` by terminating and relaunching the adapter
+ /// but by calling the `restart` request.
+ std::optional<bool> supportsRestartRequest;
+
+ /// The debug adapter supports `exceptionOptions` on the
+ /// `setExceptionBreakpoints` request.
+ std::optional<bool> supportsExceptionOptions;
+
+ /// The debug adapter supports a `format` attribute on the `stackTrace`,
+ /// `variables`, and `evaluate` requests.
+ std::optional<bool> supportsValueFormattingOptions;
+
+ /// The debug adapter supports the `exceptionInfo` request.
+ std::optional<bool> supportsExceptionInfoRequest;
+
+ /// The debug adapter supports the `terminateDebuggee` attribute on the
+ /// `disconnect` request.
+ std::optional<bool> supportTerminateDebuggee;
+
+ /// The debug adapter supports the `suspendDebuggee` attribute on the
+ /// `disconnect` request.
+ std::optional<bool> supportSuspendDebuggee;
+
+ /// The debug adapter supports the delayed loading of parts of the stack,
+ /// which requires that both the `startFrame` and `levels` arguments and the
+ /// `totalFrames` result of the `stackTrace` request are supported.
+ std::optional<bool> supportsDelayedStackTraceLoading;
+
+ /// The debug adapter supports the `loadedSources` request.
+ std::optional<bool> supportsLoadedSourcesRequest;
+
+ /// The debug adapter supports log points by interpreting the `logMessage`
+ /// attribute of the `SourceBreakpoint`.
+ std::optional<bool> supportsLogPoints;
+
+ /// The debug adapter supports the `terminateThreads` request.
+ std::optional<bool> supportsTerminateThreadsRequest;
+
+ /// The debug adapter supports the `setExpression` request.
+ std::optional<bool> supportsSetExpression;
+
+ /// The debug adapter supports the `terminate` request.
+ std::optional<bool> supportsTerminateRequest;
+
+ /// The debug adapter supports data breakpoints.
+ std::optional<bool> supportsDataBreakpoints;
+
+ /// The debug adapter supports the `readMemory` request.
+ std::optional<bool> supportsReadMemoryRequest;
+
+ /// The debug adapter supports the `writeMemory` request.
+ std::optional<bool> supportsWriteMemoryRequest;
+
+ /// The debug adapter supports the `disassemble` request.
+ std::optional<bool> supportsDisassembleRequest;
+
+ /// The debug adapter supports the `cancel` request.
+ std::optional<bool> supportsCancelRequest;
+
+ /// The debug adapter supports the `breakpointLocations` request.
+ std::optional<bool> supportsBreakpointLocationsRequest;
+
+ /// The debug adapter supports the `clipboard` context value in the `evaluate`
+ /// request.
+ std::optional<bool> supportsClipboardContext;
+
+ /// The debug adapter supports stepping granularities (argument `granularity`)
+ /// for the stepping requests.
+ std::optional<bool> supportsSteppingGranularity;
+
+ /// The debug adapter supports adding breakpoints based on instruction
+ /// references.
+ std::optional<bool> supportsInstructionBreakpoints;
+
+ /// The debug adapter supports `filterOptions` as an argument on the
+ /// `setExceptionBreakpoints` request.
+ std::optional<bool> supportsExceptionFilterOptions;
+
+ /// The debug adapter supports the `singleThread` property on the execution
+ /// requests (`continue`, `next`, `stepIn`, `stepOut`, `reverseContinue`,
+ /// `stepBack`).
+ std::optional<bool> supportsSingleThreadExecutionRequests;
+
+ /// The debug adapter supports the `asAddress` and `bytes` fields in the
+ /// `dataBreakpointInfo` request.
+ std::optional<bool> supportsDataBreakpointBytes;
+
+ /// Modes of breakpoints supported by the debug adapter, such as 'hardware' or
+ /// 'software'. If present, the client may allow the user to select a mode and
+ /// include it in its `setBreakpoints` request.
+ ///
+ /// Clients may present the first applicable mode in this array as the
+ /// 'default' mode in gestures that set breakpoints.
+ std::optional<std::vector<BreakpointMode>> breakpointModes;
+
+ /// The debug adapter supports ANSI escape sequences in styling of
+ /// `OutputEvent.output` and `Variable.value` fields.
+ std::optional<bool> supportsANSIStyling;
+
+ /// lldb-dap Extensions
+ std::optional<std::string> lldbVersion;
+};
+llvm::json::Value toJSON(const Capabilities &);
+
/// A `Source` is a descriptor for source code. It is returned from the debug
/// adapter as part of a `StackFrame` and it is used by clients when specifying
/// breakpoints.
>From b0f33aec9d88704a4e11030c96d232f29f03b9d5 Mon Sep 17 00:00:00 2001
From: John Harrison <harjohn at google.com>
Date: Wed, 26 Mar 2025 12:48:09 -0700
Subject: [PATCH 2/6] Converting the std::optional<bool> values in Capabilities
and IntializeRequestHandler into a `std::set<Feature>` to simplify these
flags.
---
lldb/tools/lldb-dap/DAP.cpp | 122 ++-------
lldb/tools/lldb-dap/DAP.h | 10 +-
.../Handler/InitializeRequestHandler.cpp | 10 +-
.../tools/lldb-dap/Handler/RequestHandler.cpp | 6 +-
lldb/tools/lldb-dap/Handler/RequestHandler.h | 94 ++++---
.../lldb-dap/Protocol/ProtocolRequests.cpp | 68 +++--
.../lldb-dap/Protocol/ProtocolRequests.h | 78 +++---
.../tools/lldb-dap/Protocol/ProtocolTypes.cpp | 220 ++++++++--------
lldb/tools/lldb-dap/Protocol/ProtocolTypes.h | 237 ++++++++----------
9 files changed, 388 insertions(+), 457 deletions(-)
diff --git a/lldb/tools/lldb-dap/DAP.cpp b/lldb/tools/lldb-dap/DAP.cpp
index 0da8ce43f73c4..fdd7a67135a68 100644
--- a/lldb/tools/lldb-dap/DAP.cpp
+++ b/lldb/tools/lldb-dap/DAP.cpp
@@ -1145,122 +1145,27 @@ lldb::SBValue Variables::FindVariable(uint64_t variablesReference,
return variable;
}
-static void mergeCapabilities(protocol::Capabilities &into,
- const protocol::Capabilities &from) {
- if (from.supportsConfigurationDoneRequest)
- into.supportsConfigurationDoneRequest =
- *from.supportsConfigurationDoneRequest;
- if (from.supportsFunctionBreakpoints)
- into.supportsFunctionBreakpoints = *from.supportsFunctionBreakpoints;
- if (from.supportsConditionalBreakpoints)
- into.supportsConditionalBreakpoints = *from.supportsConditionalBreakpoints;
- if (from.supportsHitConditionalBreakpoints)
- into.supportsHitConditionalBreakpoints =
- *from.supportsHitConditionalBreakpoints;
- if (from.supportsEvaluateForHovers)
- into.supportsEvaluateForHovers = *from.supportsEvaluateForHovers;
- if (from.exceptionBreakpointFilters)
- into.exceptionBreakpointFilters = *from.exceptionBreakpointFilters;
- if (from.supportsStepBack)
- into.supportsStepBack = *from.supportsStepBack;
- if (from.supportsSetVariable)
- into.supportsSetVariable = *from.supportsSetVariable;
- if (from.supportsRestartFrame)
- into.supportsRestartFrame = *from.supportsRestartFrame;
- if (from.supportsGotoTargetsRequest)
- into.supportsGotoTargetsRequest = *from.supportsGotoTargetsRequest;
- if (from.supportsStepInTargetsRequest)
- into.supportsStepInTargetsRequest = *from.supportsStepInTargetsRequest;
- if (from.supportsCompletionsRequest)
- into.supportsCompletionsRequest = *from.supportsCompletionsRequest;
- if (from.completionTriggerCharacters)
- into.completionTriggerCharacters = *from.completionTriggerCharacters;
- if (from.supportsModulesRequest)
- into.supportsModulesRequest = *from.supportsModulesRequest;
- if (from.additionalModuleColumns)
- into.additionalModuleColumns = *from.additionalModuleColumns;
- if (from.supportedChecksumAlgorithms)
- into.supportedChecksumAlgorithms = *from.supportedChecksumAlgorithms;
- if (from.supportsRestartRequest)
- into.supportsRestartRequest = *from.supportsRestartRequest;
- if (from.supportsExceptionOptions)
- into.supportsExceptionOptions = *from.supportsExceptionOptions;
- if (from.supportsValueFormattingOptions)
- into.supportsValueFormattingOptions = *from.supportsValueFormattingOptions;
- if (from.supportsExceptionInfoRequest)
- into.supportsExceptionInfoRequest = *from.supportsExceptionInfoRequest;
- if (from.supportTerminateDebuggee)
- into.supportTerminateDebuggee = *from.supportTerminateDebuggee;
- if (from.supportSuspendDebuggee)
- into.supportSuspendDebuggee = *from.supportSuspendDebuggee;
- if (from.supportsDelayedStackTraceLoading)
- into.supportsDelayedStackTraceLoading =
- *from.supportsDelayedStackTraceLoading;
- if (from.supportsLoadedSourcesRequest)
- into.supportsLoadedSourcesRequest = *from.supportsLoadedSourcesRequest;
- if (from.supportsLogPoints)
- into.supportsLogPoints = *from.supportsLogPoints;
- if (from.supportsTerminateThreadsRequest)
- into.supportsTerminateThreadsRequest =
- *from.supportsTerminateThreadsRequest;
- if (from.supportsSetExpression)
- into.supportsSetExpression = *from.supportsSetExpression;
- if (from.supportsTerminateRequest)
- into.supportsTerminateRequest = *from.supportsTerminateRequest;
- if (from.supportsDataBreakpoints)
- into.supportsDataBreakpoints = *from.supportsDataBreakpoints;
- if (from.supportsReadMemoryRequest)
- into.supportsReadMemoryRequest = *from.supportsReadMemoryRequest;
- if (from.supportsWriteMemoryRequest)
- into.supportsWriteMemoryRequest = *from.supportsWriteMemoryRequest;
- if (from.supportsDisassembleRequest)
- into.supportsDisassembleRequest = *from.supportsDisassembleRequest;
- if (from.supportsCancelRequest)
- into.supportsCancelRequest = *from.supportsCancelRequest;
- if (from.supportsBreakpointLocationsRequest)
- into.supportsBreakpointLocationsRequest =
- *from.supportsBreakpointLocationsRequest;
- if (from.supportsClipboardContext)
- into.supportsClipboardContext = *from.supportsClipboardContext;
- if (from.supportsSteppingGranularity)
- into.supportsSteppingGranularity = *from.supportsSteppingGranularity;
- if (from.supportsInstructionBreakpoints)
- into.supportsInstructionBreakpoints = *from.supportsInstructionBreakpoints;
- if (from.supportsExceptionFilterOptions)
- into.supportsExceptionFilterOptions = *from.supportsExceptionFilterOptions;
- if (from.supportsSingleThreadExecutionRequests)
- into.supportsSingleThreadExecutionRequests =
- *from.supportsSingleThreadExecutionRequests;
- if (from.supportsDataBreakpointBytes)
- into.supportsDataBreakpointBytes = *from.supportsDataBreakpointBytes;
- if (from.breakpointModes)
- into.breakpointModes = *from.breakpointModes;
- if (from.supportsANSIStyling)
- into.supportsANSIStyling = *from.supportsANSIStyling;
+bool DAP::isSupported(ClientFeature feature) {
+ return clientFeatures.find(feature) != clientFeatures.end();
}
protocol::Capabilities DAP::GetCapabilities() {
protocol::Capabilities capabilities;
- // Supported capabilities.
- capabilities.supportTerminateDebuggee = true;
- capabilities.supportsDataBreakpoints = true;
- capabilities.supportsDelayedStackTraceLoading = true;
- capabilities.supportsEvaluateForHovers = true;
- capabilities.supportsExceptionOptions = true;
- capabilities.supportsLogPoints = true;
- capabilities.supportsSteppingGranularity = true;
- capabilities.supportsValueFormattingOptions = true;
+ // Supported capabilities that are not specific to a single request.
+ capabilities.supportedFeatures = {
+ AdapterFeature::supportsLogPoints,
+ AdapterFeature::supportsSteppingGranularity,
+ AdapterFeature::supportsValueFormattingOptions,
+ };
// Unsupported capabilities.
- capabilities.supportsGotoTargetsRequest = false;
- capabilities.supportsLoadedSourcesRequest = false;
- capabilities.supportsRestartFrame = false;
- capabilities.supportsStepBack = false;
+ // supportsGotoTargetsRequest, supportsLoadedSourcesRequest,
+ // supportsRestartFrame, supportsStepBack
// Capabilities associated with specific requests.
for (auto &kv : request_handlers)
- mergeCapabilities(capabilities, kv.second->GetCapabilities());
+ capabilities.supportedFeatures.merge(kv.second->GetSupportedFeatures());
// Available filters or options for the setExceptionBreakpoints request.
std::vector<protocol::ExceptionBreakpointsFilter> filters;
@@ -1268,14 +1173,17 @@ protocol::Capabilities DAP::GetCapabilities() {
filters.emplace_back(CreateExceptionBreakpointFilter(exc_bp));
capabilities.exceptionBreakpointFilters = std::move(filters);
+ // FIXME: This should be registered based on the supported languages?
std::vector<std::string> completion_characters;
completion_characters.emplace_back(".");
+ // FIXME: I wonder if we should remove this key... its very aggressive
+ // triggering and accepting completions.
completion_characters.emplace_back(" ");
completion_characters.emplace_back("\t");
capabilities.completionTriggerCharacters = std::move(completion_characters);
// Put in non-DAP specification lldb specific information.
- capabilities.lldbVersion = debugger.GetVersionString();
+ capabilities.lldbExtVersion = debugger.GetVersionString();
return capabilities;
}
diff --git a/lldb/tools/lldb-dap/DAP.h b/lldb/tools/lldb-dap/DAP.h
index 2f23e5a116bc3..5d4d4de0ed9b8 100644
--- a/lldb/tools/lldb-dap/DAP.h
+++ b/lldb/tools/lldb-dap/DAP.h
@@ -16,6 +16,7 @@
#include "OutputRedirector.h"
#include "ProgressEvent.h"
#include "Protocol/ProtocolBase.h"
+#include "Protocol/ProtocolRequests.h"
#include "Protocol/ProtocolTypes.h"
#include "SourceBreakpoint.h"
#include "Transport.h"
@@ -59,6 +60,9 @@ typedef llvm::StringMap<FunctionBreakpoint> FunctionBreakpointMap;
typedef llvm::DenseMap<lldb::addr_t, InstructionBreakpoint>
InstructionBreakpointMap;
+using AdapterFeature = protocol::Capabilities::Feature;
+using ClientFeature = protocol::InitializeRequestArguments::Feature;
+
enum class OutputType { Console, Stdout, Stderr, Telemetry };
/// Buffer size for handling output events.
@@ -181,7 +185,6 @@ struct DAP {
bool enable_auto_variable_summaries;
bool enable_synthetic_child_debugging;
bool display_extended_backtrace;
- bool supports_run_in_terminal_request;
// The process event thread normally responds to process exited events by
// shutting down the entire adapter. When we're restarting, we keep the id of
// the old process here so we can detect this case and keep running.
@@ -207,6 +210,8 @@ struct DAP {
// empty; if the previous expression was a variable expression, this string
// will contain that expression.
std::string last_nonempty_var_expression;
+ /// The set of features supported by the connected client.
+ std::set<ClientFeature> clientFeatures;
/// Creates a new DAP sessions.
///
@@ -368,6 +373,9 @@ struct DAP {
/// The set of capablities supported by this adapter.
protocol::Capabilities GetCapabilities();
+ /// Returns true if the connected client supports the given feature.
+ bool isSupported(ClientFeature);
+
/// Debuggee will continue from stopped state.
void WillContinue() { variables.Clear(); }
diff --git a/lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp
index b85424975a0fc..a598030d6c320 100644
--- a/lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp
@@ -233,6 +233,8 @@ static void EventThreadFunction(DAP &dap) {
/// Initialize request; value of command field is 'initialize'.
llvm::Expected<protocol::InitializeResponseBody> InitializeRequestHandler::Run(
const protocol::InitializeRequestArguments &arguments) const {
+ dap.clientFeatures = arguments.supportedFeatures;
+
// Do not source init files until in/out/err are configured.
dap.debugger = lldb::SBDebugger::Create(false);
dap.debugger.SetInputFile(dap.in);
@@ -252,7 +254,7 @@ llvm::Expected<protocol::InitializeResponseBody> InitializeRequestHandler::Run(
// sourceInitFile option is not from formal DAP specification. It is only
// used by unit tests to prevent sourcing .lldbinit files from environment
// which may affect the outcome of tests.
- if (arguments.sourceInitFile.value_or(true)) {
+ if (arguments.lldbExtSourceInitFile.value_or(true)) {
dap.debugger.SkipLLDBInitFiles(false);
dap.debugger.SkipAppInitFiles(false);
lldb::SBCommandReturnObject init;
@@ -266,21 +268,19 @@ llvm::Expected<protocol::InitializeResponseBody> InitializeRequestHandler::Run(
dap.PopulateExceptionBreakpoints();
auto cmd = dap.debugger.GetCommandInterpreter().AddMultiwordCommand(
"lldb-dap", "Commands for managing lldb-dap.");
- if (arguments.supportsStartDebuggingRequest.value_or(false)) {
+ if (arguments.isSupported(ClientFeature::supportsStartDebuggingRequest)) {
cmd.AddCommand(
"start-debugging", new StartDebuggingRequestHandler(dap),
"Sends a startDebugging request from the debug adapter to the client "
"to start a child debug session of the same type as the caller.");
}
- dap.supports_run_in_terminal_request =
- arguments.supportsRunInTerminalRequest.value_or(false);
cmd.AddCommand(
"repl-mode", new ReplModeRequestHandler(dap),
"Get or set the repl behavior of lldb-dap evaluation requests.");
cmd.AddCommand("send-event", new SendEventRequestHandler(dap),
"Sends an DAP event to the client.");
- if (arguments.supportsProgressReporting)
+ if (arguments.isSupported(ClientFeature::supportsProgressReporting))
dap.progress_event_thread =
std::thread(ProgressEventThreadFunction, std::ref(dap));
diff --git a/lldb/tools/lldb-dap/Handler/RequestHandler.cpp b/lldb/tools/lldb-dap/Handler/RequestHandler.cpp
index d2a0da420739e..d938f2e7aaeee 100644
--- a/lldb/tools/lldb-dap/Handler/RequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/RequestHandler.cpp
@@ -12,6 +12,7 @@
#include "JSONUtils.h"
#include "LLDBUtils.h"
#include "RunInTerminal.h"
+#include "llvm/Support/Error.h"
#if !defined(_WIN32)
#include <unistd.h>
@@ -97,6 +98,10 @@ void BaseRequestHandler::SetSourceMapFromArguments(
static llvm::Error RunInTerminal(DAP &dap,
const llvm::json::Object &launch_request,
const uint64_t timeout_seconds) {
+ if (!dap.isSupported(ClientFeature::supportsRunInTerminalRequest))
+ return llvm::make_error<DAPError>("Cannot use runInTerminal, feature is "
+ "not supported by the connected client");
+
dap.is_attach = true;
lldb::SBAttachInfo attach_info;
@@ -201,7 +206,6 @@ BaseRequestHandler::LaunchProcess(const llvm::json::Object &request) const {
const auto timeout_seconds =
GetInteger<uint64_t>(arguments, "timeout").value_or(30);
- // FIXME: Check dap.supports_run_in_terminal_request.
if (GetBoolean(arguments, "runInTerminal").value_or(false)) {
if (llvm::Error err = RunInTerminal(dap, request, timeout_seconds))
error.SetErrorString(llvm::toString(std::move(err)).c_str());
diff --git a/lldb/tools/lldb-dap/Handler/RequestHandler.h b/lldb/tools/lldb-dap/Handler/RequestHandler.h
index ba854c9884cde..517a460680c3f 100644
--- a/lldb/tools/lldb-dap/Handler/RequestHandler.h
+++ b/lldb/tools/lldb-dap/Handler/RequestHandler.h
@@ -48,7 +48,7 @@ class BaseRequestHandler {
virtual void operator()(const protocol::Request &request) const = 0;
- virtual protocol::Capabilities GetCapabilities() const { return {}; }
+ virtual std::set<AdapterFeature> GetSupportedFeatures() const { return {}; }
protected:
/// Helpers used by multiple request handlers.
@@ -176,10 +176,8 @@ class BreakpointLocationsRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "breakpointLocations"; }
- protocol::Capabilities GetCapabilities() const override {
- protocol::Capabilities capabilities;
- capabilities.supportsBreakpointLocationsRequest = true;
- return capabilities;
+ std::set<AdapterFeature> GetSupportedFeatures() const override {
+ return {AdapterFeature::supportsBreakpointLocationsRequest};
}
void operator()(const llvm::json::Object &request) const override;
};
@@ -188,10 +186,8 @@ class CompletionsRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "completions"; }
- protocol::Capabilities GetCapabilities() const override {
- protocol::Capabilities capabilities;
- capabilities.supportsCompletionsRequest = true;
- return capabilities;
+ std::set<AdapterFeature> GetSupportedFeatures() const override {
+ return {AdapterFeature::supportsCompletionsRequest};
}
void operator()(const llvm::json::Object &request) const override;
};
@@ -207,10 +203,8 @@ class ConfigurationDoneRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "configurationDone"; }
- protocol::Capabilities GetCapabilities() const override {
- protocol::Capabilities capabilities;
- capabilities.supportsConfigurationDoneRequest = true;
- return capabilities;
+ std::set<AdapterFeature> GetSupportedFeatures() const override {
+ return {AdapterFeature::supportsConfigurationDoneRequest};
}
void operator()(const llvm::json::Object &request) const override;
};
@@ -221,6 +215,9 @@ class DisconnectRequestHandler
public:
using RequestHandler::RequestHandler;
static llvm::StringLiteral GetCommand() { return "disconnect"; }
+ std::set<AdapterFeature> GetSupportedFeatures() const override {
+ return {AdapterFeature::supportTerminateDebuggee};
+ }
llvm::Expected<protocol::DisconnectResponse>
Run(const std::optional<protocol::DisconnectArguments> &args) const override;
};
@@ -230,16 +227,17 @@ class EvaluateRequestHandler : public LegacyRequestHandler {
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "evaluate"; }
void operator()(const llvm::json::Object &request) const override;
+ std::set<AdapterFeature> GetSupportedFeatures() const override {
+ return {AdapterFeature::supportsEvaluateForHovers};
+ }
};
class ExceptionInfoRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "exceptionInfo"; }
- protocol::Capabilities GetCapabilities() const override {
- protocol::Capabilities capabilities;
- capabilities.supportsExceptionInfoRequest = true;
- return capabilities;
+ std::set<AdapterFeature> GetSupportedFeatures() const override {
+ return {AdapterFeature::supportsExceptionInfoRequest};
}
void operator()(const llvm::json::Object &request) const override;
};
@@ -265,10 +263,8 @@ class RestartRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "restart"; }
- protocol::Capabilities GetCapabilities() const override {
- protocol::Capabilities capabilities;
- capabilities.supportsRestartRequest = true;
- return capabilities;
+ std::set<AdapterFeature> GetSupportedFeatures() const override {
+ return {AdapterFeature::supportsRestartRequest};
}
void operator()(const llvm::json::Object &request) const override;
};
@@ -291,10 +287,8 @@ class StepInTargetsRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "stepInTargets"; }
- protocol::Capabilities GetCapabilities() const override {
- protocol::Capabilities capabilities;
- capabilities.supportsStepInTargetsRequest = true;
- return capabilities;
+ std::set<AdapterFeature> GetSupportedFeatures() const override {
+ return {AdapterFeature::supportsStepInTargetsRequest};
}
void operator()(const llvm::json::Object &request) const override;
};
@@ -310,11 +304,9 @@ class SetBreakpointsRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "setBreakpoints"; }
- protocol::Capabilities GetCapabilities() const override {
- protocol::Capabilities capabilities;
- capabilities.supportsConditionalBreakpoints = true;
- capabilities.supportsHitConditionalBreakpoints = true;
- return capabilities;
+ std::set<AdapterFeature> GetSupportedFeatures() const override {
+ return {AdapterFeature::supportsConditionalBreakpoints,
+ AdapterFeature::supportsHitConditionalBreakpoints};
}
void operator()(const llvm::json::Object &request) const override;
};
@@ -323,6 +315,9 @@ class SetExceptionBreakpointsRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "setExceptionBreakpoints"; }
+ std::set<AdapterFeature> GetSupportedFeatures() const override {
+ return {AdapterFeature::supportsExceptionOptions};
+ }
void operator()(const llvm::json::Object &request) const override;
};
@@ -330,10 +325,8 @@ class SetFunctionBreakpointsRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "setFunctionBreakpoints"; }
- protocol::Capabilities GetCapabilities() const override {
- protocol::Capabilities capabilities;
- capabilities.supportsFunctionBreakpoints = true;
- return capabilities;
+ std::set<AdapterFeature> GetSupportedFeatures() const override {
+ return {AdapterFeature::supportsFunctionBreakpoints};
}
void operator()(const llvm::json::Object &request) const override;
};
@@ -350,6 +343,9 @@ class SetDataBreakpointsRequestHandler : public LegacyRequestHandler {
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "setDataBreakpoints"; }
void operator()(const llvm::json::Object &request) const override;
+ std::set<AdapterFeature> GetSupportedFeatures() const override {
+ return {AdapterFeature::supportsDataBreakpoints};
+ }
};
class SetInstructionBreakpointsRequestHandler : public LegacyRequestHandler {
@@ -359,6 +355,9 @@ class SetInstructionBreakpointsRequestHandler : public LegacyRequestHandler {
return "setInstructionBreakpoints";
}
void operator()(const llvm::json::Object &request) const override;
+ std::set<AdapterFeature> GetSupportedFeatures() const override {
+ return {AdapterFeature::supportsInstructionBreakpoints};
+ }
};
class CompileUnitsRequestHandler : public LegacyRequestHandler {
@@ -372,10 +371,8 @@ class ModulesRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "modules"; }
- protocol::Capabilities GetCapabilities() const override {
- protocol::Capabilities capabilities;
- capabilities.supportsModulesRequest = true;
- return capabilities;
+ std::set<AdapterFeature> GetSupportedFeatures() const override {
+ return {AdapterFeature::supportsModulesRequest};
}
void operator()(const llvm::json::Object &request) const override;
};
@@ -398,10 +395,8 @@ class SetVariableRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "setVariable"; }
- protocol::Capabilities GetCapabilities() const override {
- protocol::Capabilities capabilities;
- capabilities.supportsSetVariable = true;
- return capabilities;
+ std::set<AdapterFeature> GetSupportedFeatures() const override {
+ return {AdapterFeature::supportsSetVariable};
}
void operator()(const llvm::json::Object &request) const override;
};
@@ -421,6 +416,9 @@ class StackTraceRequestHandler : public LegacyRequestHandler {
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "stackTrace"; }
void operator()(const llvm::json::Object &request) const override;
+ std::set<AdapterFeature> GetSupportedFeatures() const override {
+ return {AdapterFeature::supportsDelayedStackTraceLoading};
+ }
};
class ThreadsRequestHandler : public LegacyRequestHandler {
@@ -448,10 +446,8 @@ class DisassembleRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "disassemble"; }
- protocol::Capabilities GetCapabilities() const override {
- protocol::Capabilities capabilities;
- capabilities.supportsDisassembleRequest = true;
- return capabilities;
+ std::set<AdapterFeature> GetSupportedFeatures() const override {
+ return {AdapterFeature::supportsDisassembleRequest};
}
void operator()(const llvm::json::Object &request) const override;
};
@@ -460,10 +456,8 @@ class ReadMemoryRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "readMemory"; }
- protocol::Capabilities GetCapabilities() const override {
- protocol::Capabilities capabilities;
- capabilities.supportsReadMemoryRequest = true;
- return capabilities;
+ std::set<AdapterFeature> GetSupportedFeatures() const override {
+ return {AdapterFeature::supportsReadMemoryRequest};
}
void operator()(const llvm::json::Object &request) const override;
};
diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp
index 16d54b1184f1d..8e0a97c1ac2dc 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "Protocol/ProtocolRequests.h"
+#include "DAP.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/JSON.h"
#include <utility>
@@ -48,31 +49,48 @@ bool fromJSON(const llvm::json::Value &Params,
bool fromJSON(const llvm::json::Value &Params, InitializeRequestArguments &IRA,
llvm::json::Path P) {
- json::ObjectMapper O(Params, P);
- return O && O.mapOptional("adatperID", IRA.adatperID) &&
- O.mapOptional("clientID", IRA.clientID) &&
- O.mapOptional("clientName", IRA.clientName) &&
- O.mapOptional("locale", IRA.locale) &&
- O.mapOptional("linesStartAt1", IRA.linesStartAt1) &&
- O.mapOptional("columnsStartAt1", IRA.columnsStartAt1) &&
- O.mapOptional("pathFormat", IRA.pathFormat) &&
- O.mapOptional("supportsVariableType", IRA.supportsVariableType) &&
- O.mapOptional("supportsVariablePaging", IRA.supportsVariablePaging) &&
- O.mapOptional("supportsRunInTerminalRequest",
- IRA.supportsRunInTerminalRequest) &&
- O.mapOptional("supportsMemoryReferences",
- IRA.supportsMemoryReferences) &&
- O.mapOptional("supportsProgressReporting",
- IRA.supportsProgressReporting) &&
- O.mapOptional("supportsInvalidatedEvent",
- IRA.supportsInvalidatedEvent) &&
- O.mapOptional("supportsMemoryEvent", IRA.supportsMemoryEvent) &&
- O.mapOptional("supportsArgsCanBeInterpretedByShell",
- IRA.supportsArgsCanBeInterpretedByShell) &&
- O.mapOptional("supportsStartDebuggingRequest",
- IRA.supportsStartDebuggingRequest) &&
- O.mapOptional("supportsANSIStyling", IRA.supportsANSIStyling) &&
- O.mapOptional("$__lldb_sourceInitFile", IRA.sourceInitFile);
+ json::ObjectMapper OM(Params, P);
+ if (!OM)
+ return false;
+
+ const json::Object *O = Params.getAsObject();
+ if (std::optional<bool> v = O->getBoolean("supportsVariableType"); v && *v)
+ IRA.supportedFeatures.insert(ClientFeature::supportsVariableType);
+ if (std::optional<bool> v = O->getBoolean("supportsVariablePaging"); v && *v)
+ IRA.supportedFeatures.insert(ClientFeature::supportsVariablePaging);
+ if (std::optional<bool> v = O->getBoolean("supportsRunInTerminalRequest");
+ v && *v)
+ IRA.supportedFeatures.insert(ClientFeature::supportsRunInTerminalRequest);
+ if (std::optional<bool> v = O->getBoolean("supportsMemoryReferences");
+ v && *v)
+ IRA.supportedFeatures.insert(ClientFeature::supportsMemoryReferences);
+ if (std::optional<bool> v = O->getBoolean("supportsProgressReporting");
+ v && *v)
+ IRA.supportedFeatures.insert(ClientFeature::supportsProgressReporting);
+ if (std::optional<bool> v = O->getBoolean("supportsInvalidatedEvent");
+ v && *v)
+ IRA.supportedFeatures.insert(ClientFeature::supportsInvalidatedEvent);
+ if (std::optional<bool> v = O->getBoolean("supportsMemoryEvent"); v && *v)
+ IRA.supportedFeatures.insert(ClientFeature::supportsMemoryEvent);
+ if (std::optional<bool> v =
+ O->getBoolean("supportsArgsCanBeInterpretedByShell");
+ v && *v)
+ IRA.supportedFeatures.insert(
+ ClientFeature::supportsArgsCanBeInterpretedByShell);
+ if (std::optional<bool> v = O->getBoolean("supportsStartDebuggingRequest");
+ v && *v)
+ IRA.supportedFeatures.insert(ClientFeature::supportsStartDebuggingRequest);
+ if (std::optional<bool> v = O->getBoolean("supportsANSIStyling"); v && *v)
+ IRA.supportedFeatures.insert(ClientFeature::supportsANSIStyling);
+
+ return OM.mapOptional("adatperID", IRA.adatperID) &&
+ OM.mapOptional("clientID", IRA.clientID) &&
+ OM.mapOptional("clientName", IRA.clientName) &&
+ OM.mapOptional("locale", IRA.locale) &&
+ OM.mapOptional("linesStartAt1", IRA.linesStartAt1) &&
+ OM.mapOptional("columnsStartAt1", IRA.columnsStartAt1) &&
+ OM.mapOptional("pathFormat", IRA.pathFormat) &&
+ OM.mapOptional("$__lldb_sourceInitFile", IRA.lldbExtSourceInitFile);
}
bool fromJSON(const json::Value &Params, SourceArguments &SA, json::Path P) {
diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h
index beb573515df62..f6ca8e0562b5c 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h
@@ -68,54 +68,58 @@ struct InitializeRequestArguments {
/// The ISO-639 locale of the client using this adapter, e.g. en-US or de-CH.
std::optional<std::string> locale;
- /// If true all line numbers are 1-based (default).
- std::optional<bool> linesStartAt1;
-
- /// If true all column numbers are 1-based (default).
- std::optional<bool> columnsStartAt1;
-
enum class PathFormat { path, uri };
/// Determines in what format paths are specified. The default is `path`,
/// which is the native format.
std::optional<PathFormat> pathFormat = PathFormat::path;
- /// Client supports the `type` attribute for variables.
- std::optional<bool> supportsVariableType;
-
- /// Client supports the paging of variables.
- std::optional<bool> supportsVariablePaging;
-
- /// Client supports the `runInTerminal` request.
- std::optional<bool> supportsRunInTerminalRequest;
-
- /// Client supports memory references.
- std::optional<bool> supportsMemoryReferences;
-
- /// Client supports progress reporting.
- std::optional<bool> supportsProgressReporting;
-
- /// Client supports the `invalidated` event.
- std::optional<bool> supportsInvalidatedEvent;
-
- /// Client supports the `memory` event.
- std::optional<bool> supportsMemoryEvent;
-
- /// Client supports the `argsCanBeInterpretedByShell` attribute on the
- /// `runInTerminal` request.
- std::optional<bool> supportsArgsCanBeInterpretedByShell;
+ /// If true all line numbers are 1-based (default).
+ std::optional<bool> linesStartAt1;
- /// Client supports the `startDebugging` request.
- std::optional<bool> supportsStartDebuggingRequest;
+ /// If true all column numbers are 1-based (default).
+ std::optional<bool> columnsStartAt1;
- /// The client will interpret ANSI escape sequences in the display of
- /// `OutputEvent.output` and `Variable.value` fields when
- /// `Capabilities.supportsANSIStyling` is also enabled.
- std::optional<bool> supportsANSIStyling;
+ enum class Feature {
+ /// Client supports the `type` attribute for variables.
+ supportsVariableType,
+ /// Client supports the paging of variables.
+ supportsVariablePaging,
+ /// Client supports the `runInTerminal` request.
+ supportsRunInTerminalRequest,
+ /// Client supports memory references.
+ supportsMemoryReferences,
+ /// Client supports progress reporting.
+ supportsProgressReporting,
+ /// Client supports the `invalidated` event.
+ supportsInvalidatedEvent,
+ /// Client supports the `memory` event.
+ supportsMemoryEvent,
+ /// Client supports the `argsCanBeInterpretedByShell` attribute on the
+ /// `runInTerminal` request.
+ supportsArgsCanBeInterpretedByShell,
+ /// Client supports the `startDebugging` request.
+ supportsStartDebuggingRequest,
+ /// The client will interpret ANSI escape sequences in the display of
+ /// `OutputEvent.output` and `Variable.value` fields when
+ /// `Capabilities.supportsANSIStyling` is also enabled.
+ supportsANSIStyling,
+ };
+
+ /// The set of supported features reported by the client.
+ std::set<Feature> supportedFeatures;
+
+ bool isSupported(Feature feature) const {
+ return supportedFeatures.find(feature) != supportedFeatures.end();
+ }
/// lldb-dap Extensions
+ /// @{
+
/// Source init files when initializing lldb::SBDebugger.
- std::optional<bool> sourceInitFile;
+ std::optional<bool> lldbExtSourceInitFile;
+
+ /// @}
};
bool fromJSON(const llvm::json::Value &, InitializeRequestArguments &,
llvm::json::Path);
diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp
index d81d4bc801538..8d3a31e19b055 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp
@@ -50,7 +50,7 @@ json::Value toJSON(const ExceptionBreakpointsFilter &EBF) {
if (EBF.description)
result.insert({"description", *EBF.description});
if (EBF.defaultState)
- result.insert({"defaultState", *EBF.defaultState});
+ result.insert({"default", *EBF.defaultState});
if (EBF.supportsCondition)
result.insert({"supportsCondition", *EBF.supportsCondition});
if (EBF.conditionDescription)
@@ -127,118 +127,138 @@ json::Value toJSON(const BreakpointMode &BM) {
json::Value toJSON(const Capabilities &C) {
json::Object result;
- if (C.supportsConfigurationDoneRequest && *C.supportsConfigurationDoneRequest)
- result.insert({"supportsConfigurationDoneRequest",
- *C.supportsConfigurationDoneRequest});
- if (C.supportsFunctionBreakpoints && *C.supportsFunctionBreakpoints)
- result.insert(
- {"supportsFunctionBreakpoints", *C.supportsFunctionBreakpoints});
- if (C.supportsConditionalBreakpoints && *C.supportsConditionalBreakpoints)
- result.insert(
- {"supportsConditionalBreakpoints", *C.supportsConditionalBreakpoints});
- if (C.supportsHitConditionalBreakpoints &&
- *C.supportsHitConditionalBreakpoints)
- result.insert({"supportsHitConditionalBreakpoints",
- *C.supportsHitConditionalBreakpoints});
- if (C.supportsEvaluateForHovers && *C.supportsEvaluateForHovers)
- result.insert({"supportsEvaluateForHovers", *C.supportsEvaluateForHovers});
+ for (const auto &feature : C.supportedFeatures)
+ switch (feature) {
+ case Capabilities::Feature::supportsANSIStyling:
+ result.insert({"supportsANSIStyling", true});
+ break;
+ case Capabilities::Feature::supportsBreakpointLocationsRequest:
+ result.insert({"supportsBreakpointLocationsRequest", true});
+ break;
+ case Capabilities::Feature::supportsCancelRequest:
+ result.insert({"supportsCancelRequest", true});
+ break;
+ case Capabilities::Feature::supportsClipboardContext:
+ result.insert({"supportsClipboardContext", true});
+ break;
+ case Capabilities::Feature::supportsCompletionsRequest:
+ result.insert({"supportsCompletionsRequest", true});
+ break;
+ case Capabilities::Feature::supportsConditionalBreakpoints:
+ result.insert({"supportsConditionalBreakpoints", true});
+ break;
+ case Capabilities::Feature::supportsConfigurationDoneRequest:
+ result.insert({"supportsConfigurationDoneRequest", true});
+ break;
+ case Capabilities::Feature::supportsDataBreakpointBytes:
+ result.insert({"supportsDataBreakpointBytes", true});
+ break;
+ case Capabilities::Feature::supportsDataBreakpoints:
+ result.insert({"supportsDataBreakpoints", true});
+ break;
+ case Capabilities::Feature::supportsDelayedStackTraceLoading:
+ result.insert({"supportsDelayedStackTraceLoading", true});
+ break;
+ case Capabilities::Feature::supportsDisassembleRequest:
+ result.insert({"supportsDisassembleRequest", true});
+ break;
+ case Capabilities::Feature::supportsEvaluateForHovers:
+ result.insert({"supportsEvaluateForHovers", true});
+ break;
+ case Capabilities::Feature::supportsExceptionFilterOptions:
+ result.insert({"supportsExceptionFilterOptions", true});
+ break;
+ case Capabilities::Feature::supportsExceptionInfoRequest:
+ result.insert({"supportsExceptionInfoRequest", true});
+ break;
+ case Capabilities::Feature::supportsExceptionOptions:
+ result.insert({"supportsExceptionOptions", true});
+ break;
+ case Capabilities::Feature::supportsFunctionBreakpoints:
+ result.insert({"supportsFunctionBreakpoints", true});
+ break;
+ case Capabilities::Feature::supportsGotoTargetsRequest:
+ result.insert({"supportsGotoTargetsRequest", true});
+ break;
+ case Capabilities::Feature::supportsHitConditionalBreakpoints:
+ result.insert({"supportsHitConditionalBreakpoints", true});
+ break;
+ case Capabilities::Feature::supportsInstructionBreakpoints:
+ result.insert({"supportsInstructionBreakpoints", true});
+ break;
+ case Capabilities::Feature::supportsLoadedSourcesRequest:
+ result.insert({"supportsLoadedSourcesRequest", true});
+ break;
+ case Capabilities::Feature::supportsLogPoints:
+ result.insert({"supportsLogPoints", true});
+ break;
+ case Capabilities::Feature::supportsModulesRequest:
+ result.insert({"supportsModulesRequest", true});
+ break;
+ case Capabilities::Feature::supportsReadMemoryRequest:
+ result.insert({"supportsReadMemoryRequest", true});
+ break;
+ case Capabilities::Feature::supportsRestartFrame:
+ result.insert({"supportsRestartFrame", true});
+ break;
+ case Capabilities::Feature::supportsRestartRequest:
+ result.insert({"supportsRestartRequest", true});
+ break;
+ case Capabilities::Feature::supportsSetExpression:
+ result.insert({"supportsSetExpression", true});
+ break;
+ case Capabilities::Feature::supportsSetVariable:
+ result.insert({"supportsSetVariable", true});
+ break;
+ case Capabilities::Feature::supportsSingleThreadExecutionRequests:
+ result.insert({"supportsSingleThreadExecutionRequests", true});
+ break;
+ case Capabilities::Feature::supportsStepBack:
+ result.insert({"supportsStepBack", true});
+ break;
+ case Capabilities::Feature::supportsStepInTargetsRequest:
+ result.insert({"supportsStepInTargetsRequest", true});
+ break;
+ case Capabilities::Feature::supportsSteppingGranularity:
+ result.insert({"supportsSteppingGranularity", true});
+ break;
+ case Capabilities::Feature::supportsTerminateRequest:
+ result.insert({"supportsTerminateRequest", true});
+ break;
+ case Capabilities::Feature::supportsTerminateThreadsRequest:
+ result.insert({"supportsTerminateThreadsRequest", true});
+ break;
+ case Capabilities::Feature::supportSuspendDebuggee:
+ result.insert({"supportSuspendDebuggee", true});
+ break;
+ case Capabilities::Feature::supportsValueFormattingOptions:
+ result.insert({"supportsValueFormattingOptions", true});
+ break;
+ case Capabilities::Feature::supportsWriteMemoryRequest:
+ result.insert({"supportsWriteMemoryRequest", true});
+ break;
+ case Capabilities::Feature::supportTerminateDebuggee:
+ result.insert({"supportTerminateDebuggee", true});
+ break;
+ }
+
if (C.exceptionBreakpointFilters && !C.exceptionBreakpointFilters->empty())
result.insert(
{"exceptionBreakpointFilters", *C.exceptionBreakpointFilters});
- if (C.supportsStepBack && *C.supportsStepBack)
- result.insert({"supportsStepBack", *C.supportsStepBack});
- if (C.supportsSetVariable && *C.supportsSetVariable)
- result.insert({"supportsSetVariable", *C.supportsSetVariable});
- if (C.supportsRestartFrame && *C.supportsRestartFrame)
- result.insert({"supportsRestartFrame", *C.supportsRestartFrame});
- if (C.supportsGotoTargetsRequest && *C.supportsGotoTargetsRequest)
- result.insert(
- {"supportsGotoTargetsRequest", *C.supportsGotoTargetsRequest});
- if (C.supportsStepInTargetsRequest && *C.supportsStepInTargetsRequest)
- result.insert(
- {"supportsStepInTargetsRequest", *C.supportsStepInTargetsRequest});
- if (C.supportsCompletionsRequest && *C.supportsCompletionsRequest)
- result.insert(
- {"supportsCompletionsRequest", *C.supportsCompletionsRequest});
if (C.completionTriggerCharacters && !C.completionTriggerCharacters->empty())
result.insert(
{"completionTriggerCharacters", *C.completionTriggerCharacters});
- if (C.supportsModulesRequest && *C.supportsModulesRequest)
- result.insert({"supportsModulesRequest", *C.supportsModulesRequest});
if (C.additionalModuleColumns && !C.additionalModuleColumns->empty())
result.insert({"additionalModuleColumns", *C.additionalModuleColumns});
if (C.supportedChecksumAlgorithms && !C.supportedChecksumAlgorithms->empty())
result.insert(
{"supportedChecksumAlgorithms", *C.supportedChecksumAlgorithms});
- if (C.supportsRestartRequest && *C.supportsRestartRequest)
- result.insert({"supportsRestartRequest", *C.supportsRestartRequest});
- if (C.supportsExceptionOptions && *C.supportsExceptionOptions)
- result.insert({"supportsExceptionOptions", *C.supportsExceptionOptions});
- if (C.supportsValueFormattingOptions && *C.supportsValueFormattingOptions)
- result.insert(
- {"supportsValueFormattingOptions", *C.supportsValueFormattingOptions});
- if (C.supportsExceptionInfoRequest && *C.supportsExceptionInfoRequest)
- result.insert(
- {"supportsExceptionInfoRequest", *C.supportsExceptionInfoRequest});
- if (C.supportTerminateDebuggee && *C.supportTerminateDebuggee)
- result.insert({"supportTerminateDebuggee", *C.supportTerminateDebuggee});
- if (C.supportSuspendDebuggee && *C.supportSuspendDebuggee)
- result.insert({"supportSuspendDebuggee", *C.supportSuspendDebuggee});
- if (C.supportsDelayedStackTraceLoading && *C.supportsDelayedStackTraceLoading)
- result.insert({"supportsDelayedStackTraceLoading",
- *C.supportsDelayedStackTraceLoading});
- if (C.supportsLoadedSourcesRequest && *C.supportsLoadedSourcesRequest)
- result.insert(
- {"supportsLoadedSourcesRequest", *C.supportsLoadedSourcesRequest});
- if (C.supportsLogPoints && *C.supportsLogPoints)
- result.insert({"supportsLogPoints", *C.supportsLogPoints});
- if (C.supportsTerminateThreadsRequest && *C.supportsTerminateThreadsRequest)
- result.insert({"supportsTerminateThreadsRequest",
- *C.supportsTerminateThreadsRequest});
- if (C.supportsSetExpression && *C.supportsSetExpression)
- result.insert({"supportsSetExpression", *C.supportsSetExpression});
- if (C.supportsTerminateRequest && *C.supportsTerminateRequest)
- result.insert({"supportsTerminateRequest", *C.supportsTerminateRequest});
- if (C.supportsDataBreakpoints && *C.supportsDataBreakpoints)
- result.insert({"supportsDataBreakpoints", *C.supportsDataBreakpoints});
- if (C.supportsReadMemoryRequest && *C.supportsReadMemoryRequest)
- result.insert({"supportsReadMemoryRequest", *C.supportsReadMemoryRequest});
- if (C.supportsWriteMemoryRequest && *C.supportsWriteMemoryRequest)
- result.insert(
- {"supportsWriteMemoryRequest", *C.supportsWriteMemoryRequest});
- if (C.supportsDisassembleRequest && *C.supportsDisassembleRequest)
- result.insert(
- {"supportsDisassembleRequest", *C.supportsDisassembleRequest});
- if (C.supportsCancelRequest && *C.supportsCancelRequest)
- result.insert({"supportsCancelRequest", *C.supportsCancelRequest});
- if (C.supportsBreakpointLocationsRequest &&
- *C.supportsBreakpointLocationsRequest)
- result.insert({"supportsBreakpointLocationsRequest",
- *C.supportsBreakpointLocationsRequest});
- if (C.supportsClipboardContext && *C.supportsClipboardContext)
- result.insert({"supportsClipboardContext", *C.supportsClipboardContext});
- if (C.supportsSteppingGranularity && *C.supportsSteppingGranularity)
- result.insert(
- {"supportsSteppingGranularity", *C.supportsSteppingGranularity});
- if (C.supportsInstructionBreakpoints && *C.supportsInstructionBreakpoints)
- result.insert(
- {"supportsInstructionBreakpoints", *C.supportsInstructionBreakpoints});
- if (C.supportsExceptionFilterOptions && *C.supportsExceptionFilterOptions)
- result.insert(
- {"supportsExceptionFilterOptions", *C.supportsExceptionFilterOptions});
- if (C.supportsSingleThreadExecutionRequests &&
- *C.supportsSingleThreadExecutionRequests)
- result.insert({"supportsSingleThreadExecutionRequests",
- *C.supportsSingleThreadExecutionRequests});
- if (C.supportsDataBreakpointBytes && *C.supportsDataBreakpointBytes)
- result.insert(
- {"supportsDataBreakpointBytes", *C.supportsDataBreakpointBytes});
if (C.breakpointModes && !C.breakpointModes->empty())
result.insert({"breakpointModes", *C.breakpointModes});
- if (C.supportsANSIStyling && *C.supportsANSIStyling)
- result.insert({"supportsANSIStyling", *C.supportsANSIStyling});
- if (C.lldbVersion && !C.lldbVersion->empty())
- result.insert({"$__lldb_version", *C.lldbVersion});
+
+ // lldb-dap extensions
+ if (C.lldbExtVersion && !C.lldbExtVersion->empty())
+ result.insert({"$__lldb_version", *C.lldbExtVersion});
return result;
}
diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h
index 9a58e83b39ad1..e2c08db99bebd 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h
@@ -23,6 +23,7 @@
#include "llvm/Support/JSON.h"
#include <cstdint>
#include <optional>
+#include <set>
#include <string>
namespace lldb_dap::protocol {
@@ -123,148 +124,121 @@ llvm::json::Value toJSON(const BreakpointMode &);
/// Information about the capabilities of a debug adapter.
struct Capabilities {
- /// The debug adapter supports the `configurationDone` request.
- std::optional<bool> supportsConfigurationDoneRequest;
-
- /// The debug adapter supports function breakpoints.
- std::optional<bool> supportsFunctionBreakpoints;
-
- /// The debug adapter supports conditional breakpoints.
- std::optional<bool> supportsConditionalBreakpoints;
-
- /// The debug adapter supports breakpoints that break execution after a
- /// specified number of hits.
- std::optional<bool> supportsHitConditionalBreakpoints;
-
- /// The debug adapter supports a (side effect free) `evaluate` request for
- /// data hovers.
- std::optional<bool> supportsEvaluateForHovers;
+ enum class Feature {
+ /// The debug adapter supports ANSI escape sequences in styling of
+ /// `OutputEvent.output` and `Variable.value` fields.
+ supportsANSIStyling,
+ /// The debug adapter supports the `breakpointLocations` request.
+ supportsBreakpointLocationsRequest,
+ /// The debug adapter supports the `cancel` request.
+ supportsCancelRequest,
+ /// The debug adapter supports the `clipboard` context value in the
+ /// `evaluate` request.
+ supportsClipboardContext,
+ /// The debug adapter supports the `completions` request.
+ supportsCompletionsRequest,
+ /// The debug adapter supports conditional breakpoints.
+ supportsConditionalBreakpoints,
+ /// The debug adapter supports the `configurationDone` request.
+ supportsConfigurationDoneRequest,
+ /// The debug adapter supports the `asAddress` and `bytes` fields in the
+ /// `dataBreakpointInfo` request.
+ supportsDataBreakpointBytes,
+ /// The debug adapter supports data breakpoints.
+ supportsDataBreakpoints,
+ /// The debug adapter supports the delayed loading of parts of the stack,
+ /// which requires that both the `startFrame` and `levels` arguments and the
+ /// `totalFrames` result of the `stackTrace` request are supported.
+ supportsDelayedStackTraceLoading,
+ /// The debug adapter supports the `disassemble` request.
+ supportsDisassembleRequest,
+ /// The debug adapter supports a (side effect free) `evaluate` request for
+ /// data hovers.
+ supportsEvaluateForHovers,
+ /// The debug adapter supports `filterOptions` as an argument on the
+ /// `setExceptionBreakpoints` request.
+ supportsExceptionFilterOptions,
+ /// The debug adapter supports the `exceptionInfo` request.
+ supportsExceptionInfoRequest,
+ /// The debug adapter supports `exceptionOptions` on the
+ /// `setExceptionBreakpoints` request.
+ supportsExceptionOptions,
+ /// The debug adapter supports function breakpoints.
+ supportsFunctionBreakpoints,
+ /// The debug adapter supports the `gotoTargets` request.
+ supportsGotoTargetsRequest,
+ /// The debug adapter supports breakpoints that break execution after a
+ /// specified number of hits.
+ supportsHitConditionalBreakpoints,
+ /// The debug adapter supports adding breakpoints based on instruction
+ /// references.
+ supportsInstructionBreakpoints,
+ /// The debug adapter supports the `loadedSources` request.
+ supportsLoadedSourcesRequest,
+ /// The debug adapter supports log points by interpreting the `logMessage`
+ /// attribute of the `SourceBreakpoint`.
+ supportsLogPoints,
+ /// The debug adapter supports the `modules` request.
+ supportsModulesRequest,
+ /// The debug adapter supports the `readMemory` request.
+ supportsReadMemoryRequest,
+ /// The debug adapter supports restarting a frame.
+ supportsRestartFrame,
+ /// The debug adapter supports the `restart` request. In this case a client
+ /// should not implement `restart` by terminating and relaunching the
+ /// adapter but by calling the `restart` request.
+ supportsRestartRequest,
+ /// The debug adapter supports the `setExpression` request.
+ supportsSetExpression,
+ /// The debug adapter supports setting a variable to a value.
+ supportsSetVariable,
+ /// The debug adapter supports the `singleThread` property on the execution
+ /// requests (`continue`, `next`, `stepIn`, `stepOut`, `reverseContinue`,
+ /// `stepBack`).
+ supportsSingleThreadExecutionRequests,
+ /// The debug adapter supports stepping back via the `stepBack` and
+ /// `reverseContinue` requests.
+ supportsStepBack,
+ /// The debug adapter supports the `stepInTargets` request.
+ supportsStepInTargetsRequest,
+ /// The debug adapter supports stepping granularities (argument
+ /// `granularity`) for the stepping requests.
+ supportsSteppingGranularity,
+ /// The debug adapter supports the `terminate` request.
+ supportsTerminateRequest,
+ /// The debug adapter supports the `terminateThreads` request.
+ supportsTerminateThreadsRequest,
+ /// The debug adapter supports the `suspendDebuggee` attribute on the
+ /// `disconnect` request.
+ supportSuspendDebuggee,
+ /// The debug adapter supports a `format` attribute on the `stackTrace`,
+ /// `variables`, and `evaluate` requests.
+ supportsValueFormattingOptions,
+ /// The debug adapter supports the `writeMemory` request.
+ supportsWriteMemoryRequest,
+ /// The debug adapter supports the `terminateDebuggee` attribute on the
+ /// `disconnect` request.
+ supportTerminateDebuggee,
+ };
+
+ /// The supported features for this adapter.
+ std::set<Feature> supportedFeatures;
/// Available exception filter options for the `setExceptionBreakpoints`
/// request.
std::optional<std::vector<ExceptionBreakpointsFilter>>
exceptionBreakpointFilters;
- /// The debug adapter supports stepping back via the `stepBack` and
- /// `reverseContinue` requests.
- std::optional<bool> supportsStepBack;
-
- /// The debug adapter supports setting a variable to a value.
- std::optional<bool> supportsSetVariable;
-
- /// The debug adapter supports restarting a frame.
- std::optional<bool> supportsRestartFrame;
-
- /// The debug adapter supports the `gotoTargets` request.
- std::optional<bool> supportsGotoTargetsRequest;
-
- /// The debug adapter supports the `stepInTargets` request.
- std::optional<bool> supportsStepInTargetsRequest;
-
- /// The debug adapter supports the `completions` request.
- std::optional<bool> supportsCompletionsRequest;
-
/// The set of characters that should trigger completion in a REPL. If not
/// specified, the UI should assume the `.` character.
std::optional<std::vector<std::string>> completionTriggerCharacters;
- /// The debug adapter supports the `modules` request.
- std::optional<bool> supportsModulesRequest;
-
/// The set of additional module information exposed by the debug adapter.
std::optional<std::vector<ColumnDescriptor>> additionalModuleColumns;
/// Checksum algorithms supported by the debug adapter.
std::optional<std::vector<ChecksumAlgorithm>> supportedChecksumAlgorithms;
- /// The debug adapter supports the `restart` request. In this case a client
- /// should not implement `restart` by terminating and relaunching the adapter
- /// but by calling the `restart` request.
- std::optional<bool> supportsRestartRequest;
-
- /// The debug adapter supports `exceptionOptions` on the
- /// `setExceptionBreakpoints` request.
- std::optional<bool> supportsExceptionOptions;
-
- /// The debug adapter supports a `format` attribute on the `stackTrace`,
- /// `variables`, and `evaluate` requests.
- std::optional<bool> supportsValueFormattingOptions;
-
- /// The debug adapter supports the `exceptionInfo` request.
- std::optional<bool> supportsExceptionInfoRequest;
-
- /// The debug adapter supports the `terminateDebuggee` attribute on the
- /// `disconnect` request.
- std::optional<bool> supportTerminateDebuggee;
-
- /// The debug adapter supports the `suspendDebuggee` attribute on the
- /// `disconnect` request.
- std::optional<bool> supportSuspendDebuggee;
-
- /// The debug adapter supports the delayed loading of parts of the stack,
- /// which requires that both the `startFrame` and `levels` arguments and the
- /// `totalFrames` result of the `stackTrace` request are supported.
- std::optional<bool> supportsDelayedStackTraceLoading;
-
- /// The debug adapter supports the `loadedSources` request.
- std::optional<bool> supportsLoadedSourcesRequest;
-
- /// The debug adapter supports log points by interpreting the `logMessage`
- /// attribute of the `SourceBreakpoint`.
- std::optional<bool> supportsLogPoints;
-
- /// The debug adapter supports the `terminateThreads` request.
- std::optional<bool> supportsTerminateThreadsRequest;
-
- /// The debug adapter supports the `setExpression` request.
- std::optional<bool> supportsSetExpression;
-
- /// The debug adapter supports the `terminate` request.
- std::optional<bool> supportsTerminateRequest;
-
- /// The debug adapter supports data breakpoints.
- std::optional<bool> supportsDataBreakpoints;
-
- /// The debug adapter supports the `readMemory` request.
- std::optional<bool> supportsReadMemoryRequest;
-
- /// The debug adapter supports the `writeMemory` request.
- std::optional<bool> supportsWriteMemoryRequest;
-
- /// The debug adapter supports the `disassemble` request.
- std::optional<bool> supportsDisassembleRequest;
-
- /// The debug adapter supports the `cancel` request.
- std::optional<bool> supportsCancelRequest;
-
- /// The debug adapter supports the `breakpointLocations` request.
- std::optional<bool> supportsBreakpointLocationsRequest;
-
- /// The debug adapter supports the `clipboard` context value in the `evaluate`
- /// request.
- std::optional<bool> supportsClipboardContext;
-
- /// The debug adapter supports stepping granularities (argument `granularity`)
- /// for the stepping requests.
- std::optional<bool> supportsSteppingGranularity;
-
- /// The debug adapter supports adding breakpoints based on instruction
- /// references.
- std::optional<bool> supportsInstructionBreakpoints;
-
- /// The debug adapter supports `filterOptions` as an argument on the
- /// `setExceptionBreakpoints` request.
- std::optional<bool> supportsExceptionFilterOptions;
-
- /// The debug adapter supports the `singleThread` property on the execution
- /// requests (`continue`, `next`, `stepIn`, `stepOut`, `reverseContinue`,
- /// `stepBack`).
- std::optional<bool> supportsSingleThreadExecutionRequests;
-
- /// The debug adapter supports the `asAddress` and `bytes` fields in the
- /// `dataBreakpointInfo` request.
- std::optional<bool> supportsDataBreakpointBytes;
-
/// Modes of breakpoints supported by the debug adapter, such as 'hardware' or
/// 'software'. If present, the client may allow the user to select a mode and
/// include it in its `setBreakpoints` request.
@@ -273,12 +247,13 @@ struct Capabilities {
/// 'default' mode in gestures that set breakpoints.
std::optional<std::vector<BreakpointMode>> breakpointModes;
- /// The debug adapter supports ANSI escape sequences in styling of
- /// `OutputEvent.output` and `Variable.value` fields.
- std::optional<bool> supportsANSIStyling;
-
/// lldb-dap Extensions
- std::optional<std::string> lldbVersion;
+ /// @{
+
+ /// The version of the adapter.
+ std::optional<std::string> lldbExtVersion;
+
+ /// @}
};
llvm::json::Value toJSON(const Capabilities &);
>From 7ebfa965e0210a95f3fa65e1fc373a98d350a8a8 Mon Sep 17 00:00:00 2001
From: John Harrison <ash at greaterthaninfinity.com>
Date: Wed, 26 Mar 2025 16:35:38 -0700
Subject: [PATCH 3/6] Apply suggestions from code review
Co-authored-by: Jonas Devlieghere <jonas at devlieghere.com>
---
lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp | 5 ++---
lldb/tools/lldb-dap/Protocol/ProtocolTypes.h | 2 +-
2 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp
index a598030d6c320..84753b0e10f1c 100644
--- a/lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp
@@ -251,9 +251,8 @@ llvm::Expected<protocol::InitializeResponseBody> InitializeRequestHandler::Run(
auto interp = dap.debugger.GetCommandInterpreter();
- // sourceInitFile option is not from formal DAP specification. It is only
- // used by unit tests to prevent sourcing .lldbinit files from environment
- // which may affect the outcome of tests.
+ // The sourceInitFile option is not part of the DAP specification. It is an extension
+ // used by the test suite to prevent sourcing `.lldbinit` and changing its behavior .
if (arguments.lldbExtSourceInitFile.value_or(true)) {
dap.debugger.SkipLLDBInitFiles(false);
dap.debugger.SkipAppInitFiles(false);
diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h
index e2c08db99bebd..eb9cd2f35039c 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h
@@ -85,7 +85,7 @@ llvm::json::Value toJSON(const ColumnDescriptor &);
/// Names of checksum algorithms that may be supported by a debug adapter.
/// Values: ‘MD5’, ‘SHA1’, ‘SHA256’, ‘timestamp’.
-enum class ChecksumAlgorithm { md5, sha1, sha256, timestamp };
+enum class ChecksumAlgorithm { MD5, SHA1, SHA256, timestamp };
llvm::json::Value toJSON(const ChecksumAlgorithm &);
/// Describes one or more type of breakpoint a BreakpointMode applies to. This
>From 3d51cbf226386569e00b935dc41d55716fbe484a Mon Sep 17 00:00:00 2001
From: John Harrison <harjohn at google.com>
Date: Wed, 26 Mar 2025 17:20:20 -0700
Subject: [PATCH 4/6] Adjusting enum naming to match lldb styles, converting
from set to DenseSet/SmallDenseSet and using some lookup tables to map
strings to enum values.
---
lldb/tools/lldb-dap/DAP.cpp | 21 +-
lldb/tools/lldb-dap/DAP.h | 9 +-
.../Handler/InitializeRequestHandler.cpp | 16 +-
.../tools/lldb-dap/Handler/RequestHandler.cpp | 3 +-
lldb/tools/lldb-dap/Handler/RequestHandler.h | 79 +++---
lldb/tools/lldb-dap/Protocol/ProtocolBase.cpp | 24 +-
.../lldb-dap/Protocol/ProtocolRequests.cpp | 61 ++---
.../lldb-dap/Protocol/ProtocolRequests.h | 58 ++---
.../tools/lldb-dap/Protocol/ProtocolTypes.cpp | 232 ++++++++---------
lldb/tools/lldb-dap/Protocol/ProtocolTypes.h | 235 ++++++++++--------
10 files changed, 352 insertions(+), 386 deletions(-)
diff --git a/lldb/tools/lldb-dap/DAP.cpp b/lldb/tools/lldb-dap/DAP.cpp
index fdd7a67135a68..5e443e4b4b612 100644
--- a/lldb/tools/lldb-dap/DAP.cpp
+++ b/lldb/tools/lldb-dap/DAP.cpp
@@ -1145,27 +1145,22 @@ lldb::SBValue Variables::FindVariable(uint64_t variablesReference,
return variable;
}
-bool DAP::isSupported(ClientFeature feature) {
- return clientFeatures.find(feature) != clientFeatures.end();
-}
-
protocol::Capabilities DAP::GetCapabilities() {
protocol::Capabilities capabilities;
// Supported capabilities that are not specific to a single request.
capabilities.supportedFeatures = {
- AdapterFeature::supportsLogPoints,
- AdapterFeature::supportsSteppingGranularity,
- AdapterFeature::supportsValueFormattingOptions,
+ protocol::eAdapterFeatureSupportsLogPoints,
+ protocol::eAdapterFeatureSupportsSteppingGranularity,
+ protocol::eAdapterFeatureSupportsValueFormattingOptions,
};
- // Unsupported capabilities.
- // supportsGotoTargetsRequest, supportsLoadedSourcesRequest,
- // supportsRestartFrame, supportsStepBack
-
// Capabilities associated with specific requests.
- for (auto &kv : request_handlers)
- capabilities.supportedFeatures.merge(kv.second->GetSupportedFeatures());
+ for (auto &kv : request_handlers) {
+ llvm::SmallDenseSet<AdapterFeature, 1> features =
+ kv.second->GetSupportedFeatures();
+ capabilities.supportedFeatures.insert(features.begin(), features.end());
+ }
// Available filters or options for the setExceptionBreakpoints request.
std::vector<protocol::ExceptionBreakpointsFilter> filters;
diff --git a/lldb/tools/lldb-dap/DAP.h b/lldb/tools/lldb-dap/DAP.h
index 5d4d4de0ed9b8..6689980806047 100644
--- a/lldb/tools/lldb-dap/DAP.h
+++ b/lldb/tools/lldb-dap/DAP.h
@@ -60,8 +60,8 @@ typedef llvm::StringMap<FunctionBreakpoint> FunctionBreakpointMap;
typedef llvm::DenseMap<lldb::addr_t, InstructionBreakpoint>
InstructionBreakpointMap;
-using AdapterFeature = protocol::Capabilities::Feature;
-using ClientFeature = protocol::InitializeRequestArguments::Feature;
+using AdapterFeature = protocol::AdapterFeature;
+using ClientFeature = protocol::ClientFeature;
enum class OutputType { Console, Stdout, Stderr, Telemetry };
@@ -211,7 +211,7 @@ struct DAP {
// will contain that expression.
std::string last_nonempty_var_expression;
/// The set of features supported by the connected client.
- std::set<ClientFeature> clientFeatures;
+ llvm::DenseSet<ClientFeature> clientFeatures;
/// Creates a new DAP sessions.
///
@@ -373,9 +373,6 @@ struct DAP {
/// The set of capablities supported by this adapter.
protocol::Capabilities GetCapabilities();
- /// Returns true if the connected client supports the given feature.
- bool isSupported(ClientFeature);
-
/// Debuggee will continue from stopped state.
void WillContinue() { variables.Clear(); }
diff --git a/lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp
index 84753b0e10f1c..6e96c76ac45fe 100644
--- a/lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp
@@ -16,6 +16,7 @@
#include "lldb/API/SBStream.h"
using namespace lldb;
+using namespace lldb_dap::protocol;
namespace lldb_dap {
@@ -231,8 +232,8 @@ static void EventThreadFunction(DAP &dap) {
}
/// Initialize request; value of command field is 'initialize'.
-llvm::Expected<protocol::InitializeResponseBody> InitializeRequestHandler::Run(
- const protocol::InitializeRequestArguments &arguments) const {
+llvm::Expected<InitializeResponseBody> InitializeRequestHandler::Run(
+ const InitializeRequestArguments &arguments) const {
dap.clientFeatures = arguments.supportedFeatures;
// Do not source init files until in/out/err are configured.
@@ -251,8 +252,9 @@ llvm::Expected<protocol::InitializeResponseBody> InitializeRequestHandler::Run(
auto interp = dap.debugger.GetCommandInterpreter();
- // The sourceInitFile option is not part of the DAP specification. It is an extension
- // used by the test suite to prevent sourcing `.lldbinit` and changing its behavior .
+ // The sourceInitFile option is not part of the DAP specification. It is an
+ // extension used by the test suite to prevent sourcing `.lldbinit` and
+ // changing its behavior .
if (arguments.lldbExtSourceInitFile.value_or(true)) {
dap.debugger.SkipLLDBInitFiles(false);
dap.debugger.SkipAppInitFiles(false);
@@ -267,7 +269,8 @@ llvm::Expected<protocol::InitializeResponseBody> InitializeRequestHandler::Run(
dap.PopulateExceptionBreakpoints();
auto cmd = dap.debugger.GetCommandInterpreter().AddMultiwordCommand(
"lldb-dap", "Commands for managing lldb-dap.");
- if (arguments.isSupported(ClientFeature::supportsStartDebuggingRequest)) {
+ if (arguments.supportedFeatures.contains(
+ eClientFeatureSupportsStartDebuggingRequest)) {
cmd.AddCommand(
"start-debugging", new StartDebuggingRequestHandler(dap),
"Sends a startDebugging request from the debug adapter to the client "
@@ -279,7 +282,8 @@ llvm::Expected<protocol::InitializeResponseBody> InitializeRequestHandler::Run(
cmd.AddCommand("send-event", new SendEventRequestHandler(dap),
"Sends an DAP event to the client.");
- if (arguments.isSupported(ClientFeature::supportsProgressReporting))
+ if (arguments.supportedFeatures.contains(
+ eClientFeatureSupportsProgressReporting))
dap.progress_event_thread =
std::thread(ProgressEventThreadFunction, std::ref(dap));
diff --git a/lldb/tools/lldb-dap/Handler/RequestHandler.cpp b/lldb/tools/lldb-dap/Handler/RequestHandler.cpp
index d938f2e7aaeee..300a183fb4a1d 100644
--- a/lldb/tools/lldb-dap/Handler/RequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/RequestHandler.cpp
@@ -98,7 +98,8 @@ void BaseRequestHandler::SetSourceMapFromArguments(
static llvm::Error RunInTerminal(DAP &dap,
const llvm::json::Object &launch_request,
const uint64_t timeout_seconds) {
- if (!dap.isSupported(ClientFeature::supportsRunInTerminalRequest))
+ if (!dap.clientFeatures.contains(
+ protocol::eClientFeatureSupportsRunInTerminalRequest))
return llvm::make_error<DAPError>("Cannot use runInTerminal, feature is "
"not supported by the connected client");
diff --git a/lldb/tools/lldb-dap/Handler/RequestHandler.h b/lldb/tools/lldb-dap/Handler/RequestHandler.h
index 517a460680c3f..1d3b5103b20d7 100644
--- a/lldb/tools/lldb-dap/Handler/RequestHandler.h
+++ b/lldb/tools/lldb-dap/Handler/RequestHandler.h
@@ -16,6 +16,7 @@
#include "Protocol/ProtocolRequests.h"
#include "Protocol/ProtocolTypes.h"
#include "lldb/API/SBError.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/JSON.h"
@@ -48,7 +49,9 @@ class BaseRequestHandler {
virtual void operator()(const protocol::Request &request) const = 0;
- virtual std::set<AdapterFeature> GetSupportedFeatures() const { return {}; }
+ virtual llvm::SmallDenseSet<AdapterFeature, 1> GetSupportedFeatures() const {
+ return {};
+ }
protected:
/// Helpers used by multiple request handlers.
@@ -176,8 +179,8 @@ class BreakpointLocationsRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "breakpointLocations"; }
- std::set<AdapterFeature> GetSupportedFeatures() const override {
- return {AdapterFeature::supportsBreakpointLocationsRequest};
+ llvm::SmallDenseSet<AdapterFeature, 1> GetSupportedFeatures() const override {
+ return {protocol::eAdapterFeatureSupportsBreakpointLocationsRequest};
}
void operator()(const llvm::json::Object &request) const override;
};
@@ -186,8 +189,8 @@ class CompletionsRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "completions"; }
- std::set<AdapterFeature> GetSupportedFeatures() const override {
- return {AdapterFeature::supportsCompletionsRequest};
+ llvm::SmallDenseSet<AdapterFeature, 1> GetSupportedFeatures() const override {
+ return {protocol::eAdapterFeatureSupportsCompletionsRequest};
}
void operator()(const llvm::json::Object &request) const override;
};
@@ -203,8 +206,8 @@ class ConfigurationDoneRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "configurationDone"; }
- std::set<AdapterFeature> GetSupportedFeatures() const override {
- return {AdapterFeature::supportsConfigurationDoneRequest};
+ llvm::SmallDenseSet<AdapterFeature, 1> GetSupportedFeatures() const override {
+ return {protocol::eAdapterFeatureSupportsConfigurationDoneRequest};
}
void operator()(const llvm::json::Object &request) const override;
};
@@ -215,8 +218,8 @@ class DisconnectRequestHandler
public:
using RequestHandler::RequestHandler;
static llvm::StringLiteral GetCommand() { return "disconnect"; }
- std::set<AdapterFeature> GetSupportedFeatures() const override {
- return {AdapterFeature::supportTerminateDebuggee};
+ llvm::SmallDenseSet<AdapterFeature, 1> GetSupportedFeatures() const override {
+ return {protocol::eAdapterFeatureSupportTerminateDebuggee};
}
llvm::Expected<protocol::DisconnectResponse>
Run(const std::optional<protocol::DisconnectArguments> &args) const override;
@@ -227,8 +230,8 @@ class EvaluateRequestHandler : public LegacyRequestHandler {
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "evaluate"; }
void operator()(const llvm::json::Object &request) const override;
- std::set<AdapterFeature> GetSupportedFeatures() const override {
- return {AdapterFeature::supportsEvaluateForHovers};
+ llvm::SmallDenseSet<AdapterFeature, 1> GetSupportedFeatures() const override {
+ return {protocol::eAdapterFeatureSupportsEvaluateForHovers};
}
};
@@ -236,8 +239,8 @@ class ExceptionInfoRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "exceptionInfo"; }
- std::set<AdapterFeature> GetSupportedFeatures() const override {
- return {AdapterFeature::supportsExceptionInfoRequest};
+ llvm::SmallDenseSet<AdapterFeature, 1> GetSupportedFeatures() const override {
+ return {protocol::eAdapterFeatureSupportsExceptionInfoRequest};
}
void operator()(const llvm::json::Object &request) const override;
};
@@ -263,8 +266,8 @@ class RestartRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "restart"; }
- std::set<AdapterFeature> GetSupportedFeatures() const override {
- return {AdapterFeature::supportsRestartRequest};
+ llvm::SmallDenseSet<AdapterFeature, 1> GetSupportedFeatures() const override {
+ return {protocol::eAdapterFeatureSupportsRestartRequest};
}
void operator()(const llvm::json::Object &request) const override;
};
@@ -287,8 +290,8 @@ class StepInTargetsRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "stepInTargets"; }
- std::set<AdapterFeature> GetSupportedFeatures() const override {
- return {AdapterFeature::supportsStepInTargetsRequest};
+ llvm::SmallDenseSet<AdapterFeature, 1> GetSupportedFeatures() const override {
+ return {protocol::eAdapterFeatureSupportsStepInTargetsRequest};
}
void operator()(const llvm::json::Object &request) const override;
};
@@ -304,9 +307,9 @@ class SetBreakpointsRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "setBreakpoints"; }
- std::set<AdapterFeature> GetSupportedFeatures() const override {
- return {AdapterFeature::supportsConditionalBreakpoints,
- AdapterFeature::supportsHitConditionalBreakpoints};
+ llvm::SmallDenseSet<AdapterFeature, 1> GetSupportedFeatures() const override {
+ return {protocol::eAdapterFeatureSupportsConditionalBreakpoints,
+ protocol::eAdapterFeatureSupportsHitConditionalBreakpoints};
}
void operator()(const llvm::json::Object &request) const override;
};
@@ -315,8 +318,8 @@ class SetExceptionBreakpointsRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "setExceptionBreakpoints"; }
- std::set<AdapterFeature> GetSupportedFeatures() const override {
- return {AdapterFeature::supportsExceptionOptions};
+ llvm::SmallDenseSet<AdapterFeature, 1> GetSupportedFeatures() const override {
+ return {protocol::eAdapterFeatureSupportsExceptionOptions};
}
void operator()(const llvm::json::Object &request) const override;
};
@@ -325,8 +328,8 @@ class SetFunctionBreakpointsRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "setFunctionBreakpoints"; }
- std::set<AdapterFeature> GetSupportedFeatures() const override {
- return {AdapterFeature::supportsFunctionBreakpoints};
+ llvm::SmallDenseSet<AdapterFeature, 1> GetSupportedFeatures() const override {
+ return {protocol::eAdapterFeatureSupportsFunctionBreakpoints};
}
void operator()(const llvm::json::Object &request) const override;
};
@@ -343,8 +346,8 @@ class SetDataBreakpointsRequestHandler : public LegacyRequestHandler {
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "setDataBreakpoints"; }
void operator()(const llvm::json::Object &request) const override;
- std::set<AdapterFeature> GetSupportedFeatures() const override {
- return {AdapterFeature::supportsDataBreakpoints};
+ llvm::SmallDenseSet<AdapterFeature, 1> GetSupportedFeatures() const override {
+ return {protocol::eAdapterFeatureSupportsDataBreakpoints};
}
};
@@ -355,8 +358,8 @@ class SetInstructionBreakpointsRequestHandler : public LegacyRequestHandler {
return "setInstructionBreakpoints";
}
void operator()(const llvm::json::Object &request) const override;
- std::set<AdapterFeature> GetSupportedFeatures() const override {
- return {AdapterFeature::supportsInstructionBreakpoints};
+ llvm::SmallDenseSet<AdapterFeature, 1> GetSupportedFeatures() const override {
+ return {protocol::eAdapterFeatureSupportsInstructionBreakpoints};
}
};
@@ -371,8 +374,8 @@ class ModulesRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "modules"; }
- std::set<AdapterFeature> GetSupportedFeatures() const override {
- return {AdapterFeature::supportsModulesRequest};
+ llvm::SmallDenseSet<AdapterFeature, 1> GetSupportedFeatures() const override {
+ return {protocol::eAdapterFeatureSupportsModulesRequest};
}
void operator()(const llvm::json::Object &request) const override;
};
@@ -395,8 +398,8 @@ class SetVariableRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "setVariable"; }
- std::set<AdapterFeature> GetSupportedFeatures() const override {
- return {AdapterFeature::supportsSetVariable};
+ llvm::SmallDenseSet<AdapterFeature, 1> GetSupportedFeatures() const override {
+ return {protocol::eAdapterFeatureSupportsSetVariable};
}
void operator()(const llvm::json::Object &request) const override;
};
@@ -416,8 +419,8 @@ class StackTraceRequestHandler : public LegacyRequestHandler {
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "stackTrace"; }
void operator()(const llvm::json::Object &request) const override;
- std::set<AdapterFeature> GetSupportedFeatures() const override {
- return {AdapterFeature::supportsDelayedStackTraceLoading};
+ llvm::SmallDenseSet<AdapterFeature, 1> GetSupportedFeatures() const override {
+ return {protocol::eAdapterFeatureSupportsDelayedStackTraceLoading};
}
};
@@ -446,8 +449,8 @@ class DisassembleRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "disassemble"; }
- std::set<AdapterFeature> GetSupportedFeatures() const override {
- return {AdapterFeature::supportsDisassembleRequest};
+ llvm::SmallDenseSet<AdapterFeature, 1> GetSupportedFeatures() const override {
+ return {protocol::eAdapterFeatureSupportsDisassembleRequest};
}
void operator()(const llvm::json::Object &request) const override;
};
@@ -456,8 +459,8 @@ class ReadMemoryRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "readMemory"; }
- std::set<AdapterFeature> GetSupportedFeatures() const override {
- return {AdapterFeature::supportsReadMemoryRequest};
+ llvm::SmallDenseSet<AdapterFeature, 1> GetSupportedFeatures() const override {
+ return {protocol::eAdapterFeatureSupportsReadMemoryRequest};
}
void operator()(const llvm::json::Object &request) const override;
};
diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolBase.cpp b/lldb/tools/lldb-dap/Protocol/ProtocolBase.cpp
index 0ef90eb7d76bd..86e26f4deb111 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolBase.cpp
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolBase.cpp
@@ -31,7 +31,11 @@ static bool mapRaw(const json::Value &Params, StringLiteral Prop,
namespace lldb_dap::protocol {
-enum class MessageType { request, response, event };
+enum MessageType {
+ eMessageTypeRequest,
+ eMessageTypeResponse,
+ eMessageTypeEvent
+};
bool fromJSON(const json::Value &Params, MessageType &M, json::Path P) {
auto rawType = Params.getAsString();
@@ -41,9 +45,9 @@ bool fromJSON(const json::Value &Params, MessageType &M, json::Path P) {
}
std::optional<MessageType> type =
StringSwitch<std::optional<MessageType>>(*rawType)
- .Case("request", MessageType::request)
- .Case("response", MessageType::response)
- .Case("event", MessageType::event)
+ .Case("request", eMessageTypeRequest)
+ .Case("response", eMessageTypeResponse)
+ .Case("event", eMessageTypeEvent)
.Default(std::nullopt);
if (!type) {
P.report("unexpected value, expected 'request', 'response' or 'event'");
@@ -76,7 +80,7 @@ bool fromJSON(json::Value const &Params, Request &R, json::Path P) {
!O.map("seq", R.seq))
return false;
- if (type != MessageType::request) {
+ if (type != eMessageTypeRequest) {
P.field("type").report("expected to be 'request'");
return false;
}
@@ -154,7 +158,7 @@ bool fromJSON(json::Value const &Params, Response &R, json::Path P) {
!O.map("command", R.command) || !O.map("request_seq", R.request_seq))
return false;
- if (type != MessageType::response) {
+ if (type != eMessageTypeResponse) {
P.field("type").report("expected to be 'response'");
return false;
}
@@ -231,7 +235,7 @@ bool fromJSON(json::Value const &Params, Event &E, json::Path P) {
if (!O.map("type", type) || !O.map("seq", seq) || !O.map("event", E.event))
return false;
- if (type != MessageType::event) {
+ if (type != eMessageTypeEvent) {
P.field("type").report("expected to be 'event'");
return false;
}
@@ -259,21 +263,21 @@ bool fromJSON(const json::Value &Params, Message &PM, json::Path P) {
return false;
switch (type) {
- case MessageType::request: {
+ case eMessageTypeRequest: {
Request req;
if (!fromJSON(Params, req, P))
return false;
PM = std::move(req);
return true;
}
- case MessageType::response: {
+ case eMessageTypeResponse: {
Response resp;
if (!fromJSON(Params, resp, P))
return false;
PM = std::move(resp);
return true;
}
- case MessageType::event:
+ case eMessageTypeEvent:
Event evt;
if (!fromJSON(Params, evt, P))
return false;
diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp
index 8e0a97c1ac2dc..5a712124f72b1 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp
@@ -8,6 +8,7 @@
#include "Protocol/ProtocolRequests.h"
#include "DAP.h"
+#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/JSON.h"
#include <utility>
@@ -24,19 +25,18 @@ bool fromJSON(const json::Value &Params, DisconnectArguments &DA,
O.mapOptional("suspendDebuggee", DA.suspendDebuggee);
}
-bool fromJSON(const llvm::json::Value &Params,
- InitializeRequestArguments::PathFormat &PF, llvm::json::Path P) {
+bool fromJSON(const llvm::json::Value &Params, PathFormat &PF,
+ llvm::json::Path P) {
auto rawPathFormat = Params.getAsString();
if (!rawPathFormat) {
P.report("expected a string");
return false;
}
- std::optional<InitializeRequestArguments::PathFormat> pathFormat =
- StringSwitch<std::optional<InitializeRequestArguments::PathFormat>>(
- *rawPathFormat)
- .Case("path", InitializeRequestArguments::PathFormat::path)
- .Case("uri", InitializeRequestArguments::PathFormat::uri)
+ std::optional<PathFormat> pathFormat =
+ StringSwitch<std::optional<PathFormat>>(*rawPathFormat)
+ .Case("path", ePatFormatPath)
+ .Case("uri", ePathFormatURI)
.Default(std::nullopt);
if (!pathFormat) {
P.report("unexpected value, expected 'path' or 'uri'");
@@ -47,6 +47,21 @@ bool fromJSON(const llvm::json::Value &Params,
return true;
}
+static const llvm::StringMap<ClientFeature> ClientFeatureByKey{
+ {"supportsVariableType", eClientFeatureSupportsVariableType},
+ {"supportsVariablePaging", eClientFeatureSupportsVariablePaging},
+ {"supportsRunInTerminalRequest",
+ eClientFeatureSupportsRunInTerminalRequest},
+ {"supportsMemoryReferences", eClientFeatureSupportsMemoryReferences},
+ {"supportsProgressReporting", eClientFeatureSupportsProgressReporting},
+ {"supportsInvalidatedEvent", eClientFeatureSupportsInvalidatedEvent},
+ {"supportsMemoryEvent", eClientFeatureSupportsMemoryEvent},
+ {"supportsArgsCanBeInterpretedByShell",
+ eClientFeatureSupportsArgsCanBeInterpretedByShell},
+ {"supportsStartDebuggingRequest",
+ eClientFeatureSupportsStartDebuggingRequest},
+ {"supportsANSIStyling", eClientFeatureSupportsANSIStyling}};
+
bool fromJSON(const llvm::json::Value &Params, InitializeRequestArguments &IRA,
llvm::json::Path P) {
json::ObjectMapper OM(Params, P);
@@ -54,34 +69,10 @@ bool fromJSON(const llvm::json::Value &Params, InitializeRequestArguments &IRA,
return false;
const json::Object *O = Params.getAsObject();
- if (std::optional<bool> v = O->getBoolean("supportsVariableType"); v && *v)
- IRA.supportedFeatures.insert(ClientFeature::supportsVariableType);
- if (std::optional<bool> v = O->getBoolean("supportsVariablePaging"); v && *v)
- IRA.supportedFeatures.insert(ClientFeature::supportsVariablePaging);
- if (std::optional<bool> v = O->getBoolean("supportsRunInTerminalRequest");
- v && *v)
- IRA.supportedFeatures.insert(ClientFeature::supportsRunInTerminalRequest);
- if (std::optional<bool> v = O->getBoolean("supportsMemoryReferences");
- v && *v)
- IRA.supportedFeatures.insert(ClientFeature::supportsMemoryReferences);
- if (std::optional<bool> v = O->getBoolean("supportsProgressReporting");
- v && *v)
- IRA.supportedFeatures.insert(ClientFeature::supportsProgressReporting);
- if (std::optional<bool> v = O->getBoolean("supportsInvalidatedEvent");
- v && *v)
- IRA.supportedFeatures.insert(ClientFeature::supportsInvalidatedEvent);
- if (std::optional<bool> v = O->getBoolean("supportsMemoryEvent"); v && *v)
- IRA.supportedFeatures.insert(ClientFeature::supportsMemoryEvent);
- if (std::optional<bool> v =
- O->getBoolean("supportsArgsCanBeInterpretedByShell");
- v && *v)
- IRA.supportedFeatures.insert(
- ClientFeature::supportsArgsCanBeInterpretedByShell);
- if (std::optional<bool> v = O->getBoolean("supportsStartDebuggingRequest");
- v && *v)
- IRA.supportedFeatures.insert(ClientFeature::supportsStartDebuggingRequest);
- if (std::optional<bool> v = O->getBoolean("supportsANSIStyling"); v && *v)
- IRA.supportedFeatures.insert(ClientFeature::supportsANSIStyling);
+
+ for (auto &kv : ClientFeatureByKey)
+ if (std::optional<bool> v = O->getBoolean(kv.first()); v && *v)
+ IRA.supportedFeatures.insert(kv.second);
return OM.mapOptional("adatperID", IRA.adatperID) &&
OM.mapOptional("clientID", IRA.clientID) &&
diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h
index f6ca8e0562b5c..d4d61db576994 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h
@@ -54,6 +54,28 @@ bool fromJSON(const llvm::json::Value &, DisconnectArguments &,
/// body field is required.
using DisconnectResponse = VoidResponse;
+/// Features supported by DAP clients.
+enum ClientFeature {
+ eClientFeatureSupportsVariableType,
+ eClientFeatureSupportsVariablePaging,
+ eClientFeatureSupportsRunInTerminalRequest,
+ eClientFeatureSupportsMemoryReferences,
+ eClientFeatureSupportsProgressReporting,
+ eClientFeatureSupportsInvalidatedEvent,
+ eClientFeatureSupportsMemoryEvent,
+ /// Client supports the `argsCanBeInterpretedByShell` attribute on the
+ /// `runInTerminal` request.
+ eClientFeatureSupportsArgsCanBeInterpretedByShell,
+ eClientFeatureSupportsStartDebuggingRequest,
+ /// The client will interpret ANSI escape sequences in the display of
+ /// `OutputEvent.output` and `Variable.value` fields when
+ /// `Capabilities.supportsANSIStyling` is also enabled.
+ eClientFeatureSupportsANSIStyling,
+};
+
+/// Format of paths reported by the debug adapter.
+enum PathFormat { ePatFormatPath, ePathFormatURI };
+
/// Arguments for `initialize` request.
struct InitializeRequestArguments {
/// The ID of the debug adapter.
@@ -68,11 +90,9 @@ struct InitializeRequestArguments {
/// The ISO-639 locale of the client using this adapter, e.g. en-US or de-CH.
std::optional<std::string> locale;
- enum class PathFormat { path, uri };
-
/// Determines in what format paths are specified. The default is `path`,
/// which is the native format.
- std::optional<PathFormat> pathFormat = PathFormat::path;
+ std::optional<PathFormat> pathFormat = ePatFormatPath;
/// If true all line numbers are 1-based (default).
std::optional<bool> linesStartAt1;
@@ -80,38 +100,8 @@ struct InitializeRequestArguments {
/// If true all column numbers are 1-based (default).
std::optional<bool> columnsStartAt1;
- enum class Feature {
- /// Client supports the `type` attribute for variables.
- supportsVariableType,
- /// Client supports the paging of variables.
- supportsVariablePaging,
- /// Client supports the `runInTerminal` request.
- supportsRunInTerminalRequest,
- /// Client supports memory references.
- supportsMemoryReferences,
- /// Client supports progress reporting.
- supportsProgressReporting,
- /// Client supports the `invalidated` event.
- supportsInvalidatedEvent,
- /// Client supports the `memory` event.
- supportsMemoryEvent,
- /// Client supports the `argsCanBeInterpretedByShell` attribute on the
- /// `runInTerminal` request.
- supportsArgsCanBeInterpretedByShell,
- /// Client supports the `startDebugging` request.
- supportsStartDebuggingRequest,
- /// The client will interpret ANSI escape sequences in the display of
- /// `OutputEvent.output` and `Variable.value` fields when
- /// `Capabilities.supportsANSIStyling` is also enabled.
- supportsANSIStyling,
- };
-
/// The set of supported features reported by the client.
- std::set<Feature> supportedFeatures;
-
- bool isSupported(Feature feature) const {
- return supportedFeatures.find(feature) != supportedFeatures.end();
- }
+ llvm::DenseSet<ClientFeature> supportedFeatures;
/// lldb-dap Extensions
/// @{
diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp
index 8d3a31e19b055..a7cf8631ae431 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp
@@ -16,18 +16,17 @@ using namespace llvm;
namespace lldb_dap::protocol {
-bool fromJSON(const json::Value &Params, Source::PresentationHint &PH,
- json::Path P) {
+bool fromJSON(const json::Value &Params, PresentationHint &PH, json::Path P) {
auto rawHint = Params.getAsString();
if (!rawHint) {
P.report("expected a string");
return false;
}
- std::optional<Source::PresentationHint> hint =
- StringSwitch<std::optional<Source::PresentationHint>>(*rawHint)
- .Case("normal", Source::PresentationHint::normal)
- .Case("emphasize", Source::PresentationHint::emphasize)
- .Case("deemphasize", Source::PresentationHint::deemphasize)
+ std::optional<PresentationHint> hint =
+ StringSwitch<std::optional<PresentationHint>>(*rawHint)
+ .Case("normal", ePresentationHintNormal)
+ .Case("emphasize", ePresentationHintEmphasize)
+ .Case("deemphasize", ePresentationHintDeemphasize)
.Default(std::nullopt);
if (!hint) {
P.report("unexpected value");
@@ -59,15 +58,15 @@ json::Value toJSON(const ExceptionBreakpointsFilter &EBF) {
return result;
}
-json::Value toJSON(const ColumnDescriptor::Type &T) {
+json::Value toJSON(const ColumnType &T) {
switch (T) {
- case ColumnDescriptor::Type::String:
+ case eColumnTypeString:
return "string";
- case ColumnDescriptor::Type::Number:
+ case eColumnTypeNumber:
return "number";
- case ColumnDescriptor::Type::Boolean:
+ case eColumnTypeBoolean:
return "boolean";
- case ColumnDescriptor::Type::Timestamp:
+ case eColumnTypeTimestamp:
return "unixTimestampUTC";
}
}
@@ -87,26 +86,26 @@ json::Value toJSON(const ColumnDescriptor &CD) {
json::Value toJSON(const ChecksumAlgorithm &CA) {
switch (CA) {
- case ChecksumAlgorithm::md5:
+ case eChecksumAlgorithmMD5:
return "MD5";
- case ChecksumAlgorithm::sha1:
+ case eChecksumAlgorithmSHA1:
return "SHA1";
- case ChecksumAlgorithm::sha256:
+ case eChecksumAlgorithmSHA256:
return "SHA256";
- case ChecksumAlgorithm::timestamp:
+ case eChecksumAlgorithmTimestamp:
return "timestamp";
}
}
json::Value toJSON(const BreakpointModeApplicability &BMA) {
switch (BMA) {
- case BreakpointModeApplicability::source:
+ case eBreakpointModeApplicabilitySource:
return "source";
- case BreakpointModeApplicability::exception:
+ case eBreakpointModeApplicabilityException:
return "exception";
- case BreakpointModeApplicability::data:
+ case eBreakpointModeApplicabilityData:
return "data";
- case BreakpointModeApplicability::instruction:
+ case eBreakpointModeApplicabilityInstruction:
return "instruction";
}
}
@@ -124,123 +123,90 @@ json::Value toJSON(const BreakpointMode &BM) {
return result;
}
+static llvm::StringLiteral ToString(AdapterFeature feature) {
+ switch (feature) {
+ case eAdapterFeatureSupportsANSIStyling:
+ return "supportsANSIStyling";
+ case eAdapterFeatureSupportsBreakpointLocationsRequest:
+ return "supportsBreakpointLocationsRequest";
+ case eAdapterFeatureSupportsCancelRequest:
+ return "supportsCancelRequest";
+ case eAdapterFeatureSupportsClipboardContext:
+ return "supportsClipboardContext";
+ case eAdapterFeatureSupportsCompletionsRequest:
+ return "supportsCompletionsRequest";
+ case eAdapterFeatureSupportsConditionalBreakpoints:
+ return "supportsConditionalBreakpoints";
+ case eAdapterFeatureSupportsConfigurationDoneRequest:
+ return "supportsConfigurationDoneRequest";
+ case eAdapterFeatureSupportsDataBreakpointBytes:
+ return "supportsDataBreakpointBytes";
+ case eAdapterFeatureSupportsDataBreakpoints:
+ return "supportsDataBreakpoints";
+ case eAdapterFeatureSupportsDelayedStackTraceLoading:
+ return "supportsDelayedStackTraceLoading";
+ case eAdapterFeatureSupportsDisassembleRequest:
+ return "supportsDisassembleRequest";
+ case eAdapterFeatureSupportsEvaluateForHovers:
+ return "supportsEvaluateForHovers";
+ case eAdapterFeatureSupportsExceptionFilterOptions:
+ return "supportsExceptionFilterOptions";
+ case eAdapterFeatureSupportsExceptionInfoRequest:
+ return "supportsExceptionInfoRequest";
+ case eAdapterFeatureSupportsExceptionOptions:
+ return "supportsExceptionOptions";
+ case eAdapterFeatureSupportsFunctionBreakpoints:
+ return "supportsFunctionBreakpoints";
+ case eAdapterFeatureSupportsGotoTargetsRequest:
+ return "supportsGotoTargetsRequest";
+ case eAdapterFeatureSupportsHitConditionalBreakpoints:
+ return "supportsHitConditionalBreakpoints";
+ case eAdapterFeatureSupportsInstructionBreakpoints:
+ return "supportsInstructionBreakpoints";
+ case eAdapterFeatureSupportsLoadedSourcesRequest:
+ return "supportsLoadedSourcesRequest";
+ case eAdapterFeatureSupportsLogPoints:
+ return "supportsLogPoints";
+ case eAdapterFeatureSupportsModulesRequest:
+ return "supportsModulesRequest";
+ case eAdapterFeatureSupportsReadMemoryRequest:
+ return "supportsReadMemoryRequest";
+ case eAdapterFeatureSupportsRestartFrame:
+ return "supportsRestartFrame";
+ case eAdapterFeatureSupportsRestartRequest:
+ return "supportsRestartRequest";
+ case eAdapterFeatureSupportsSetExpression:
+ return "supportsSetExpression";
+ case eAdapterFeatureSupportsSetVariable:
+ return "supportsSetVariable";
+ case eAdapterFeatureSupportsSingleThreadExecutionRequests:
+ return "supportsSingleThreadExecutionRequests";
+ case eAdapterFeatureSupportsStepBack:
+ return "supportsStepBack";
+ case eAdapterFeatureSupportsStepInTargetsRequest:
+ return "supportsStepInTargetsRequest";
+ case eAdapterFeatureSupportsSteppingGranularity:
+ return "supportsSteppingGranularity";
+ case eAdapterFeatureSupportsTerminateRequest:
+ return "supportsTerminateRequest";
+ case eAdapterFeatureSupportsTerminateThreadsRequest:
+ return "supportsTerminateThreadsRequest";
+ case eAdapterFeatureSupportSuspendDebuggee:
+ return "supportSuspendDebuggee";
+ case eAdapterFeatureSupportsValueFormattingOptions:
+ return "supportsValueFormattingOptions";
+ case eAdapterFeatureSupportsWriteMemoryRequest:
+ return "supportsWriteMemoryRequest";
+ case eAdapterFeatureSupportTerminateDebuggee:
+ return "supportTerminateDebuggee";
+ }
+}
+
json::Value toJSON(const Capabilities &C) {
json::Object result;
for (const auto &feature : C.supportedFeatures)
- switch (feature) {
- case Capabilities::Feature::supportsANSIStyling:
- result.insert({"supportsANSIStyling", true});
- break;
- case Capabilities::Feature::supportsBreakpointLocationsRequest:
- result.insert({"supportsBreakpointLocationsRequest", true});
- break;
- case Capabilities::Feature::supportsCancelRequest:
- result.insert({"supportsCancelRequest", true});
- break;
- case Capabilities::Feature::supportsClipboardContext:
- result.insert({"supportsClipboardContext", true});
- break;
- case Capabilities::Feature::supportsCompletionsRequest:
- result.insert({"supportsCompletionsRequest", true});
- break;
- case Capabilities::Feature::supportsConditionalBreakpoints:
- result.insert({"supportsConditionalBreakpoints", true});
- break;
- case Capabilities::Feature::supportsConfigurationDoneRequest:
- result.insert({"supportsConfigurationDoneRequest", true});
- break;
- case Capabilities::Feature::supportsDataBreakpointBytes:
- result.insert({"supportsDataBreakpointBytes", true});
- break;
- case Capabilities::Feature::supportsDataBreakpoints:
- result.insert({"supportsDataBreakpoints", true});
- break;
- case Capabilities::Feature::supportsDelayedStackTraceLoading:
- result.insert({"supportsDelayedStackTraceLoading", true});
- break;
- case Capabilities::Feature::supportsDisassembleRequest:
- result.insert({"supportsDisassembleRequest", true});
- break;
- case Capabilities::Feature::supportsEvaluateForHovers:
- result.insert({"supportsEvaluateForHovers", true});
- break;
- case Capabilities::Feature::supportsExceptionFilterOptions:
- result.insert({"supportsExceptionFilterOptions", true});
- break;
- case Capabilities::Feature::supportsExceptionInfoRequest:
- result.insert({"supportsExceptionInfoRequest", true});
- break;
- case Capabilities::Feature::supportsExceptionOptions:
- result.insert({"supportsExceptionOptions", true});
- break;
- case Capabilities::Feature::supportsFunctionBreakpoints:
- result.insert({"supportsFunctionBreakpoints", true});
- break;
- case Capabilities::Feature::supportsGotoTargetsRequest:
- result.insert({"supportsGotoTargetsRequest", true});
- break;
- case Capabilities::Feature::supportsHitConditionalBreakpoints:
- result.insert({"supportsHitConditionalBreakpoints", true});
- break;
- case Capabilities::Feature::supportsInstructionBreakpoints:
- result.insert({"supportsInstructionBreakpoints", true});
- break;
- case Capabilities::Feature::supportsLoadedSourcesRequest:
- result.insert({"supportsLoadedSourcesRequest", true});
- break;
- case Capabilities::Feature::supportsLogPoints:
- result.insert({"supportsLogPoints", true});
- break;
- case Capabilities::Feature::supportsModulesRequest:
- result.insert({"supportsModulesRequest", true});
- break;
- case Capabilities::Feature::supportsReadMemoryRequest:
- result.insert({"supportsReadMemoryRequest", true});
- break;
- case Capabilities::Feature::supportsRestartFrame:
- result.insert({"supportsRestartFrame", true});
- break;
- case Capabilities::Feature::supportsRestartRequest:
- result.insert({"supportsRestartRequest", true});
- break;
- case Capabilities::Feature::supportsSetExpression:
- result.insert({"supportsSetExpression", true});
- break;
- case Capabilities::Feature::supportsSetVariable:
- result.insert({"supportsSetVariable", true});
- break;
- case Capabilities::Feature::supportsSingleThreadExecutionRequests:
- result.insert({"supportsSingleThreadExecutionRequests", true});
- break;
- case Capabilities::Feature::supportsStepBack:
- result.insert({"supportsStepBack", true});
- break;
- case Capabilities::Feature::supportsStepInTargetsRequest:
- result.insert({"supportsStepInTargetsRequest", true});
- break;
- case Capabilities::Feature::supportsSteppingGranularity:
- result.insert({"supportsSteppingGranularity", true});
- break;
- case Capabilities::Feature::supportsTerminateRequest:
- result.insert({"supportsTerminateRequest", true});
- break;
- case Capabilities::Feature::supportsTerminateThreadsRequest:
- result.insert({"supportsTerminateThreadsRequest", true});
- break;
- case Capabilities::Feature::supportSuspendDebuggee:
- result.insert({"supportSuspendDebuggee", true});
- break;
- case Capabilities::Feature::supportsValueFormattingOptions:
- result.insert({"supportsValueFormattingOptions", true});
- break;
- case Capabilities::Feature::supportsWriteMemoryRequest:
- result.insert({"supportsWriteMemoryRequest", true});
- break;
- case Capabilities::Feature::supportTerminateDebuggee:
- result.insert({"supportTerminateDebuggee", true});
- break;
- }
+ result.insert({ToString(feature), true});
if (C.exceptionBreakpointFilters && !C.exceptionBreakpointFilters->empty())
result.insert(
diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h
index eb9cd2f35039c..e7afb7f938ce9 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h
@@ -20,10 +20,10 @@
#ifndef LLDB_TOOLS_LLDB_DAP_PROTOCOL_PROTOCOL_TYPES_H
#define LLDB_TOOLS_LLDB_DAP_PROTOCOL_PROTOCOL_TYPES_H
+#include "llvm/ADT/DenseSet.h"
#include "llvm/Support/JSON.h"
#include <cstdint>
#include <optional>
-#include <set>
#include <string>
namespace lldb_dap::protocol {
@@ -56,6 +56,13 @@ struct ExceptionBreakpointsFilter {
};
llvm::json::Value toJSON(const ExceptionBreakpointsFilter &);
+enum ColumnType {
+ eColumnTypeString,
+ eColumnTypeNumber,
+ eColumnTypeBoolean,
+ eColumnTypeTimestamp
+};
+
/// A ColumnDescriptor specifies what module attribute to show in a column of
/// the modules view, how to format it, and what the column’s label should be.
///
@@ -72,11 +79,9 @@ struct ColumnDescriptor {
/// strings looks like.
std::optional<std::string> format;
- enum class Type { String, Number, Boolean, Timestamp };
-
/// Datatype of values in this column. Defaults to `string` if not specified.
/// Values: 'string', 'number', 'boolean', 'unixTimestampUTC'.
- std::optional<Type> type;
+ std::optional<ColumnType> type;
/// Width of this column in characters (hint only).
std::optional<int> width;
@@ -85,21 +90,26 @@ llvm::json::Value toJSON(const ColumnDescriptor &);
/// Names of checksum algorithms that may be supported by a debug adapter.
/// Values: ‘MD5’, ‘SHA1’, ‘SHA256’, ‘timestamp’.
-enum class ChecksumAlgorithm { MD5, SHA1, SHA256, timestamp };
+enum ChecksumAlgorithm {
+ eChecksumAlgorithmMD5,
+ eChecksumAlgorithmSHA1,
+ eChecksumAlgorithmSHA256,
+ eChecksumAlgorithmTimestamp
+};
llvm::json::Value toJSON(const ChecksumAlgorithm &);
/// Describes one or more type of breakpoint a BreakpointMode applies to. This
/// is a non-exhaustive enumeration and may expand as future breakpoint types
/// are added.
-enum class BreakpointModeApplicability {
+enum BreakpointModeApplicability {
/// In `SourceBreakpoint`'s.
- source,
+ eBreakpointModeApplicabilitySource,
/// In exception breakpoints applied in the `ExceptionFilterOptions`.
- exception,
+ eBreakpointModeApplicabilityException,
/// In data breakpoints requested in the `DataBreakpointInfo` request.
- data,
+ eBreakpointModeApplicabilityData,
/// In `InstructionBreakpoint`'s.
- instruction
+ eBreakpointModeApplicabilityInstruction
};
llvm::json::Value toJSON(const BreakpointModeApplicability &);
@@ -122,107 +132,108 @@ struct BreakpointMode {
};
llvm::json::Value toJSON(const BreakpointMode &);
+/// Debug Adapter Features flags supported by lldb-dap.
+enum AdapterFeature {
+ /// The debug adapter supports ANSI escape sequences in styling of
+ /// `OutputEvent.output` and `Variable.value` fields.
+ eAdapterFeatureSupportsANSIStyling,
+ /// The debug adapter supports the `breakpointLocations` request.
+ eAdapterFeatureSupportsBreakpointLocationsRequest,
+ /// The debug adapter supports the `cancel` request.
+ eAdapterFeatureSupportsCancelRequest,
+ /// The debug adapter supports the `clipboard` context value in the
+ /// `evaluate` request.
+ eAdapterFeatureSupportsClipboardContext,
+ /// The debug adapter supports the `completions` request.
+ eAdapterFeatureSupportsCompletionsRequest,
+ /// The debug adapter supports conditional breakpoints.
+ eAdapterFeatureSupportsConditionalBreakpoints,
+ /// The debug adapter supports the `configurationDone` request.
+ eAdapterFeatureSupportsConfigurationDoneRequest,
+ /// The debug adapter supports the `asAddress` and `bytes` fields in the
+ /// `dataBreakpointInfo` request.
+ eAdapterFeatureSupportsDataBreakpointBytes,
+ /// The debug adapter supports data breakpoints.
+ eAdapterFeatureSupportsDataBreakpoints,
+ /// The debug adapter supports the delayed loading of parts of the stack,
+ /// which requires that both the `startFrame` and `levels` arguments and the
+ /// `totalFrames` result of the `stackTrace` request are supported.
+ eAdapterFeatureSupportsDelayedStackTraceLoading,
+ /// The debug adapter supports the `disassemble` request.
+ eAdapterFeatureSupportsDisassembleRequest,
+ /// The debug adapter supports a (side effect free) `evaluate` request for
+ /// data hovers.
+ eAdapterFeatureSupportsEvaluateForHovers,
+ /// The debug adapter supports `filterOptions` as an argument on the
+ /// `setExceptionBreakpoints` request.
+ eAdapterFeatureSupportsExceptionFilterOptions,
+ /// The debug adapter supports the `exceptionInfo` request.
+ eAdapterFeatureSupportsExceptionInfoRequest,
+ /// The debug adapter supports `exceptionOptions` on the
+ /// `setExceptionBreakpoints` request.
+ eAdapterFeatureSupportsExceptionOptions,
+ /// The debug adapter supports function breakpoints.
+ eAdapterFeatureSupportsFunctionBreakpoints,
+ /// The debug adapter supports the `gotoTargets` request.
+ eAdapterFeatureSupportsGotoTargetsRequest,
+ /// The debug adapter supports breakpoints that break execution after a
+ /// specified number of hits.
+ eAdapterFeatureSupportsHitConditionalBreakpoints,
+ /// The debug adapter supports adding breakpoints based on instruction
+ /// references.
+ eAdapterFeatureSupportsInstructionBreakpoints,
+ /// The debug adapter supports the `loadedSources` request.
+ eAdapterFeatureSupportsLoadedSourcesRequest,
+ /// The debug adapter supports log points by interpreting the `logMessage`
+ /// attribute of the `SourceBreakpoint`.
+ eAdapterFeatureSupportsLogPoints,
+ /// The debug adapter supports the `modules` request.
+ eAdapterFeatureSupportsModulesRequest,
+ /// The debug adapter supports the `readMemory` request.
+ eAdapterFeatureSupportsReadMemoryRequest,
+ /// The debug adapter supports restarting a frame.
+ eAdapterFeatureSupportsRestartFrame,
+ /// The debug adapter supports the `restart` request. In this case a client
+ /// should not implement `restart` by terminating and relaunching the
+ /// adapter but by calling the `restart` request.
+ eAdapterFeatureSupportsRestartRequest,
+ /// The debug adapter supports the `setExpression` request.
+ eAdapterFeatureSupportsSetExpression,
+ /// The debug adapter supports setting a variable to a value.
+ eAdapterFeatureSupportsSetVariable,
+ /// The debug adapter supports the `singleThread` property on the execution
+ /// requests (`continue`, `next`, `stepIn`, `stepOut`, `reverseContinue`,
+ /// `stepBack`).
+ eAdapterFeatureSupportsSingleThreadExecutionRequests,
+ /// The debug adapter supports stepping back via the `stepBack` and
+ /// `reverseContinue` requests.
+ eAdapterFeatureSupportsStepBack,
+ /// The debug adapter supports the `stepInTargets` request.
+ eAdapterFeatureSupportsStepInTargetsRequest,
+ /// The debug adapter supports stepping granularities (argument
+ /// `granularity`) for the stepping requests.
+ eAdapterFeatureSupportsSteppingGranularity,
+ /// The debug adapter supports the `terminate` request.
+ eAdapterFeatureSupportsTerminateRequest,
+ /// The debug adapter supports the `terminateThreads` request.
+ eAdapterFeatureSupportsTerminateThreadsRequest,
+ /// The debug adapter supports the `suspendDebuggee` attribute on the
+ /// `disconnect` request.
+ eAdapterFeatureSupportSuspendDebuggee,
+ /// The debug adapter supports a `format` attribute on the `stackTrace`,
+ /// `variables`, and `evaluate` requests.
+ eAdapterFeatureSupportsValueFormattingOptions,
+ /// The debug adapter supports the `writeMemory` request.
+ eAdapterFeatureSupportsWriteMemoryRequest,
+ /// The debug adapter supports the `terminateDebuggee` attribute on the
+ /// `disconnect` request.
+ eAdapterFeatureSupportTerminateDebuggee,
+};
+
/// Information about the capabilities of a debug adapter.
struct Capabilities {
- enum class Feature {
- /// The debug adapter supports ANSI escape sequences in styling of
- /// `OutputEvent.output` and `Variable.value` fields.
- supportsANSIStyling,
- /// The debug adapter supports the `breakpointLocations` request.
- supportsBreakpointLocationsRequest,
- /// The debug adapter supports the `cancel` request.
- supportsCancelRequest,
- /// The debug adapter supports the `clipboard` context value in the
- /// `evaluate` request.
- supportsClipboardContext,
- /// The debug adapter supports the `completions` request.
- supportsCompletionsRequest,
- /// The debug adapter supports conditional breakpoints.
- supportsConditionalBreakpoints,
- /// The debug adapter supports the `configurationDone` request.
- supportsConfigurationDoneRequest,
- /// The debug adapter supports the `asAddress` and `bytes` fields in the
- /// `dataBreakpointInfo` request.
- supportsDataBreakpointBytes,
- /// The debug adapter supports data breakpoints.
- supportsDataBreakpoints,
- /// The debug adapter supports the delayed loading of parts of the stack,
- /// which requires that both the `startFrame` and `levels` arguments and the
- /// `totalFrames` result of the `stackTrace` request are supported.
- supportsDelayedStackTraceLoading,
- /// The debug adapter supports the `disassemble` request.
- supportsDisassembleRequest,
- /// The debug adapter supports a (side effect free) `evaluate` request for
- /// data hovers.
- supportsEvaluateForHovers,
- /// The debug adapter supports `filterOptions` as an argument on the
- /// `setExceptionBreakpoints` request.
- supportsExceptionFilterOptions,
- /// The debug adapter supports the `exceptionInfo` request.
- supportsExceptionInfoRequest,
- /// The debug adapter supports `exceptionOptions` on the
- /// `setExceptionBreakpoints` request.
- supportsExceptionOptions,
- /// The debug adapter supports function breakpoints.
- supportsFunctionBreakpoints,
- /// The debug adapter supports the `gotoTargets` request.
- supportsGotoTargetsRequest,
- /// The debug adapter supports breakpoints that break execution after a
- /// specified number of hits.
- supportsHitConditionalBreakpoints,
- /// The debug adapter supports adding breakpoints based on instruction
- /// references.
- supportsInstructionBreakpoints,
- /// The debug adapter supports the `loadedSources` request.
- supportsLoadedSourcesRequest,
- /// The debug adapter supports log points by interpreting the `logMessage`
- /// attribute of the `SourceBreakpoint`.
- supportsLogPoints,
- /// The debug adapter supports the `modules` request.
- supportsModulesRequest,
- /// The debug adapter supports the `readMemory` request.
- supportsReadMemoryRequest,
- /// The debug adapter supports restarting a frame.
- supportsRestartFrame,
- /// The debug adapter supports the `restart` request. In this case a client
- /// should not implement `restart` by terminating and relaunching the
- /// adapter but by calling the `restart` request.
- supportsRestartRequest,
- /// The debug adapter supports the `setExpression` request.
- supportsSetExpression,
- /// The debug adapter supports setting a variable to a value.
- supportsSetVariable,
- /// The debug adapter supports the `singleThread` property on the execution
- /// requests (`continue`, `next`, `stepIn`, `stepOut`, `reverseContinue`,
- /// `stepBack`).
- supportsSingleThreadExecutionRequests,
- /// The debug adapter supports stepping back via the `stepBack` and
- /// `reverseContinue` requests.
- supportsStepBack,
- /// The debug adapter supports the `stepInTargets` request.
- supportsStepInTargetsRequest,
- /// The debug adapter supports stepping granularities (argument
- /// `granularity`) for the stepping requests.
- supportsSteppingGranularity,
- /// The debug adapter supports the `terminate` request.
- supportsTerminateRequest,
- /// The debug adapter supports the `terminateThreads` request.
- supportsTerminateThreadsRequest,
- /// The debug adapter supports the `suspendDebuggee` attribute on the
- /// `disconnect` request.
- supportSuspendDebuggee,
- /// The debug adapter supports a `format` attribute on the `stackTrace`,
- /// `variables`, and `evaluate` requests.
- supportsValueFormattingOptions,
- /// The debug adapter supports the `writeMemory` request.
- supportsWriteMemoryRequest,
- /// The debug adapter supports the `terminateDebuggee` attribute on the
- /// `disconnect` request.
- supportTerminateDebuggee,
- };
-
/// The supported features for this adapter.
- std::set<Feature> supportedFeatures;
+ llvm::DenseSet<AdapterFeature> supportedFeatures;
/// Available exception filter options for the `setExceptionBreakpoints`
/// request.
@@ -257,12 +268,16 @@ struct Capabilities {
};
llvm::json::Value toJSON(const Capabilities &);
+enum PresentationHint {
+ ePresentationHintNormal,
+ ePresentationHintEmphasize,
+ ePresentationHintDeemphasize,
+};
+
/// A `Source` is a descriptor for source code. It is returned from the debug
/// adapter as part of a `StackFrame` and it is used by clients when specifying
/// breakpoints.
struct Source {
- enum class PresentationHint { normal, emphasize, deemphasize };
-
/// The short name of the source. Every source returned from the debug adapter
/// has a name. When sending a source to the debug adapter this name is
/// optional.
>From f5775aea07a7a252d7a77cc984868af3ecb2d0d5 Mon Sep 17 00:00:00 2001
From: John Harrison <ash at greaterthaninfinity.com>
Date: Thu, 27 Mar 2025 09:10:43 -0700
Subject: [PATCH 5/6] Update lldb/tools/lldb-dap/Handler/RequestHandler.h
Co-authored-by: Jonas Devlieghere <jonas at devlieghere.com>
---
lldb/tools/lldb-dap/Handler/RequestHandler.h | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/lldb/tools/lldb-dap/Handler/RequestHandler.h b/lldb/tools/lldb-dap/Handler/RequestHandler.h
index 1d3b5103b20d7..7b0c82f42c249 100644
--- a/lldb/tools/lldb-dap/Handler/RequestHandler.h
+++ b/lldb/tools/lldb-dap/Handler/RequestHandler.h
@@ -49,7 +49,8 @@ class BaseRequestHandler {
virtual void operator()(const protocol::Request &request) const = 0;
- virtual llvm::SmallDenseSet<AdapterFeature, 1> GetSupportedFeatures() const {
+ using FeatureSet = llvm::SmallDenseSet<AdapterFeature, 1>;
+ virtual FeatureSet GetSupportedFeatures() const {
return {};
}
>From f88dbd65ad026c9e2d85d46ddb003bababbfb323 Mon Sep 17 00:00:00 2001
From: John Harrison <harjohn at google.com>
Date: Thu, 27 Mar 2025 09:21:42 -0700
Subject: [PATCH 6/6] Shortening the name of feature flags to remove 'support'.
---
lldb/tools/lldb-dap/DAP.cpp | 6 +-
.../Handler/InitializeRequestHandler.cpp | 5 +-
.../tools/lldb-dap/Handler/RequestHandler.cpp | 2 +-
lldb/tools/lldb-dap/Handler/RequestHandler.h | 80 +++++++++----------
.../lldb-dap/Protocol/ProtocolRequests.cpp | 22 +++--
.../lldb-dap/Protocol/ProtocolRequests.h | 20 ++---
.../tools/lldb-dap/Protocol/ProtocolTypes.cpp | 74 ++++++++---------
lldb/tools/lldb-dap/Protocol/ProtocolTypes.h | 74 ++++++++---------
8 files changed, 139 insertions(+), 144 deletions(-)
diff --git a/lldb/tools/lldb-dap/DAP.cpp b/lldb/tools/lldb-dap/DAP.cpp
index 5e443e4b4b612..23f0400c8bd4d 100644
--- a/lldb/tools/lldb-dap/DAP.cpp
+++ b/lldb/tools/lldb-dap/DAP.cpp
@@ -1150,9 +1150,9 @@ protocol::Capabilities DAP::GetCapabilities() {
// Supported capabilities that are not specific to a single request.
capabilities.supportedFeatures = {
- protocol::eAdapterFeatureSupportsLogPoints,
- protocol::eAdapterFeatureSupportsSteppingGranularity,
- protocol::eAdapterFeatureSupportsValueFormattingOptions,
+ protocol::eAdapterFeatureLogPoints,
+ protocol::eAdapterFeatureSteppingGranularity,
+ protocol::eAdapterFeatureValueFormattingOptions,
};
// Capabilities associated with specific requests.
diff --git a/lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp
index 6e96c76ac45fe..dc2252c90cc52 100644
--- a/lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp
@@ -270,7 +270,7 @@ llvm::Expected<InitializeResponseBody> InitializeRequestHandler::Run(
auto cmd = dap.debugger.GetCommandInterpreter().AddMultiwordCommand(
"lldb-dap", "Commands for managing lldb-dap.");
if (arguments.supportedFeatures.contains(
- eClientFeatureSupportsStartDebuggingRequest)) {
+ eClientFeatureStartDebuggingRequest)) {
cmd.AddCommand(
"start-debugging", new StartDebuggingRequestHandler(dap),
"Sends a startDebugging request from the debug adapter to the client "
@@ -282,8 +282,7 @@ llvm::Expected<InitializeResponseBody> InitializeRequestHandler::Run(
cmd.AddCommand("send-event", new SendEventRequestHandler(dap),
"Sends an DAP event to the client.");
- if (arguments.supportedFeatures.contains(
- eClientFeatureSupportsProgressReporting))
+ if (arguments.supportedFeatures.contains(eClientFeatureProgressReporting))
dap.progress_event_thread =
std::thread(ProgressEventThreadFunction, std::ref(dap));
diff --git a/lldb/tools/lldb-dap/Handler/RequestHandler.cpp b/lldb/tools/lldb-dap/Handler/RequestHandler.cpp
index 300a183fb4a1d..f067dfc5544fe 100644
--- a/lldb/tools/lldb-dap/Handler/RequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/RequestHandler.cpp
@@ -99,7 +99,7 @@ static llvm::Error RunInTerminal(DAP &dap,
const llvm::json::Object &launch_request,
const uint64_t timeout_seconds) {
if (!dap.clientFeatures.contains(
- protocol::eClientFeatureSupportsRunInTerminalRequest))
+ protocol::eClientFeatureRunInTerminalRequest))
return llvm::make_error<DAPError>("Cannot use runInTerminal, feature is "
"not supported by the connected client");
diff --git a/lldb/tools/lldb-dap/Handler/RequestHandler.h b/lldb/tools/lldb-dap/Handler/RequestHandler.h
index 7b0c82f42c249..396815b04c84a 100644
--- a/lldb/tools/lldb-dap/Handler/RequestHandler.h
+++ b/lldb/tools/lldb-dap/Handler/RequestHandler.h
@@ -49,10 +49,8 @@ class BaseRequestHandler {
virtual void operator()(const protocol::Request &request) const = 0;
- using FeatureSet = llvm::SmallDenseSet<AdapterFeature, 1>;
- virtual FeatureSet GetSupportedFeatures() const {
- return {};
- }
+ using FeatureSet = llvm::SmallDenseSet<AdapterFeature, 1>;
+ virtual FeatureSet GetSupportedFeatures() const { return {}; }
protected:
/// Helpers used by multiple request handlers.
@@ -180,8 +178,8 @@ class BreakpointLocationsRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "breakpointLocations"; }
- llvm::SmallDenseSet<AdapterFeature, 1> GetSupportedFeatures() const override {
- return {protocol::eAdapterFeatureSupportsBreakpointLocationsRequest};
+ FeatureSet GetSupportedFeatures() const override {
+ return {protocol::eAdapterFeatureBreakpointLocationsRequest};
}
void operator()(const llvm::json::Object &request) const override;
};
@@ -190,8 +188,8 @@ class CompletionsRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "completions"; }
- llvm::SmallDenseSet<AdapterFeature, 1> GetSupportedFeatures() const override {
- return {protocol::eAdapterFeatureSupportsCompletionsRequest};
+ FeatureSet GetSupportedFeatures() const override {
+ return {protocol::eAdapterFeatureCompletionsRequest};
}
void operator()(const llvm::json::Object &request) const override;
};
@@ -207,8 +205,8 @@ class ConfigurationDoneRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "configurationDone"; }
- llvm::SmallDenseSet<AdapterFeature, 1> GetSupportedFeatures() const override {
- return {protocol::eAdapterFeatureSupportsConfigurationDoneRequest};
+ FeatureSet GetSupportedFeatures() const override {
+ return {protocol::eAdapterFeatureConfigurationDoneRequest};
}
void operator()(const llvm::json::Object &request) const override;
};
@@ -219,8 +217,8 @@ class DisconnectRequestHandler
public:
using RequestHandler::RequestHandler;
static llvm::StringLiteral GetCommand() { return "disconnect"; }
- llvm::SmallDenseSet<AdapterFeature, 1> GetSupportedFeatures() const override {
- return {protocol::eAdapterFeatureSupportTerminateDebuggee};
+ FeatureSet GetSupportedFeatures() const override {
+ return {protocol::eAdapterFeatureTerminateDebuggee};
}
llvm::Expected<protocol::DisconnectResponse>
Run(const std::optional<protocol::DisconnectArguments> &args) const override;
@@ -231,8 +229,8 @@ class EvaluateRequestHandler : public LegacyRequestHandler {
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "evaluate"; }
void operator()(const llvm::json::Object &request) const override;
- llvm::SmallDenseSet<AdapterFeature, 1> GetSupportedFeatures() const override {
- return {protocol::eAdapterFeatureSupportsEvaluateForHovers};
+ FeatureSet GetSupportedFeatures() const override {
+ return {protocol::eAdapterFeatureEvaluateForHovers};
}
};
@@ -240,8 +238,8 @@ class ExceptionInfoRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "exceptionInfo"; }
- llvm::SmallDenseSet<AdapterFeature, 1> GetSupportedFeatures() const override {
- return {protocol::eAdapterFeatureSupportsExceptionInfoRequest};
+ FeatureSet GetSupportedFeatures() const override {
+ return {protocol::eAdapterFeatureExceptionInfoRequest};
}
void operator()(const llvm::json::Object &request) const override;
};
@@ -267,8 +265,8 @@ class RestartRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "restart"; }
- llvm::SmallDenseSet<AdapterFeature, 1> GetSupportedFeatures() const override {
- return {protocol::eAdapterFeatureSupportsRestartRequest};
+ FeatureSet GetSupportedFeatures() const override {
+ return {protocol::eAdapterFeatureRestartRequest};
}
void operator()(const llvm::json::Object &request) const override;
};
@@ -291,8 +289,8 @@ class StepInTargetsRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "stepInTargets"; }
- llvm::SmallDenseSet<AdapterFeature, 1> GetSupportedFeatures() const override {
- return {protocol::eAdapterFeatureSupportsStepInTargetsRequest};
+ FeatureSet GetSupportedFeatures() const override {
+ return {protocol::eAdapterFeatureStepInTargetsRequest};
}
void operator()(const llvm::json::Object &request) const override;
};
@@ -308,9 +306,9 @@ class SetBreakpointsRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "setBreakpoints"; }
- llvm::SmallDenseSet<AdapterFeature, 1> GetSupportedFeatures() const override {
- return {protocol::eAdapterFeatureSupportsConditionalBreakpoints,
- protocol::eAdapterFeatureSupportsHitConditionalBreakpoints};
+ FeatureSet GetSupportedFeatures() const override {
+ return {protocol::eAdapterFeatureConditionalBreakpoints,
+ protocol::eAdapterFeatureHitConditionalBreakpoints};
}
void operator()(const llvm::json::Object &request) const override;
};
@@ -319,8 +317,8 @@ class SetExceptionBreakpointsRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "setExceptionBreakpoints"; }
- llvm::SmallDenseSet<AdapterFeature, 1> GetSupportedFeatures() const override {
- return {protocol::eAdapterFeatureSupportsExceptionOptions};
+ FeatureSet GetSupportedFeatures() const override {
+ return {protocol::eAdapterFeatureExceptionOptions};
}
void operator()(const llvm::json::Object &request) const override;
};
@@ -329,8 +327,8 @@ class SetFunctionBreakpointsRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "setFunctionBreakpoints"; }
- llvm::SmallDenseSet<AdapterFeature, 1> GetSupportedFeatures() const override {
- return {protocol::eAdapterFeatureSupportsFunctionBreakpoints};
+ FeatureSet GetSupportedFeatures() const override {
+ return {protocol::eAdapterFeatureFunctionBreakpoints};
}
void operator()(const llvm::json::Object &request) const override;
};
@@ -347,8 +345,8 @@ class SetDataBreakpointsRequestHandler : public LegacyRequestHandler {
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "setDataBreakpoints"; }
void operator()(const llvm::json::Object &request) const override;
- llvm::SmallDenseSet<AdapterFeature, 1> GetSupportedFeatures() const override {
- return {protocol::eAdapterFeatureSupportsDataBreakpoints};
+ FeatureSet GetSupportedFeatures() const override {
+ return {protocol::eAdapterFeatureDataBreakpoints};
}
};
@@ -359,8 +357,8 @@ class SetInstructionBreakpointsRequestHandler : public LegacyRequestHandler {
return "setInstructionBreakpoints";
}
void operator()(const llvm::json::Object &request) const override;
- llvm::SmallDenseSet<AdapterFeature, 1> GetSupportedFeatures() const override {
- return {protocol::eAdapterFeatureSupportsInstructionBreakpoints};
+ FeatureSet GetSupportedFeatures() const override {
+ return {protocol::eAdapterFeatureInstructionBreakpoints};
}
};
@@ -375,8 +373,8 @@ class ModulesRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "modules"; }
- llvm::SmallDenseSet<AdapterFeature, 1> GetSupportedFeatures() const override {
- return {protocol::eAdapterFeatureSupportsModulesRequest};
+ FeatureSet GetSupportedFeatures() const override {
+ return {protocol::eAdapterFeatureModulesRequest};
}
void operator()(const llvm::json::Object &request) const override;
};
@@ -399,8 +397,8 @@ class SetVariableRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "setVariable"; }
- llvm::SmallDenseSet<AdapterFeature, 1> GetSupportedFeatures() const override {
- return {protocol::eAdapterFeatureSupportsSetVariable};
+ FeatureSet GetSupportedFeatures() const override {
+ return {protocol::eAdapterFeatureSetVariable};
}
void operator()(const llvm::json::Object &request) const override;
};
@@ -420,8 +418,8 @@ class StackTraceRequestHandler : public LegacyRequestHandler {
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "stackTrace"; }
void operator()(const llvm::json::Object &request) const override;
- llvm::SmallDenseSet<AdapterFeature, 1> GetSupportedFeatures() const override {
- return {protocol::eAdapterFeatureSupportsDelayedStackTraceLoading};
+ FeatureSet GetSupportedFeatures() const override {
+ return {protocol::eAdapterFeatureDelayedStackTraceLoading};
}
};
@@ -450,8 +448,8 @@ class DisassembleRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "disassemble"; }
- llvm::SmallDenseSet<AdapterFeature, 1> GetSupportedFeatures() const override {
- return {protocol::eAdapterFeatureSupportsDisassembleRequest};
+ FeatureSet GetSupportedFeatures() const override {
+ return {protocol::eAdapterFeatureDisassembleRequest};
}
void operator()(const llvm::json::Object &request) const override;
};
@@ -460,8 +458,8 @@ class ReadMemoryRequestHandler : public LegacyRequestHandler {
public:
using LegacyRequestHandler::LegacyRequestHandler;
static llvm::StringLiteral GetCommand() { return "readMemory"; }
- llvm::SmallDenseSet<AdapterFeature, 1> GetSupportedFeatures() const override {
- return {protocol::eAdapterFeatureSupportsReadMemoryRequest};
+ FeatureSet GetSupportedFeatures() const override {
+ return {protocol::eAdapterFeatureReadMemoryRequest};
}
void operator()(const llvm::json::Object &request) const override;
};
diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp
index 5a712124f72b1..9a613128739c2 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp
@@ -48,19 +48,17 @@ bool fromJSON(const llvm::json::Value &Params, PathFormat &PF,
}
static const llvm::StringMap<ClientFeature> ClientFeatureByKey{
- {"supportsVariableType", eClientFeatureSupportsVariableType},
- {"supportsVariablePaging", eClientFeatureSupportsVariablePaging},
- {"supportsRunInTerminalRequest",
- eClientFeatureSupportsRunInTerminalRequest},
- {"supportsMemoryReferences", eClientFeatureSupportsMemoryReferences},
- {"supportsProgressReporting", eClientFeatureSupportsProgressReporting},
- {"supportsInvalidatedEvent", eClientFeatureSupportsInvalidatedEvent},
- {"supportsMemoryEvent", eClientFeatureSupportsMemoryEvent},
+ {"supportsVariableType", eClientFeatureVariableType},
+ {"supportsVariablePaging", eClientFeatureVariablePaging},
+ {"supportsRunInTerminalRequest", eClientFeatureRunInTerminalRequest},
+ {"supportsMemoryReferences", eClientFeatureMemoryReferences},
+ {"supportsProgressReporting", eClientFeatureProgressReporting},
+ {"supportsInvalidatedEvent", eClientFeatureInvalidatedEvent},
+ {"supportsMemoryEvent", eClientFeatureMemoryEvent},
{"supportsArgsCanBeInterpretedByShell",
- eClientFeatureSupportsArgsCanBeInterpretedByShell},
- {"supportsStartDebuggingRequest",
- eClientFeatureSupportsStartDebuggingRequest},
- {"supportsANSIStyling", eClientFeatureSupportsANSIStyling}};
+ eClientFeatureArgsCanBeInterpretedByShell},
+ {"supportsStartDebuggingRequest", eClientFeatureStartDebuggingRequest},
+ {"supportsANSIStyling", eClientFeatureANSIStyling}};
bool fromJSON(const llvm::json::Value &Params, InitializeRequestArguments &IRA,
llvm::json::Path P) {
diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h
index d4d61db576994..c49a13711f8c7 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h
@@ -56,21 +56,21 @@ using DisconnectResponse = VoidResponse;
/// Features supported by DAP clients.
enum ClientFeature {
- eClientFeatureSupportsVariableType,
- eClientFeatureSupportsVariablePaging,
- eClientFeatureSupportsRunInTerminalRequest,
- eClientFeatureSupportsMemoryReferences,
- eClientFeatureSupportsProgressReporting,
- eClientFeatureSupportsInvalidatedEvent,
- eClientFeatureSupportsMemoryEvent,
+ eClientFeatureVariableType,
+ eClientFeatureVariablePaging,
+ eClientFeatureRunInTerminalRequest,
+ eClientFeatureMemoryReferences,
+ eClientFeatureProgressReporting,
+ eClientFeatureInvalidatedEvent,
+ eClientFeatureMemoryEvent,
/// Client supports the `argsCanBeInterpretedByShell` attribute on the
/// `runInTerminal` request.
- eClientFeatureSupportsArgsCanBeInterpretedByShell,
- eClientFeatureSupportsStartDebuggingRequest,
+ eClientFeatureArgsCanBeInterpretedByShell,
+ eClientFeatureStartDebuggingRequest,
/// The client will interpret ANSI escape sequences in the display of
/// `OutputEvent.output` and `Variable.value` fields when
/// `Capabilities.supportsANSIStyling` is also enabled.
- eClientFeatureSupportsANSIStyling,
+ eClientFeatureANSIStyling,
};
/// Format of paths reported by the debug adapter.
diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp
index a7cf8631ae431..d1dd9ad9c5fee 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp
@@ -125,79 +125,79 @@ json::Value toJSON(const BreakpointMode &BM) {
static llvm::StringLiteral ToString(AdapterFeature feature) {
switch (feature) {
- case eAdapterFeatureSupportsANSIStyling:
+ case eAdapterFeatureANSIStyling:
return "supportsANSIStyling";
- case eAdapterFeatureSupportsBreakpointLocationsRequest:
+ case eAdapterFeatureBreakpointLocationsRequest:
return "supportsBreakpointLocationsRequest";
- case eAdapterFeatureSupportsCancelRequest:
+ case eAdapterFeatureCancelRequest:
return "supportsCancelRequest";
- case eAdapterFeatureSupportsClipboardContext:
+ case eAdapterFeatureClipboardContext:
return "supportsClipboardContext";
- case eAdapterFeatureSupportsCompletionsRequest:
+ case eAdapterFeatureCompletionsRequest:
return "supportsCompletionsRequest";
- case eAdapterFeatureSupportsConditionalBreakpoints:
+ case eAdapterFeatureConditionalBreakpoints:
return "supportsConditionalBreakpoints";
- case eAdapterFeatureSupportsConfigurationDoneRequest:
+ case eAdapterFeatureConfigurationDoneRequest:
return "supportsConfigurationDoneRequest";
- case eAdapterFeatureSupportsDataBreakpointBytes:
+ case eAdapterFeatureDataBreakpointBytes:
return "supportsDataBreakpointBytes";
- case eAdapterFeatureSupportsDataBreakpoints:
+ case eAdapterFeatureDataBreakpoints:
return "supportsDataBreakpoints";
- case eAdapterFeatureSupportsDelayedStackTraceLoading:
+ case eAdapterFeatureDelayedStackTraceLoading:
return "supportsDelayedStackTraceLoading";
- case eAdapterFeatureSupportsDisassembleRequest:
+ case eAdapterFeatureDisassembleRequest:
return "supportsDisassembleRequest";
- case eAdapterFeatureSupportsEvaluateForHovers:
+ case eAdapterFeatureEvaluateForHovers:
return "supportsEvaluateForHovers";
- case eAdapterFeatureSupportsExceptionFilterOptions:
+ case eAdapterFeatureExceptionFilterOptions:
return "supportsExceptionFilterOptions";
- case eAdapterFeatureSupportsExceptionInfoRequest:
+ case eAdapterFeatureExceptionInfoRequest:
return "supportsExceptionInfoRequest";
- case eAdapterFeatureSupportsExceptionOptions:
+ case eAdapterFeatureExceptionOptions:
return "supportsExceptionOptions";
- case eAdapterFeatureSupportsFunctionBreakpoints:
+ case eAdapterFeatureFunctionBreakpoints:
return "supportsFunctionBreakpoints";
- case eAdapterFeatureSupportsGotoTargetsRequest:
+ case eAdapterFeatureGotoTargetsRequest:
return "supportsGotoTargetsRequest";
- case eAdapterFeatureSupportsHitConditionalBreakpoints:
+ case eAdapterFeatureHitConditionalBreakpoints:
return "supportsHitConditionalBreakpoints";
- case eAdapterFeatureSupportsInstructionBreakpoints:
+ case eAdapterFeatureInstructionBreakpoints:
return "supportsInstructionBreakpoints";
- case eAdapterFeatureSupportsLoadedSourcesRequest:
+ case eAdapterFeatureLoadedSourcesRequest:
return "supportsLoadedSourcesRequest";
- case eAdapterFeatureSupportsLogPoints:
+ case eAdapterFeatureLogPoints:
return "supportsLogPoints";
- case eAdapterFeatureSupportsModulesRequest:
+ case eAdapterFeatureModulesRequest:
return "supportsModulesRequest";
- case eAdapterFeatureSupportsReadMemoryRequest:
+ case eAdapterFeatureReadMemoryRequest:
return "supportsReadMemoryRequest";
- case eAdapterFeatureSupportsRestartFrame:
+ case eAdapterFeatureRestartFrame:
return "supportsRestartFrame";
- case eAdapterFeatureSupportsRestartRequest:
+ case eAdapterFeatureRestartRequest:
return "supportsRestartRequest";
- case eAdapterFeatureSupportsSetExpression:
+ case eAdapterFeatureSetExpression:
return "supportsSetExpression";
- case eAdapterFeatureSupportsSetVariable:
+ case eAdapterFeatureSetVariable:
return "supportsSetVariable";
- case eAdapterFeatureSupportsSingleThreadExecutionRequests:
+ case eAdapterFeatureSingleThreadExecutionRequests:
return "supportsSingleThreadExecutionRequests";
- case eAdapterFeatureSupportsStepBack:
+ case eAdapterFeatureStepBack:
return "supportsStepBack";
- case eAdapterFeatureSupportsStepInTargetsRequest:
+ case eAdapterFeatureStepInTargetsRequest:
return "supportsStepInTargetsRequest";
- case eAdapterFeatureSupportsSteppingGranularity:
+ case eAdapterFeatureSteppingGranularity:
return "supportsSteppingGranularity";
- case eAdapterFeatureSupportsTerminateRequest:
+ case eAdapterFeatureTerminateRequest:
return "supportsTerminateRequest";
- case eAdapterFeatureSupportsTerminateThreadsRequest:
+ case eAdapterFeatureTerminateThreadsRequest:
return "supportsTerminateThreadsRequest";
- case eAdapterFeatureSupportSuspendDebuggee:
+ case eAdapterFeatureSuspendDebuggee:
return "supportSuspendDebuggee";
- case eAdapterFeatureSupportsValueFormattingOptions:
+ case eAdapterFeatureValueFormattingOptions:
return "supportsValueFormattingOptions";
- case eAdapterFeatureSupportsWriteMemoryRequest:
+ case eAdapterFeatureWriteMemoryRequest:
return "supportsWriteMemoryRequest";
- case eAdapterFeatureSupportTerminateDebuggee:
+ case eAdapterFeatureTerminateDebuggee:
return "supportTerminateDebuggee";
}
}
diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h
index e7afb7f938ce9..934368aa2435f 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h
@@ -136,98 +136,98 @@ llvm::json::Value toJSON(const BreakpointMode &);
enum AdapterFeature {
/// The debug adapter supports ANSI escape sequences in styling of
/// `OutputEvent.output` and `Variable.value` fields.
- eAdapterFeatureSupportsANSIStyling,
+ eAdapterFeatureANSIStyling,
/// The debug adapter supports the `breakpointLocations` request.
- eAdapterFeatureSupportsBreakpointLocationsRequest,
+ eAdapterFeatureBreakpointLocationsRequest,
/// The debug adapter supports the `cancel` request.
- eAdapterFeatureSupportsCancelRequest,
+ eAdapterFeatureCancelRequest,
/// The debug adapter supports the `clipboard` context value in the
/// `evaluate` request.
- eAdapterFeatureSupportsClipboardContext,
+ eAdapterFeatureClipboardContext,
/// The debug adapter supports the `completions` request.
- eAdapterFeatureSupportsCompletionsRequest,
+ eAdapterFeatureCompletionsRequest,
/// The debug adapter supports conditional breakpoints.
- eAdapterFeatureSupportsConditionalBreakpoints,
+ eAdapterFeatureConditionalBreakpoints,
/// The debug adapter supports the `configurationDone` request.
- eAdapterFeatureSupportsConfigurationDoneRequest,
+ eAdapterFeatureConfigurationDoneRequest,
/// The debug adapter supports the `asAddress` and `bytes` fields in the
/// `dataBreakpointInfo` request.
- eAdapterFeatureSupportsDataBreakpointBytes,
+ eAdapterFeatureDataBreakpointBytes,
/// The debug adapter supports data breakpoints.
- eAdapterFeatureSupportsDataBreakpoints,
+ eAdapterFeatureDataBreakpoints,
/// The debug adapter supports the delayed loading of parts of the stack,
/// which requires that both the `startFrame` and `levels` arguments and the
/// `totalFrames` result of the `stackTrace` request are supported.
- eAdapterFeatureSupportsDelayedStackTraceLoading,
+ eAdapterFeatureDelayedStackTraceLoading,
/// The debug adapter supports the `disassemble` request.
- eAdapterFeatureSupportsDisassembleRequest,
+ eAdapterFeatureDisassembleRequest,
/// The debug adapter supports a (side effect free) `evaluate` request for
/// data hovers.
- eAdapterFeatureSupportsEvaluateForHovers,
+ eAdapterFeatureEvaluateForHovers,
/// The debug adapter supports `filterOptions` as an argument on the
/// `setExceptionBreakpoints` request.
- eAdapterFeatureSupportsExceptionFilterOptions,
+ eAdapterFeatureExceptionFilterOptions,
/// The debug adapter supports the `exceptionInfo` request.
- eAdapterFeatureSupportsExceptionInfoRequest,
+ eAdapterFeatureExceptionInfoRequest,
/// The debug adapter supports `exceptionOptions` on the
/// `setExceptionBreakpoints` request.
- eAdapterFeatureSupportsExceptionOptions,
+ eAdapterFeatureExceptionOptions,
/// The debug adapter supports function breakpoints.
- eAdapterFeatureSupportsFunctionBreakpoints,
+ eAdapterFeatureFunctionBreakpoints,
/// The debug adapter supports the `gotoTargets` request.
- eAdapterFeatureSupportsGotoTargetsRequest,
+ eAdapterFeatureGotoTargetsRequest,
/// The debug adapter supports breakpoints that break execution after a
/// specified number of hits.
- eAdapterFeatureSupportsHitConditionalBreakpoints,
+ eAdapterFeatureHitConditionalBreakpoints,
/// The debug adapter supports adding breakpoints based on instruction
/// references.
- eAdapterFeatureSupportsInstructionBreakpoints,
+ eAdapterFeatureInstructionBreakpoints,
/// The debug adapter supports the `loadedSources` request.
- eAdapterFeatureSupportsLoadedSourcesRequest,
+ eAdapterFeatureLoadedSourcesRequest,
/// The debug adapter supports log points by interpreting the `logMessage`
/// attribute of the `SourceBreakpoint`.
- eAdapterFeatureSupportsLogPoints,
+ eAdapterFeatureLogPoints,
/// The debug adapter supports the `modules` request.
- eAdapterFeatureSupportsModulesRequest,
+ eAdapterFeatureModulesRequest,
/// The debug adapter supports the `readMemory` request.
- eAdapterFeatureSupportsReadMemoryRequest,
+ eAdapterFeatureReadMemoryRequest,
/// The debug adapter supports restarting a frame.
- eAdapterFeatureSupportsRestartFrame,
+ eAdapterFeatureRestartFrame,
/// The debug adapter supports the `restart` request. In this case a client
/// should not implement `restart` by terminating and relaunching the
/// adapter but by calling the `restart` request.
- eAdapterFeatureSupportsRestartRequest,
+ eAdapterFeatureRestartRequest,
/// The debug adapter supports the `setExpression` request.
- eAdapterFeatureSupportsSetExpression,
+ eAdapterFeatureSetExpression,
/// The debug adapter supports setting a variable to a value.
- eAdapterFeatureSupportsSetVariable,
+ eAdapterFeatureSetVariable,
/// The debug adapter supports the `singleThread` property on the execution
/// requests (`continue`, `next`, `stepIn`, `stepOut`, `reverseContinue`,
/// `stepBack`).
- eAdapterFeatureSupportsSingleThreadExecutionRequests,
+ eAdapterFeatureSingleThreadExecutionRequests,
/// The debug adapter supports stepping back via the `stepBack` and
/// `reverseContinue` requests.
- eAdapterFeatureSupportsStepBack,
+ eAdapterFeatureStepBack,
/// The debug adapter supports the `stepInTargets` request.
- eAdapterFeatureSupportsStepInTargetsRequest,
+ eAdapterFeatureStepInTargetsRequest,
/// The debug adapter supports stepping granularities (argument
/// `granularity`) for the stepping requests.
- eAdapterFeatureSupportsSteppingGranularity,
+ eAdapterFeatureSteppingGranularity,
/// The debug adapter supports the `terminate` request.
- eAdapterFeatureSupportsTerminateRequest,
+ eAdapterFeatureTerminateRequest,
/// The debug adapter supports the `terminateThreads` request.
- eAdapterFeatureSupportsTerminateThreadsRequest,
+ eAdapterFeatureTerminateThreadsRequest,
/// The debug adapter supports the `suspendDebuggee` attribute on the
/// `disconnect` request.
- eAdapterFeatureSupportSuspendDebuggee,
+ eAdapterFeatureSuspendDebuggee,
/// The debug adapter supports a `format` attribute on the `stackTrace`,
/// `variables`, and `evaluate` requests.
- eAdapterFeatureSupportsValueFormattingOptions,
+ eAdapterFeatureValueFormattingOptions,
/// The debug adapter supports the `writeMemory` request.
- eAdapterFeatureSupportsWriteMemoryRequest,
+ eAdapterFeatureWriteMemoryRequest,
/// The debug adapter supports the `terminateDebuggee` attribute on the
/// `disconnect` request.
- eAdapterFeatureSupportTerminateDebuggee,
+ eAdapterFeatureTerminateDebuggee,
};
/// Information about the capabilities of a debug adapter.
More information about the lldb-commits
mailing list