Skip to content

[lldb-dap] Move request capabilities into request handlers (NFC) #131943

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 19, 2025

Conversation

JDevlieghere
Copy link
Member

This distributes the registration of request related capabilities to the corresponding request handler. Global and unsupported capabilities are registered at the DAP level.

@llvmbot
Copy link
Member

llvmbot commented Mar 19, 2025

@llvm/pr-subscribers-lldb

Author: Jonas Devlieghere (JDevlieghere)

Changes

This distributes the registration of request related capabilities to the corresponding request handler. Global and unsupported capabilities are registered at the DAP level.


Full diff: https://github.com/llvm/llvm-project/pull/131943.diff

4 Files Affected:

  • (modified) lldb/tools/lldb-dap/DAP.cpp (+29)
  • (modified) lldb/tools/lldb-dap/DAP.h (+3)
  • (modified) lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp (+8-75)
  • (modified) lldb/tools/lldb-dap/Handler/RequestHandler.h (+42)
diff --git a/lldb/tools/lldb-dap/DAP.cpp b/lldb/tools/lldb-dap/DAP.cpp
index a1e2187288768..cab33c640b684 100644
--- a/lldb/tools/lldb-dap/DAP.cpp
+++ b/lldb/tools/lldb-dap/DAP.cpp
@@ -1145,4 +1145,33 @@ lldb::SBValue Variables::FindVariable(uint64_t variablesReference,
   return variable;
 }
 
+llvm::StringMap<bool> DAP::GetCapabilities() {
+  llvm::StringMap<bool> 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;
+
+  // Unsupported capabilities.
+  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();
+  }
+
+  return capabilities;
+}
+
 } // namespace lldb_dap
diff --git a/lldb/tools/lldb-dap/DAP.h b/lldb/tools/lldb-dap/DAP.h
index 4c57f9fef3d89..9a823c2d04fe7 100644
--- a/lldb/tools/lldb-dap/DAP.h
+++ b/lldb/tools/lldb-dap/DAP.h
@@ -364,6 +364,9 @@ struct DAP {
     request_handlers[Handler::getCommand()] = std::make_unique<Handler>(*this);
   }
 
+  /// Return a key-value list of capabilities.
+  llvm::StringMap<bool> 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 3262b70042a0e..442fad52d51e0 100644
--- a/lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp
@@ -13,6 +13,7 @@
 #include "lldb/API/SBEvent.h"
 #include "lldb/API/SBListener.h"
 #include "lldb/API/SBStream.h"
+#include "llvm/Support/raw_ostream.h"
 
 using namespace lldb;
 
