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