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