150
|
1 //===--- Protocol.cpp - Language Server Protocol Implementation -----------===//
|
|
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 the serialization code for the LSP structs.
|
|
10 //
|
|
11 //===----------------------------------------------------------------------===//
|
|
12
|
|
13 #include "Protocol.h"
|
|
14 #include "URI.h"
|
173
|
15 #include "support/Logger.h"
|
150
|
16 #include "clang/Basic/LLVM.h"
|
173
|
17 #include "clang/Index/IndexSymbol.h"
|
150
|
18 #include "llvm/ADT/Hashing.h"
|
|
19 #include "llvm/ADT/SmallString.h"
|
|
20 #include "llvm/ADT/StringSwitch.h"
|
|
21 #include "llvm/Support/ErrorHandling.h"
|
|
22 #include "llvm/Support/Format.h"
|
|
23 #include "llvm/Support/FormatVariadic.h"
|
|
24 #include "llvm/Support/JSON.h"
|
|
25 #include "llvm/Support/Path.h"
|
|
26 #include "llvm/Support/raw_ostream.h"
|
|
27
|
|
28 namespace clang {
|
|
29 namespace clangd {
|
221
|
30 namespace {
|
|
31
|
|
32 // Helper that doesn't treat `null` and absent fields as failures.
|
|
33 template <typename T>
|
|
34 bool mapOptOrNull(const llvm::json::Value &Params, llvm::StringLiteral Prop,
|
|
35 T &Out, llvm::json::Path P) {
|
|
36 auto *O = Params.getAsObject();
|
|
37 assert(O);
|
|
38 auto *V = O->get(Prop);
|
|
39 // Field is missing or null.
|
|
40 if (!V || V->getAsNull().hasValue())
|
|
41 return true;
|
|
42 return fromJSON(*V, Out, P.field(Prop));
|
|
43 }
|
|
44 } // namespace
|
150
|
45
|
|
46 char LSPError::ID;
|
|
47
|
|
48 URIForFile URIForFile::canonicalize(llvm::StringRef AbsPath,
|
|
49 llvm::StringRef TUPath) {
|
|
50 assert(llvm::sys::path::is_absolute(AbsPath) && "the path is relative");
|
|
51 auto Resolved = URI::resolvePath(AbsPath, TUPath);
|
|
52 if (!Resolved) {
|
|
53 elog("URIForFile: failed to resolve path {0} with TU path {1}: "
|
|
54 "{2}.\nUsing unresolved path.",
|
|
55 AbsPath, TUPath, Resolved.takeError());
|
|
56 return URIForFile(std::string(AbsPath));
|
|
57 }
|
|
58 return URIForFile(std::move(*Resolved));
|
|
59 }
|
|
60
|
|
61 llvm::Expected<URIForFile> URIForFile::fromURI(const URI &U,
|
|
62 llvm::StringRef HintPath) {
|
|
63 auto Resolved = URI::resolve(U, HintPath);
|
|
64 if (!Resolved)
|
|
65 return Resolved.takeError();
|
|
66 return URIForFile(std::move(*Resolved));
|
|
67 }
|
|
68
|
221
|
69 bool fromJSON(const llvm::json::Value &E, URIForFile &R, llvm::json::Path P) {
|
150
|
70 if (auto S = E.getAsString()) {
|
|
71 auto Parsed = URI::parse(*S);
|
|
72 if (!Parsed) {
|
221
|
73 consumeError(Parsed.takeError());
|
|
74 P.report("failed to parse URI");
|
150
|
75 return false;
|
|
76 }
|
|
77 if (Parsed->scheme() != "file" && Parsed->scheme() != "test") {
|
221
|
78 P.report("clangd only supports 'file' URI scheme for workspace files");
|
150
|
79 return false;
|
|
80 }
|
|
81 // "file" and "test" schemes do not require hint path.
|
|
82 auto U = URIForFile::fromURI(*Parsed, /*HintPath=*/"");
|
|
83 if (!U) {
|
221
|
84 P.report("unresolvable URI");
|
|
85 consumeError(U.takeError());
|
150
|
86 return false;
|
|
87 }
|
|
88 R = std::move(*U);
|
|
89 return true;
|
|
90 }
|
|
91 return false;
|
|
92 }
|
|
93
|
|
94 llvm::json::Value toJSON(const URIForFile &U) { return U.uri(); }
|
|
95
|
|
96 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const URIForFile &U) {
|
|
97 return OS << U.uri();
|
|
98 }
|
|
99
|
|
100 llvm::json::Value toJSON(const TextDocumentIdentifier &R) {
|
|
101 return llvm::json::Object{{"uri", R.uri}};
|
|
102 }
|
|
103
|
221
|
104 bool fromJSON(const llvm::json::Value &Params, TextDocumentIdentifier &R,
|
|
105 llvm::json::Path P) {
|
|
106 llvm::json::ObjectMapper O(Params, P);
|
150
|
107 return O && O.map("uri", R.uri);
|
|
108 }
|
|
109
|
173
|
110 llvm::json::Value toJSON(const VersionedTextDocumentIdentifier &R) {
|
|
111 auto Result = toJSON(static_cast<const TextDocumentIdentifier &>(R));
|
|
112 Result.getAsObject()->try_emplace("version", R.version);
|
|
113 return Result;
|
|
114 }
|
|
115
|
|
116 bool fromJSON(const llvm::json::Value &Params,
|
221
|
117 VersionedTextDocumentIdentifier &R, llvm::json::Path P) {
|
|
118 llvm::json::ObjectMapper O(Params, P);
|
|
119 return fromJSON(Params, static_cast<TextDocumentIdentifier &>(R), P) && O &&
|
173
|
120 O.map("version", R.version);
|
|
121 }
|
|
122
|
221
|
123 bool fromJSON(const llvm::json::Value &Params, Position &R,
|
|
124 llvm::json::Path P) {
|
|
125 llvm::json::ObjectMapper O(Params, P);
|
150
|
126 return O && O.map("line", R.line) && O.map("character", R.character);
|
|
127 }
|
|
128
|
|
129 llvm::json::Value toJSON(const Position &P) {
|
|
130 return llvm::json::Object{
|
|
131 {"line", P.line},
|
|
132 {"character", P.character},
|
|
133 };
|
|
134 }
|
|
135
|
|
136 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Position &P) {
|
|
137 return OS << P.line << ':' << P.character;
|
|
138 }
|
|
139
|
221
|
140 bool fromJSON(const llvm::json::Value &Params, Range &R, llvm::json::Path P) {
|
|
141 llvm::json::ObjectMapper O(Params, P);
|
150
|
142 return O && O.map("start", R.start) && O.map("end", R.end);
|
|
143 }
|
|
144
|
|
145 llvm::json::Value toJSON(const Range &P) {
|
|
146 return llvm::json::Object{
|
|
147 {"start", P.start},
|
|
148 {"end", P.end},
|
|
149 };
|
|
150 }
|
|
151
|
|
152 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Range &R) {
|
|
153 return OS << R.start << '-' << R.end;
|
|
154 }
|
|
155
|
|
156 llvm::json::Value toJSON(const Location &P) {
|
|
157 return llvm::json::Object{
|
|
158 {"uri", P.uri},
|
|
159 {"range", P.range},
|
|
160 };
|
|
161 }
|
|
162
|
|
163 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Location &L) {
|
|
164 return OS << L.range << '@' << L.uri;
|
|
165 }
|
|
166
|
221
|
167 bool fromJSON(const llvm::json::Value &Params, TextDocumentItem &R,
|
|
168 llvm::json::Path P) {
|
|
169 llvm::json::ObjectMapper O(Params, P);
|
150
|
170 return O && O.map("uri", R.uri) && O.map("languageId", R.languageId) &&
|
|
171 O.map("version", R.version) && O.map("text", R.text);
|
|
172 }
|
|
173
|
221
|
174 bool fromJSON(const llvm::json::Value &Params, TextEdit &R,
|
|
175 llvm::json::Path P) {
|
|
176 llvm::json::ObjectMapper O(Params, P);
|
150
|
177 return O && O.map("range", R.range) && O.map("newText", R.newText);
|
|
178 }
|
|
179
|
|
180 llvm::json::Value toJSON(const TextEdit &P) {
|
|
181 return llvm::json::Object{
|
|
182 {"range", P.range},
|
|
183 {"newText", P.newText},
|
|
184 };
|
|
185 }
|
|
186
|
|
187 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const TextEdit &TE) {
|
|
188 OS << TE.range << " => \"";
|
|
189 llvm::printEscapedString(TE.newText, OS);
|
|
190 return OS << '"';
|
|
191 }
|
|
192
|
221
|
193 bool fromJSON(const llvm::json::Value &E, TraceLevel &Out, llvm::json::Path P) {
|
150
|
194 if (auto S = E.getAsString()) {
|
|
195 if (*S == "off") {
|
|
196 Out = TraceLevel::Off;
|
|
197 return true;
|
221
|
198 }
|
|
199 if (*S == "messages") {
|
150
|
200 Out = TraceLevel::Messages;
|
|
201 return true;
|
221
|
202 }
|
|
203 if (*S == "verbose") {
|
150
|
204 Out = TraceLevel::Verbose;
|
|
205 return true;
|
|
206 }
|
|
207 }
|
|
208 return false;
|
|
209 }
|
|
210
|
221
|
211 bool fromJSON(const llvm::json::Value &E, SymbolKind &Out, llvm::json::Path P) {
|
150
|
212 if (auto T = E.getAsInteger()) {
|
|
213 if (*T < static_cast<int>(SymbolKind::File) ||
|
|
214 *T > static_cast<int>(SymbolKind::TypeParameter))
|
|
215 return false;
|
|
216 Out = static_cast<SymbolKind>(*T);
|
|
217 return true;
|
|
218 }
|
|
219 return false;
|
|
220 }
|
|
221
|
221
|
222 bool fromJSON(const llvm::json::Value &E, SymbolKindBitset &Out,
|
|
223 llvm::json::Path P) {
|
150
|
224 if (auto *A = E.getAsArray()) {
|
|
225 for (size_t I = 0; I < A->size(); ++I) {
|
|
226 SymbolKind KindOut;
|
221
|
227 if (fromJSON((*A)[I], KindOut, P.index(I)))
|
150
|
228 Out.set(size_t(KindOut));
|
|
229 }
|
|
230 return true;
|
|
231 }
|
|
232 return false;
|
|
233 }
|
|
234
|
|
235 SymbolKind adjustKindToCapability(SymbolKind Kind,
|
|
236 SymbolKindBitset &SupportedSymbolKinds) {
|
|
237 auto KindVal = static_cast<size_t>(Kind);
|
|
238 if (KindVal >= SymbolKindMin && KindVal <= SupportedSymbolKinds.size() &&
|
|
239 SupportedSymbolKinds[KindVal])
|
|
240 return Kind;
|
|
241
|
|
242 switch (Kind) {
|
|
243 // Provide some fall backs for common kinds that are close enough.
|
|
244 case SymbolKind::Struct:
|
|
245 return SymbolKind::Class;
|
|
246 case SymbolKind::EnumMember:
|
|
247 return SymbolKind::Enum;
|
|
248 default:
|
|
249 return SymbolKind::String;
|
|
250 }
|
|
251 }
|
|
252
|
|
253 SymbolKind indexSymbolKindToSymbolKind(index::SymbolKind Kind) {
|
|
254 switch (Kind) {
|
|
255 case index::SymbolKind::Unknown:
|
|
256 return SymbolKind::Variable;
|
|
257 case index::SymbolKind::Module:
|
|
258 return SymbolKind::Module;
|
|
259 case index::SymbolKind::Namespace:
|
|
260 return SymbolKind::Namespace;
|
|
261 case index::SymbolKind::NamespaceAlias:
|
|
262 return SymbolKind::Namespace;
|
|
263 case index::SymbolKind::Macro:
|
|
264 return SymbolKind::String;
|
|
265 case index::SymbolKind::Enum:
|
|
266 return SymbolKind::Enum;
|
|
267 case index::SymbolKind::Struct:
|
|
268 return SymbolKind::Struct;
|
|
269 case index::SymbolKind::Class:
|
|
270 return SymbolKind::Class;
|
|
271 case index::SymbolKind::Protocol:
|
|
272 return SymbolKind::Interface;
|
|
273 case index::SymbolKind::Extension:
|
|
274 return SymbolKind::Interface;
|
|
275 case index::SymbolKind::Union:
|
|
276 return SymbolKind::Class;
|
|
277 case index::SymbolKind::TypeAlias:
|
|
278 return SymbolKind::Class;
|
|
279 case index::SymbolKind::Function:
|
|
280 return SymbolKind::Function;
|
|
281 case index::SymbolKind::Variable:
|
|
282 return SymbolKind::Variable;
|
|
283 case index::SymbolKind::Field:
|
|
284 return SymbolKind::Field;
|
|
285 case index::SymbolKind::EnumConstant:
|
|
286 return SymbolKind::EnumMember;
|
|
287 case index::SymbolKind::InstanceMethod:
|
|
288 case index::SymbolKind::ClassMethod:
|
|
289 case index::SymbolKind::StaticMethod:
|
|
290 return SymbolKind::Method;
|
|
291 case index::SymbolKind::InstanceProperty:
|
|
292 case index::SymbolKind::ClassProperty:
|
|
293 case index::SymbolKind::StaticProperty:
|
|
294 return SymbolKind::Property;
|
|
295 case index::SymbolKind::Constructor:
|
|
296 case index::SymbolKind::Destructor:
|
|
297 return SymbolKind::Constructor;
|
|
298 case index::SymbolKind::ConversionFunction:
|
|
299 return SymbolKind::Function;
|
|
300 case index::SymbolKind::Parameter:
|
173
|
301 case index::SymbolKind::NonTypeTemplateParm:
|
150
|
302 return SymbolKind::Variable;
|
|
303 case index::SymbolKind::Using:
|
|
304 return SymbolKind::Namespace;
|
173
|
305 case index::SymbolKind::TemplateTemplateParm:
|
|
306 case index::SymbolKind::TemplateTypeParm:
|
|
307 return SymbolKind::TypeParameter;
|
150
|
308 }
|
|
309 llvm_unreachable("invalid symbol kind");
|
|
310 }
|
|
311
|
221
|
312 bool fromJSON(const llvm::json::Value &Params, ClientCapabilities &R,
|
|
313 llvm::json::Path P) {
|
150
|
314 const llvm::json::Object *O = Params.getAsObject();
|
221
|
315 if (!O) {
|
|
316 P.report("expected object");
|
150
|
317 return false;
|
221
|
318 }
|
150
|
319 if (auto *TextDocument = O->getObject("textDocument")) {
|
|
320 if (auto *SemanticHighlighting =
|
|
321 TextDocument->getObject("semanticHighlightingCapabilities")) {
|
|
322 if (auto SemanticHighlightingSupport =
|
|
323 SemanticHighlighting->getBoolean("semanticHighlighting"))
|
173
|
324 R.TheiaSemanticHighlighting = *SemanticHighlightingSupport;
|
150
|
325 }
|
173
|
326 if (TextDocument->getObject("semanticTokens"))
|
|
327 R.SemanticTokens = true;
|
150
|
328 if (auto *Diagnostics = TextDocument->getObject("publishDiagnostics")) {
|
|
329 if (auto CategorySupport = Diagnostics->getBoolean("categorySupport"))
|
|
330 R.DiagnosticCategory = *CategorySupport;
|
|
331 if (auto CodeActions = Diagnostics->getBoolean("codeActionsInline"))
|
|
332 R.DiagnosticFixes = *CodeActions;
|
|
333 if (auto RelatedInfo = Diagnostics->getBoolean("relatedInformation"))
|
|
334 R.DiagnosticRelatedInformation = *RelatedInfo;
|
|
335 }
|
|
336 if (auto *Completion = TextDocument->getObject("completion")) {
|
|
337 if (auto *Item = Completion->getObject("completionItem")) {
|
|
338 if (auto SnippetSupport = Item->getBoolean("snippetSupport"))
|
|
339 R.CompletionSnippets = *SnippetSupport;
|
221
|
340 if (const auto *DocumentationFormat =
|
|
341 Item->getArray("documentationFormat")) {
|
173
|
342 for (const auto &Format : *DocumentationFormat) {
|
221
|
343 if (fromJSON(Format, R.CompletionDocumentationFormat, P))
|
173
|
344 break;
|
|
345 }
|
|
346 }
|
150
|
347 }
|
|
348 if (auto *ItemKind = Completion->getObject("completionItemKind")) {
|
|
349 if (auto *ValueSet = ItemKind->get("valueSet")) {
|
|
350 R.CompletionItemKinds.emplace();
|
221
|
351 if (!fromJSON(*ValueSet, *R.CompletionItemKinds,
|
|
352 P.field("textDocument")
|
|
353 .field("completion")
|
|
354 .field("completionItemKind")
|
|
355 .field("valueSet")))
|
150
|
356 return false;
|
|
357 }
|
|
358 }
|
|
359 if (auto EditsNearCursor = Completion->getBoolean("editsNearCursor"))
|
|
360 R.CompletionFixes = *EditsNearCursor;
|
|
361 }
|
|
362 if (auto *CodeAction = TextDocument->getObject("codeAction")) {
|
|
363 if (CodeAction->getObject("codeActionLiteralSupport"))
|
|
364 R.CodeActionStructure = true;
|
|
365 }
|
|
366 if (auto *DocumentSymbol = TextDocument->getObject("documentSymbol")) {
|
|
367 if (auto HierarchicalSupport =
|
|
368 DocumentSymbol->getBoolean("hierarchicalDocumentSymbolSupport"))
|
|
369 R.HierarchicalDocumentSymbol = *HierarchicalSupport;
|
|
370 }
|
|
371 if (auto *Hover = TextDocument->getObject("hover")) {
|
|
372 if (auto *ContentFormat = Hover->getArray("contentFormat")) {
|
|
373 for (const auto &Format : *ContentFormat) {
|
221
|
374 if (fromJSON(Format, R.HoverContentFormat, P))
|
150
|
375 break;
|
|
376 }
|
|
377 }
|
|
378 }
|
|
379 if (auto *Help = TextDocument->getObject("signatureHelp")) {
|
|
380 R.HasSignatureHelp = true;
|
|
381 if (auto *Info = Help->getObject("signatureInformation")) {
|
|
382 if (auto *Parameter = Info->getObject("parameterInformation")) {
|
|
383 if (auto OffsetSupport = Parameter->getBoolean("labelOffsetSupport"))
|
|
384 R.OffsetsInSignatureHelp = *OffsetSupport;
|
|
385 }
|
|
386 }
|
|
387 }
|
|
388 if (auto *Rename = TextDocument->getObject("rename")) {
|
|
389 if (auto RenameSupport = Rename->getBoolean("prepareSupport"))
|
|
390 R.RenamePrepareSupport = *RenameSupport;
|
|
391 }
|
|
392 }
|
|
393 if (auto *Workspace = O->getObject("workspace")) {
|
|
394 if (auto *Symbol = Workspace->getObject("symbol")) {
|
|
395 if (auto *SymbolKind = Symbol->getObject("symbolKind")) {
|
|
396 if (auto *ValueSet = SymbolKind->get("valueSet")) {
|
|
397 R.WorkspaceSymbolKinds.emplace();
|
221
|
398 if (!fromJSON(*ValueSet, *R.WorkspaceSymbolKinds,
|
|
399 P.field("workspace")
|
|
400 .field("symbol")
|
|
401 .field("symbolKind")
|
|
402 .field("valueSet")))
|
150
|
403 return false;
|
|
404 }
|
|
405 }
|
|
406 }
|
221
|
407 if (auto *SemanticTokens = Workspace->getObject("semanticTokens")) {
|
|
408 if (auto RefreshSupport = SemanticTokens->getBoolean("refreshSupport"))
|
|
409 R.SemanticTokenRefreshSupport = *RefreshSupport;
|
|
410 }
|
150
|
411 }
|
|
412 if (auto *Window = O->getObject("window")) {
|
|
413 if (auto WorkDoneProgress = Window->getBoolean("workDoneProgress"))
|
|
414 R.WorkDoneProgress = *WorkDoneProgress;
|
|
415 if (auto Implicit = Window->getBoolean("implicitWorkDoneProgressCreate"))
|
|
416 R.ImplicitProgressCreation = *Implicit;
|
|
417 }
|
221
|
418 if (auto *General = O->getObject("general")) {
|
|
419 if (auto *StaleRequestSupport = General->getObject("staleRequestSupport")) {
|
|
420 if (auto Cancel = StaleRequestSupport->getBoolean("cancel"))
|
|
421 R.CancelsStaleRequests = *Cancel;
|
|
422 }
|
|
423 }
|
150
|
424 if (auto *OffsetEncoding = O->get("offsetEncoding")) {
|
|
425 R.offsetEncoding.emplace();
|
221
|
426 if (!fromJSON(*OffsetEncoding, *R.offsetEncoding,
|
|
427 P.field("offsetEncoding")))
|
150
|
428 return false;
|
|
429 }
|
|
430 return true;
|
|
431 }
|
|
432
|
221
|
433 bool fromJSON(const llvm::json::Value &Params, InitializeParams &R,
|
|
434 llvm::json::Path P) {
|
|
435 llvm::json::ObjectMapper O(Params, P);
|
150
|
436 if (!O)
|
|
437 return false;
|
|
438 // We deliberately don't fail if we can't parse individual fields.
|
|
439 // Failing to handle a slightly malformed initialize would be a disaster.
|
|
440 O.map("processId", R.processId);
|
|
441 O.map("rootUri", R.rootUri);
|
|
442 O.map("rootPath", R.rootPath);
|
|
443 O.map("capabilities", R.capabilities);
|
221
|
444 if (auto *RawCaps = Params.getAsObject()->getObject("capabilities"))
|
|
445 R.rawCapabilities = *RawCaps;
|
150
|
446 O.map("trace", R.trace);
|
|
447 O.map("initializationOptions", R.initializationOptions);
|
|
448 return true;
|
|
449 }
|
|
450
|
|
451 llvm::json::Value toJSON(const WorkDoneProgressCreateParams &P) {
|
|
452 return llvm::json::Object{{"token", P.token}};
|
|
453 }
|
|
454
|
|
455 llvm::json::Value toJSON(const WorkDoneProgressBegin &P) {
|
|
456 llvm::json::Object Result{
|
|
457 {"kind", "begin"},
|
|
458 {"title", P.title},
|
|
459 };
|
|
460 if (P.cancellable)
|
|
461 Result["cancellable"] = true;
|
|
462 if (P.percentage)
|
|
463 Result["percentage"] = 0;
|
173
|
464
|
|
465 // FIXME: workaround for older gcc/clang
|
|
466 return std::move(Result);
|
150
|
467 }
|
|
468
|
|
469 llvm::json::Value toJSON(const WorkDoneProgressReport &P) {
|
|
470 llvm::json::Object Result{{"kind", "report"}};
|
|
471 if (P.cancellable)
|
|
472 Result["cancellable"] = *P.cancellable;
|
|
473 if (P.message)
|
|
474 Result["message"] = *P.message;
|
|
475 if (P.percentage)
|
|
476 Result["percentage"] = *P.percentage;
|
173
|
477 // FIXME: workaround for older gcc/clang
|
|
478 return std::move(Result);
|
150
|
479 }
|
|
480
|
|
481 llvm::json::Value toJSON(const WorkDoneProgressEnd &P) {
|
|
482 llvm::json::Object Result{{"kind", "end"}};
|
|
483 if (P.message)
|
|
484 Result["message"] = *P.message;
|
173
|
485 // FIXME: workaround for older gcc/clang
|
|
486 return std::move(Result);
|
150
|
487 }
|
|
488
|
|
489 llvm::json::Value toJSON(const MessageType &R) {
|
|
490 return static_cast<int64_t>(R);
|
|
491 }
|
|
492
|
|
493 llvm::json::Value toJSON(const ShowMessageParams &R) {
|
|
494 return llvm::json::Object{{"type", R.type}, {"message", R.message}};
|
|
495 }
|
|
496
|
221
|
497 bool fromJSON(const llvm::json::Value &Params, DidOpenTextDocumentParams &R,
|
|
498 llvm::json::Path P) {
|
|
499 llvm::json::ObjectMapper O(Params, P);
|
150
|
500 return O && O.map("textDocument", R.textDocument);
|
|
501 }
|
|
502
|
221
|
503 bool fromJSON(const llvm::json::Value &Params, DidCloseTextDocumentParams &R,
|
|
504 llvm::json::Path P) {
|
|
505 llvm::json::ObjectMapper O(Params, P);
|
150
|
506 return O && O.map("textDocument", R.textDocument);
|
|
507 }
|
|
508
|
221
|
509 bool fromJSON(const llvm::json::Value &Params, DidSaveTextDocumentParams &R,
|
|
510 llvm::json::Path P) {
|
|
511 llvm::json::ObjectMapper O(Params, P);
|
173
|
512 return O && O.map("textDocument", R.textDocument);
|
|
513 }
|
|
514
|
221
|
515 bool fromJSON(const llvm::json::Value &Params, DidChangeTextDocumentParams &R,
|
|
516 llvm::json::Path P) {
|
|
517 llvm::json::ObjectMapper O(Params, P);
|
|
518 return O && O.map("textDocument", R.textDocument) &&
|
150
|
519 O.map("contentChanges", R.contentChanges) &&
|
221
|
520 O.map("wantDiagnostics", R.wantDiagnostics) &&
|
|
521 mapOptOrNull(Params, "forceRebuild", R.forceRebuild, P);
|
150
|
522 }
|
|
523
|
221
|
524 bool fromJSON(const llvm::json::Value &E, FileChangeType &Out,
|
|
525 llvm::json::Path P) {
|
150
|
526 if (auto T = E.getAsInteger()) {
|
|
527 if (*T < static_cast<int>(FileChangeType::Created) ||
|
|
528 *T > static_cast<int>(FileChangeType::Deleted))
|
|
529 return false;
|
|
530 Out = static_cast<FileChangeType>(*T);
|
|
531 return true;
|
|
532 }
|
|
533 return false;
|
|
534 }
|
|
535
|
221
|
536 bool fromJSON(const llvm::json::Value &Params, FileEvent &R,
|
|
537 llvm::json::Path P) {
|
|
538 llvm::json::ObjectMapper O(Params, P);
|
150
|
539 return O && O.map("uri", R.uri) && O.map("type", R.type);
|
|
540 }
|
|
541
|
221
|
542 bool fromJSON(const llvm::json::Value &Params, DidChangeWatchedFilesParams &R,
|
|
543 llvm::json::Path P) {
|
|
544 llvm::json::ObjectMapper O(Params, P);
|
150
|
545 return O && O.map("changes", R.changes);
|
|
546 }
|
|
547
|
|
548 bool fromJSON(const llvm::json::Value &Params,
|
221
|
549 TextDocumentContentChangeEvent &R, llvm::json::Path P) {
|
|
550 llvm::json::ObjectMapper O(Params, P);
|
150
|
551 return O && O.map("range", R.range) && O.map("rangeLength", R.rangeLength) &&
|
|
552 O.map("text", R.text);
|
|
553 }
|
|
554
|
221
|
555 bool fromJSON(const llvm::json::Value &Params, DocumentRangeFormattingParams &R,
|
|
556 llvm::json::Path P) {
|
|
557 llvm::json::ObjectMapper O(Params, P);
|
150
|
558 return O && O.map("textDocument", R.textDocument) && O.map("range", R.range);
|
|
559 }
|
|
560
|
|
561 bool fromJSON(const llvm::json::Value &Params,
|
221
|
562 DocumentOnTypeFormattingParams &R, llvm::json::Path P) {
|
|
563 llvm::json::ObjectMapper O(Params, P);
|
150
|
564 return O && O.map("textDocument", R.textDocument) &&
|
|
565 O.map("position", R.position) && O.map("ch", R.ch);
|
|
566 }
|
|
567
|
221
|
568 bool fromJSON(const llvm::json::Value &Params, DocumentFormattingParams &R,
|
|
569 llvm::json::Path P) {
|
|
570 llvm::json::ObjectMapper O(Params, P);
|
150
|
571 return O && O.map("textDocument", R.textDocument);
|
|
572 }
|
|
573
|
221
|
574 bool fromJSON(const llvm::json::Value &Params, DocumentSymbolParams &R,
|
|
575 llvm::json::Path P) {
|
|
576 llvm::json::ObjectMapper O(Params, P);
|
150
|
577 return O && O.map("textDocument", R.textDocument);
|
|
578 }
|
|
579
|
|
580 llvm::json::Value toJSON(const DiagnosticRelatedInformation &DRI) {
|
|
581 return llvm::json::Object{
|
|
582 {"location", DRI.location},
|
|
583 {"message", DRI.message},
|
|
584 };
|
|
585 }
|
|
586
|
|
587 llvm::json::Value toJSON(const Diagnostic &D) {
|
|
588 llvm::json::Object Diag{
|
|
589 {"range", D.range},
|
|
590 {"severity", D.severity},
|
|
591 {"message", D.message},
|
|
592 };
|
|
593 if (D.category)
|
|
594 Diag["category"] = *D.category;
|
|
595 if (D.codeActions)
|
|
596 Diag["codeActions"] = D.codeActions;
|
|
597 if (!D.code.empty())
|
|
598 Diag["code"] = D.code;
|
|
599 if (!D.source.empty())
|
|
600 Diag["source"] = D.source;
|
|
601 if (D.relatedInformation)
|
|
602 Diag["relatedInformation"] = *D.relatedInformation;
|
221
|
603 if (!D.data.empty())
|
|
604 Diag["data"] = llvm::json::Object(D.data);
|
173
|
605 // FIXME: workaround for older gcc/clang
|
150
|
606 return std::move(Diag);
|
|
607 }
|
|
608
|
221
|
609 bool fromJSON(const llvm::json::Value &Params, Diagnostic &R,
|
|
610 llvm::json::Path P) {
|
|
611 llvm::json::ObjectMapper O(Params, P);
|
|
612 if (!O)
|
150
|
613 return false;
|
221
|
614 if (auto *Data = Params.getAsObject()->getObject("data"))
|
|
615 R.data = *Data;
|
|
616 return O.map("range", R.range) && O.map("message", R.message) &&
|
|
617 mapOptOrNull(Params, "severity", R.severity, P) &&
|
|
618 mapOptOrNull(Params, "category", R.category, P) &&
|
|
619 mapOptOrNull(Params, "code", R.code, P) &&
|
|
620 mapOptOrNull(Params, "source", R.source, P);
|
150
|
621 }
|
|
622
|
173
|
623 llvm::json::Value toJSON(const PublishDiagnosticsParams &PDP) {
|
|
624 llvm::json::Object Result{
|
|
625 {"uri", PDP.uri},
|
|
626 {"diagnostics", PDP.diagnostics},
|
|
627 };
|
|
628 if (PDP.version)
|
|
629 Result["version"] = PDP.version;
|
|
630 return std::move(Result);
|
|
631 }
|
|
632
|
221
|
633 bool fromJSON(const llvm::json::Value &Params, CodeActionContext &R,
|
|
634 llvm::json::Path P) {
|
|
635 llvm::json::ObjectMapper O(Params, P);
|
|
636 if (!O || !O.map("diagnostics", R.diagnostics))
|
|
637 return false;
|
|
638 O.map("only", R.only);
|
|
639 return true;
|
150
|
640 }
|
|
641
|
|
642 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Diagnostic &D) {
|
|
643 OS << D.range << " [";
|
|
644 switch (D.severity) {
|
|
645 case 1:
|
|
646 OS << "error";
|
|
647 break;
|
|
648 case 2:
|
|
649 OS << "warning";
|
|
650 break;
|
|
651 case 3:
|
|
652 OS << "note";
|
|
653 break;
|
|
654 case 4:
|
|
655 OS << "remark";
|
|
656 break;
|
|
657 default:
|
|
658 OS << "diagnostic";
|
|
659 break;
|
|
660 }
|
|
661 return OS << '(' << D.severity << "): " << D.message << "]";
|
|
662 }
|
|
663
|
221
|
664 bool fromJSON(const llvm::json::Value &Params, CodeActionParams &R,
|
|
665 llvm::json::Path P) {
|
|
666 llvm::json::ObjectMapper O(Params, P);
|
150
|
667 return O && O.map("textDocument", R.textDocument) &&
|
|
668 O.map("range", R.range) && O.map("context", R.context);
|
|
669 }
|
|
670
|
221
|
671 bool fromJSON(const llvm::json::Value &Params, WorkspaceEdit &R,
|
|
672 llvm::json::Path P) {
|
|
673 llvm::json::ObjectMapper O(Params, P);
|
150
|
674 return O && O.map("changes", R.changes);
|
|
675 }
|
|
676
|
221
|
677 bool fromJSON(const llvm::json::Value &Params, ExecuteCommandParams &R,
|
|
678 llvm::json::Path P) {
|
|
679 llvm::json::ObjectMapper O(Params, P);
|
150
|
680 if (!O || !O.map("command", R.command))
|
|
681 return false;
|
|
682
|
221
|
683 const auto *Args = Params.getAsObject()->get("arguments");
|
|
684 if (!Args)
|
|
685 return true; // Missing args is ok, argument is null.
|
|
686 const auto *ArgsArray = Args->getAsArray();
|
|
687 if (!ArgsArray) {
|
|
688 P.field("arguments").report("expected array");
|
|
689 return false;
|
150
|
690 }
|
221
|
691 if (ArgsArray->size() > 1) {
|
|
692 P.field("arguments").report("Command should have 0 or 1 argument");
|
|
693 return false;
|
|
694 } else if (ArgsArray->size() == 1) {
|
|
695 R.argument = ArgsArray->front();
|
|
696 }
|
|
697 return true;
|
150
|
698 }
|
|
699
|
|
700 llvm::json::Value toJSON(const SymbolInformation &P) {
|
221
|
701 llvm::json::Object O{
|
150
|
702 {"name", P.name},
|
|
703 {"kind", static_cast<int>(P.kind)},
|
|
704 {"location", P.location},
|
|
705 {"containerName", P.containerName},
|
|
706 };
|
221
|
707 if (P.score)
|
|
708 O["score"] = *P.score;
|
|
709 return std::move(O);
|
150
|
710 }
|
|
711
|
|
712 llvm::raw_ostream &operator<<(llvm::raw_ostream &O,
|
|
713 const SymbolInformation &SI) {
|
|
714 O << SI.containerName << "::" << SI.name << " - " << toJSON(SI);
|
|
715 return O;
|
|
716 }
|
|
717
|
|
718 bool operator==(const SymbolDetails &LHS, const SymbolDetails &RHS) {
|
|
719 return LHS.name == RHS.name && LHS.containerName == RHS.containerName &&
|
|
720 LHS.USR == RHS.USR && LHS.ID == RHS.ID;
|
|
721 }
|
|
722
|
|
723 llvm::json::Value toJSON(const SymbolDetails &P) {
|
|
724 llvm::json::Object Result{{"name", llvm::json::Value(nullptr)},
|
|
725 {"containerName", llvm::json::Value(nullptr)},
|
|
726 {"usr", llvm::json::Value(nullptr)},
|
|
727 {"id", llvm::json::Value(nullptr)}};
|
|
728
|
|
729 if (!P.name.empty())
|
|
730 Result["name"] = P.name;
|
|
731
|
|
732 if (!P.containerName.empty())
|
|
733 Result["containerName"] = P.containerName;
|
|
734
|
|
735 if (!P.USR.empty())
|
|
736 Result["usr"] = P.USR;
|
|
737
|
221
|
738 if (P.ID)
|
|
739 Result["id"] = P.ID.str();
|
150
|
740
|
173
|
741 // FIXME: workaround for older gcc/clang
|
|
742 return std::move(Result);
|
150
|
743 }
|
|
744
|
|
745 llvm::raw_ostream &operator<<(llvm::raw_ostream &O, const SymbolDetails &S) {
|
|
746 if (!S.containerName.empty()) {
|
|
747 O << S.containerName;
|
|
748 llvm::StringRef ContNameRef;
|
|
749 if (!ContNameRef.endswith("::")) {
|
|
750 O << " ";
|
|
751 }
|
|
752 }
|
|
753 O << S.name << " - " << toJSON(S);
|
|
754 return O;
|
|
755 }
|
|
756
|
221
|
757 bool fromJSON(const llvm::json::Value &Params, WorkspaceSymbolParams &R,
|
|
758 llvm::json::Path P) {
|
|
759 llvm::json::ObjectMapper O(Params, P);
|
|
760 return O && O.map("query", R.query) &&
|
|
761 mapOptOrNull(Params, "limit", R.limit, P);
|
150
|
762 }
|
|
763
|
|
764 llvm::json::Value toJSON(const Command &C) {
|
|
765 auto Cmd = llvm::json::Object{{"title", C.title}, {"command", C.command}};
|
221
|
766 if (!C.argument.getAsNull())
|
|
767 Cmd["arguments"] = llvm::json::Array{C.argument};
|
150
|
768 return std::move(Cmd);
|
|
769 }
|
|
770
|
|
771 const llvm::StringLiteral CodeAction::QUICKFIX_KIND = "quickfix";
|
|
772 const llvm::StringLiteral CodeAction::REFACTOR_KIND = "refactor";
|
|
773 const llvm::StringLiteral CodeAction::INFO_KIND = "info";
|
|
774
|
|
775 llvm::json::Value toJSON(const CodeAction &CA) {
|
|
776 auto CodeAction = llvm::json::Object{{"title", CA.title}};
|
|
777 if (CA.kind)
|
|
778 CodeAction["kind"] = *CA.kind;
|
|
779 if (CA.diagnostics)
|
|
780 CodeAction["diagnostics"] = llvm::json::Array(*CA.diagnostics);
|
221
|
781 if (CA.isPreferred)
|
|
782 CodeAction["isPreferred"] = true;
|
150
|
783 if (CA.edit)
|
|
784 CodeAction["edit"] = *CA.edit;
|
|
785 if (CA.command)
|
|
786 CodeAction["command"] = *CA.command;
|
|
787 return std::move(CodeAction);
|
|
788 }
|
|
789
|
|
790 llvm::raw_ostream &operator<<(llvm::raw_ostream &O, const DocumentSymbol &S) {
|
|
791 return O << S.name << " - " << toJSON(S);
|
|
792 }
|
|
793
|
|
794 llvm::json::Value toJSON(const DocumentSymbol &S) {
|
|
795 llvm::json::Object Result{{"name", S.name},
|
|
796 {"kind", static_cast<int>(S.kind)},
|
|
797 {"range", S.range},
|
|
798 {"selectionRange", S.selectionRange}};
|
|
799
|
|
800 if (!S.detail.empty())
|
|
801 Result["detail"] = S.detail;
|
|
802 if (!S.children.empty())
|
|
803 Result["children"] = S.children;
|
|
804 if (S.deprecated)
|
|
805 Result["deprecated"] = true;
|
173
|
806 // FIXME: workaround for older gcc/clang
|
|
807 return std::move(Result);
|
150
|
808 }
|
|
809
|
|
810 llvm::json::Value toJSON(const WorkspaceEdit &WE) {
|
|
811 llvm::json::Object FileChanges;
|
221
|
812 for (auto &Change : WE.changes)
|
150
|
813 FileChanges[Change.first] = llvm::json::Array(Change.second);
|
|
814 return llvm::json::Object{{"changes", std::move(FileChanges)}};
|
|
815 }
|
|
816
|
221
|
817 bool fromJSON(const llvm::json::Value &Params, TweakArgs &A,
|
|
818 llvm::json::Path P) {
|
|
819 llvm::json::ObjectMapper O(Params, P);
|
150
|
820 return O && O.map("file", A.file) && O.map("selection", A.selection) &&
|
|
821 O.map("tweakID", A.tweakID);
|
|
822 }
|
|
823
|
|
824 llvm::json::Value toJSON(const TweakArgs &A) {
|
|
825 return llvm::json::Object{
|
|
826 {"tweakID", A.tweakID}, {"selection", A.selection}, {"file", A.file}};
|
|
827 }
|
|
828
|
|
829 llvm::json::Value toJSON(const ApplyWorkspaceEditParams &Params) {
|
|
830 return llvm::json::Object{{"edit", Params.edit}};
|
|
831 }
|
|
832
|
221
|
833 bool fromJSON(const llvm::json::Value &Response, ApplyWorkspaceEditResponse &R,
|
|
834 llvm::json::Path P) {
|
|
835 llvm::json::ObjectMapper O(Response, P);
|
|
836 return O && O.map("applied", R.applied) &&
|
|
837 O.map("failureReason", R.failureReason);
|
150
|
838 }
|
|
839
|
221
|
840 bool fromJSON(const llvm::json::Value &Params, TextDocumentPositionParams &R,
|
|
841 llvm::json::Path P) {
|
|
842 llvm::json::ObjectMapper O(Params, P);
|
150
|
843 return O && O.map("textDocument", R.textDocument) &&
|
|
844 O.map("position", R.position);
|
|
845 }
|
|
846
|
221
|
847 bool fromJSON(const llvm::json::Value &Params, CompletionContext &R,
|
|
848 llvm::json::Path P) {
|
|
849 llvm::json::ObjectMapper O(Params, P);
|
150
|
850 int TriggerKind;
|
221
|
851 if (!O || !O.map("triggerKind", TriggerKind) ||
|
|
852 !mapOptOrNull(Params, "triggerCharacter", R.triggerCharacter, P))
|
150
|
853 return false;
|
|
854 R.triggerKind = static_cast<CompletionTriggerKind>(TriggerKind);
|
|
855 return true;
|
|
856 }
|
|
857
|
221
|
858 bool fromJSON(const llvm::json::Value &Params, CompletionParams &R,
|
|
859 llvm::json::Path P) {
|
|
860 if (!fromJSON(Params, static_cast<TextDocumentPositionParams &>(R), P) ||
|
|
861 !mapOptOrNull(Params, "limit", R.limit, P))
|
150
|
862 return false;
|
|
863 if (auto *Context = Params.getAsObject()->get("context"))
|
221
|
864 return fromJSON(*Context, R.context, P.field("context"));
|
150
|
865 return true;
|
|
866 }
|
|
867
|
|
868 static llvm::StringRef toTextKind(MarkupKind Kind) {
|
|
869 switch (Kind) {
|
|
870 case MarkupKind::PlainText:
|
|
871 return "plaintext";
|
|
872 case MarkupKind::Markdown:
|
|
873 return "markdown";
|
|
874 }
|
|
875 llvm_unreachable("Invalid MarkupKind");
|
|
876 }
|
|
877
|
221
|
878 bool fromJSON(const llvm::json::Value &V, MarkupKind &K, llvm::json::Path P) {
|
150
|
879 auto Str = V.getAsString();
|
|
880 if (!Str) {
|
221
|
881 P.report("expected string");
|
150
|
882 return false;
|
|
883 }
|
|
884 if (*Str == "plaintext")
|
|
885 K = MarkupKind::PlainText;
|
|
886 else if (*Str == "markdown")
|
|
887 K = MarkupKind::Markdown;
|
|
888 else {
|
221
|
889 P.report("unknown markup kind");
|
150
|
890 return false;
|
|
891 }
|
|
892 return true;
|
|
893 }
|
|
894
|
|
895 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, MarkupKind K) {
|
|
896 return OS << toTextKind(K);
|
|
897 }
|
|
898
|
|
899 llvm::json::Value toJSON(const MarkupContent &MC) {
|
|
900 if (MC.value.empty())
|
|
901 return nullptr;
|
|
902
|
|
903 return llvm::json::Object{
|
|
904 {"kind", toTextKind(MC.kind)},
|
|
905 {"value", MC.value},
|
|
906 };
|
|
907 }
|
|
908
|
|
909 llvm::json::Value toJSON(const Hover &H) {
|
|
910 llvm::json::Object Result{{"contents", toJSON(H.contents)}};
|
|
911
|
|
912 if (H.range.hasValue())
|
|
913 Result["range"] = toJSON(*H.range);
|
|
914
|
|
915 return std::move(Result);
|
|
916 }
|
|
917
|
221
|
918 bool fromJSON(const llvm::json::Value &E, CompletionItemKind &Out,
|
|
919 llvm::json::Path P) {
|
150
|
920 if (auto T = E.getAsInteger()) {
|
|
921 if (*T < static_cast<int>(CompletionItemKind::Text) ||
|
|
922 *T > static_cast<int>(CompletionItemKind::TypeParameter))
|
|
923 return false;
|
|
924 Out = static_cast<CompletionItemKind>(*T);
|
|
925 return true;
|
|
926 }
|
|
927 return false;
|
|
928 }
|
|
929
|
|
930 CompletionItemKind
|
|
931 adjustKindToCapability(CompletionItemKind Kind,
|
|
932 CompletionItemKindBitset &SupportedCompletionItemKinds) {
|
|
933 auto KindVal = static_cast<size_t>(Kind);
|
|
934 if (KindVal >= CompletionItemKindMin &&
|
|
935 KindVal <= SupportedCompletionItemKinds.size() &&
|
|
936 SupportedCompletionItemKinds[KindVal])
|
|
937 return Kind;
|
|
938
|
|
939 switch (Kind) {
|
|
940 // Provide some fall backs for common kinds that are close enough.
|
|
941 case CompletionItemKind::Folder:
|
|
942 return CompletionItemKind::File;
|
|
943 case CompletionItemKind::EnumMember:
|
|
944 return CompletionItemKind::Enum;
|
|
945 case CompletionItemKind::Struct:
|
|
946 return CompletionItemKind::Class;
|
|
947 default:
|
|
948 return CompletionItemKind::Text;
|
|
949 }
|
|
950 }
|
|
951
|
221
|
952 bool fromJSON(const llvm::json::Value &E, CompletionItemKindBitset &Out,
|
|
953 llvm::json::Path P) {
|
150
|
954 if (auto *A = E.getAsArray()) {
|
|
955 for (size_t I = 0; I < A->size(); ++I) {
|
|
956 CompletionItemKind KindOut;
|
221
|
957 if (fromJSON((*A)[I], KindOut, P.index(I)))
|
150
|
958 Out.set(size_t(KindOut));
|
|
959 }
|
|
960 return true;
|
|
961 }
|
|
962 return false;
|
|
963 }
|
|
964
|
|
965 llvm::json::Value toJSON(const CompletionItem &CI) {
|
|
966 assert(!CI.label.empty() && "completion item label is required");
|
|
967 llvm::json::Object Result{{"label", CI.label}};
|
|
968 if (CI.kind != CompletionItemKind::Missing)
|
|
969 Result["kind"] = static_cast<int>(CI.kind);
|
|
970 if (!CI.detail.empty())
|
|
971 Result["detail"] = CI.detail;
|
173
|
972 if (CI.documentation)
|
150
|
973 Result["documentation"] = CI.documentation;
|
|
974 if (!CI.sortText.empty())
|
|
975 Result["sortText"] = CI.sortText;
|
|
976 if (!CI.filterText.empty())
|
|
977 Result["filterText"] = CI.filterText;
|
|
978 if (!CI.insertText.empty())
|
|
979 Result["insertText"] = CI.insertText;
|
|
980 if (CI.insertTextFormat != InsertTextFormat::Missing)
|
|
981 Result["insertTextFormat"] = static_cast<int>(CI.insertTextFormat);
|
|
982 if (CI.textEdit)
|
|
983 Result["textEdit"] = *CI.textEdit;
|
|
984 if (!CI.additionalTextEdits.empty())
|
|
985 Result["additionalTextEdits"] = llvm::json::Array(CI.additionalTextEdits);
|
|
986 if (CI.deprecated)
|
|
987 Result["deprecated"] = CI.deprecated;
|
173
|
988 Result["score"] = CI.score;
|
150
|
989 return std::move(Result);
|
|
990 }
|
|
991
|
|
992 llvm::raw_ostream &operator<<(llvm::raw_ostream &O, const CompletionItem &I) {
|
|
993 O << I.label << " - " << toJSON(I);
|
|
994 return O;
|
|
995 }
|
|
996
|
|
997 bool operator<(const CompletionItem &L, const CompletionItem &R) {
|
|
998 return (L.sortText.empty() ? L.label : L.sortText) <
|
|
999 (R.sortText.empty() ? R.label : R.sortText);
|
|
1000 }
|
|
1001
|
|
1002 llvm::json::Value toJSON(const CompletionList &L) {
|
|
1003 return llvm::json::Object{
|
|
1004 {"isIncomplete", L.isIncomplete},
|
|
1005 {"items", llvm::json::Array(L.items)},
|
|
1006 };
|
|
1007 }
|
|
1008
|
|
1009 llvm::json::Value toJSON(const ParameterInformation &PI) {
|
|
1010 assert((PI.labelOffsets.hasValue() || !PI.labelString.empty()) &&
|
|
1011 "parameter information label is required");
|
|
1012 llvm::json::Object Result;
|
|
1013 if (PI.labelOffsets)
|
|
1014 Result["label"] =
|
|
1015 llvm::json::Array({PI.labelOffsets->first, PI.labelOffsets->second});
|
|
1016 else
|
|
1017 Result["label"] = PI.labelString;
|
|
1018 if (!PI.documentation.empty())
|
|
1019 Result["documentation"] = PI.documentation;
|
|
1020 return std::move(Result);
|
|
1021 }
|
|
1022
|
|
1023 llvm::json::Value toJSON(const SignatureInformation &SI) {
|
|
1024 assert(!SI.label.empty() && "signature information label is required");
|
|
1025 llvm::json::Object Result{
|
|
1026 {"label", SI.label},
|
|
1027 {"parameters", llvm::json::Array(SI.parameters)},
|
|
1028 };
|
|
1029 if (!SI.documentation.empty())
|
|
1030 Result["documentation"] = SI.documentation;
|
|
1031 return std::move(Result);
|
|
1032 }
|
|
1033
|
|
1034 llvm::raw_ostream &operator<<(llvm::raw_ostream &O,
|
|
1035 const SignatureInformation &I) {
|
|
1036 O << I.label << " - " << toJSON(I);
|
|
1037 return O;
|
|
1038 }
|
|
1039
|
|
1040 llvm::json::Value toJSON(const SignatureHelp &SH) {
|
|
1041 assert(SH.activeSignature >= 0 &&
|
|
1042 "Unexpected negative value for number of active signatures.");
|
|
1043 assert(SH.activeParameter >= 0 &&
|
|
1044 "Unexpected negative value for active parameter index");
|
|
1045 return llvm::json::Object{
|
|
1046 {"activeSignature", SH.activeSignature},
|
|
1047 {"activeParameter", SH.activeParameter},
|
|
1048 {"signatures", llvm::json::Array(SH.signatures)},
|
|
1049 };
|
|
1050 }
|
|
1051
|
221
|
1052 bool fromJSON(const llvm::json::Value &Params, RenameParams &R,
|
|
1053 llvm::json::Path P) {
|
|
1054 llvm::json::ObjectMapper O(Params, P);
|
150
|
1055 return O && O.map("textDocument", R.textDocument) &&
|
|
1056 O.map("position", R.position) && O.map("newName", R.newName);
|
|
1057 }
|
|
1058
|
|
1059 llvm::json::Value toJSON(const DocumentHighlight &DH) {
|
|
1060 return llvm::json::Object{
|
|
1061 {"range", toJSON(DH.range)},
|
|
1062 {"kind", static_cast<int>(DH.kind)},
|
|
1063 };
|
|
1064 }
|
|
1065
|
|
1066 llvm::json::Value toJSON(const FileStatus &FStatus) {
|
|
1067 return llvm::json::Object{
|
|
1068 {"uri", FStatus.uri},
|
|
1069 {"state", FStatus.state},
|
|
1070 };
|
|
1071 }
|
|
1072
|
173
|
1073 constexpr unsigned SemanticTokenEncodingSize = 5;
|
|
1074 static llvm::json::Value encodeTokens(llvm::ArrayRef<SemanticToken> Toks) {
|
|
1075 llvm::json::Array Result;
|
221
|
1076 Result.reserve(SemanticTokenEncodingSize * Toks.size());
|
173
|
1077 for (const auto &Tok : Toks) {
|
|
1078 Result.push_back(Tok.deltaLine);
|
|
1079 Result.push_back(Tok.deltaStart);
|
|
1080 Result.push_back(Tok.length);
|
|
1081 Result.push_back(Tok.tokenType);
|
|
1082 Result.push_back(Tok.tokenModifiers);
|
|
1083 }
|
|
1084 assert(Result.size() == SemanticTokenEncodingSize * Toks.size());
|
|
1085 return std::move(Result);
|
|
1086 }
|
|
1087
|
|
1088 bool operator==(const SemanticToken &L, const SemanticToken &R) {
|
|
1089 return std::tie(L.deltaLine, L.deltaStart, L.length, L.tokenType,
|
|
1090 L.tokenModifiers) == std::tie(R.deltaLine, R.deltaStart,
|
|
1091 R.length, R.tokenType,
|
|
1092 R.tokenModifiers);
|
|
1093 }
|
|
1094
|
|
1095 llvm::json::Value toJSON(const SemanticTokens &Tokens) {
|
|
1096 return llvm::json::Object{{"resultId", Tokens.resultId},
|
|
1097 {"data", encodeTokens(Tokens.tokens)}};
|
|
1098 }
|
|
1099
|
|
1100 llvm::json::Value toJSON(const SemanticTokensEdit &Edit) {
|
|
1101 return llvm::json::Object{
|
|
1102 {"start", SemanticTokenEncodingSize * Edit.startToken},
|
|
1103 {"deleteCount", SemanticTokenEncodingSize * Edit.deleteTokens},
|
|
1104 {"data", encodeTokens(Edit.tokens)}};
|
|
1105 }
|
|
1106
|
221
|
1107 llvm::json::Value toJSON(const SemanticTokensOrDelta &TE) {
|
173
|
1108 llvm::json::Object Result{{"resultId", TE.resultId}};
|
|
1109 if (TE.edits)
|
|
1110 Result["edits"] = *TE.edits;
|
|
1111 if (TE.tokens)
|
|
1112 Result["data"] = encodeTokens(*TE.tokens);
|
|
1113 return std::move(Result);
|
|
1114 }
|
|
1115
|
221
|
1116 bool fromJSON(const llvm::json::Value &Params, SemanticTokensParams &R,
|
|
1117 llvm::json::Path P) {
|
|
1118 llvm::json::ObjectMapper O(Params, P);
|
173
|
1119 return O && O.map("textDocument", R.textDocument);
|
|
1120 }
|
|
1121
|
221
|
1122 bool fromJSON(const llvm::json::Value &Params, SemanticTokensDeltaParams &R,
|
|
1123 llvm::json::Path P) {
|
|
1124 llvm::json::ObjectMapper O(Params, P);
|
173
|
1125 return O && O.map("textDocument", R.textDocument) &&
|
|
1126 O.map("previousResultId", R.previousResultId);
|
|
1127 }
|
|
1128
|
150
|
1129 llvm::raw_ostream &operator<<(llvm::raw_ostream &O,
|
|
1130 const DocumentHighlight &V) {
|
|
1131 O << V.range;
|
|
1132 if (V.kind == DocumentHighlightKind::Read)
|
|
1133 O << "(r)";
|
|
1134 if (V.kind == DocumentHighlightKind::Write)
|
|
1135 O << "(w)";
|
|
1136 return O;
|
|
1137 }
|
|
1138
|
|
1139 bool fromJSON(const llvm::json::Value &Params,
|
221
|
1140 DidChangeConfigurationParams &CCP, llvm::json::Path P) {
|
|
1141 llvm::json::ObjectMapper O(Params, P);
|
150
|
1142 return O && O.map("settings", CCP.settings);
|
|
1143 }
|
|
1144
|
221
|
1145 bool fromJSON(const llvm::json::Value &Params, ClangdCompileCommand &CDbUpdate,
|
|
1146 llvm::json::Path P) {
|
|
1147 llvm::json::ObjectMapper O(Params, P);
|
150
|
1148 return O && O.map("workingDirectory", CDbUpdate.workingDirectory) &&
|
|
1149 O.map("compilationCommand", CDbUpdate.compilationCommand);
|
|
1150 }
|
|
1151
|
221
|
1152 bool fromJSON(const llvm::json::Value &Params, ConfigurationSettings &S,
|
|
1153 llvm::json::Path P) {
|
|
1154 llvm::json::ObjectMapper O(Params, P);
|
150
|
1155 if (!O)
|
|
1156 return true; // 'any' type in LSP.
|
221
|
1157 return mapOptOrNull(Params, "compilationDatabaseChanges",
|
|
1158 S.compilationDatabaseChanges, P);
|
150
|
1159 }
|
|
1160
|
221
|
1161 bool fromJSON(const llvm::json::Value &Params, InitializationOptions &Opts,
|
|
1162 llvm::json::Path P) {
|
|
1163 llvm::json::ObjectMapper O(Params, P);
|
150
|
1164 if (!O)
|
|
1165 return true; // 'any' type in LSP.
|
|
1166
|
221
|
1167 return fromJSON(Params, Opts.ConfigSettings, P) &&
|
|
1168 O.map("compilationDatabasePath", Opts.compilationDatabasePath) &&
|
|
1169 mapOptOrNull(Params, "fallbackFlags", Opts.fallbackFlags, P) &&
|
|
1170 mapOptOrNull(Params, "clangdFileStatus", Opts.FileStatus, P);
|
150
|
1171 }
|
|
1172
|
221
|
1173 bool fromJSON(const llvm::json::Value &E, TypeHierarchyDirection &Out,
|
|
1174 llvm::json::Path P) {
|
150
|
1175 auto T = E.getAsInteger();
|
|
1176 if (!T)
|
|
1177 return false;
|
|
1178 if (*T < static_cast<int>(TypeHierarchyDirection::Children) ||
|
|
1179 *T > static_cast<int>(TypeHierarchyDirection::Both))
|
|
1180 return false;
|
|
1181 Out = static_cast<TypeHierarchyDirection>(*T);
|
|
1182 return true;
|
|
1183 }
|
|
1184
|
221
|
1185 bool fromJSON(const llvm::json::Value &Params, TypeHierarchyParams &R,
|
|
1186 llvm::json::Path P) {
|
|
1187 llvm::json::ObjectMapper O(Params, P);
|
150
|
1188 return O && O.map("textDocument", R.textDocument) &&
|
|
1189 O.map("position", R.position) && O.map("resolve", R.resolve) &&
|
|
1190 O.map("direction", R.direction);
|
|
1191 }
|
|
1192
|
|
1193 llvm::raw_ostream &operator<<(llvm::raw_ostream &O,
|
|
1194 const TypeHierarchyItem &I) {
|
|
1195 return O << I.name << " - " << toJSON(I);
|
|
1196 }
|
|
1197
|
|
1198 llvm::json::Value toJSON(const TypeHierarchyItem &I) {
|
|
1199 llvm::json::Object Result{{"name", I.name},
|
|
1200 {"kind", static_cast<int>(I.kind)},
|
|
1201 {"range", I.range},
|
|
1202 {"selectionRange", I.selectionRange},
|
|
1203 {"uri", I.uri}};
|
|
1204
|
|
1205 if (I.detail)
|
|
1206 Result["detail"] = I.detail;
|
|
1207 if (I.deprecated)
|
|
1208 Result["deprecated"] = I.deprecated;
|
|
1209 if (I.parents)
|
|
1210 Result["parents"] = I.parents;
|
|
1211 if (I.children)
|
|
1212 Result["children"] = I.children;
|
|
1213 if (I.data)
|
|
1214 Result["data"] = I.data;
|
|
1215 return std::move(Result);
|
|
1216 }
|
|
1217
|
221
|
1218 bool fromJSON(const llvm::json::Value &Params, TypeHierarchyItem &I,
|
|
1219 llvm::json::Path P) {
|
|
1220 llvm::json::ObjectMapper O(Params, P);
|
150
|
1221
|
|
1222 // Required fields.
|
221
|
1223 return O && O.map("name", I.name) && O.map("kind", I.kind) &&
|
|
1224 O.map("uri", I.uri) && O.map("range", I.range) &&
|
|
1225 O.map("selectionRange", I.selectionRange) &&
|
|
1226 mapOptOrNull(Params, "detail", I.detail, P) &&
|
|
1227 mapOptOrNull(Params, "deprecated", I.deprecated, P) &&
|
|
1228 mapOptOrNull(Params, "parents", I.parents, P) &&
|
|
1229 mapOptOrNull(Params, "children", I.children, P) &&
|
|
1230 mapOptOrNull(Params, "data", I.data, P);
|
150
|
1231 }
|
|
1232
|
|
1233 bool fromJSON(const llvm::json::Value &Params,
|
221
|
1234 ResolveTypeHierarchyItemParams &R, llvm::json::Path P) {
|
|
1235 llvm::json::ObjectMapper O(Params, P);
|
|
1236 return O && O.map("item", R.item) && O.map("resolve", R.resolve) &&
|
|
1237 O.map("direction", R.direction);
|
|
1238 }
|
|
1239
|
|
1240 bool fromJSON(const llvm::json::Value &Params, ReferenceContext &R,
|
|
1241 llvm::json::Path P) {
|
|
1242 llvm::json::ObjectMapper O(Params, P);
|
|
1243 return O && O.mapOptional("includeDeclaration", R.includeDeclaration);
|
|
1244 }
|
|
1245
|
|
1246 bool fromJSON(const llvm::json::Value &Params, ReferenceParams &R,
|
|
1247 llvm::json::Path P) {
|
|
1248 TextDocumentPositionParams &Base = R;
|
|
1249 llvm::json::ObjectMapper O(Params, P);
|
|
1250 return fromJSON(Params, Base, P) && O && O.mapOptional("context", R.context);
|
|
1251 }
|
|
1252
|
|
1253 llvm::json::Value toJSON(SymbolTag Tag) {
|
|
1254 return llvm::json::Value{static_cast<int>(Tag)};
|
|
1255 }
|
|
1256
|
|
1257 llvm::json::Value toJSON(const CallHierarchyItem &I) {
|
|
1258 llvm::json::Object Result{{"name", I.name},
|
|
1259 {"kind", static_cast<int>(I.kind)},
|
|
1260 {"range", I.range},
|
|
1261 {"selectionRange", I.selectionRange},
|
|
1262 {"uri", I.uri}};
|
|
1263 if (!I.tags.empty())
|
|
1264 Result["tags"] = I.tags;
|
|
1265 if (!I.detail.empty())
|
|
1266 Result["detail"] = I.detail;
|
|
1267 if (!I.data.empty())
|
|
1268 Result["data"] = I.data;
|
|
1269 return std::move(Result);
|
150
|
1270 }
|
|
1271
|
221
|
1272 bool fromJSON(const llvm::json::Value &Params, CallHierarchyItem &I,
|
|
1273 llvm::json::Path P) {
|
|
1274 llvm::json::ObjectMapper O(Params, P);
|
|
1275
|
|
1276 // Populate the required fields only. We don't care about the
|
|
1277 // optional fields `Tags` and `Detail` for the purpose of
|
|
1278 // client --> server communication.
|
|
1279 return O && O.map("name", I.name) && O.map("kind", I.kind) &&
|
|
1280 O.map("uri", I.uri) && O.map("range", I.range) &&
|
|
1281 O.map("selectionRange", I.selectionRange) &&
|
|
1282 mapOptOrNull(Params, "data", I.data, P);
|
|
1283 }
|
|
1284
|
|
1285 bool fromJSON(const llvm::json::Value &Params,
|
|
1286 CallHierarchyIncomingCallsParams &C, llvm::json::Path P) {
|
|
1287 llvm::json::ObjectMapper O(Params, P);
|
|
1288 return O.map("item", C.item);
|
|
1289 }
|
|
1290
|
|
1291 llvm::json::Value toJSON(const CallHierarchyIncomingCall &C) {
|
|
1292 return llvm::json::Object{{"from", C.from}, {"fromRanges", C.fromRanges}};
|
|
1293 }
|
|
1294
|
|
1295 bool fromJSON(const llvm::json::Value &Params,
|
|
1296 CallHierarchyOutgoingCallsParams &C, llvm::json::Path P) {
|
|
1297 llvm::json::ObjectMapper O(Params, P);
|
|
1298 return O.map("item", C.item);
|
|
1299 }
|
|
1300
|
|
1301 llvm::json::Value toJSON(const CallHierarchyOutgoingCall &C) {
|
|
1302 return llvm::json::Object{{"to", C.to}, {"fromRanges", C.fromRanges}};
|
|
1303 }
|
|
1304
|
|
1305 bool fromJSON(const llvm::json::Value &Params, InlayHintsParams &R,
|
|
1306 llvm::json::Path P) {
|
|
1307 llvm::json::ObjectMapper O(Params, P);
|
|
1308 return O && O.map("textDocument", R.textDocument);
|
|
1309 }
|
|
1310
|
|
1311 llvm::json::Value toJSON(InlayHintKind K) {
|
|
1312 switch (K) {
|
|
1313 case InlayHintKind::ParameterHint:
|
|
1314 return "parameter";
|
|
1315 case InlayHintKind::TypeHint:
|
|
1316 return "type";
|
|
1317 }
|
|
1318 llvm_unreachable("Unknown clang.clangd.InlayHintKind");
|
|
1319 }
|
|
1320
|
|
1321 llvm::json::Value toJSON(const InlayHint &H) {
|
|
1322 return llvm::json::Object{
|
|
1323 {"range", H.range}, {"kind", H.kind}, {"label", H.label}};
|
150
|
1324 }
|
|
1325
|
|
1326 static const char *toString(OffsetEncoding OE) {
|
|
1327 switch (OE) {
|
|
1328 case OffsetEncoding::UTF8:
|
|
1329 return "utf-8";
|
|
1330 case OffsetEncoding::UTF16:
|
|
1331 return "utf-16";
|
|
1332 case OffsetEncoding::UTF32:
|
|
1333 return "utf-32";
|
|
1334 case OffsetEncoding::UnsupportedEncoding:
|
|
1335 return "unknown";
|
|
1336 }
|
|
1337 llvm_unreachable("Unknown clang.clangd.OffsetEncoding");
|
|
1338 }
|
|
1339 llvm::json::Value toJSON(const OffsetEncoding &OE) { return toString(OE); }
|
221
|
1340 bool fromJSON(const llvm::json::Value &V, OffsetEncoding &OE,
|
|
1341 llvm::json::Path P) {
|
150
|
1342 auto Str = V.getAsString();
|
|
1343 if (!Str)
|
|
1344 return false;
|
|
1345 OE = llvm::StringSwitch<OffsetEncoding>(*Str)
|
|
1346 .Case("utf-8", OffsetEncoding::UTF8)
|
|
1347 .Case("utf-16", OffsetEncoding::UTF16)
|
|
1348 .Case("utf-32", OffsetEncoding::UTF32)
|
|
1349 .Default(OffsetEncoding::UnsupportedEncoding);
|
|
1350 return true;
|
|
1351 }
|
|
1352 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, OffsetEncoding Enc) {
|
|
1353 return OS << toString(Enc);
|
|
1354 }
|
|
1355
|
221
|
1356 bool fromJSON(const llvm::json::Value &Params, SelectionRangeParams &S,
|
|
1357 llvm::json::Path P) {
|
|
1358 llvm::json::ObjectMapper O(Params, P);
|
|
1359 return O && O.map("textDocument", S.textDocument) &&
|
|
1360 O.map("positions", S.positions);
|
150
|
1361 }
|
|
1362
|
|
1363 llvm::json::Value toJSON(const SelectionRange &Out) {
|
|
1364 if (Out.parent) {
|
|
1365 return llvm::json::Object{{"range", Out.range},
|
|
1366 {"parent", toJSON(*Out.parent)}};
|
|
1367 }
|
|
1368 return llvm::json::Object{{"range", Out.range}};
|
|
1369 }
|
|
1370
|
221
|
1371 bool fromJSON(const llvm::json::Value &Params, DocumentLinkParams &R,
|
|
1372 llvm::json::Path P) {
|
|
1373 llvm::json::ObjectMapper O(Params, P);
|
150
|
1374 return O && O.map("textDocument", R.textDocument);
|
|
1375 }
|
|
1376
|
|
1377 llvm::json::Value toJSON(const DocumentLink &DocumentLink) {
|
|
1378 return llvm::json::Object{
|
|
1379 {"range", DocumentLink.range},
|
|
1380 {"target", DocumentLink.target},
|
|
1381 };
|
|
1382 }
|
|
1383
|
221
|
1384 bool fromJSON(const llvm::json::Value &Params, FoldingRangeParams &R,
|
|
1385 llvm::json::Path P) {
|
|
1386 llvm::json::ObjectMapper O(Params, P);
|
|
1387 return O && O.map("textDocument", R.textDocument);
|
|
1388 }
|
|
1389
|
|
1390 llvm::json::Value toJSON(const FoldingRange &Range) {
|
|
1391 llvm::json::Object Result{
|
|
1392 {"startLine", Range.startLine},
|
|
1393 {"endLine", Range.endLine},
|
|
1394 };
|
|
1395 if (Range.startCharacter)
|
|
1396 Result["startCharacter"] = Range.startCharacter;
|
|
1397 if (Range.endCharacter)
|
|
1398 Result["endCharacter"] = Range.endCharacter;
|
|
1399 if (Range.kind)
|
|
1400 Result["kind"] = *Range.kind;
|
|
1401 return Result;
|
|
1402 }
|
|
1403
|
|
1404 llvm::json::Value toJSON(const MemoryTree &MT) {
|
|
1405 llvm::json::Object Out;
|
|
1406 int64_t Total = MT.self();
|
|
1407 Out["_self"] = Total;
|
|
1408 for (const auto &Entry : MT.children()) {
|
|
1409 auto Child = toJSON(Entry.getSecond());
|
|
1410 Total += *Child.getAsObject()->getInteger("_total");
|
|
1411 Out[Entry.first] = std::move(Child);
|
|
1412 }
|
|
1413 Out["_total"] = Total;
|
|
1414 return Out;
|
|
1415 }
|
|
1416
|
|
1417 bool fromJSON(const llvm::json::Value &Params, ASTParams &R,
|
|
1418 llvm::json::Path P) {
|
|
1419 llvm::json::ObjectMapper O(Params, P);
|
|
1420 return O && O.map("textDocument", R.textDocument) && O.map("range", R.range);
|
|
1421 }
|
|
1422
|
|
1423 llvm::json::Value toJSON(const ASTNode &N) {
|
|
1424 llvm::json::Object Result{
|
|
1425 {"role", N.role},
|
|
1426 {"kind", N.kind},
|
|
1427 };
|
|
1428 if (!N.children.empty())
|
|
1429 Result["children"] = N.children;
|
|
1430 if (!N.detail.empty())
|
|
1431 Result["detail"] = N.detail;
|
|
1432 if (!N.arcana.empty())
|
|
1433 Result["arcana"] = N.arcana;
|
|
1434 if (N.range)
|
|
1435 Result["range"] = *N.range;
|
|
1436 return Result;
|
|
1437 }
|
|
1438
|
|
1439 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const ASTNode &Root) {
|
|
1440 std::function<void(const ASTNode &, unsigned)> Print = [&](const ASTNode &N,
|
|
1441 unsigned Level) {
|
|
1442 OS.indent(2 * Level) << N.role << ": " << N.kind;
|
|
1443 if (!N.detail.empty())
|
|
1444 OS << " - " << N.detail;
|
|
1445 OS << "\n";
|
|
1446 for (const ASTNode &C : N.children)
|
|
1447 Print(C, Level + 1);
|
|
1448 };
|
|
1449 Print(Root, 0);
|
|
1450 return OS;
|
|
1451 }
|
|
1452
|
150
|
1453 } // namespace clangd
|
|
1454 } // namespace clang
|