-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[lldb-dap] Creating an API for sending custom dap events from lldb-dap. #112384
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
Conversation
@llvm/pr-subscribers-lldb Author: John Harrison (ashgti) ChangesCustom DAP events can be detected using https://code.visualstudio.com/api/references/vscode-api#debug.onDidReceiveDebugSessionCustomEvent. This API allows an lldb python script to send custom events to the DAP client to allow extensions to handle these custom events. Full diff: https://github.com/llvm/llvm-project/pull/112384.diff 8 Files Affected:
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 b095171d8fd1a4..a43dd1aa7b9496 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
@@ -1230,7 +1230,7 @@ def run_vscode(dbg, args, options):
def main():
parser = optparse.OptionParser(
description=(
- "A testing framework for the Visual Studio Code Debug " "Adaptor protocol"
+ "A testing framework for the Visual Studio Code Debug Adaptor protocol"
)
)
diff --git a/lldb/test/API/tools/lldb-dap/custom-event/Makefile b/lldb/test/API/tools/lldb-dap/custom-event/Makefile
new file mode 100644
index 00000000000000..10495940055b63
--- /dev/null
+++ b/lldb/test/API/tools/lldb-dap/custom-event/Makefile
@@ -0,0 +1,3 @@
+C_SOURCES := main.c
+
+include Makefile.rules
diff --git a/lldb/test/API/tools/lldb-dap/custom-event/TestDAP_customEvent.py b/lldb/test/API/tools/lldb-dap/custom-event/TestDAP_customEvent.py
new file mode 100644
index 00000000000000..2ae02b09c9f0fc
--- /dev/null
+++ b/lldb/test/API/tools/lldb-dap/custom-event/TestDAP_customEvent.py
@@ -0,0 +1,46 @@
+"""
+Test lldb-dap custom-event integration.
+"""
+
+import json
+
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+import lldbdap_testcase
+
+
+class TestDAP_customEvent(lldbdap_testcase.DAPTestCaseBase):
+ def test_custom_event(self):
+ """
+ Test sending a custom event.
+ """
+ program = self.getBuildArtifact("a.out")
+ source = "main.c"
+ custom_event_body = {
+ "key": 321,
+ "arr": [True],
+ }
+ self.build_and_launch(
+ program,
+ stopCommands=[
+ "lldb-dap custom-event my-custom-event-no-body",
+ "lldb-dap custom-event my-custom-event '{}'".format(
+ json.dumps(custom_event_body)
+ ),
+ ],
+ )
+
+ breakpoint_line = line_number(source, "// breakpoint")
+
+ self.set_source_breakpoints(source, [breakpoint_line])
+ self.continue_to_next_stop()
+
+ custom_event = self.dap_server.wait_for_event(
+ filter=["my-custom-event-no-body"]
+ )
+ self.assertEquals(custom_event["event"], "my-custom-event-no-body")
+ self.assertIsNone(custom_event.get("body", None))
+
+ custom_event = self.dap_server.wait_for_event(filter=["my-custom-event"])
+ self.assertEquals(custom_event["event"], "my-custom-event")
+ self.assertEquals(custom_event["body"], custom_event_body)
diff --git a/lldb/test/API/tools/lldb-dap/custom-event/main.c b/lldb/test/API/tools/lldb-dap/custom-event/main.c
new file mode 100644
index 00000000000000..27bc22b94794b6
--- /dev/null
+++ b/lldb/test/API/tools/lldb-dap/custom-event/main.c
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+int main(int argc, char const *argv[]) {
+ printf("example\n"); // breakpoint 1
+ return 0;
+}
diff --git a/lldb/test/API/tools/lldb-dap/startDebugging/TestDAP_startDebugging.py b/lldb/test/API/tools/lldb-dap/startDebugging/TestDAP_startDebugging.py
index fd48e69cae5e25..fd452d91e472bd 100644
--- a/lldb/test/API/tools/lldb-dap/startDebugging/TestDAP_startDebugging.py
+++ b/lldb/test/API/tools/lldb-dap/startDebugging/TestDAP_startDebugging.py
@@ -1,12 +1,10 @@
"""
-Test lldb-dap startDebugging reverse request
+Test lldb-dap start-debugging reverse requests.
"""
-import dap_server
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
-from lldbsuite.test import lldbutil
import lldbdap_testcase
@@ -25,7 +23,7 @@ def test_startDebugging(self):
self.set_source_breakpoints(source, [breakpoint_line])
self.continue_to_next_stop()
self.dap_server.request_evaluate(
- "`lldb-dap startDebugging attach '{\"pid\":321}'", context="repl"
+ "`lldb-dap start-debugging attach '{\"pid\":321}'", context="repl"
)
self.continue_to_exit()
diff --git a/lldb/tools/lldb-dap/DAP.cpp b/lldb/tools/lldb-dap/DAP.cpp
index 6012ee52110b73..b8887ac367f44f 100644
--- a/lldb/tools/lldb-dap/DAP.cpp
+++ b/lldb/tools/lldb-dap/DAP.cpp
@@ -863,42 +863,35 @@ int64_t Variables::InsertExpandableVariable(lldb::SBValue variable,
bool StartDebuggingRequestHandler::DoExecute(
lldb::SBDebugger debugger, char **command,
lldb::SBCommandReturnObject &result) {
- // Command format like: `startDebugging <launch|attach> <configuration>`
+ // Command format like: `start-debugging <launch|attach> <configuration>`
if (!command) {
- result.SetError("Invalid use of startDebugging");
- result.SetStatus(lldb::eReturnStatusFailed);
+ result.SetError("Invalid use of start-debugging, expected format "
+ "`start-debugging <launch|attach> <configuration>`.");
return false;
}
if (!command[0] || llvm::StringRef(command[0]).empty()) {
- result.SetError("startDebugging request type missing.");
- result.SetStatus(lldb::eReturnStatusFailed);
+ result.SetError("start-debugging request type missing.");
return false;
}
if (!command[1] || llvm::StringRef(command[1]).empty()) {
- result.SetError("configuration missing.");
- result.SetStatus(lldb::eReturnStatusFailed);
+ result.SetError("start-debugging debug configuration missing.");
return false;
}
llvm::StringRef request{command[0]};
std::string raw_configuration{command[1]};
- int i = 2;
- while (command[i]) {
- raw_configuration.append(" ").append(command[i]);
- }
-
llvm::Expected<llvm::json::Value> configuration =
llvm::json::parse(raw_configuration);
if (!configuration) {
llvm::Error err = configuration.takeError();
- std::string msg =
- "Failed to parse json configuration: " + llvm::toString(std::move(err));
+ std::string msg = "Failed to parse json configuration: " +
+ llvm::toString(std::move(err)) + "\n\n" +
+ raw_configuration;
result.SetError(msg.c_str());
- result.SetStatus(lldb::eReturnStatusFailed);
return false;
}
@@ -966,6 +959,44 @@ bool ReplModeRequestHandler::DoExecute(lldb::SBDebugger debugger,
return true;
}
+// Sends a custom DAP event with an optional body.
+//
+// See
+// https://code.visualstudio.com/api/references/vscode-api#debug.onDidReceiveDebugSessionCustomEvent
+bool CustomDAPEventRequestHandler::DoExecute(
+ lldb::SBDebugger debugger, char **command,
+ lldb::SBCommandReturnObject &result) {
+ // Command format like: `custom-event <name> <body>?`
+ if (!command || !command[0] || llvm::StringRef(command[0]).empty()) {
+ result.SetError("Invalid use of custom-event, expected format "
+ "`custom-event <name> <body>?`.");
+ return false;
+ }
+
+ llvm::StringRef name{command[0]};
+ llvm::json::Object event(CreateEventObject(name));
+
+ if (command[1] && !llvm::StringRef(command[1]).empty()) {
+ llvm::StringRef raw_body{command[1]};
+
+ llvm::Expected<llvm::json::Value> body = llvm::json::parse(raw_body);
+
+ if (!body) {
+ llvm::Error err = body.takeError();
+ std::string msg = "Failed to parse custom event body: " +
+ llvm::toString(std::move(err));
+ result.SetError(msg.c_str());
+ return false;
+ }
+
+ event.try_emplace("body", std::move(*body));
+ }
+
+ g_dap.SendJSON(llvm::json::Value(std::move(event)));
+ result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
+ return true;
+}
+
void DAP::SetFrameFormat(llvm::StringRef format) {
if (format.empty())
return;
diff --git a/lldb/tools/lldb-dap/DAP.h b/lldb/tools/lldb-dap/DAP.h
index f4fdec6e895ad1..92108f8bbe86c3 100644
--- a/lldb/tools/lldb-dap/DAP.h
+++ b/lldb/tools/lldb-dap/DAP.h
@@ -150,6 +150,11 @@ struct ReplModeRequestHandler : public lldb::SBCommandPluginInterface {
lldb::SBCommandReturnObject &result) override;
};
+struct CustomDAPEventRequestHandler : public lldb::SBCommandPluginInterface {
+ bool DoExecute(lldb::SBDebugger debugger, char **command,
+ lldb::SBCommandReturnObject &result) override;
+};
+
struct DAP {
std::string debug_adaptor_path;
InputStream input;
diff --git a/lldb/tools/lldb-dap/lldb-dap.cpp b/lldb/tools/lldb-dap/lldb-dap.cpp
index c5c4b09f15622b..d3adc8f7fbcd35 100644
--- a/lldb/tools/lldb-dap/lldb-dap.cpp
+++ b/lldb/tools/lldb-dap/lldb-dap.cpp
@@ -1629,13 +1629,15 @@ void request_initialize(const llvm::json::Object &request) {
"lldb-dap", "Commands for managing lldb-dap.");
if (GetBoolean(arguments, "supportsStartDebuggingRequest", false)) {
cmd.AddCommand(
- "startDebugging", new StartDebuggingRequestHandler(),
+ "start-debugging", new StartDebuggingRequestHandler(),
"Sends a startDebugging request from the debug adapter to the client "
"to start a child debug session of the same type as the caller.");
}
cmd.AddCommand(
"repl-mode", new ReplModeRequestHandler(),
"Get or set the repl behavior of lldb-dap evaluation requests.");
+ cmd.AddCommand("custom-event", new CustomDAPEventRequestHandler(),
+ "Fires a custom lldb-dap event.");
g_dap.progress_event_thread = std::thread(ProgressEventThreadFunction);
|
0ffb658
to
5ec5d35
Compare
be42193
to
61f5407
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks pretty good. Just a minor nit
lldb/tools/lldb-dap/lldb-dap.cpp
Outdated
@@ -1896,6 +1896,8 @@ void request_initialize(const llvm::json::Object &request) { | |||
cmd.AddCommand( | |||
"repl-mode", new ReplModeRequestHandler(), | |||
"Get or set the repl behavior of lldb-dap evaluation requests."); | |||
cmd.AddCommand("custom-event", new CustomDAPEventRequestHandler(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what about custom-dap-event?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The command is in the lldb-dap
command group, so I think that would become a bit redundant as lldb-dap custom-dap-event
, but with vogelsgesang's comment below, how about lldb-dap send-event
?
✅ With the latest revision this PR passed the C/C++ code formatter. |
✅ With the latest revision this PR passed the Python code formatter. |
Custom DAP events can be detected using https://code.visualstudio.com/api/references/vscode-api#debug.onDidReceiveDebugSessionCustomEvent. This API allows an lldb python script to send custom events to the DAP client to allow extensions to handle these custom events.
…nt` and implemented a check for stateful internal events.
732bf29
to
fcd79e1
Compare
…db-dap. (llvm#112384) Custom DAP events can be detected using https://code.visualstudio.com/api/references/vscode-api#debug.onDidReceiveDebugSessionCustomEvent. This API allows an lldb python script to send events to the DAP client to allow extensions to handle these custom events. (cherry picked from commit c5c11f3)
Custom DAP events can be detected using https://code.visualstudio.com/api/references/vscode-api#debug.onDidReceiveDebugSessionCustomEvent.
This API allows an lldb python script to send custom events to the DAP client to allow extensions to handle these custom events.