From 5267ade04a9af4fcd06e69e1b93111dfc693fc78 Mon Sep 17 00:00:00 2001 From: Druzhkov Sergei Date: Fri, 12 Dec 2025 00:06:37 +0300 Subject: [PATCH 1/3] [lldb-dap] Migrate compileUnits request to structured types --- .../Handler/CompileUnitsRequestHandler.cpp | 76 +++++-------------- lldb/tools/lldb-dap/Handler/RequestHandler.h | 11 ++- lldb/tools/lldb-dap/JSONUtils.cpp | 9 --- lldb/tools/lldb-dap/JSONUtils.h | 2 - .../lldb-dap/Protocol/ProtocolRequests.cpp | 11 +++ .../lldb-dap/Protocol/ProtocolRequests.h | 15 ++++ .../tools/lldb-dap/Protocol/ProtocolTypes.cpp | 5 ++ lldb/tools/lldb-dap/Protocol/ProtocolTypes.h | 6 ++ lldb/unittests/DAP/ProtocolRequestsTest.cpp | 31 ++++++++ 9 files changed, 94 insertions(+), 72 deletions(-) diff --git a/lldb/tools/lldb-dap/Handler/CompileUnitsRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/CompileUnitsRequestHandler.cpp index 0e5c2b23d8d67..e79000230de1f 100644 --- a/lldb/tools/lldb-dap/Handler/CompileUnitsRequestHandler.cpp +++ b/lldb/tools/lldb-dap/Handler/CompileUnitsRequestHandler.cpp @@ -8,75 +8,35 @@ #include "DAP.h" #include "EventHelper.h" -#include "JSONUtils.h" +#include "Protocol/ProtocolRequests.h" #include "RequestHandler.h" -namespace lldb_dap { +using namespace lldb_dap; +using namespace lldb_dap::protocol; -// "compileUnitsRequest": { -// "allOf": [ { "$ref": "#/definitions/Request" }, { -// "type": "object", -// "description": "Compile Unit request; value of command field is -// 'compileUnits'.", -// "properties": { -// "command": { -// "type": "string", -// "enum": [ "compileUnits" ] -// }, -// "arguments": { -// "$ref": "#/definitions/compileUnitRequestArguments" -// } -// }, -// "required": [ "command", "arguments" ] -// }] -// }, -// "compileUnitsRequestArguments": { -// "type": "object", -// "description": "Arguments for 'compileUnits' request.", -// "properties": { -// "moduleId": { -// "type": "string", -// "description": "The ID of the module." -// } -// }, -// "required": [ "moduleId" ] -// }, -// "compileUnitsResponse": { -// "allOf": [ { "$ref": "#/definitions/Response" }, { -// "type": "object", -// "description": "Response to 'compileUnits' request.", -// "properties": { -// "body": { -// "description": "Response to 'compileUnits' request. Array of -// paths of compile units." -// } -// } -// }] -// } -void CompileUnitsRequestHandler::operator()( - const llvm::json::Object &request) const { - llvm::json::Object response; - FillResponse(request, response); - llvm::json::Object body; - llvm::json::Array units; - const auto *arguments = request.getObject("arguments"); - const llvm::StringRef module_id = - GetString(arguments, "moduleId").value_or(""); +static CompileUnit CreateCompileUnit(lldb::SBCompileUnit &unit) { + char unit_path_arr[PATH_MAX]; + unit.GetFileSpec().GetPath(unit_path_arr, sizeof(unit_path_arr)); + std::string unit_path(unit_path_arr); + return {std::move(unit_path)}; +} + +/// The `compileUnits` request returns an array of path of compile units for +/// given module specified by `moduleId`. +llvm::Expected CompileUnitsRequestHandler::Run( + const std::optional &args) const { + std::vector units; int num_modules = dap.target.GetNumModules(); for (int i = 0; i < num_modules; i++) { auto curr_module = dap.target.GetModuleAtIndex(i); - if (module_id == llvm::StringRef(curr_module.GetUUIDString())) { + if (args->moduleId == llvm::StringRef(curr_module.GetUUIDString())) { int num_units = curr_module.GetNumCompileUnits(); for (int j = 0; j < num_units; j++) { auto curr_unit = curr_module.GetCompileUnitAtIndex(j); units.emplace_back(CreateCompileUnit(curr_unit)); } - body.try_emplace("compileUnits", std::move(units)); break; } } - response.try_emplace("body", std::move(body)); - dap.SendJSON(llvm::json::Value(std::move(response))); -} - -} // namespace lldb_dap + return CompileUnitsResponseBody{std::move(units)}; +}; diff --git a/lldb/tools/lldb-dap/Handler/RequestHandler.h b/lldb/tools/lldb-dap/Handler/RequestHandler.h index 8f42a28160751..c9418ede12491 100644 --- a/lldb/tools/lldb-dap/Handler/RequestHandler.h +++ b/lldb/tools/lldb-dap/Handler/RequestHandler.h @@ -472,11 +472,16 @@ class SetInstructionBreakpointsRequestHandler Run(const protocol::SetInstructionBreakpointsArguments &args) const override; }; -class CompileUnitsRequestHandler : public LegacyRequestHandler { +class CompileUnitsRequestHandler + : public RequestHandler< + std::optional, + llvm::Expected> { public: - using LegacyRequestHandler::LegacyRequestHandler; + using RequestHandler::RequestHandler; static llvm::StringLiteral GetCommand() { return "compileUnits"; } - void operator()(const llvm::json::Object &request) const override; + llvm::Expected + Run(const std::optional &args) + const override; }; class ModulesRequestHandler final diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp b/lldb/tools/lldb-dap/JSONUtils.cpp index bb3f8aaaded89..1f9719110cedb 100644 --- a/lldb/tools/lldb-dap/JSONUtils.cpp +++ b/lldb/tools/lldb-dap/JSONUtils.cpp @@ -865,15 +865,6 @@ std::pair UnpackLocation(int64_t location_id) { return std::pair{location_id >> 1, location_id & 1}; } -llvm::json::Value CreateCompileUnit(lldb::SBCompileUnit &unit) { - llvm::json::Object object; - char unit_path_arr[PATH_MAX]; - unit.GetFileSpec().GetPath(unit_path_arr, sizeof(unit_path_arr)); - std::string unit_path(unit_path_arr); - object.try_emplace("compileUnitPath", unit_path); - return llvm::json::Value(std::move(object)); -} - /// See /// https://microsoft.github.io/debug-adapter-protocol/specification#Reverse_Requests_RunInTerminal llvm::json::Object CreateRunInTerminalReverseRequest( diff --git a/lldb/tools/lldb-dap/JSONUtils.h b/lldb/tools/lldb-dap/JSONUtils.h index 7fad7409b11fe..0a907599fc9ee 100644 --- a/lldb/tools/lldb-dap/JSONUtils.h +++ b/lldb/tools/lldb-dap/JSONUtils.h @@ -368,8 +368,6 @@ int64_t PackLocation(int64_t var_ref, bool is_value_location); /// Reverse of `PackLocation` std::pair UnpackLocation(int64_t location_id); -llvm::json::Value CreateCompileUnit(lldb::SBCompileUnit &unit); - /// Create a runInTerminal reverse request object /// /// \param[in] program diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp index 42acc70333a7b..9db60f6da8f99 100644 --- a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp +++ b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp @@ -721,4 +721,15 @@ llvm::json::Value toJSON(const LocationsResponseBody &Body) { return result; } +bool fromJSON(const llvm::json::Value &Params, CompileUnitsArguments &Args, + llvm::json::Path Path) { + json::ObjectMapper O(Params, Path); + return O && O.map("moduleId", Args.moduleId); +} + +llvm::json::Value toJSON(const CompileUnitsResponseBody &Body) { + json::Object result{{"compileUnits", Body.compileUnits}}; + return result; +} + } // namespace lldb_dap::protocol diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h index 104520f2c24c2..6a4d585f2c08f 100644 --- a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h +++ b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h @@ -1230,6 +1230,21 @@ struct LocationsResponseBody { }; llvm::json::Value toJSON(const LocationsResponseBody &); +/// Arguments for `compileUnits` request. +struct CompileUnitsArguments { + /// The ID of the module. + std::string moduleId; +}; +bool fromJSON(const llvm::json::Value &, CompileUnitsArguments &, + llvm::json::Path); + +/// Response to `compileUnits` request. +struct CompileUnitsResponseBody { + /// Array of compile units. + std::vector compileUnits; +}; +llvm::json::Value toJSON(const CompileUnitsResponseBody &); + } // namespace lldb_dap::protocol #endif diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp index 95007013742a0..c7f7c447b5b6f 100644 --- a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp +++ b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp @@ -1169,4 +1169,9 @@ json::Value toJSON(const ExceptionDetails &ED) { return result; } +llvm::json::Value toJSON(const CompileUnit &CU) { + json::Object result{{"compileUnitPath", CU.compileUnitPath}}; + 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 ee103ddf0b7a2..4ead4786bc661 100644 --- a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h +++ b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h @@ -1038,6 +1038,12 @@ struct ExceptionDetails { }; llvm::json::Value toJSON(const ExceptionDetails &); +struct CompileUnit { + /// Path of compile unit. + std::string compileUnitPath; +}; +llvm::json::Value toJSON(const CompileUnit &); + } // namespace lldb_dap::protocol #endif diff --git a/lldb/unittests/DAP/ProtocolRequestsTest.cpp b/lldb/unittests/DAP/ProtocolRequestsTest.cpp index 50b8335ba46cc..23501389fc92e 100644 --- a/lldb/unittests/DAP/ProtocolRequestsTest.cpp +++ b/lldb/unittests/DAP/ProtocolRequestsTest.cpp @@ -243,3 +243,34 @@ TEST(ProtocolRequestsTest, LocationsResponseBody) { ASSERT_THAT_EXPECTED(expected, llvm::Succeeded()); EXPECT_EQ(PrettyPrint(*expected), PrettyPrint(body)); } + +TEST(ProtocolRequestsTest, CompileUnitsArguments) { + llvm::Expected expected = + parse(R"({"moduleId": "42"})"); + ASSERT_THAT_EXPECTED(expected, llvm::Succeeded()); + EXPECT_EQ(expected->moduleId, "42"); + + // Check required keys. + EXPECT_THAT_EXPECTED(parse(R"({})"), + FailedWithMessage("missing value at (root).moduleId")); +} + +TEST(ProtocolRequestsTest, CompileUnitsResponseBody) { + CompileUnitsResponseBody body; + body.compileUnits = {{"main.cpp"}, {"util.cpp"}}; + + // Check required keys. + Expected expected = parse(R"({ + "compileUnits": [ + { + "compileUnitPath": "main.cpp" + }, + { + "compileUnitPath": "util.cpp" + } + ] + })"); + + ASSERT_THAT_EXPECTED(expected, llvm::Succeeded()); + EXPECT_EQ(PrettyPrint(*expected), PrettyPrint(body)); +} From a793023ee190b9a4a7dfa752be0a6222530a5d38 Mon Sep 17 00:00:00 2001 From: Druzhkov Sergei Date: Sat, 13 Dec 2025 00:07:15 +0300 Subject: [PATCH 2/3] [lldb-dap] Migrate testGetTargetBreakpoints request --- lldb/tools/lldb-dap/Handler/RequestHandler.h | 14 ++++----- ...TestGetTargetBreakpointsRequestHandler.cpp | 27 ++++++++--------- .../lldb-dap/Protocol/ProtocolRequests.cpp | 5 ++++ .../lldb-dap/Protocol/ProtocolRequests.h | 10 +++++++ lldb/unittests/DAP/ProtocolRequestsTest.cpp | 30 +++++++++++++++++++ 5 files changed, 65 insertions(+), 21 deletions(-) diff --git a/lldb/tools/lldb-dap/Handler/RequestHandler.h b/lldb/tools/lldb-dap/Handler/RequestHandler.h index c9418ede12491..0669be50597e9 100644 --- a/lldb/tools/lldb-dap/Handler/RequestHandler.h +++ b/lldb/tools/lldb-dap/Handler/RequestHandler.h @@ -630,17 +630,17 @@ class ModuleSymbolsRequestHandler Run(const protocol::ModuleSymbolsArguments &args) const override; }; -/// A request used in testing to get the details on all breakpoints that are -/// currently set in the target. This helps us to test "setBreakpoints" and -/// "setFunctionBreakpoints" requests to verify we have the correct set of -/// breakpoints currently set in LLDB. -class TestGetTargetBreakpointsRequestHandler : public LegacyRequestHandler { +class TestGetTargetBreakpointsRequestHandler + : public RequestHandler< + protocol::TestGetTargetBreakpointsArguments, + llvm::Expected> { public: - using LegacyRequestHandler::LegacyRequestHandler; + using RequestHandler::RequestHandler; static llvm::StringLiteral GetCommand() { return "_testGetTargetBreakpoints"; } - void operator()(const llvm::json::Object &request) const override; + llvm::Expected + Run(const protocol::TestGetTargetBreakpointsArguments &args) const override; }; class WriteMemoryRequestHandler final diff --git a/lldb/tools/lldb-dap/Handler/TestGetTargetBreakpointsRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/TestGetTargetBreakpointsRequestHandler.cpp index 5f4f016f6a1ef..d1b6a8e189032 100644 --- a/lldb/tools/lldb-dap/Handler/TestGetTargetBreakpointsRequestHandler.cpp +++ b/lldb/tools/lldb-dap/Handler/TestGetTargetBreakpointsRequestHandler.cpp @@ -8,24 +8,23 @@ #include "DAP.h" #include "EventHelper.h" -#include "JSONUtils.h" +#include "Protocol/ProtocolRequests.h" #include "RequestHandler.h" -namespace lldb_dap { +using namespace lldb_dap; +using namespace lldb_dap::protocol; -void TestGetTargetBreakpointsRequestHandler::operator()( - const llvm::json::Object &request) const { - llvm::json::Object response; - FillResponse(request, response); - llvm::json::Array response_breakpoints; +/// A request used in testing to get the details on all breakpoints that are +/// currently set in the target. This helps us to test "setBreakpoints" and +/// "setFunctionBreakpoints" requests to verify we have the correct set of +/// breakpoints currently set in LLDB. +llvm::Expected +TestGetTargetBreakpointsRequestHandler::Run( + const TestGetTargetBreakpointsArguments &args) const { + std::vector breakpoints; for (uint32_t i = 0; dap.target.GetBreakpointAtIndex(i).IsValid(); ++i) { auto bp = Breakpoint(dap, dap.target.GetBreakpointAtIndex(i)); - response_breakpoints.push_back(bp.ToProtocolBreakpoint()); + breakpoints.push_back(bp.ToProtocolBreakpoint()); } - llvm::json::Object body; - body.try_emplace("breakpoints", std::move(response_breakpoints)); - response.try_emplace("body", std::move(body)); - dap.SendJSON(llvm::json::Value(std::move(response))); + return TestGetTargetBreakpointsResponseBody{std::move(breakpoints)}; } - -} // namespace lldb_dap diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp index 9db60f6da8f99..bf470b78077df 100644 --- a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp +++ b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp @@ -732,4 +732,9 @@ llvm::json::Value toJSON(const CompileUnitsResponseBody &Body) { return result; } +llvm::json::Value toJSON(const TestGetTargetBreakpointsResponseBody &Body) { + json::Object result{{"breakpoints", Body.breakpoints}}; + return result; +} + } // namespace lldb_dap::protocol diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h index 6a4d585f2c08f..cc123943ec0b6 100644 --- a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h +++ b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h @@ -1245,6 +1245,16 @@ struct CompileUnitsResponseBody { }; llvm::json::Value toJSON(const CompileUnitsResponseBody &); +/// Arguments for `testGetTargetBreakpoints` request. +using TestGetTargetBreakpointsArguments = EmptyArguments; + +/// Response to `testGetTargetBreakpoints` request. +struct TestGetTargetBreakpointsResponseBody { + /// Array of all breakpoints that are currently set in the target. + std::vector breakpoints; +}; +llvm::json::Value toJSON(const TestGetTargetBreakpointsResponseBody &); + } // namespace lldb_dap::protocol #endif diff --git a/lldb/unittests/DAP/ProtocolRequestsTest.cpp b/lldb/unittests/DAP/ProtocolRequestsTest.cpp index 23501389fc92e..710b78960ef09 100644 --- a/lldb/unittests/DAP/ProtocolRequestsTest.cpp +++ b/lldb/unittests/DAP/ProtocolRequestsTest.cpp @@ -274,3 +274,33 @@ TEST(ProtocolRequestsTest, CompileUnitsResponseBody) { ASSERT_THAT_EXPECTED(expected, llvm::Succeeded()); EXPECT_EQ(PrettyPrint(*expected), PrettyPrint(body)); } + +TEST(ProtocolRequestsTest, TestGetTargetBreakpointsResponseBody) { + Breakpoint breakpoint1; + breakpoint1.id = 1; + breakpoint1.verified = true; + Breakpoint breakpoint2; + breakpoint2.id = 2; + breakpoint2.verified = false; + breakpoint2.message = "Failed to set breakpoint"; + TestGetTargetBreakpointsResponseBody body; + body.breakpoints = {breakpoint1, breakpoint2}; + + // Check required keys. + Expected expected = parse(R"({ + "breakpoints": [ + { + "id": 1, + "verified": true + }, + { + "id": 2, + "verified": false, + "message": "Failed to set breakpoint" + } + ] + })"); + + ASSERT_THAT_EXPECTED(expected, llvm::Succeeded()); + EXPECT_EQ(PrettyPrint(*expected), PrettyPrint(body)); +} From a3036114accb254a9789e73433577710b396ab73 Mon Sep 17 00:00:00 2001 From: Druzhkov Sergei Date: Mon, 15 Dec 2025 14:18:24 +0300 Subject: [PATCH 3/3] Fix CI --- lldb/tools/lldb-dap/Handler/CompileUnitsRequestHandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lldb/tools/lldb-dap/Handler/CompileUnitsRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/CompileUnitsRequestHandler.cpp index e79000230de1f..230c10470bedb 100644 --- a/lldb/tools/lldb-dap/Handler/CompileUnitsRequestHandler.cpp +++ b/lldb/tools/lldb-dap/Handler/CompileUnitsRequestHandler.cpp @@ -39,4 +39,4 @@ llvm::Expected CompileUnitsRequestHandler::Run( } } return CompileUnitsResponseBody{std::move(units)}; -}; +}