[Lldb-commits] [lldb] [lldb-dap] Creating well defined structures for DAP messages. (PR #129155)
John Harrison via lldb-commits
lldb-commits at lists.llvm.org
Fri Feb 28 09:42:27 PST 2025
https://github.com/ashgti updated https://github.com/llvm/llvm-project/pull/129155
>From 5ec870632250a2bf59341c2699a6a93b31c155ba Mon Sep 17 00:00:00 2001
From: John Harrison <harjohn at google.com>
Date: Thu, 27 Feb 2025 15:27:41 -0800
Subject: [PATCH 1/3] [lldb-dap] Creating a new set of types for handling DAP
messages.
This adds a new Protocol.{h,cpp} for defining structured types that represent Debug Adapter Protocol messages.
This adds static types to define well structure messages for the protocol. This iteration includes only the basic `Event`, `Request` and `Response` types.
In a follow-up patch I plan on adding more types as need to allow for incrementally migrating raw `llvm::json::Value` usage to well defined types.
---
lldb/tools/lldb-dap/CMakeLists.txt | 1 +
lldb/tools/lldb-dap/Protocol.cpp | 191 +++++++++++++++++++++++++++++
lldb/tools/lldb-dap/Protocol.h | 187 ++++++++++++++++++++++++++++
3 files changed, 379 insertions(+)
create mode 100644 lldb/tools/lldb-dap/Protocol.cpp
create mode 100644 lldb/tools/lldb-dap/Protocol.h
diff --git a/lldb/tools/lldb-dap/CMakeLists.txt b/lldb/tools/lldb-dap/CMakeLists.txt
index 8b3c520ec4360..9a2d604f4d573 100644
--- a/lldb/tools/lldb-dap/CMakeLists.txt
+++ b/lldb/tools/lldb-dap/CMakeLists.txt
@@ -35,6 +35,7 @@ add_lldb_tool(lldb-dap
ProgressEvent.cpp
RunInTerminal.cpp
SourceBreakpoint.cpp
+ Protocol.cpp
Watchpoint.cpp
Handler/ResponseHandler.cpp
diff --git a/lldb/tools/lldb-dap/Protocol.cpp b/lldb/tools/lldb-dap/Protocol.cpp
new file mode 100644
index 0000000000000..71c4dc080a5b1
--- /dev/null
+++ b/lldb/tools/lldb-dap/Protocol.cpp
@@ -0,0 +1,191 @@
+//===-- Protocol.cpp ------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "Protocol.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/JSON.h"
+#include <optional>
+#include <utility>
+
+namespace llvm {
+namespace json {
+bool fromJSON(const llvm::json::Value &Params, llvm::json::Value &V,
+ llvm::json::Path P) {
+ V = std::move(Params);
+ return true;
+}
+} // namespace json
+} // namespace llvm
+
+namespace lldb_dap {
+namespace protocol {
+
+enum class MessageType { request, response, event };
+
+bool fromJSON(const llvm::json::Value &Params, MessageType &M,
+ llvm::json::Path P) {
+ auto rawType = Params.getAsString();
+ if (!rawType) {
+ P.report("expected a string");
+ return false;
+ }
+ std::optional<MessageType> type =
+ llvm::StringSwitch<std::optional<MessageType>>(*rawType)
+ .Case("request", MessageType::request)
+ .Case("response", MessageType::response)
+ .Case("event", MessageType::event)
+ .Default(std::nullopt);
+ if (!type) {
+ P.report("unexpected value");
+ return false;
+ }
+ M = *type;
+ return true;
+}
+
+llvm::json::Value toJSON(const Request &R) {
+ llvm::json::Object Result{
+ {"type", "request"},
+ {"seq", R.seq},
+ {"command", R.command},
+ };
+ if (R.rawArguments)
+ Result.insert({"arguments", R.rawArguments});
+ return std::move(Result);
+}
+
+bool fromJSON(llvm::json::Value const &Params, Request &R, llvm::json::Path P) {
+ llvm::json::ObjectMapper O(Params, P);
+ MessageType type;
+ if (!O.map("type", type)) {
+ return false;
+ }
+ if (type != MessageType::request) {
+ P.field("type").report("expected to be 'request'");
+ return false;
+ }
+
+ return O && O.map("command", R.command) && O.map("seq", R.seq) &&
+ O.map("arguments", R.rawArguments);
+}
+
+llvm::json::Value toJSON(const Response &R) {
+ llvm::json::Object Result{{"type", "response"},
+ {"req", 0},
+ {"command", R.command},
+ {"request_seq", R.request_seq},
+ {"success", R.success}};
+
+ if (R.message)
+ Result.insert({"message", R.message});
+ if (R.rawBody)
+ Result.insert({"body", R.rawBody});
+
+ return std::move(Result);
+}
+
+bool fromJSON(llvm::json::Value const &Params, Response &R,
+ llvm::json::Path P) {
+ llvm::json::ObjectMapper O(Params, P);
+ MessageType type;
+ if (!O.map("type", type)) {
+ return false;
+ }
+ if (type != MessageType::response) {
+ P.field("type").report("expected to be 'response'");
+ return false;
+ }
+ return O && O.map("command", R.command) &&
+ O.map("request_seq", R.request_seq) && O.map("success", R.success) &&
+ O.mapOptional("message", R.message) &&
+ O.mapOptional("body", R.rawBody);
+}
+
+llvm::json::Value toJSON(const Event &E) {
+ llvm::json::Object Result{
+ {"type", "event"},
+ {"seq", 0},
+ {"event", E.event},
+ };
+ if (E.rawBody)
+ Result.insert({"body", E.rawBody});
+ if (E.statistics)
+ Result.insert({"statistics", E.statistics});
+ return std::move(Result);
+}
+
+bool fromJSON(llvm::json::Value const &Params, Event &E, llvm::json::Path P) {
+ llvm::json::ObjectMapper O(Params, P);
+ MessageType type;
+ if (!O.map("type", type)) {
+ return false;
+ }
+ if (type != MessageType::event) {
+ P.field("type").report("expected to be 'event'");
+ return false;
+ }
+
+ return O && O.map("event", E.event) && O.mapOptional("body", E.rawBody) &&
+ O.mapOptional("statistics", E.statistics);
+}
+
+bool fromJSON(const llvm::json::Value &Params, ProtocolMessage &PM,
+ llvm::json::Path P) {
+ llvm::json::ObjectMapper O(Params, P);
+ if (!O)
+ return false;
+
+ MessageType type;
+ if (!O.map("type", type))
+ return false;
+
+ switch (type) {
+ case MessageType::request: {
+ Request req;
+ if (!fromJSON(Params, req, P)) {
+ return false;
+ }
+ PM = std::move(req);
+ return true;
+ }
+ case MessageType::response: {
+ Response resp;
+ if (!fromJSON(Params, resp, P)) {
+ return false;
+ }
+ PM = std::move(resp);
+ return true;
+ }
+ case MessageType::event:
+ Event evt;
+ if (!fromJSON(Params, evt, P)) {
+ return false;
+ }
+ PM = std::move(evt);
+ return true;
+ }
+ llvm_unreachable("Unsupported protocol message");
+}
+
+llvm::json::Value toJSON(const ProtocolMessage &PM) {
+ if (auto const *Req = std::get_if<Request>(&PM)) {
+ return toJSON(*Req);
+ }
+ if (auto const *Resp = std::get_if<Response>(&PM)) {
+ return toJSON(*Resp);
+ }
+ if (auto const *Evt = std::get_if<Event>(&PM)) {
+ return toJSON(*Evt);
+ }
+ llvm_unreachable("Unsupported protocol message");
+}
+
+} // namespace protocol
+} // namespace lldb_dap
diff --git a/lldb/tools/lldb-dap/Protocol.h b/lldb/tools/lldb-dap/Protocol.h
new file mode 100644
index 0000000000000..0d38f8b249094
--- /dev/null
+++ b/lldb/tools/lldb-dap/Protocol.h
@@ -0,0 +1,187 @@
+//===-- Protocol.h --------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains POD structs based on the DAP specification at
+// https://microsoft.github.io/debug-adapter-protocol/specification
+//
+// This is not meant to be a complete implementation, new interfaces are added
+// when they're needed.
+//
+// Each struct has a toJSON and fromJSON function, that converts between
+// the struct and a JSON representation. (See JSON.h)
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_TOOLS_LLDB_DAP_PROTOCOL_H
+#define LLDB_TOOLS_LLDB_DAP_PROTOCOL_H
+
+#include "llvm/Support/JSON.h"
+#include <cstddef>
+#include <cstdint>
+#include <optional>
+#include <string>
+#include <variant>
+
+namespace lldb_dap {
+namespace protocol {
+
+// MARK: Base Protocol
+
+// "Request": {
+// "allOf": [ { "$ref": "#/definitions/ProtocolMessage" }, {
+// "type": "object",
+// "description": "A client or debug adapter initiated request.",
+// "properties": {
+// "type": {
+// "type": "string",
+// "enum": [ "request" ]
+// },
+// "command": {
+// "type": "string",
+// "description": "The command to execute."
+// },
+// "arguments": {
+// "type": [ "array", "boolean", "integer", "null", "number" , "object",
+// "string" ], "description": "Object containing arguments for the
+// command."
+// }
+// },
+// "required": [ "type", "command" ]
+// }]
+// },
+struct Request {
+ int64_t seq;
+ std::string command;
+ std::optional<llvm::json::Value> rawArguments;
+};
+llvm::json::Value toJSON(const Request &);
+bool fromJSON(const llvm::json::Value &, Request &, llvm::json::Path);
+
+// "Event": {
+// "allOf": [ { "$ref": "#/definitions/ProtocolMessage" }, {
+// "type": "object",
+// "description": "A debug adapter initiated event.",
+// "properties": {
+// "type": {
+// "type": "string",
+// "enum": [ "event" ]
+// },
+// "event": {
+// "type": "string",
+// "description": "Type of event."
+// },
+// "body": {
+// "type": [ "array", "boolean", "integer", "null", "number" , "object",
+// "string" ], "description": "Event-specific information."
+// }
+// },
+// "required": [ "type", "event" ]
+// }]
+// },
+struct Event {
+ std::string event;
+ std::optional<llvm::json::Value> rawBody;
+
+ /// lldb-dap specific extension on the 'terminated' event specifically.
+ std::optional<llvm::json::Value> statistics;
+};
+llvm::json::Value toJSON(const Event &);
+bool fromJSON(const llvm::json::Value &, Event &, llvm::json::Path);
+
+// "Response" : {
+// "allOf" : [
+// {"$ref" : "#/definitions/ProtocolMessage"}, {
+// "type" : "object",
+// "description" : "Response for a request.",
+// "properties" : {
+// "type" : {"type" : "string", "enum" : ["response"]},
+// "request_seq" : {
+// "type" : "integer",
+// "description" : "Sequence number of the corresponding request."
+// },
+// "success" : {
+// "type" : "boolean",
+// "description" :
+// "Outcome of the request.\nIf true, the request was successful "
+// "and the `body` attribute may contain the result of the "
+// "request.\nIf the value is false, the attribute `message` "
+// "contains the error in short form and the `body` may contain "
+// "additional information (see `ErrorResponse.body.error`)."
+// },
+// "command" :
+// {"type" : "string", "description" : "The command requested."},
+// "message" : {
+// "type" : "string",
+// "description" :
+// "Contains the raw error in short form if `success` is "
+// "false.\nThis raw error might be interpreted by the client and
+// " "is not shown in the UI.\nSome predefined values exist.",
+// "_enum" : [ "cancelled", "notStopped" ],
+// "enumDescriptions" : [
+// "the request was cancelled.", "the request may be retried once
+// the "
+// "adapter is in a 'stopped' state."
+// ]
+// },
+// "body" : {
+// "type" : [
+// "array", "boolean", "integer", "null", "number", "object",
+// "string"
+// ],
+// "description" : "Contains request result if success is true and "
+// "error details if success is false."
+// }
+// },
+// "required" : [ "type", "request_seq", "success", "command" ]
+// }
+// ]
+// }
+struct Response {
+ int64_t request_seq;
+ bool success;
+ std::string command;
+ std::optional<std::string> message;
+ std::optional<llvm::json::Value> rawBody;
+};
+bool fromJSON(const llvm::json::Value &, Response &, llvm::json::Path);
+llvm::json::Value toJSON(const Response &);
+
+// A void response body for any response without a specific value.
+using VoidResponseBody = std::nullptr_t;
+
+// "ProtocolMessage": {
+// "type": "object",
+// "title": "Base Protocol",
+// "description": "Base class of requests, responses, and events.",
+// "properties": {
+// "seq": {
+// "type": "integer",
+// "description": "Sequence number of the message (also known as
+// message ID). The `seq` for the first message sent by a client or
+// debug adapter is 1, and for each subsequent message is 1 greater
+// than the previous message sent by that actor. `seq` can be used to
+// order requests, responses, and events, and to associate requests
+// with their corresponding responses. For protocol messages of type
+// `request` the sequence number can be used to cancel the request."
+// },
+// "type": {
+// "type": "string",
+// "description": "Message type.",
+// "_enum": [ "request", "response", "event" ]
+// }
+// },
+// "required": [ "seq", "type" ]
+// },
+using ProtocolMessage = std::variant<Request, Response, Event>;
+bool fromJSON(const llvm::json::Value &, ProtocolMessage &, llvm::json::Path);
+llvm::json::Value toJSON(const ProtocolMessage &);
+
+} // namespace protocol
+} // namespace lldb_dap
+
+#endif
>From b171e5e821f57ae31bcbbc1b81388358182c56ca Mon Sep 17 00:00:00 2001
From: John Harrison <harjohn at google.com>
Date: Fri, 28 Feb 2025 09:32:49 -0800
Subject: [PATCH 2/3] Addressing style comments and reviewer feedback.
---
lldb/tools/lldb-dap/Protocol.cpp | 166 +++++++++++++++++++------------
lldb/tools/lldb-dap/Protocol.h | 6 +-
2 files changed, 106 insertions(+), 66 deletions(-)
diff --git a/lldb/tools/lldb-dap/Protocol.cpp b/lldb/tools/lldb-dap/Protocol.cpp
index 71c4dc080a5b1..d7f527b1a7d22 100644
--- a/lldb/tools/lldb-dap/Protocol.cpp
+++ b/lldb/tools/lldb-dap/Protocol.cpp
@@ -14,131 +14,184 @@
#include <optional>
#include <utility>
-namespace llvm {
-namespace json {
-bool fromJSON(const llvm::json::Value &Params, llvm::json::Value &V,
- llvm::json::Path P) {
- V = std::move(Params);
+using namespace llvm;
+
+static bool mapRaw(const json::Value &Params, StringLiteral Prop,
+ std::optional<json::Value> &V, json::Path P) {
+ const auto *O = Params.getAsObject();
+ if (!O) {
+ P.report("expected object");
+ return false;
+ }
+ if (const json::Value *E = O->get(Prop))
+ V = std::move(Params);
return true;
}
-} // namespace json
-} // namespace llvm
namespace lldb_dap {
namespace protocol {
enum class MessageType { request, response, event };
-bool fromJSON(const llvm::json::Value &Params, MessageType &M,
- llvm::json::Path P) {
+bool fromJSON(const json::Value &Params, MessageType &M, json::Path P) {
auto rawType = Params.getAsString();
if (!rawType) {
P.report("expected a string");
return false;
}
std::optional<MessageType> type =
- llvm::StringSwitch<std::optional<MessageType>>(*rawType)
+ StringSwitch<std::optional<MessageType>>(*rawType)
.Case("request", MessageType::request)
.Case("response", MessageType::response)
.Case("event", MessageType::event)
.Default(std::nullopt);
if (!type) {
- P.report("unexpected value");
+ P.report("unexpected value, expected 'request', 'response' or 'event'");
return false;
}
M = *type;
return true;
}
-llvm::json::Value toJSON(const Request &R) {
- llvm::json::Object Result{
+json::Value toJSON(const Request &R) {
+ json::Object Result{
{"type", "request"},
{"seq", R.seq},
{"command", R.command},
};
+
if (R.rawArguments)
Result.insert({"arguments", R.rawArguments});
+
return std::move(Result);
}
-bool fromJSON(llvm::json::Value const &Params, Request &R, llvm::json::Path P) {
- llvm::json::ObjectMapper O(Params, P);
+bool fromJSON(json::Value const &Params, Request &R, json::Path P) {
+ json::ObjectMapper O(Params, P);
+ if (!O)
+ return false;
+
MessageType type;
- if (!O.map("type", type)) {
+ if (!O.map("type", type) || !O.map("command", R.command) ||
+ !O.map("seq", R.seq))
return false;
- }
+
if (type != MessageType::request) {
P.field("type").report("expected to be 'request'");
return false;
}
- return O && O.map("command", R.command) && O.map("seq", R.seq) &&
- O.map("arguments", R.rawArguments);
+ if (R.command.empty()) {
+ P.field("command").report("expected to not be ''");
+ return false;
+ }
+
+ if (!R.seq) {
+ P.field("seq").report("expected to not be '0'");
+ return false;
+ }
+
+ return mapRaw(Params, "arguments", R.rawArguments, P);
}
-llvm::json::Value toJSON(const Response &R) {
- llvm::json::Object Result{{"type", "response"},
- {"req", 0},
- {"command", R.command},
- {"request_seq", R.request_seq},
- {"success", R.success}};
+json::Value toJSON(const Response &R) {
+ json::Object Result{{"type", "response"},
+ {"req", 0},
+ {"command", R.command},
+ {"request_seq", R.request_seq},
+ {"success", R.success}};
if (R.message)
Result.insert({"message", R.message});
+
if (R.rawBody)
Result.insert({"body", R.rawBody});
return std::move(Result);
}
-bool fromJSON(llvm::json::Value const &Params, Response &R,
- llvm::json::Path P) {
- llvm::json::ObjectMapper O(Params, P);
+bool fromJSON(json::Value const &Params, Response &R, json::Path P) {
+ json::ObjectMapper O(Params, P);
+ if (!O)
+ return false;
+
MessageType type;
- if (!O.map("type", type)) {
+ int64_t seq;
+ if (!O.map("type", type) || !O.map("seq", seq) ||
+ !O.map("command", R.command) || !O.map("request_seq", R.request_seq))
return false;
- }
+
if (type != MessageType::response) {
P.field("type").report("expected to be 'response'");
return false;
}
- return O && O.map("command", R.command) &&
- O.map("request_seq", R.request_seq) && O.map("success", R.success) &&
- O.mapOptional("message", R.message) &&
- O.mapOptional("body", R.rawBody);
+
+ if (seq != 0) {
+ P.field("seq").report("expected to be '0'");
+ return false;
+ }
+
+ if (R.command.empty()) {
+ P.field("command").report("expected to not be ''");
+ return false;
+ }
+
+ if (R.request_seq == 0) {
+ P.field("request_seq").report("expected to not be '0'");
+ return false;
+ }
+
+ return O.map("success", R.success) && O.mapOptional("message", R.message) &&
+ mapRaw(Params, "body", R.rawBody, P);
}
-llvm::json::Value toJSON(const Event &E) {
- llvm::json::Object Result{
+json::Value toJSON(const Event &E) {
+ json::Object Result{
{"type", "event"},
{"seq", 0},
{"event", E.event},
};
+
if (E.rawBody)
Result.insert({"body", E.rawBody});
+
if (E.statistics)
Result.insert({"statistics", E.statistics});
+
return std::move(Result);
}
-bool fromJSON(llvm::json::Value const &Params, Event &E, llvm::json::Path P) {
- llvm::json::ObjectMapper O(Params, P);
+bool fromJSON(json::Value const &Params, Event &E, json::Path P) {
+ json::ObjectMapper O(Params, P);
+ if (!O)
+ return false;
+
MessageType type;
- if (!O.map("type", type)) {
+ int64_t seq;
+ if (!O.map("type", type) || !O.map("seq", seq) || O.map("event", E.event))
return false;
- }
+
if (type != MessageType::event) {
P.field("type").report("expected to be 'event'");
return false;
}
- return O && O.map("event", E.event) && O.mapOptional("body", E.rawBody) &&
- O.mapOptional("statistics", E.statistics);
+ if (seq != 0) {
+ P.field("seq").report("expected to be '0'");
+ return false;
+ }
+
+ if (E.event.empty()) {
+ P.field("event").report("expected to not be ''");
+ return false;
+ }
+
+ return mapRaw(Params, "body", E.rawBody, P) &&
+ mapRaw(Params, "statistics", E.statistics, P);
}
-bool fromJSON(const llvm::json::Value &Params, ProtocolMessage &PM,
- llvm::json::Path P) {
- llvm::json::ObjectMapper O(Params, P);
+bool fromJSON(const json::Value &Params, Message &PM, json::Path P) {
+ json::ObjectMapper O(Params, P);
if (!O)
return false;
@@ -149,42 +202,29 @@ bool fromJSON(const llvm::json::Value &Params, ProtocolMessage &PM,
switch (type) {
case MessageType::request: {
Request req;
- if (!fromJSON(Params, req, P)) {
+ if (!fromJSON(Params, req, P))
return false;
- }
PM = std::move(req);
return true;
}
case MessageType::response: {
Response resp;
- if (!fromJSON(Params, resp, P)) {
+ if (!fromJSON(Params, resp, P))
return false;
- }
PM = std::move(resp);
return true;
}
case MessageType::event:
Event evt;
- if (!fromJSON(Params, evt, P)) {
+ if (!fromJSON(Params, evt, P))
return false;
- }
PM = std::move(evt);
return true;
}
- llvm_unreachable("Unsupported protocol message");
}
-llvm::json::Value toJSON(const ProtocolMessage &PM) {
- if (auto const *Req = std::get_if<Request>(&PM)) {
- return toJSON(*Req);
- }
- if (auto const *Resp = std::get_if<Response>(&PM)) {
- return toJSON(*Resp);
- }
- if (auto const *Evt = std::get_if<Event>(&PM)) {
- return toJSON(*Evt);
- }
- llvm_unreachable("Unsupported protocol message");
+json::Value toJSON(const Message &M) {
+ return std::visit([](auto &M) { return toJSON(M); }, M);
}
} // namespace protocol
diff --git a/lldb/tools/lldb-dap/Protocol.h b/lldb/tools/lldb-dap/Protocol.h
index 0d38f8b249094..0318161fd4eb6 100644
--- a/lldb/tools/lldb-dap/Protocol.h
+++ b/lldb/tools/lldb-dap/Protocol.h
@@ -177,9 +177,9 @@ using VoidResponseBody = std::nullptr_t;
// },
// "required": [ "seq", "type" ]
// },
-using ProtocolMessage = std::variant<Request, Response, Event>;
-bool fromJSON(const llvm::json::Value &, ProtocolMessage &, llvm::json::Path);
-llvm::json::Value toJSON(const ProtocolMessage &);
+using Message = std::variant<Request, Response, Event>;
+bool fromJSON(const llvm::json::Value &, Message &, llvm::json::Path);
+llvm::json::Value toJSON(const Message &);
} // namespace protocol
} // namespace lldb_dap
>From a76b3eb2cde75f0ecb2b5e04cf8fe540090e1cc6 Mon Sep 17 00:00:00 2001
From: John Harrison <harjohn at google.com>
Date: Fri, 28 Feb 2025 09:42:12 -0800
Subject: [PATCH 3/3] Applying reviewer suggestions.
---
lldb/tools/lldb-dap/Protocol.h | 9 ++-------
1 file changed, 2 insertions(+), 7 deletions(-)
diff --git a/lldb/tools/lldb-dap/Protocol.h b/lldb/tools/lldb-dap/Protocol.h
index 0318161fd4eb6..ff75f47aa2d95 100644
--- a/lldb/tools/lldb-dap/Protocol.h
+++ b/lldb/tools/lldb-dap/Protocol.h
@@ -27,8 +27,7 @@
#include <string>
#include <variant>
-namespace lldb_dap {
-namespace protocol {
+namespace lldb_dap::protocol {
// MARK: Base Protocol
@@ -151,9 +150,6 @@ struct Response {
bool fromJSON(const llvm::json::Value &, Response &, llvm::json::Path);
llvm::json::Value toJSON(const Response &);
-// A void response body for any response without a specific value.
-using VoidResponseBody = std::nullptr_t;
-
// "ProtocolMessage": {
// "type": "object",
// "title": "Base Protocol",
@@ -181,7 +177,6 @@ using Message = std::variant<Request, Response, Event>;
bool fromJSON(const llvm::json::Value &, Message &, llvm::json::Path);
llvm::json::Value toJSON(const Message &);
-} // namespace protocol
-} // namespace lldb_dap
+} // namespace lldb_dap::protocol
#endif
More information about the lldb-commits
mailing list