Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/Plugins/Protocol/MCP/Protocol.cpp
213845 views
1
//===- Protocol.cpp -------------------------------------------------------===//
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
#include "Protocol.h"
10
#include "llvm/Support/JSON.h"
11
12
using namespace llvm;
13
14
namespace lldb_private::mcp::protocol {
15
16
static bool mapRaw(const json::Value &Params, StringLiteral Prop,
17
std::optional<json::Value> &V, json::Path P) {
18
const auto *O = Params.getAsObject();
19
if (!O) {
20
P.report("expected object");
21
return false;
22
}
23
const json::Value *E = O->get(Prop);
24
if (E)
25
V = std::move(*E);
26
return true;
27
}
28
29
llvm::json::Value toJSON(const Request &R) {
30
json::Object Result{{"jsonrpc", "2.0"}, {"id", R.id}, {"method", R.method}};
31
if (R.params)
32
Result.insert({"params", R.params});
33
return Result;
34
}
35
36
bool fromJSON(const llvm::json::Value &V, Request &R, llvm::json::Path P) {
37
llvm::json::ObjectMapper O(V, P);
38
if (!O || !O.map("id", R.id) || !O.map("method", R.method))
39
return false;
40
return mapRaw(V, "params", R.params, P);
41
}
42
43
llvm::json::Value toJSON(const ErrorInfo &EI) {
44
llvm::json::Object Result{{"code", EI.code}, {"message", EI.message}};
45
if (!EI.data.empty())
46
Result.insert({"data", EI.data});
47
return Result;
48
}
49
50
bool fromJSON(const llvm::json::Value &V, ErrorInfo &EI, llvm::json::Path P) {
51
llvm::json::ObjectMapper O(V, P);
52
return O && O.map("code", EI.code) && O.map("message", EI.message) &&
53
O.mapOptional("data", EI.data);
54
}
55
56
llvm::json::Value toJSON(const Error &E) {
57
return json::Object{{"jsonrpc", "2.0"}, {"id", E.id}, {"error", E.error}};
58
}
59
60
bool fromJSON(const llvm::json::Value &V, Error &E, llvm::json::Path P) {
61
llvm::json::ObjectMapper O(V, P);
62
return O && O.map("id", E.id) && O.map("error", E.error);
63
}
64
65
llvm::json::Value toJSON(const Response &R) {
66
llvm::json::Object Result{{"jsonrpc", "2.0"}, {"id", R.id}};
67
if (R.result)
68
Result.insert({"result", R.result});
69
if (R.error)
70
Result.insert({"error", R.error});
71
return Result;
72
}
73
74
bool fromJSON(const llvm::json::Value &V, Response &R, llvm::json::Path P) {
75
llvm::json::ObjectMapper O(V, P);
76
if (!O || !O.map("id", R.id) || !O.map("error", R.error))
77
return false;
78
return mapRaw(V, "result", R.result, P);
79
}
80
81
llvm::json::Value toJSON(const Notification &N) {
82
llvm::json::Object Result{{"jsonrpc", "2.0"}, {"method", N.method}};
83
if (N.params)
84
Result.insert({"params", N.params});
85
return Result;
86
}
87
88
bool fromJSON(const llvm::json::Value &V, Notification &N, llvm::json::Path P) {
89
llvm::json::ObjectMapper O(V, P);
90
if (!O || !O.map("method", N.method))
91
return false;
92
auto *Obj = V.getAsObject();
93
if (!Obj)
94
return false;
95
if (auto *Params = Obj->get("params"))
96
N.params = *Params;
97
return true;
98
}
99
100
llvm::json::Value toJSON(const ToolCapability &TC) {
101
return llvm::json::Object{{"listChanged", TC.listChanged}};
102
}
103
104
bool fromJSON(const llvm::json::Value &V, ToolCapability &TC,
105
llvm::json::Path P) {
106
llvm::json::ObjectMapper O(V, P);
107
return O && O.map("listChanged", TC.listChanged);
108
}
109
110
llvm::json::Value toJSON(const ResourceCapability &RC) {
111
return llvm::json::Object{{"listChanged", RC.listChanged},
112
{"subscribe", RC.subscribe}};
113
}
114
115
bool fromJSON(const llvm::json::Value &V, ResourceCapability &RC,
116
llvm::json::Path P) {
117
llvm::json::ObjectMapper O(V, P);
118
return O && O.map("listChanged", RC.listChanged) &&
119
O.map("subscribe", RC.subscribe);
120
}
121
122
llvm::json::Value toJSON(const Capabilities &C) {
123
return llvm::json::Object{{"tools", C.tools}, {"resources", C.resources}};
124
}
125
126
bool fromJSON(const llvm::json::Value &V, Resource &R, llvm::json::Path P) {
127
llvm::json::ObjectMapper O(V, P);
128
return O && O.map("uri", R.uri) && O.map("name", R.name) &&
129
O.mapOptional("description", R.description) &&
130
O.mapOptional("mimeType", R.mimeType);
131
}
132
133
llvm::json::Value toJSON(const Resource &R) {
134
llvm::json::Object Result{{"uri", R.uri}, {"name", R.name}};
135
if (!R.description.empty())
136
Result.insert({"description", R.description});
137
if (!R.mimeType.empty())
138
Result.insert({"mimeType", R.mimeType});
139
return Result;
140
}
141
142
bool fromJSON(const llvm::json::Value &V, Capabilities &C, llvm::json::Path P) {
143
llvm::json::ObjectMapper O(V, P);
144
return O && O.map("tools", C.tools);
145
}
146
147
llvm::json::Value toJSON(const ResourceContents &RC) {
148
llvm::json::Object Result{{"uri", RC.uri}, {"text", RC.text}};
149
if (!RC.mimeType.empty())
150
Result.insert({"mimeType", RC.mimeType});
151
return Result;
152
}
153
154
bool fromJSON(const llvm::json::Value &V, ResourceContents &RC,
155
llvm::json::Path P) {
156
llvm::json::ObjectMapper O(V, P);
157
return O && O.map("uri", RC.uri) && O.map("text", RC.text) &&
158
O.mapOptional("mimeType", RC.mimeType);
159
}
160
161
llvm::json::Value toJSON(const ResourceResult &RR) {
162
return llvm::json::Object{{"contents", RR.contents}};
163
}
164
165
bool fromJSON(const llvm::json::Value &V, ResourceResult &RR,
166
llvm::json::Path P) {
167
llvm::json::ObjectMapper O(V, P);
168
return O && O.map("contents", RR.contents);
169
}
170
171
llvm::json::Value toJSON(const TextContent &TC) {
172
return llvm::json::Object{{"type", "text"}, {"text", TC.text}};
173
}
174
175
bool fromJSON(const llvm::json::Value &V, TextContent &TC, llvm::json::Path P) {
176
llvm::json::ObjectMapper O(V, P);
177
return O && O.map("text", TC.text);
178
}
179
180
llvm::json::Value toJSON(const TextResult &TR) {
181
return llvm::json::Object{{"content", TR.content}, {"isError", TR.isError}};
182
}
183
184
bool fromJSON(const llvm::json::Value &V, TextResult &TR, llvm::json::Path P) {
185
llvm::json::ObjectMapper O(V, P);
186
return O && O.map("content", TR.content) && O.map("isError", TR.isError);
187
}
188
189
llvm::json::Value toJSON(const ToolDefinition &TD) {
190
llvm::json::Object Result{{"name", TD.name}};
191
if (!TD.description.empty())
192
Result.insert({"description", TD.description});
193
if (TD.inputSchema)
194
Result.insert({"inputSchema", TD.inputSchema});
195
return Result;
196
}
197
198
bool fromJSON(const llvm::json::Value &V, ToolDefinition &TD,
199
llvm::json::Path P) {
200
201
llvm::json::ObjectMapper O(V, P);
202
if (!O || !O.map("name", TD.name) ||
203
!O.mapOptional("description", TD.description))
204
return false;
205
return mapRaw(V, "inputSchema", TD.inputSchema, P);
206
}
207
208
llvm::json::Value toJSON(const Message &M) {
209
return std::visit([](auto &M) { return toJSON(M); }, M);
210
}
211
212
bool fromJSON(const llvm::json::Value &V, Message &M, llvm::json::Path P) {
213
const auto *O = V.getAsObject();
214
if (!O) {
215
P.report("expected object");
216
return false;
217
}
218
219
if (const json::Value *V = O->get("jsonrpc")) {
220
if (V->getAsString().value_or("") != "2.0") {
221
P.report("unsupported JSON RPC version");
222
return false;
223
}
224
} else {
225
P.report("not a valid JSON RPC message");
226
return false;
227
}
228
229
// A message without an ID is a Notification.
230
if (!O->get("id")) {
231
protocol::Notification N;
232
if (!fromJSON(V, N, P))
233
return false;
234
M = std::move(N);
235
return true;
236
}
237
238
if (O->get("error")) {
239
protocol::Error E;
240
if (!fromJSON(V, E, P))
241
return false;
242
M = std::move(E);
243
return true;
244
}
245
246
if (O->get("result")) {
247
protocol::Response R;
248
if (!fromJSON(V, R, P))
249
return false;
250
M = std::move(R);
251
return true;
252
}
253
254
if (O->get("method")) {
255
protocol::Request R;
256
if (!fromJSON(V, R, P))
257
return false;
258
M = std::move(R);
259
return true;
260
}
261
262
P.report("unrecognized message type");
263
return false;
264
}
265
266
} // namespace lldb_private::mcp::protocol
267
268