Skip to content

Commit fbb8929

Browse files
ashgtivogelsgesang
andauthored
[lldb-dap] Updating RequestHandler to encode/decode arguments and response. (#130090)
This is a work in progress refactor to add explicit types instead of generic 'llvm::json::Value' types to the DAP protocol. This updates RequestHandler to have take the type of the arguments and response body for serialization for requests. The 'source' and 'disconnect' request is updated to show how the new flow works and includes serialization handling for optional arguments and 'void' responses. This is built on top of #130026 --------- Co-authored-by: Adrian Vogelsgesang <[email protected]>
1 parent 47f7daa commit fbb8929

20 files changed

+686
-537
lines changed

lldb/tools/lldb-dap/CMakeLists.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ add_lldb_tool(lldb-dap
3232
LLDBUtils.cpp
3333
OutputRedirector.cpp
3434
ProgressEvent.cpp
35-
Protocol.cpp
3635
RunInTerminal.cpp
3736
SourceBreakpoint.cpp
3837
Transport.cpp
@@ -74,6 +73,10 @@ add_lldb_tool(lldb-dap
7473
Handler/TestGetTargetBreakpointsRequestHandler.cpp
7574
Handler/ThreadsRequestHandler.cpp
7675
Handler/VariablesRequestHandler.cpp
76+
77+
Protocol/ProtocolBase.cpp
78+
Protocol/ProtocolTypes.cpp
79+
Protocol/ProtocolRequests.cpp
7780

7881
LINK_LIBS
7982
liblldb

lldb/tools/lldb-dap/DAP.cpp

Lines changed: 42 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@
88

99
#include "DAP.h"
1010
#include "DAPLog.h"
11+
#include "Handler/RequestHandler.h"
1112
#include "Handler/ResponseHandler.h"
1213
#include "JSONUtils.h"
1314
#include "LLDBUtils.h"
1415
#include "OutputRedirector.h"
16+
#include "Protocol/ProtocolBase.h"
1517
#include "Transport.h"
1618
#include "lldb/API/SBBreakpoint.h"
1719
#include "lldb/API/SBCommandInterpreter.h"
@@ -25,6 +27,7 @@
2527
#include "lldb/lldb-defines.h"
2628
#include "lldb/lldb-enumerations.h"
2729
#include "llvm/ADT/ArrayRef.h"
30+
#include "llvm/ADT/STLExtras.h"
2831
#include "llvm/ADT/ScopeExit.h"
2932
#include "llvm/ADT/StringExtras.h"
3033
#include "llvm/ADT/StringRef.h"
@@ -41,6 +44,7 @@
4144
#include <fstream>
4245
#include <memory>
4346
#include <mutex>
47+
#include <string>
4448
#include <utility>
4549

4650
#if defined(_WIN32)
@@ -233,6 +237,10 @@ void DAP::SendJSON(const llvm::json::Value &json) {
233237
transport.GetClientName());
234238
return;
235239
}
240+
Send(message);
241+
}
242+
243+
void DAP::Send(const protocol::Message &message) {
236244
if (llvm::Error err = transport.Write(message))
237245
DAP_LOG_ERROR(log, std::move(err), "({1}) write failed: {0}",
238246
transport.GetClientName());
@@ -665,58 +673,65 @@ void DAP::SetTarget(const lldb::SBTarget target) {
665673
}
666674

667675
bool DAP::HandleObject(const protocol::Message &M) {
668-
// FIXME: Directly handle `Message` instead of serializing to JSON.
669-
llvm::json::Value v = toJSON(M);
670-
llvm::json::Object object = *v.getAsObject();
671-
const auto packet_type = GetString(object, "type");
672-
if (packet_type == "request") {
673-
const auto command = GetString(object, "command").value_or("");
674-
675-
auto new_handler_pos = request_handlers.find(command);
676-
if (new_handler_pos != request_handlers.end()) {
677-
(*new_handler_pos->second)(object);
676+
if (const auto *req = std::get_if<protocol::Request>(&M)) {
677+
auto handler_pos = request_handlers.find(req->command);
678+
if (handler_pos != request_handlers.end()) {
679+
(*handler_pos->second)(*req);
678680
return true; // Success
679681
}
680682

681683
DAP_LOG(log, "({0}) error: unhandled command '{1}'",
682-
transport.GetClientName(), command);
684+
transport.GetClientName(), req->command);
683685
return false; // Fail
684686
}
685687

686-
if (packet_type == "response") {
687-
auto id = GetInteger<int64_t>(object, "request_seq").value_or(0);
688-
688+
if (const auto *resp = std::get_if<protocol::Response>(&M)) {
689689
std::unique_ptr<ResponseHandler> response_handler;
690690
{
691691
std::lock_guard<std::mutex> locker(call_mutex);
692-
auto inflight = inflight_reverse_requests.find(id);
692+
auto inflight = inflight_reverse_requests.find(resp->request_seq);
693693
if (inflight != inflight_reverse_requests.end()) {
694694
response_handler = std::move(inflight->second);
695695
inflight_reverse_requests.erase(inflight);
696696
}
697697
}
698698

699699
if (!response_handler)
700-
response_handler = std::make_unique<UnknownResponseHandler>("", id);
700+
response_handler =
701+
std::make_unique<UnknownResponseHandler>("", resp->request_seq);
701702

702703
// Result should be given, use null if not.
703-
if (GetBoolean(object, "success").value_or(false)) {
704-
llvm::json::Value Result = nullptr;
705-
if (auto *B = object.get("body"))
706-
Result = std::move(*B);
707-
(*response_handler)(Result);
704+
if (resp->success) {
705+
(*response_handler)(resp->body);
708706
} else {
709-
llvm::StringRef message = GetString(object, "message").value_or("");
710-
if (message.empty()) {
711-
message = "Unknown error, response failed";
707+
llvm::StringRef message = "Unknown error, response failed";
708+
if (resp->message) {
709+
message =
710+
std::visit(llvm::makeVisitor(
711+
[](const std::string &message) -> llvm::StringRef {
712+
return message;
713+
},
714+
[](const protocol::Response::Message &message)
715+
-> llvm::StringRef {
716+
switch (message) {
717+
case protocol::Response::Message::cancelled:
718+
return "cancelled";
719+
case protocol::Response::Message::notStopped:
720+
return "notStopped";
721+
}
722+
}),
723+
*resp->message);
712724
}
725+
713726
(*response_handler)(llvm::createStringError(
714727
std::error_code(-1, std::generic_category()), message));
715728
}
716729

717730
return true;
718731
}
719732

733+
DAP_LOG(log, "Unsupported protocol message");
734+
720735
return false;
721736
}
722737

@@ -730,9 +745,9 @@ void DAP::SendTerminatedEvent() {
730745
});
731746
}
732747

733-
lldb::SBError DAP::Disconnect() { return Disconnect(is_attach); }
748+
llvm::Error DAP::Disconnect() { return Disconnect(is_attach); }
734749

735-
lldb::SBError DAP::Disconnect(bool terminateDebuggee) {
750+
llvm::Error DAP::Disconnect(bool terminateDebuggee) {
736751
lldb::SBError error;
737752
lldb::SBProcess process = target.GetProcess();
738753
auto state = process.GetState();
@@ -760,7 +775,7 @@ lldb::SBError DAP::Disconnect(bool terminateDebuggee) {
760775

761776
disconnecting = true;
762777

763-
return error;
778+
return ToError(error);
764779
}
765780

766781
llvm::Error DAP::Loop() {

lldb/tools/lldb-dap/DAP.h

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,10 @@
1212
#include "DAPForward.h"
1313
#include "ExceptionBreakpoint.h"
1414
#include "FunctionBreakpoint.h"
15-
#include "Handler/RequestHandler.h"
16-
#include "Handler/ResponseHandler.h"
1715
#include "InstructionBreakpoint.h"
1816
#include "OutputRedirector.h"
1917
#include "ProgressEvent.h"
20-
#include "Protocol.h"
18+
#include "Protocol/ProtocolBase.h"
2119
#include "SourceBreakpoint.h"
2220
#include "Transport.h"
2321
#include "lldb/API/SBBroadcaster.h"
@@ -187,7 +185,7 @@ struct DAP {
187185
// the old process here so we can detect this case and keep running.
188186
lldb::pid_t restarting_process_id;
189187
bool configuration_done_sent;
190-
llvm::StringMap<std::unique_ptr<RequestHandler>> request_handlers;
188+
llvm::StringMap<std::unique_ptr<BaseRequestHandler>> request_handlers;
191189
bool waiting_for_run_in_terminal;
192190
ProgressEventReporter progress_event_reporter;
193191
// Keep track of the last stop thread index IDs as threads won't go away
@@ -245,9 +243,11 @@ struct DAP {
245243
/// Stop event handler threads.
246244
void StopEventHandlers();
247245

248-
// Serialize the JSON value into a string and send the JSON packet to
249-
// the "out" stream.
246+
/// Serialize the JSON value into a string and send the JSON packet to the
247+
/// "out" stream.
250248
void SendJSON(const llvm::json::Value &json);
249+
/// Send the given message to the client
250+
void Send(const protocol::Message &message);
251251

252252
void SendOutput(OutputType o, const llvm::StringRef output);
253253

@@ -324,10 +324,10 @@ struct DAP {
324324
bool HandleObject(const protocol::Message &M);
325325

326326
/// Disconnect the DAP session.
327-
lldb::SBError Disconnect();
327+
llvm::Error Disconnect();
328328

329329
/// Disconnect the DAP session and optionally terminate the debuggee.
330-
lldb::SBError Disconnect(bool terminateDebuggee);
330+
llvm::Error Disconnect(bool terminateDebuggee);
331331

332332
/// Send a "terminated" event to indicate the process is done being debugged.
333333
void SendTerminatedEvent();

lldb/tools/lldb-dap/DAPForward.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ struct SourceBreakpoint;
1919
struct Watchpoint;
2020
struct InstructionBreakpoint;
2121
struct DAP;
22+
class BaseRequestHandler;
23+
class ResponseHandler;
2224
} // namespace lldb_dap
2325

2426
namespace lldb {

lldb/tools/lldb-dap/Handler/DisconnectRequestHandler.cpp

Lines changed: 15 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -7,70 +7,27 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "DAP.h"
10-
#include "EventHelper.h"
11-
#include "JSONUtils.h"
10+
#include "Protocol/ProtocolRequests.h"
1211
#include "RequestHandler.h"
12+
#include "llvm/Support/Error.h"
13+
#include <optional>
14+
15+
using namespace llvm;
16+
using namespace lldb_dap::protocol;
1317

1418
namespace lldb_dap {
1519

16-
// "DisconnectRequest": {
17-
// "allOf": [ { "$ref": "#/definitions/Request" }, {
18-
// "type": "object",
19-
// "description": "Disconnect request; value of command field is
20-
// 'disconnect'.",
21-
// "properties": {
22-
// "command": {
23-
// "type": "string",
24-
// "enum": [ "disconnect" ]
25-
// },
26-
// "arguments": {
27-
// "$ref": "#/definitions/DisconnectArguments"
28-
// }
29-
// },
30-
// "required": [ "command" ]
31-
// }]
32-
// },
33-
// "DisconnectArguments": {
34-
// "type": "object",
35-
// "description": "Arguments for 'disconnect' request.",
36-
// "properties": {
37-
// "terminateDebuggee": {
38-
// "type": "boolean",
39-
// "description": "Indicates whether the debuggee should be terminated
40-
// when the debugger is disconnected. If unspecified,
41-
// the debug adapter is free to do whatever it thinks
42-
// is best. A client can only rely on this attribute
43-
// being properly honored if a debug adapter returns
44-
// true for the 'supportTerminateDebuggee' capability."
45-
// },
46-
// "restart": {
47-
// "type": "boolean",
48-
// "description": "Indicates whether the debuggee should be restart
49-
// the process."
50-
// }
51-
// }
52-
// },
53-
// "DisconnectResponse": {
54-
// "allOf": [ { "$ref": "#/definitions/Response" }, {
55-
// "type": "object",
56-
// "description": "Response to 'disconnect' request. This is just an
57-
// acknowledgement, so no body field is required."
58-
// }]
59-
// }
60-
void DisconnectRequestHandler::operator()(
61-
const llvm::json::Object &request) const {
62-
llvm::json::Object response;
63-
FillResponse(request, response);
64-
const auto *arguments = request.getObject("arguments");
20+
/// Disconnect request; value of command field is 'disconnect'.
21+
Expected<DisconnectResponse> DisconnectRequestHandler::Run(
22+
const std::optional<DisconnectArguments> &arguments) const {
23+
bool terminateDebuggee = dap.is_attach ? false : true;
6524

66-
bool defaultTerminateDebuggee = dap.is_attach ? false : true;
67-
bool terminateDebuggee = GetBoolean(arguments, "terminateDebuggee")
68-
.value_or(defaultTerminateDebuggee);
25+
if (arguments && arguments->terminateDebuggee)
26+
terminateDebuggee = *arguments->terminateDebuggee;
6927

70-
lldb::SBError error = dap.Disconnect(terminateDebuggee);
71-
if (error.Fail())
72-
EmplaceSafeString(response, "error", error.GetCString());
28+
if (Error error = dap.Disconnect(terminateDebuggee))
29+
return error;
7330

74-
dap.SendJSON(llvm::json::Value(std::move(response)));
31+
return DisconnectResponse();
7532
}
7633
} // namespace lldb_dap

lldb/tools/lldb-dap/Handler/RequestHandler.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9-
#include "RequestHandler.h"
9+
#include "Handler/RequestHandler.h"
1010
#include "DAP.h"
11+
#include "Handler/ResponseHandler.h"
1112
#include "JSONUtils.h"
1213
#include "LLDBUtils.h"
1314
#include "RunInTerminal.h"
@@ -45,7 +46,7 @@ static uint32_t SetLaunchFlag(uint32_t flags, const llvm::json::Object *obj,
4546

4647
// Both attach and launch take either a sourcePath or a sourceMap
4748
// argument (or neither), from which we need to set the target.source-map.
48-
void RequestHandler::SetSourceMapFromArguments(
49+
void BaseRequestHandler::SetSourceMapFromArguments(
4950
const llvm::json::Object &arguments) const {
5051
const char *sourceMapHelp =
5152
"source must be be an array of two-element arrays, "
@@ -159,7 +160,7 @@ static llvm::Error RunInTerminal(DAP &dap,
159160
}
160161

161162
lldb::SBError
162-
RequestHandler::LaunchProcess(const llvm::json::Object &request) const {
163+
BaseRequestHandler::LaunchProcess(const llvm::json::Object &request) const {
163164
lldb::SBError error;
164165
const auto *arguments = request.getObject("arguments");
165166
auto launchCommands = GetStrings(arguments, "launchCommands");
@@ -228,13 +229,13 @@ RequestHandler::LaunchProcess(const llvm::json::Object &request) const {
228229
return error;
229230
}
230231

231-
void RequestHandler::PrintWelcomeMessage() const {
232+
void BaseRequestHandler::PrintWelcomeMessage() const {
232233
#ifdef LLDB_DAP_WELCOME_MESSAGE
233234
dap.SendOutput(OutputType::Console, LLDB_DAP_WELCOME_MESSAGE);
234235
#endif
235236
}
236237

237-
bool RequestHandler::HasInstructionGranularity(
238+
bool BaseRequestHandler::HasInstructionGranularity(
238239
const llvm::json::Object &arguments) const {
239240
if (std::optional<llvm::StringRef> value = arguments.getString("granularity"))
240241
return value == "instruction";

0 commit comments

Comments
 (0)