@@ -377,49 +378,17 @@ void InitializeRequestHandler::operator()(
   // process and more.
   dap.event_thread = std::thread(EventThreadFunction, std::ref(dap));
 
-  // The debug adapter supports the configurationDoneRequest.
-  body.try_emplace("supportsConfigurationDoneRequest", true);
-  // The debug adapter supports function breakpoints.
-  body.try_emplace("supportsFunctionBreakpoints", true);
-  // The debug adapter supports conditional breakpoints.
-  body.try_emplace("supportsConditionalBreakpoints", true);
-  // The debug adapter supports breakpoints that break execution after a
-  // specified number of hits.
-  body.try_emplace("supportsHitConditionalBreakpoints", true);
-  // The debug adapter supports a (side effect free) evaluate request for
-  // data hovers.
-  body.try_emplace("supportsEvaluateForHovers", true);
+  llvm::StringMap<bool> capabilities = dap.GetCapabilities();
+  for (auto &kv : capabilities) {
+    llvm::outs() << kv.getKey() << ": " << kv.getValue() << '\n';
+    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) {
+  for (const auto &exc_bp : *dap.exception_breakpoints)
     filters.emplace_back(CreateExceptionBreakpointFilter(exc_bp));
-  }
   body.try_emplace("exceptionBreakpointFilters", std::move(filters));
-  // The debug adapter supports launching a debugee in intergrated VSCode
-  // terminal.
-  body.try_emplace("supportsRunInTerminalRequest", true);
-  // The debug adapter supports stepping back via the stepBack and
-  // reverseContinue requests.
-  body.try_emplace("supportsStepBack", false);
-  // The debug adapter supports setting a variable to a value.
-  body.try_emplace("supportsSetVariable", true);
-  // The debug adapter supports restarting a frame.
-  body.try_emplace("supportsRestartFrame", false);
-  // The debug adapter supports the gotoTargetsRequest.
-  body.try_emplace("supportsGotoTargetsRequest", false);
-  // The debug adapter supports the stepInTargetsRequest.
-  body.try_emplace("supportsStepInTargetsRequest", true);
-  // The debug adapter supports the completions request.
-  body.try_emplace("supportsCompletionsRequest", true);
-  // The debug adapter supports the disassembly request.
-  body.try_emplace("supportsDisassembleRequest", true);
-  // The debug adapter supports the `breakpointLocations` request.
-  body.try_emplace("supportsBreakpointLocationsRequest", true);
-  // The debug adapter supports stepping granularities (argument `granularity`)
-  // for the stepping requests.
-  body.try_emplace("supportsSteppingGranularity", true);
-  // The debug adapter support for instruction breakpoint.
-  body.try_emplace("supportsInstructionBreakpoints", true);
 
   llvm::json::Array completion_characters;
   completion_characters.emplace_back(".");
@@ -428,42 +397,6 @@ void InitializeRequestHandler::operator()(
   body.try_emplace("completionTriggerCharacters",
                    std::move(completion_characters));
 
-  // The debug adapter supports the modules request.
-  body.try_emplace("supportsModulesRequest", true);
-  // The set of additional module information exposed by the debug adapter.
-  //   body.try_emplace("additionalModuleColumns"] = ColumnDescriptor
-  // Checksum algorithms supported by the debug adapter.
-  //   body.try_emplace("supportedChecksumAlgorithms"] = ChecksumAlgorithm
-  // The debug adapter supports the RestartRequest. In this case a client
-  // should not implement 'restart' by terminating and relaunching the adapter
-  // but by calling the RestartRequest.
-  body.try_emplace("supportsRestartRequest", true);
-  // The debug adapter supports 'exceptionOptions' on the
-  // setExceptionBreakpoints request.
-  body.try_emplace("supportsExceptionOptions", true);
-  // The debug adapter supports a 'format' attribute on the stackTraceRequest,
-  // variablesRequest, and evaluateRequest.
-  body.try_emplace("supportsValueFormattingOptions", true);
-  // The debug adapter supports the exceptionInfo request.
-  body.try_emplace("supportsExceptionInfoRequest", true);
-  // The debug adapter supports the 'terminateDebuggee' attribute on the
-  // 'disconnect' request.
-  body.try_emplace("supportTerminateDebuggee", true);
-  // 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.
-  body.try_emplace("supportsDelayedStackTraceLoading", true);
-  // The debug adapter supports the 'loadedSources' request.
-  body.try_emplace("supportsLoadedSourcesRequest", false);
-  // The debug adapter supports sending progress reporting events.
-  body.try_emplace("supportsProgressReporting", true);
-  // The debug adapter supports 'logMessage' in breakpoint.
-  body.try_emplace("supportsLogPoints", true);
-  // The debug adapter supports data watchpoints.
-  body.try_emplace("supportsDataBreakpoints", true);
-  // The debug adapter supports the `readMemory` request.
-  body.try_emplace("supportsReadMemoryRequest", true);
-
   // Put in non-DAP specification lldb specific information.
   llvm::json::Object lldb_json;
   lldb_json.try_emplace("version", dap.debugger.GetVersionString());
diff --git a/lldb/tools/lldb-dap/Handler/RequestHandler.h b/lldb/tools/lldb-dap/Handler/RequestHandler.h
index c9bcf15933c33..4856e199ea6b8 100644
--- a/lldb/tools/lldb-dap/Handler/RequestHandler.h
+++ b/lldb/tools/lldb-dap/Handler/RequestHandler.h
@@ -45,6 +45,8 @@ class BaseRequestHandler {
 
   virtual void operator()(const protocol::Request &request) const = 0;
 
+  virtual llvm::StringMap<bool> GetCapabilities() const { return {}; }
+
 protected:
   /// Helpers used by multiple request handlers.
   /// FIXME: Move these into the DAP class?
@@ -153,6 +155,9 @@ class BreakpointLocationsRequestHandler : public LegacyRequestHandler {
 public:
   using LegacyRequestHandler::LegacyRequestHandler;
   static llvm::StringLiteral getCommand() { return "breakpointLocations"; }
+  llvm::StringMap<bool> GetCapabilities() const override {
+    return {{"supportsBreakpointLocationsRequest", true}};
+  }
   void operator()(const llvm::json::Object &request) const override;
 };
 
@@ -160,6 +165,9 @@ class CompletionsRequestHandler : public LegacyRequestHandler {
 public:
   using LegacyRequestHandler::LegacyRequestHandler;
   static llvm::StringLiteral getCommand() { return "completions"; }
+  llvm::StringMap<bool> GetCapabilities() const override {
+    return {{"supportsCompletionsRequest", true}};
+  }
   void operator()(const llvm::json::Object &request) const override;
 };
 
@@ -174,6 +182,9 @@ class ConfigurationDoneRequestHandler : public LegacyRequestHandler {
 public:
   using LegacyRequestHandler::LegacyRequestHandler;
   static llvm::StringLiteral getCommand() { return "configurationDone"; }
+  llvm::StringMap<bool> GetCapabilities() const override {
+    return {{"supportsConfigurationDoneRequest", true}};
+  }
   void operator()(const llvm::json::Object &request) const override;
 };
 
@@ -198,6 +209,9 @@ class ExceptionInfoRequestHandler : public LegacyRequestHandler {
 public:
   using LegacyRequestHandler::LegacyRequestHandler;
   static llvm::StringLiteral getCommand() { return "exceptionInfo"; }
+  llvm::StringMap<bool> GetCapabilities() const override {
+    return {{"supportsExceptionInfoRequest", true}};
+  }
   void operator()(const llvm::json::Object &request) const override;
 };
 
@@ -205,6 +219,9 @@ class InitializeRequestHandler : public LegacyRequestHandler {
 public:
   using LegacyRequestHandler::LegacyRequestHandler;
   static llvm::StringLiteral getCommand() { return "initialize"; }
+  llvm::StringMap<bool> GetCapabilities() const override {
+    return {{"supportsRunInTerminalRequest", true}};
+  }
   void operator()(const llvm::json::Object &request) const override;
 };
 
@@ -219,6 +236,9 @@ class RestartRequestHandler : public LegacyRequestHandler {
 public:
   using LegacyRequestHandler::LegacyRequestHandler;
   static llvm::StringLiteral getCommand() { return "restart"; }
+  llvm::StringMap<bool> GetCapabilities() const override {
+    return {{"supportsRestartRequest", true}};
+  }
   void operator()(const llvm::json::Object &request) const override;
 };
 
@@ -240,6 +260,9 @@ class StepInTargetsRequestHandler : public LegacyRequestHandler {
 public:
   using LegacyRequestHandler::LegacyRequestHandler;
   static llvm::StringLiteral getCommand() { return "stepInTargets"; }
+  llvm::StringMap<bool> GetCapabilities() const override {
+    return {{"supportsStepInTargetsRequest", true}};
+  }
   void operator()(const llvm::json::Object &request) const override;
 };
 
@@ -254,6 +277,10 @@ 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}};
+  }
   void operator()(const llvm::json::Object &request) const override;
 };
 
