1 | //===-- ProtocolBase.h ----------------------------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file contains POD structs based on the DAP specification at |
10 | // https://microsoft.github.io/debug-adapter-protocol/specification |
11 | // |
12 | // This is not meant to be a complete implementation, new interfaces are added |
13 | // when they're needed. |
14 | // |
15 | // Each struct has a toJSON and fromJSON function, that converts between |
16 | // the struct and a JSON representation. (See JSON.h) |
17 | // |
18 | //===----------------------------------------------------------------------===// |
19 | |
20 | #ifndef LLDB_TOOLS_LLDB_DAP_PROTOCOL_PROTOCOL_BASE_H |
21 | #define LLDB_TOOLS_LLDB_DAP_PROTOCOL_PROTOCOL_BASE_H |
22 | |
23 | #include "llvm/Support/JSON.h" |
24 | #include <cstdint> |
25 | #include <optional> |
26 | #include <string> |
27 | #include <variant> |
28 | |
29 | namespace lldb_dap::protocol { |
30 | |
31 | // MARK: Base Protocol |
32 | |
33 | /// A client or debug adapter initiated request. |
34 | struct Request { |
35 | /// Sequence number of the message (also known as message ID). The `seq` for |
36 | /// the first message sent by a client or debug adapter is 1, and for each |
37 | /// subsequent message is 1 greater than the previous message sent by that |
38 | /// actor. `seq` can be used to order requests, responses, and events, and to |
39 | /// associate requests with their corresponding responses. For protocol |
40 | /// messages of type `request` the sequence number can be used to cancel the |
41 | /// request. |
42 | int64_t seq; |
43 | |
44 | /// The command to execute. |
45 | std::string command; |
46 | |
47 | /// Object containing arguments for the command. |
48 | /// |
49 | /// Request handlers are expected to validate the arguments, which is handled |
50 | /// by `RequestHandler`. |
51 | std::optional<llvm::json::Value> arguments; |
52 | }; |
53 | llvm::json::Value toJSON(const Request &); |
54 | bool fromJSON(const llvm::json::Value &, Request &, llvm::json::Path); |
55 | |
56 | /// A debug adapter initiated event. |
57 | struct Event { |
58 | /// Type of event. |
59 | std::string event; |
60 | |
61 | /// Event-specific information. |
62 | std::optional<llvm::json::Value> body; |
63 | }; |
64 | llvm::json::Value toJSON(const Event &); |
65 | bool fromJSON(const llvm::json::Value &, Event &, llvm::json::Path); |
66 | |
67 | enum ResponseMessage : unsigned { |
68 | /// The request was cancelled |
69 | eResponseMessageCancelled, |
70 | /// The request may be retried once the adapter is in a 'stopped' state |
71 | eResponseMessageNotStopped, |
72 | }; |
73 | |
74 | /// Response for a request. |
75 | struct Response { |
76 | /// Sequence number of the corresponding request. |
77 | int64_t request_seq; |
78 | |
79 | /// The command requested. |
80 | std::string command; |
81 | |
82 | /// Outcome of the request. If true, the request was successful and the `body` |
83 | /// attribute may contain the result of the request. If the value is false, |
84 | /// the attribute `message` contains the error in short form and the `body` |
85 | /// may contain additional information (see `ErrorMessage`). |
86 | bool success; |
87 | |
88 | // FIXME: Migrate usage of fallback string to ErrorMessage |
89 | |
90 | /// Contains the raw error in short form if `success` is false. This raw error |
91 | /// might be interpreted by the client and is not shown in the UI. Some |
92 | /// predefined values exist. |
93 | std::optional<std::variant<ResponseMessage, std::string>> message; |
94 | |
95 | /// Contains request result if success is true and error details if success is |
96 | /// false. |
97 | /// |
98 | /// Request handlers are expected to build an appropriate body, see |
99 | /// `RequestHandler`. |
100 | std::optional<llvm::json::Value> body; |
101 | }; |
102 | bool fromJSON(const llvm::json::Value &, Response &, llvm::json::Path); |
103 | llvm::json::Value toJSON(const Response &); |
104 | |
105 | /// A structured message object. Used to return errors from requests. |
106 | struct ErrorMessage { |
107 | /// Unique (within a debug adapter implementation) identifier for the message. |
108 | /// The purpose of these error IDs is to help extension authors that have the |
109 | /// requirement that every user visible error message needs a corresponding |
110 | /// error number, so that users or customer support can find information about |
111 | /// the specific error more easily. |
112 | uint64_t id = 0; |
113 | |
114 | /// A format string for the message. Embedded variables have the form |
115 | /// `{name}`. If variable name starts with an underscore character, the |
116 | /// variable does not contain user data (PII) and can be safely used for |
117 | /// telemetry purposes. |
118 | std::string format; |
119 | |
120 | /// An object used as a dictionary for looking up the variables in the format |
121 | /// string. |
122 | std::optional<std::map<std::string, std::string>> variables; |
123 | |
124 | /// If true send to telemetry. |
125 | bool sendTelemetry = false; |
126 | |
127 | /// If true show user. |
128 | bool showUser = false; |
129 | |
130 | /// A url where additional information about this message can be found. |
131 | std::optional<std::string> url; |
132 | |
133 | /// A label that is presented to the user as the UI for opening the url. |
134 | std::optional<std::string> urlLabel; |
135 | }; |
136 | bool fromJSON(const llvm::json::Value &, ErrorMessage &, llvm::json::Path); |
137 | llvm::json::Value toJSON(const ErrorMessage &); |
138 | |
139 | /// An individual protocol message of requests, responses, and events. |
140 | using Message = std::variant<Request, Response, Event>; |
141 | bool fromJSON(const llvm::json::Value &, Message &, llvm::json::Path); |
142 | llvm::json::Value toJSON(const Message &); |
143 | |
144 | inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Message &V) { |
145 | OS << toJSON(V); |
146 | return OS; |
147 | } |
148 | |
149 | /// On error (whenever `success` is false), the body can provide more details. |
150 | struct ErrorResponseBody { |
151 | /// A structured error message. |
152 | std::optional<ErrorMessage> error; |
153 | }; |
154 | llvm::json::Value toJSON(const ErrorResponseBody &); |
155 | |
156 | /// This is a placehold for requests with an empty, null or undefined arguments. |
157 | using EmptyArguments = std::optional<std::monostate>; |
158 | |
159 | /// This is just an acknowledgement, so no body field is required. |
160 | using VoidResponse = llvm::Error; |
161 | |
162 | } // namespace lldb_dap::protocol |
163 | |
164 | #endif |
165 | |