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