https://github.com/ashgti created https://github.com/llvm/llvm-project/pull/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 custom events to the DAP client to allow extensions to handle these custom events. >From 0ffb658030e1ec70545115bd32e6e53c9a486969 Mon Sep 17 00:00:00 2001 From: John Harrison <harj...@google.com> Date: Mon, 14 Oct 2024 14:52:51 -0700 Subject: [PATCH] [lldb-dap] Creating an API for sending custom dap events from lldb-dap. 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. --- .../test/tools/lldb-dap/dap_server.py | 2 +- .../API/tools/lldb-dap/custom-event/Makefile | 3 + .../custom-event/TestDAP_customEvent.py | 46 ++++++++++++++ .../API/tools/lldb-dap/custom-event/main.c | 6 ++ .../startDebugging/TestDAP_startDebugging.py | 6 +- lldb/tools/lldb-dap/DAP.cpp | 61 ++++++++++++++----- lldb/tools/lldb-dap/DAP.h | 5 ++ lldb/tools/lldb-dap/lldb-dap.cpp | 4 +- 8 files changed, 112 insertions(+), 21 deletions(-) create mode 100644 lldb/test/API/tools/lldb-dap/custom-event/Makefile create mode 100644 lldb/test/API/tools/lldb-dap/custom-event/TestDAP_customEvent.py create mode 100644 lldb/test/API/tools/lldb-dap/custom-event/main.c 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); _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits