clang-tools  8.0.0
Protocol.cpp
Go to the documentation of this file.
1 //===--- Protocol.cpp - Language Server Protocol Implementation -----------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file contains the serialization code for the LSP structs.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "Protocol.h"
15 #include "Logger.h"
16 #include "URI.h"
17 #include "index/Index.h"
18 #include "clang/Basic/LLVM.h"
19 #include "llvm/ADT/Hashing.h"
20 #include "llvm/ADT/SmallString.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 
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;
210  return SymbolKind::Enum;
211  default:
212  return SymbolKind::String;
213  }
214 }
215 
216 bool fromJSON(const llvm::json::Value &Params, ClientCapabilities &R) {
217  const llvm::json::Object *O = Params.getAsObject();
218  if (!O)
219  return false;
220  if (auto *TextDocument = O->getObject("textDocument")) {
221  if (auto *Diagnostics = TextDocument->getObject("publishDiagnostics")) {
222  if (auto CategorySupport = Diagnostics->getBoolean("categorySupport"))
223  R.DiagnosticCategory = *CategorySupport;
224  if (auto CodeActions = Diagnostics->getBoolean("codeActionsInline"))
225  R.DiagnosticFixes = *CodeActions;
226  }
227  if (auto *Completion = TextDocument->getObject("completion")) {
228  if (auto *Item = Completion->getObject("completionItem")) {
229  if (auto SnippetSupport = Item->getBoolean("snippetSupport"))
230  R.CompletionSnippets = *SnippetSupport;
231  }
232  if (auto *ItemKind = Completion->getObject("completionItemKind")) {
233  if (auto *ValueSet = ItemKind->get("valueSet")) {
234  R.CompletionItemKinds.emplace();
235  if (!fromJSON(*ValueSet, *R.CompletionItemKinds))
236  return false;
237  }
238  }
239  }
240  if (auto *CodeAction = TextDocument->getObject("codeAction")) {
241  if (CodeAction->getObject("codeActionLiteralSupport"))
242  R.CodeActionStructure = true;
243  }
244  if (auto *DocumentSymbol = TextDocument->getObject("documentSymbol")) {
245  if (auto HierarchicalSupport =
246  DocumentSymbol->getBoolean("hierarchicalDocumentSymbolSupport"))
247  R.HierarchicalDocumentSymbol = *HierarchicalSupport;
248  }
249  }
250  if (auto *Workspace = O->getObject("workspace")) {
251  if (auto *Symbol = Workspace->getObject("symbol")) {
252  if (auto *SymbolKind = Symbol->getObject("symbolKind")) {
253  if (auto *ValueSet = SymbolKind->get("valueSet")) {
254  R.WorkspaceSymbolKinds.emplace();
255  if (!fromJSON(*ValueSet, *R.WorkspaceSymbolKinds))
256  return false;
257  }
258  }
259  }
260  }
261  return true;
262 }
263 
264 bool fromJSON(const llvm::json::Value &Params, InitializeParams &R) {
265  llvm::json::ObjectMapper O(Params);
266  if (!O)
267  return false;
268  // We deliberately don't fail if we can't parse individual fields.
269  // Failing to handle a slightly malformed initialize would be a disaster.
270  O.map("processId", R.processId);
271  O.map("rootUri", R.rootUri);
272  O.map("rootPath", R.rootPath);
273  O.map("capabilities", R.capabilities);
274  O.map("trace", R.trace);
275  O.map("initializationOptions", R.initializationOptions);
276  return true;
277 }
278 
279 bool fromJSON(const llvm::json::Value &Params, DidOpenTextDocumentParams &R) {
280  llvm::json::ObjectMapper O(Params);
281  return O && O.map("textDocument", R.textDocument);
282 }
283 
284 bool fromJSON(const llvm::json::Value &Params, DidCloseTextDocumentParams &R) {
285  llvm::json::ObjectMapper O(Params);
286  return O && O.map("textDocument", R.textDocument);
287 }
288 
289 bool fromJSON(const llvm::json::Value &Params, DidChangeTextDocumentParams &R) {
290  llvm::json::ObjectMapper O(Params);
291  return O && O.map("textDocument", R.textDocument) &&
292  O.map("contentChanges", R.contentChanges) &&
293  O.map("wantDiagnostics", R.wantDiagnostics);
294 }
295 
296 bool fromJSON(const llvm::json::Value &E, FileChangeType &Out) {
297  if (auto T = E.getAsInteger()) {
298  if (*T < static_cast<int>(FileChangeType::Created) ||
299  *T > static_cast<int>(FileChangeType::Deleted))
300  return false;
301  Out = static_cast<FileChangeType>(*T);
302  return true;
303  }
304  return false;
305 }
306 
307 bool fromJSON(const llvm::json::Value &Params, FileEvent &R) {
308  llvm::json::ObjectMapper O(Params);
309  return O && O.map("uri", R.uri) && O.map("type", R.type);
310 }
311 
312 bool fromJSON(const llvm::json::Value &Params, DidChangeWatchedFilesParams &R) {
313  llvm::json::ObjectMapper O(Params);
314  return O && O.map("changes", R.changes);
315 }
316 
317 bool fromJSON(const llvm::json::Value &Params,
319  llvm::json::ObjectMapper O(Params);
320  return O && O.map("range", R.range) && O.map("rangeLength", R.rangeLength) &&
321  O.map("text", R.text);
322 }
323 
324 bool fromJSON(const llvm::json::Value &Params, FormattingOptions &R) {
325  llvm::json::ObjectMapper O(Params);
326  return O && O.map("tabSize", R.tabSize) &&
327  O.map("insertSpaces", R.insertSpaces);
328 }
329 
330 llvm::json::Value toJSON(const FormattingOptions &P) {
331  return llvm::json::Object{
332  {"tabSize", P.tabSize},
333  {"insertSpaces", P.insertSpaces},
334  };
335 }
336 
337 bool fromJSON(const llvm::json::Value &Params,
339  llvm::json::ObjectMapper O(Params);
340  return O && O.map("textDocument", R.textDocument) &&
341  O.map("range", R.range) && O.map("options", R.options);
342 }
343 
344 bool fromJSON(const llvm::json::Value &Params,
346  llvm::json::ObjectMapper O(Params);
347  return O && O.map("textDocument", R.textDocument) &&
348  O.map("position", R.position) && O.map("ch", R.ch) &&
349  O.map("options", R.options);
350 }
351 
352 bool fromJSON(const llvm::json::Value &Params, DocumentFormattingParams &R) {
353  llvm::json::ObjectMapper O(Params);
354  return O && O.map("textDocument", R.textDocument) &&
355  O.map("options", R.options);
356 }
357 
358 bool fromJSON(const llvm::json::Value &Params, DocumentSymbolParams &R) {
359  llvm::json::ObjectMapper O(Params);
360  return O && O.map("textDocument", R.textDocument);
361 }
362 
363 llvm::json::Value toJSON(const Diagnostic &D) {
364  llvm::json::Object Diag{
365  {"range", D.range},
366  {"severity", D.severity},
367  {"message", D.message},
368  };
369  if (D.category)
370  Diag["category"] = *D.category;
371  if (D.codeActions)
372  Diag["codeActions"] = D.codeActions;
373  return std::move(Diag);
374 }
375 
376 bool fromJSON(const llvm::json::Value &Params, Diagnostic &R) {
377  llvm::json::ObjectMapper O(Params);
378  if (!O || !O.map("range", R.range) || !O.map("message", R.message))
379  return false;
380  O.map("severity", R.severity);
381  O.map("category", R.category);
382  return true;
383 }
384 
385 bool fromJSON(const llvm::json::Value &Params, CodeActionContext &R) {
386  llvm::json::ObjectMapper O(Params);
387  return O && O.map("diagnostics", R.diagnostics);
388 }
389 
390 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Diagnostic &D) {
391  OS << D.range << " [";
392  switch (D.severity) {
393  case 1:
394  OS << "error";
395  break;
396  case 2:
397  OS << "warning";
398  break;
399  case 3:
400  OS << "note";
401  break;
402  case 4:
403  OS << "remark";
404  break;
405  default:
406  OS << "diagnostic";
407  break;
408  }
409  return OS << '(' << D.severity << "): " << D.message << "]";
410 }
411 
412 bool fromJSON(const llvm::json::Value &Params, CodeActionParams &R) {
413  llvm::json::ObjectMapper O(Params);
414  return O && O.map("textDocument", R.textDocument) &&
415  O.map("range", R.range) && O.map("context", R.context);
416 }
417 
418 bool fromJSON(const llvm::json::Value &Params, WorkspaceEdit &R) {
419  llvm::json::ObjectMapper O(Params);
420  return O && O.map("changes", R.changes);
421 }
422 
423 const llvm::StringLiteral ExecuteCommandParams::CLANGD_APPLY_FIX_COMMAND =
424  "clangd.applyFix";
425 bool fromJSON(const llvm::json::Value &Params, ExecuteCommandParams &R) {
426  llvm::json::ObjectMapper O(Params);
427  if (!O || !O.map("command", R.command))
428  return false;
429 
430  auto Args = Params.getAsObject()->getArray("arguments");
431  if (R.command == ExecuteCommandParams::CLANGD_APPLY_FIX_COMMAND) {
432  return Args && Args->size() == 1 &&
433  fromJSON(Args->front(), R.workspaceEdit);
434  }
435  return false; // Unrecognized command.
436 }
437 
438 llvm::json::Value toJSON(const SymbolInformation &P) {
439  return llvm::json::Object{
440  {"name", P.name},
441  {"kind", static_cast<int>(P.kind)},
442  {"location", P.location},
443  {"containerName", P.containerName},
444  };
445 }
446 
447 llvm::raw_ostream &operator<<(llvm::raw_ostream &O,
448  const SymbolInformation &SI) {
449  O << SI.containerName << "::" << SI.name << " - " << toJSON(SI);
450  return O;
451 }
452 
453 bool operator==(const SymbolDetails &LHS, const SymbolDetails &RHS) {
454  return LHS.name == RHS.name && LHS.containerName == RHS.containerName &&
455  LHS.USR == RHS.USR && LHS.ID == RHS.ID;
456 }
457 
458 llvm::json::Value toJSON(const SymbolDetails &P) {
459  llvm::json::Object result{{"name", llvm::json::Value(nullptr)},
460  {"containerName", llvm::json::Value(nullptr)},
461  {"usr", llvm::json::Value(nullptr)},
462  {"id", llvm::json::Value(nullptr)}};
463 
464  if (!P.name.empty())
465  result["name"] = P.name;
466 
467  if (!P.containerName.empty())
468  result["containerName"] = P.containerName;
469 
470  if (!P.USR.empty())
471  result["usr"] = P.USR;
472 
473  if (P.ID.hasValue())
474  result["id"] = P.ID.getValue().str();
475 
476  // Older clang cannot compile 'return Result', even though it is legal.
477  return llvm::json::Value(std::move(result));
478 }
479 
480 llvm::raw_ostream &operator<<(llvm::raw_ostream &O, const SymbolDetails &S) {
481  if (!S.containerName.empty()) {
482  O << S.containerName;
483  llvm::StringRef ContNameRef;
484  if (!ContNameRef.endswith("::")) {
485  O << " ";
486  }
487  }
488  O << S.name << " - " << toJSON(S);
489  return O;
490 }
491 
492 bool fromJSON(const llvm::json::Value &Params, WorkspaceSymbolParams &R) {
493  llvm::json::ObjectMapper O(Params);
494  return O && O.map("query", R.query);
495 }
496 
497 llvm::json::Value toJSON(const Command &C) {
498  auto Cmd = llvm::json::Object{{"title", C.title}, {"command", C.command}};
499  if (C.workspaceEdit)
500  Cmd["arguments"] = {*C.workspaceEdit};
501  return std::move(Cmd);
502 }
503 
504 const llvm::StringLiteral CodeAction::QUICKFIX_KIND = "quickfix";
505 
506 llvm::json::Value toJSON(const CodeAction &CA) {
507  auto CodeAction = llvm::json::Object{{"title", CA.title}};
508  if (CA.kind)
509  CodeAction["kind"] = *CA.kind;
510  if (CA.diagnostics)
511  CodeAction["diagnostics"] = llvm::json::Array(*CA.diagnostics);
512  if (CA.edit)
513  CodeAction["edit"] = *CA.edit;
514  if (CA.command)
515  CodeAction["command"] = *CA.command;
516  return std::move(CodeAction);
517 }
518 
519 llvm::raw_ostream &operator<<(llvm::raw_ostream &O, const DocumentSymbol &S) {
520  return O << S.name << " - " << toJSON(S);
521 }
522 
523 llvm::json::Value toJSON(const DocumentSymbol &S) {
524  llvm::json::Object Result{{"name", S.name},
525  {"kind", static_cast<int>(S.kind)},
526  {"range", S.range},
527  {"selectionRange", S.selectionRange}};
528 
529  if (!S.detail.empty())
530  Result["detail"] = S.detail;
531  if (!S.children.empty())
532  Result["children"] = S.children;
533  if (S.deprecated)
534  Result["deprecated"] = true;
535  // Older gcc cannot compile 'return Result', even though it is legal.
536  return llvm::json::Value(std::move(Result));
537 }
538 
539 llvm::json::Value toJSON(const WorkspaceEdit &WE) {
540  if (!WE.changes)
541  return llvm::json::Object{};
542  llvm::json::Object FileChanges;
543  for (auto &Change : *WE.changes)
544  FileChanges[Change.first] = llvm::json::Array(Change.second);
545  return llvm::json::Object{{"changes", std::move(FileChanges)}};
546 }
547 
548 llvm::json::Value toJSON(const ApplyWorkspaceEditParams &Params) {
549  return llvm::json::Object{{"edit", Params.edit}};
550 }
551 
552 bool fromJSON(const llvm::json::Value &Params, TextDocumentPositionParams &R) {
553  llvm::json::ObjectMapper O(Params);
554  return O && O.map("textDocument", R.textDocument) &&
555  O.map("position", R.position);
556 }
557 
558 bool fromJSON(const llvm::json::Value &Params, CompletionContext &R) {
559  llvm::json::ObjectMapper O(Params);
560  if (!O)
561  return false;
562 
563  int triggerKind;
564  if (!O.map("triggerKind", triggerKind))
565  return false;
566  R.triggerKind = static_cast<CompletionTriggerKind>(triggerKind);
567 
568  if (auto *TC = Params.getAsObject()->get("triggerCharacter"))
569  return fromJSON(*TC, R.triggerCharacter);
570  return true;
571 }
572 
573 bool fromJSON(const llvm::json::Value &Params, CompletionParams &R) {
574  if (!fromJSON(Params, static_cast<TextDocumentPositionParams &>(R)))
575  return false;
576  if (auto *Context = Params.getAsObject()->get("context"))
577  return fromJSON(*Context, R.context);
578  return true;
579 }
580 
581 static llvm::StringRef toTextKind(MarkupKind Kind) {
582  switch (Kind) {
584  return "plaintext";
586  return "markdown";
587  }
588  llvm_unreachable("Invalid MarkupKind");
589 }
590 
591 llvm::json::Value toJSON(const MarkupContent &MC) {
592  if (MC.value.empty())
593  return nullptr;
594 
595  return llvm::json::Object{
596  {"kind", toTextKind(MC.kind)},
597  {"value", MC.value},
598  };
599 }
600 
601 llvm::json::Value toJSON(const Hover &H) {
602  llvm::json::Object Result{{"contents", toJSON(H.contents)}};
603 
604  if (H.range.hasValue())
605  Result["range"] = toJSON(*H.range);
606 
607  return std::move(Result);
608 }
609 
610 bool fromJSON(const llvm::json::Value &E, CompletionItemKind &Out) {
611  if (auto T = E.getAsInteger()) {
612  if (*T < static_cast<int>(CompletionItemKind::Text) ||
613  *T > static_cast<int>(CompletionItemKind::TypeParameter))
614  return false;
615  Out = static_cast<CompletionItemKind>(*T);
616  return true;
617  }
618  return false;
619 }
620 
623  CompletionItemKindBitset &supportedCompletionItemKinds) {
624  auto KindVal = static_cast<size_t>(Kind);
625  if (KindVal >= CompletionItemKindMin &&
626  KindVal <= supportedCompletionItemKinds.size() &&
627  supportedCompletionItemKinds[KindVal])
628  return Kind;
629 
630  switch (Kind) {
631  // Provide some fall backs for common kinds that are close enough.
638  default:
640  }
641 }
642 
643 bool fromJSON(const llvm::json::Value &E, CompletionItemKindBitset &Out) {
644  if (auto *A = E.getAsArray()) {
645  for (size_t I = 0; I < A->size(); ++I) {
646  CompletionItemKind KindOut;
647  if (fromJSON((*A)[I], KindOut))
648  Out.set(size_t(KindOut));
649  }
650  return true;
651  }
652  return false;
653 }
654 
655 llvm::json::Value toJSON(const CompletionItem &CI) {
656  assert(!CI.label.empty() && "completion item label is required");
657  llvm::json::Object Result{{"label", CI.label}};
659  Result["kind"] = static_cast<int>(CI.kind);
660  if (!CI.detail.empty())
661  Result["detail"] = CI.detail;
662  if (!CI.documentation.empty())
663  Result["documentation"] = CI.documentation;
664  if (!CI.sortText.empty())
665  Result["sortText"] = CI.sortText;
666  if (!CI.filterText.empty())
667  Result["filterText"] = CI.filterText;
668  if (!CI.insertText.empty())
669  Result["insertText"] = CI.insertText;
671  Result["insertTextFormat"] = static_cast<int>(CI.insertTextFormat);
672  if (CI.textEdit)
673  Result["textEdit"] = *CI.textEdit;
674  if (!CI.additionalTextEdits.empty())
675  Result["additionalTextEdits"] = llvm::json::Array(CI.additionalTextEdits);
676  if (CI.deprecated)
677  Result["deprecated"] = CI.deprecated;
678  return std::move(Result);
679 }
680 
681 llvm::raw_ostream &operator<<(llvm::raw_ostream &O, const CompletionItem &I) {
682  O << I.label << " - " << toJSON(I);
683  return O;
684 }
685 
686 bool operator<(const CompletionItem &L, const CompletionItem &R) {
687  return (L.sortText.empty() ? L.label : L.sortText) <
688  (R.sortText.empty() ? R.label : R.sortText);
689 }
690 
691 llvm::json::Value toJSON(const CompletionList &L) {
692  return llvm::json::Object{
693  {"isIncomplete", L.isIncomplete},
694  {"items", llvm::json::Array(L.items)},
695  };
696 }
697 
698 llvm::json::Value toJSON(const ParameterInformation &PI) {
699  assert(!PI.label.empty() && "parameter information label is required");
700  llvm::json::Object Result{{"label", PI.label}};
701  if (!PI.documentation.empty())
702  Result["documentation"] = PI.documentation;
703  return std::move(Result);
704 }
705 
706 llvm::json::Value toJSON(const SignatureInformation &SI) {
707  assert(!SI.label.empty() && "signature information label is required");
708  llvm::json::Object Result{
709  {"label", SI.label},
710  {"parameters", llvm::json::Array(SI.parameters)},
711  };
712  if (!SI.documentation.empty())
713  Result["documentation"] = SI.documentation;
714  return std::move(Result);
715 }
716 
717 llvm::raw_ostream &operator<<(llvm::raw_ostream &O,
718  const SignatureInformation &I) {
719  O << I.label << " - " << toJSON(I);
720  return O;
721 }
722 
723 llvm::json::Value toJSON(const SignatureHelp &SH) {
724  assert(SH.activeSignature >= 0 &&
725  "Unexpected negative value for number of active signatures.");
726  assert(SH.activeParameter >= 0 &&
727  "Unexpected negative value for active parameter index");
728  return llvm::json::Object{
729  {"activeSignature", SH.activeSignature},
730  {"activeParameter", SH.activeParameter},
731  {"signatures", llvm::json::Array(SH.signatures)},
732  };
733 }
734 
735 bool fromJSON(const llvm::json::Value &Params, RenameParams &R) {
736  llvm::json::ObjectMapper O(Params);
737  return O && O.map("textDocument", R.textDocument) &&
738  O.map("position", R.position) && O.map("newName", R.newName);
739 }
740 
741 llvm::json::Value toJSON(const DocumentHighlight &DH) {
742  return llvm::json::Object{
743  {"range", toJSON(DH.range)},
744  {"kind", static_cast<int>(DH.kind)},
745  };
746 }
747 
748 llvm::json::Value toJSON(const FileStatus &FStatus) {
749  return llvm::json::Object{
750  {"uri", FStatus.uri},
751  {"state", FStatus.state},
752  };
753 }
754 
755 llvm::raw_ostream &operator<<(llvm::raw_ostream &O,
756  const DocumentHighlight &V) {
757  O << V.range;
759  O << "(r)";
761  O << "(w)";
762  return O;
763 }
764 
765 bool fromJSON(const llvm::json::Value &Params,
767  llvm::json::ObjectMapper O(Params);
768  return O && O.map("settings", CCP.settings);
769 }
770 
771 bool fromJSON(const llvm::json::Value &Params,
772  ClangdCompileCommand &CDbUpdate) {
773  llvm::json::ObjectMapper O(Params);
774  return O && O.map("workingDirectory", CDbUpdate.workingDirectory) &&
775  O.map("compilationCommand", CDbUpdate.compilationCommand);
776 }
777 
778 bool fromJSON(const llvm::json::Value &Params, ConfigurationSettings &S) {
779  llvm::json::ObjectMapper O(Params);
780  if (!O)
781  return true; // 'any' type in LSP.
782  O.map("compilationDatabaseChanges", S.compilationDatabaseChanges);
783  return true;
784 }
785 
786 bool fromJSON(const llvm::json::Value &Params, InitializationOptions &Opts) {
787  llvm::json::ObjectMapper O(Params);
788  if (!O)
789  return true; // 'any' type in LSP.
790 
791  fromJSON(Params, Opts.ConfigSettings);
792  O.map("compilationDatabasePath", Opts.compilationDatabasePath);
793  O.map("fallbackFlags", Opts.fallbackFlags);
794  O.map("clangdFileStatus", Opts.FileStatus);
795  return true;
796 }
797 
798 bool fromJSON(const llvm::json::Value &Params, ReferenceParams &R) {
799  TextDocumentPositionParams &Base = R;
800  return fromJSON(Params, Base);
801 }
802 
803 } // namespace clangd
804 } // namespace clang
std::string insertText
A string that should be inserted to a document when selecting this completion.
Definition: Protocol.h:868
Range range
The range to format.
Definition: Protocol.h:523
std::string USR
Unified Symbol Resolution identifier This is an opaque string uniquely identifying a symbol...
Definition: Protocol.h:749
const tooling::CompileCommand & Command
TextDocumentIdentifier textDocument
The document to format.
Definition: Protocol.h:547
URIForFile uri
The file&#39;s URI.
Definition: Protocol.h:491
llvm::json::Value toJSON(const FuzzyFindRequest &Request)
Definition: Index.cpp:189
Location location
The location of this symbol.
Definition: Protocol.h:729
llvm::Optional< TextEdit > textEdit
An edit which is applied to a document when selecting this completion.
Definition: Protocol.h:879
Exact commands are not specified in the protocol so we define the ones supported by Clangd here...
Definition: Protocol.h:643
TextDocumentIdentifier textDocument
The document to format.
Definition: Protocol.h:532
llvm::Optional< SymbolKindBitset > WorkspaceSymbolKinds
The supported set of SymbolKinds for workspace/symbol.
Definition: Protocol.h:341
llvm::Optional< URIForFile > rootUri
The rootUri of the workspace.
Definition: Protocol.h:422
Position start
The range&#39;s start position.
Definition: Protocol.h:156
friend bool operator==(const URIForFile &LHS, const URIForFile &RHS)
Definition: Protocol.h:96
Represents a collection of completion items to be presented in the editor.
Definition: Protocol.h:901
Range range
The range this highlight applies to.
Definition: Protocol.h:979
std::string label
The label of this parameter. Mandatory.
Definition: Protocol.h:915
llvm::Optional< bool > wantDiagnostics
Forces diagnostics to be generated, or to not be generated, for this version of the file...
Definition: Protocol.h:475
std::vector< std::string > compilationCommand
Definition: Protocol.h:374
Range range
The range for which the command was invoked.
Definition: Protocol.h:618
CodeActionContext context
Context carrying additional information.
Definition: Protocol.h:621
static const llvm::StringLiteral CLANGD_APPLY_FIX_COMMAND
Definition: Protocol.h:645
CompletionItemKind kind
The kind of this completion item.
Definition: Protocol.h:849
Clangd extension: parameters configurable at initialize time.
Definition: Protocol.h:390
bool CompletionSnippets
Client supports snippets as insert text.
Definition: Protocol.h:354
std::string ch
The character that has been typed.
Definition: Protocol.h:538
std::vector< CompletionItem > items
The completion items.
Definition: Protocol.h:907
llvm::Optional< std::vector< CodeAction > > codeActions
Clangd extension: code actions related to this diagnostic.
Definition: Protocol.h:590
llvm::Optional< std::map< std::string, std::vector< TextEdit > > > changes
Holds changes to existing resources.
Definition: Protocol.h:627
llvm::Optional< std::string > kind
The kind of the code action.
Definition: Protocol.h:671
std::string title
A short, human-readable, title for this code action.
Definition: Protocol.h:667
llvm::Optional< Range > range
An optional range is a range inside a text document that is used to visualize a hover, e.g.
Definition: Protocol.h:820
TextDocumentIdentifier textDocument
The document that was closed.
Definition: Protocol.h:446
static llvm::StringRef toTextKind(MarkupKind Kind)
Definition: Protocol.cpp:581
std::string label
The label of this signature. Mandatory.
Definition: Protocol.h:926
std::string state
The human-readable string presents the current state of the file, can be shown in the UI (e...
Definition: Protocol.h:1011
A code action represents a change that can be performed in code, e.g.
Definition: Protocol.h:665
URIForFile uri
The text document&#39;s URI.
Definition: Protocol.h:182
std::string text
The new text of the range/document.
Definition: Protocol.h:458
llvm::Optional< WorkspaceEdit > edit
The workspace edit this code action performs.
Definition: Protocol.h:678
Range selectionRange
The range that should be selected and revealed when this symbol is being picked, e.g the name of a function.
Definition: Protocol.h:711
constexpr auto SymbolKindMin
Definition: Protocol.h:328
llvm::Optional< std::string > compilationDatabasePath
Definition: Protocol.h:395
std::string sortText
A string that should be used when comparing this item with other items.
Definition: Protocol.h:860
constexpr auto CompletionItemKindMin
Definition: Protocol.h:288
std::vector< ParameterInformation > parameters
The parameters of this signature.
Definition: Protocol.h:932
std::bitset< CompletionItemKindMax+1 > CompletionItemKindBitset
Definition: Protocol.h:292
bool isIncomplete
The list is not complete.
Definition: Protocol.h:904
std::string documentation
A human-readable string that represents a doc-comment.
Definition: Protocol.h:856
Range range
The range enclosing this symbol not including leading/trailing whitespace but everything else like co...
Definition: Protocol.h:707
URIForFile uri
The text document&#39;s URI.
Definition: Protocol.h:1008
FormattingOptions options
The format options.
Definition: Protocol.h:541
std::vector< TextEdit > additionalTextEdits
An optional array of additional text edits that are applied when selecting this completion.
Definition: Protocol.h:884
void elog(const char *Fmt, Ts &&... Vals)
Definition: Logger.h:57
int tabSize
Size of a tab in spaces.
Definition: Protocol.h:510
Represents programming constructs like variables, classes, interfaces etc.
Definition: Protocol.h:690
llvm::Optional< int > processId
The process Id of the parent process that started the server.
Definition: Protocol.h:411
CompletionItemKind
The kind of a completion entry.
Definition: Protocol.h:259
ConfigurationSettings ConfigSettings
Definition: Protocol.h:393
A top-level diagnostic that may have Notes and Fixes.
Definition: Diagnostics.h:67
std::string uri() const
Definition: Protocol.h:94
BindArgumentKind Kind
MarkupContent contents
The hover&#39;s content.
Definition: Protocol.h:816
A document highlight is a range inside a text document which deserves special attention.
Definition: Protocol.h:977
URIForFile uri
The text document&#39;s URI.
Definition: Protocol.h:219
std::string detail
A human-readable string with additional information about this item, like type or symbol information...
Definition: Protocol.h:853
const Type * get(const Key< Type > &Key) const
Get data stored for a typed Key.
Definition: Context.h:101
llvm::Optional< SymbolID > ID
Definition: Protocol.h:751
TextDocumentIdentifier textDocument
The document that was opened.
Definition: Protocol.h:961
std::string newText
The string to be inserted.
Definition: Protocol.h:207
bool DiagnosticCategory
Whether the client accepts diagnostics with category attached to it using the "category" extension...
Definition: Protocol.h:350
std::string newName
The new name of the symbol.
Definition: Protocol.h:967
Represents the signature of something callable.
Definition: Protocol.h:923
Clangd extension: parameters configurable at any time, via the workspace/didChangeConfiguration notif...
Definition: Protocol.h:381
std::string command
The command identifier, e.g. CLANGD_APPLY_FIX_COMMAND.
Definition: Protocol.h:648
static llvm::Expected< URIForFile > fromURI(const URI &U, llvm::StringRef HintPath)
Definition: Protocol.cpp:45
InitializationOptions initializationOptions
User-provided initialization options.
Definition: Protocol.h:434
TextDocumentIdentifier textDocument
Definition: Protocol.h:556
std::string filterText
A string that should be used when filtering a set of completion items.
Definition: Protocol.h:864
TextDocumentIdentifier textDocument
The document in which the command was invoked.
Definition: Protocol.h:615
Range range
The range of the text document to be manipulated.
Definition: Protocol.h:203
static llvm::Expected< std::string > resolvePath(llvm::StringRef AbsPath, llvm::StringRef HintPath="")
Resolves AbsPath into a canonical path of its URI, by converting AbsPath to URI and resolving the URI...
Definition: URI.cpp:232
bool deprecated
Indicates if this item is deprecated.
Definition: Protocol.h:887
int activeSignature
The active signature.
Definition: Protocol.h:945
std::vector< std::string > fallbackFlags
Definition: Protocol.h:399
int activeParameter
The active parameter of the active signature.
Definition: Protocol.h:948
llvm::Optional< Range > range
The range of the document that changed.
Definition: Protocol.h:452
llvm::Optional< std::string > category
The diagnostic&#39;s category.
Definition: Protocol.h:585
CompletionTriggerKind triggerKind
How the completion was triggered.
Definition: Protocol.h:791
static URIForFile canonicalize(llvm::StringRef AbsPath, llvm::StringRef TUPath)
Canonicalizes AbsPath via URI.
Definition: Protocol.cpp:32
Position position
The position inside the text document.
Definition: Protocol.h:774
std::vector< DocumentSymbol > children
Children of this symbol, e.g. properties of a class.
Definition: Protocol.h:714
const Decl * D
Definition: XRefs.cpp:79
llvm::Optional< llvm::Expected< tooling::AtomicChanges > > Result
std::string documentation
The documentation of this parameter. Optional.
Definition: Protocol.h:918
SymbolKind kind
The kind of this symbol.
Definition: Protocol.h:726
std::vector< SignatureInformation > signatures
The resulting signatures.
Definition: Protocol.h:942
llvm::Optional< int > rangeLength
The length of the range that got replaced.
Definition: Protocol.h:455
bool FileStatus
Clients supports show file status for textDocument/clangd.fileStatus.
Definition: Protocol.h:402
std::string name
The name of this symbol.
Definition: Protocol.h:692
bool DiagnosticFixes
Whether the client accepts diagnostics with codeActions attached inline.
Definition: Protocol.h:345
ClientCapabilities capabilities
The capabilities provided by the client (editor or tool)
Definition: Protocol.h:428
TextDocumentItem textDocument
The document that was opened.
Definition: Protocol.h:440
A context is an immutable container for per-request data that must be propagated through layers that ...
Definition: Context.h:70
TextDocumentIdentifier textDocument
The document that did change.
Definition: Protocol.h:466
std::map< std::string, ClangdCompileCommand > compilationDatabaseChanges
Definition: Protocol.h:384
std::string detail
More detail for this symbol, e.g the signature of a function.
Definition: Protocol.h:695
std::vector< FileEvent > changes
The actual file events.
Definition: Protocol.h:499
FormattingOptions options
The format options.
Definition: Protocol.h:526
llvm::Optional< CompletionItemKindBitset > CompletionItemKinds
The supported set of CompletionItemKinds for textDocument/completion.
Definition: Protocol.h:361
std::string languageId
The text document&#39;s language identifier.
Definition: Protocol.h:222
llvm::Optional< std::string > rootPath
The rootPath of the workspace.
Definition: Protocol.h:417
Position position
The position at which this request was sent.
Definition: Protocol.h:535
bool CodeActionStructure
Client supports CodeAction return value for textDocument/codeAction.
Definition: Protocol.h:365
bool fromJSON(const llvm::json::Value &Parameters, FuzzyFindRequest &Request)
Definition: Index.cpp:176
A single parameter of a particular signature.
Definition: Protocol.h:912
FormattingOptions options
The format options.
Definition: Protocol.h:550
int line
Line position in a document (zero-based).
Definition: Protocol.h:127
std::vector< TextDocumentContentChangeEvent > contentChanges
The actual content changes.
Definition: Protocol.h:469
int character
Character offset on a line in a document (zero-based).
Definition: Protocol.h:132
CompletionContext context
Definition: Protocol.h:799
Represents the signature of a callable.
Definition: Protocol.h:939
std::string query
A non-empty query string.
Definition: Protocol.h:760
SymbolKind kind
The kind of this symbol.
Definition: Protocol.h:698
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
std::bitset< SymbolKindMax+1 > SymbolKindBitset
Definition: Protocol.h:330
SymbolKind
A symbol kind.
Definition: Protocol.h:299
std::string message
The diagnostic&#39;s code.
Definition: Protocol.h:579
std::string triggerCharacter
The trigger character (a single character) that has trigger code complete.
Definition: Protocol.h:794
TextDocumentIdentifier textDocument
The text document.
Definition: Protocol.h:771
std::string label
The label of this completion item.
Definition: Protocol.h:845
DocumentHighlightKind kind
The highlight kind, default is DocumentHighlightKind.Text.
Definition: Protocol.h:982
SymbolKind adjustKindToCapability(SymbolKind Kind, SymbolKindBitset &SupportedSymbolKinds)
Definition: Protocol.cpp:198
static const llvm::StringLiteral QUICKFIX_KIND
Definition: Protocol.h:672
A URI describes the location of a source file.
Definition: URI.h:29
std::vector< Diagnostic > diagnostics
An array of diagnostics.
Definition: Protocol.h:609
int severity
The diagnostic&#39;s severity.
Definition: Protocol.h:567
bool deprecated
Indicates if this symbol is deprecated.
Definition: Protocol.h:701
llvm::Optional< Command > command
A command this code action executes.
Definition: Protocol.h:682
The parameters of a Workspace Symbol Request.
Definition: Protocol.h:758
FileChangeType type
The change type.
Definition: Protocol.h:493
std::string text
The content of the opened text document.
Definition: Protocol.h:228
Clangd extension: indicates the current state of the file in clangd, sent from server via the textDoc...
Definition: Protocol.h:1006
static llvm::Expected< std::string > resolve(const URI &U, llvm::StringRef HintPath="")
Resolves the absolute path of U.
Definition: URI.cpp:224
std::string containerName
The name of the symbol containing this symbol.
Definition: Protocol.h:732
llvm::Optional< std::vector< Diagnostic > > diagnostics
The diagnostics that this code action resolves.
Definition: Protocol.h:675
Position position
The position at which this request was sent.
Definition: Protocol.h:964
URIForFile uri
The text document&#39;s URI.
Definition: Protocol.h:120
static llvm::Expected< URI > parse(llvm::StringRef Uri)
Parse a URI string "<scheme>:[//<authority>/]<path>".
Definition: URI.cpp:166
Range range
The range at which the message applies.
Definition: Protocol.h:563
friend bool operator<(const URIForFile &LHS, const URIForFile &RHS)
Definition: Protocol.h:104
int version
The version number of this document (it will strictly increase after each.
Definition: Protocol.h:225
TextDocumentIdentifier textDocument
The document to format.
Definition: Protocol.h:520
Position end
The range&#39;s end position.
Definition: Protocol.h:159
llvm::Optional< WorkspaceEdit > workspaceEdit
Definition: Protocol.h:651
llvm::raw_ostream & operator<<(llvm::raw_ostream &OS, const CodeCompletion &C)
std::string name
The name of this symbol.
Definition: Protocol.h:723
InsertTextFormat insertTextFormat
The format of the insert text.
Definition: Protocol.h:872
Clangd extension that&#39;s used in the &#39;compilationDatabaseChanges&#39; in workspace/didChangeConfiguration ...
Definition: Protocol.h:372
Represents information about identifier.
Definition: Protocol.h:739
bool insertSpaces
Prefer spaces over tabs.
Definition: Protocol.h:513
llvm::Optional< TraceLevel > trace
The initial trace setting. If omitted trace is disabled (&#39;off&#39;).
Definition: Protocol.h:431
std::string documentation
The documentation of this signature. Optional.
Definition: Protocol.h:929
bool HierarchicalDocumentSymbol
Client supports hierarchical document symbols.
Definition: Protocol.h:357
Represents information about programming constructs like variables, classes, interfaces etc...
Definition: Protocol.h:721