@@ -268,6 +295,9 @@ class SetFunctionBreakpointsRequestHandler : public LegacyRequestHandler {
 public:
   using LegacyRequestHandler::LegacyRequestHandler;
   static llvm::StringLiteral getCommand() { return "setFunctionBreakpoints"; }
+  llvm::StringMap<bool> GetCapabilities() const override {
+    return {{"supportsFunctionBreakpoints", true}};
+  }
   void operator()(const llvm::json::Object &request) const override;
 };
 
@@ -305,6 +335,9 @@ class ModulesRequestHandler : public LegacyRequestHandler {
 public:
   using LegacyRequestHandler::LegacyRequestHandler;
   static llvm::StringLiteral getCommand() { return "modules"; }
+  llvm::StringMap<bool> GetCapabilities() const override {
+    return {{"supportsModulesRequest", true}};
+  }
   void operator()(const llvm::json::Object &request) const override;
 };
 
@@ -326,6 +359,9 @@ class SetVariableRequestHandler : public LegacyRequestHandler {
 public:
   using LegacyRequestHandler::LegacyRequestHandler;
   static llvm::StringLiteral getCommand() { return "setVariable"; }
+  llvm::StringMap<bool> GetCapabilities() const override {
+    return {{"supportsSetVariable", true}};
+  }
   void operator()(const llvm::json::Object &request) const override;
 };
 
@@ -371,6 +407,9 @@ class DisassembleRequestHandler : public LegacyRequestHandler {
 public:
   using LegacyRequestHandler::LegacyRequestHandler;
   static llvm::StringLiteral getCommand() { return "disassemble"; }
+  llvm::StringMap<bool> GetCapabilities() const override {
+    return {{"supportsDisassembleRequest", true}};
+  }
   void operator()(const llvm::json::Object &request) const override;
 };
 
@@ -378,6 +417,9 @@ class ReadMemoryRequestHandler : public LegacyRequestHandler {
 public:
   using LegacyRequestHandler::LegacyRequestHandler;
   static llvm::StringLiteral getCommand() { return "readMemory"; }
+  llvm::StringMap<bool> GetCapabilities() const override {
+    return {{"supportsReadMemoryRequest", true}};
+  }
   void operator()(const llvm::json::Object &request) const override;
 };
 

Comment on lines +1152 to +1160
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;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm sure some of these could be associated with a specific request handler. Let me know if anyone feels strongly about moving any of these.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a lot of those are general enough (like LogPoints that spans all the breakpoint types) that it makes sense to leave them as top level capabilities.

This distributes the registration of request related capabilities to the
corresponding request handler. Global and unsupported capabilities are
registered at the DAP level.
@JDevlieghere JDevlieghere force-pushed the lldb-dap-capabilities branch from f2d2cf9 to c9770d1 Compare March 19, 2025 00:49
@JDevlieghere JDevlieghere merged commit 4088557 into llvm:main Mar 19, 2025
6 of 9 checks passed
@JDevlieghere JDevlieghere deleted the lldb-dap-capabilities branch March 19, 2025 02:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants