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