[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
Fri Mar 28 09:08:09 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/7] [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/7] 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/7] 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/7] 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/7] 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/7] 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.

>From 8791afa78c99d1e7743d50399e4f57f000ebfc1f Mon Sep 17 00:00:00 2001
From: John Harrison <harjohn at google.com>
Date: Fri, 28 Mar 2025 09:07:51 -0700
Subject: [PATCH 7/7] Adjusting whitespace in a comment.

---
 lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp
index dc2252c90cc52..e7c565aad13a3 100644
--- a/lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp
@@ -254,7 +254,7 @@ llvm::Expected<InitializeResponseBody> InitializeRequestHandler::Run(
 
   // 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 .
+  // changing its behavior.
   if (arguments.lldbExtSourceInitFile.value_or(true)) {
     dap.debugger.SkipLLDBInitFiles(false);
     dap.debugger.SkipAppInitFiles(false);



More information about the lldb-commits mailing list