16#include <llvm/ADT/StringExtras.h>
17#include <llvm/ADT/StringRef.h>
18#include <llvm/ADT/StringSwitch.h>
19#include <llvm/Support/ErrorHandling.h>
20#include <llvm/Support/JSON.h>
21#include <llvm/Support/Path.h>
22#include <llvm/Support/raw_ostream.h>
29bool mapOptOrNull(
const llvm::json::Value &Params, llvm::StringLiteral Prop,
30 T &Out, llvm::json::Path P) {
31 auto *O = Params.getAsObject();
33 auto *V = O->get(Prop);
35 if (!V || V->getAsNull())
37 return fromJSON(*V, Out, P.field(Prop));
44 llvm::StringRef TUPath) {
45 assert(llvm::sys::path::is_absolute(AbsPath) &&
"the path is relative");
48 elog(
"URIForFile: failed to resolve path {0} with TU path {1}: "
49 "{2}.\nUsing unresolved path.",
50 AbsPath, TUPath, Resolved.takeError());
57 llvm::StringRef HintPath) {
60 return Resolved.takeError();
65 if (
auto S = E.getAsString()) {
68 consumeError(Parsed.takeError());
69 P.report(
"failed to parse URI");
72 if (Parsed->scheme() !=
"file" && Parsed->scheme() !=
"test") {
73 P.report(
"clangd only supports 'file' URI scheme for workspace files");
79 P.report(
"unresolvable URI");
80 consumeError(U.takeError());
96 return llvm::json::Object{{
"uri", R.
uri}};
100 llvm::json::Path P) {
101 llvm::json::ObjectMapper O(Params, P);
102 return O && O.map(
"uri", R.
uri);
107 Result.getAsObject()->try_emplace(
"version", R.
version);
113 llvm::json::ObjectMapper O(Params, P);
119 llvm::json::Path P) {
120 llvm::json::ObjectMapper O(Params, P);
121 return O && O.map(
"line", R.
line) && O.map(
"character", R.
character);
125 return llvm::json::Object{
135bool fromJSON(
const llvm::json::Value &Params,
Range &R, llvm::json::Path P) {
136 llvm::json::ObjectMapper O(Params, P);
137 return O && O.map(
"start", R.
start) && O.map(
"end", R.
end);
141 return llvm::json::Object{
148 return OS << R.
start <<
'-' << R.
end;
152 return llvm::json::Object{
159 llvm::json::Path P) {
160 llvm::json::ObjectMapper O(Params, P);
161 return O && O.map(
"uri", R.
uri) && O.map(
"range", R.
range);
165 return OS << L.
range <<
'@' << L.
uri;
169 llvm::json::Object Result{
185 llvm::json::Path P) {
186 llvm::json::ObjectMapper O(Params, P);
187 return O && O.map(
"uri", R.
uri) && O.map(
"languageId", R.
languageId) &&
188 O.map(
"version", R.
version) && O.map(
"text", R.
text);
192 llvm::json::Path P) {
193 llvm::json::ObjectMapper O(Params, P);
194 return O && O.map(
"range", R.
range) && O.map(
"newText", R.
newText) &&
199 llvm::json::Object Result{
209 llvm::json::Path P) {
210 llvm::json::ObjectMapper O(Params, P);
211 return O && O.map(
"label", R.
label) &&
216 llvm::json::Object Result{{
"label", CA.
label}};
225 llvm::json::Path P) {
226 llvm::json::ObjectMapper O(Params, P);
230 llvm::json::Object Result{{
"textDocument", P.
textDocument},
240 llvm::json::Object Result;
249 llvm::json::Object Result{
254 Result[
"options"] = *P.
options;
261 llvm::json::Object Result;
270 llvm::json::Object Result{
276 Result[
"options"] = *P.
options;
283 llvm::json::Object Result;
292 llvm::json::Object Result{
297 Result[
"options"] = *P.
options;
305 [](
const auto &Change) -> llvm::json::Value {
return toJSON(Change); },
310 llvm::json::Path P) {
314 const auto *O = Params.getAsObject();
319 if (
auto Kind = O->getString(
"kind")) {
320 if (*Kind ==
"create") {
325 if (
const auto *OptsObj = O->getObject(
"options")) {
327 if (
auto Overwrite = OptsObj->getBoolean(
"overwrite"))
328 CF.
options->overwrite = *Overwrite;
329 if (
auto IgnoreIfExists = OptsObj->getBoolean(
"ignoreIfExists"))
330 CF.
options->ignoreIfExists = *IgnoreIfExists;
332 if (
auto AnnotationId = O->getString(
"annotationId"))
337 if (*Kind ==
"rename") {
342 if (
const auto *OptsObj = O->getObject(
"options")) {
344 if (
auto Overwrite = OptsObj->getBoolean(
"overwrite"))
345 RF.
options->overwrite = *Overwrite;
346 if (
auto IgnoreIfExists = OptsObj->getBoolean(
"ignoreIfExists"))
347 RF.
options->ignoreIfExists = *IgnoreIfExists;
349 if (
auto AnnotationId = O->getString(
"annotationId"))
354 if (*Kind ==
"delete") {
358 if (
const auto *OptsObj = O->getObject(
"options")) {
360 if (
auto Recursive = OptsObj->getBoolean(
"recursive"))
361 DF.
options->recursive = *Recursive;
362 if (
auto IgnoreIfNotExists = OptsObj->getBoolean(
"ignoreIfNotExists"))
363 DF.
options->ignoreIfNotExists = *IgnoreIfNotExists;
365 if (
auto AnnotationId = O->getString(
"annotationId"))
370 P.report(
"unknown document change kind");
383 OS << TE.
range <<
" => \"";
384 llvm::printEscapedString(TE.
newText, OS);
389 if (
auto S = E.getAsString()) {
394 if (*S ==
"messages") {
398 if (*S ==
"verbose") {
407 if (
auto T = E.getAsInteger()) {
418 llvm::json::Path P) {
419 if (
auto *A = E.getAsArray()) {
420 for (
size_t I = 0; I < A->size(); ++I) {
422 if (
fromJSON((*A)[I], KindOut, P.index(I)))
423 Out.set(
size_t(KindOut));
432 auto KindVal =
static_cast<size_t>(Kind);
433 if (KindVal >=
SymbolKindMin && KindVal <= SupportedSymbolKinds.size() &&
434 SupportedSymbolKinds[KindVal])
449 llvm::json::Path P) {
450 const llvm::json::Object *O = Params.getAsObject();
452 P.report(
"expected object");
455 if (
auto *TextDocument = O->getObject(
"textDocument")) {
456 if (
auto *SemanticHighlighting =
457 TextDocument->getObject(
"semanticHighlightingCapabilities")) {
458 if (
auto SemanticHighlightingSupport =
459 SemanticHighlighting->getBoolean(
"semanticHighlighting"))
462 if (
auto *InactiveRegions =
463 TextDocument->getObject(
"inactiveRegionsCapabilities")) {
464 if (
auto InactiveRegionsSupport =
465 InactiveRegions->getBoolean(
"inactiveRegions")) {
469 if (TextDocument->getObject(
"semanticTokens"))
471 if (
auto *Diagnostics = TextDocument->getObject(
"publishDiagnostics")) {
472 if (
auto CategorySupport = Diagnostics->getBoolean(
"categorySupport"))
474 if (
auto CodeActions = Diagnostics->getBoolean(
"codeActionsInline"))
476 if (
auto RelatedInfo = Diagnostics->getBoolean(
"relatedInformation"))
479 if (
auto *References = TextDocument->getObject(
"references"))
480 if (
auto ContainerSupport = References->getBoolean(
"container"))
482 if (
auto *Completion = TextDocument->getObject(
"completion")) {
483 if (
auto *Item = Completion->getObject(
"completionItem")) {
484 if (
auto SnippetSupport = Item->getBoolean(
"snippetSupport"))
486 if (
const auto *DocumentationFormat =
487 Item->getArray(
"documentationFormat")) {
488 for (
const auto &Format : *DocumentationFormat) {
494 if (
auto *ItemKind = Completion->getObject(
"completionItemKind")) {
495 if (
auto *ValueSet = ItemKind->get(
"valueSet")) {
498 P.field(
"textDocument")
500 .field(
"completionItemKind")
505 if (
auto EditsNearCursor = Completion->getBoolean(
"editsNearCursor"))
508 if (
auto *
CodeAction = TextDocument->getObject(
"codeAction")) {
509 if (
CodeAction->getObject(
"codeActionLiteralSupport"))
512 if (
auto *
DocumentSymbol = TextDocument->getObject(
"documentSymbol")) {
513 if (
auto HierarchicalSupport =
517 if (
auto *
Hover = TextDocument->getObject(
"hover")) {
518 if (
auto *ContentFormat =
Hover->getArray(
"contentFormat")) {
519 for (
const auto &Format : *ContentFormat) {
525 if (
auto *Help = TextDocument->getObject(
"signatureHelp")) {
527 if (
auto *
Info = Help->getObject(
"signatureInformation")) {
528 if (
auto *
Parameter =
Info->getObject(
"parameterInformation")) {
529 if (
auto OffsetSupport =
Parameter->getBoolean(
"labelOffsetSupport"))
532 if (
const auto *DocumentationFormat =
533 Info->getArray(
"documentationFormat")) {
534 for (
const auto &Format : *DocumentationFormat) {
541 if (
auto *Folding = TextDocument->getObject(
"foldingRange")) {
542 if (
auto LineFolding = Folding->getBoolean(
"lineFoldingOnly"))
545 if (
auto *Rename = TextDocument->getObject(
"rename")) {
546 if (
auto RenameSupport = Rename->getBoolean(
"prepareSupport"))
550 if (
auto *Workspace = O->getObject(
"workspace")) {
551 if (
auto *Symbol = Workspace->getObject(
"symbol")) {
552 if (
auto *
SymbolKind = Symbol->getObject(
"symbolKind")) {
553 if (
auto *ValueSet =
SymbolKind->get(
"valueSet")) {
565 if (
auto WorkspaceConfiguration = Workspace->getBoolean(
"configuration")) {
569 if (
auto *
SemanticTokens = Workspace->getObject(
"semanticTokens")) {
570 if (
auto RefreshSupport =
SemanticTokens->getBoolean(
"refreshSupport"))
573 if (
auto *
WorkspaceEdit = Workspace->getObject(
"workspaceEdit")) {
574 if (
auto DocumentChanges =
WorkspaceEdit->getBoolean(
"documentChanges"))
581 if (
auto *Window = O->getObject(
"window")) {
582 if (
auto WorkDoneProgress = Window->getBoolean(
"workDoneProgress"))
584 if (
auto Implicit = Window->getBoolean(
"implicitWorkDoneProgressCreate"))
587 if (
auto *General = O->getObject(
"general")) {
588 if (
auto *StaleRequestSupport = General->getObject(
"staleRequestSupport")) {
589 if (
auto Cancel = StaleRequestSupport->getBoolean(
"cancel"))
596 P.field(
"offsetEncoding")))
603 llvm::json::Path P) {
604 llvm::json::ObjectMapper O(Params, P);
613 if (
auto *RawCaps = Params.getAsObject()->getObject(
"capabilities"))
615 O.map(
"trace", R.
trace);
621 return llvm::json::Object{{
"token", P.
token}};
625 llvm::json::Object Result{
630 Result[
"cancellable"] =
true;
632 Result[
"percentage"] = 0;
639 llvm::json::Object Result{{
"kind",
"report"}};
643 Result[
"message"] = *P.
message;
651 llvm::json::Object Result{{
"kind",
"end"}};
653 Result[
"message"] = *P.
message;
659 return static_cast<int64_t
>(R);
663 return llvm::json::Object{{
"type", R.
type}, {
"message", R.
message}};
667 llvm::json::Path P) {
668 llvm::json::ObjectMapper O(Params, P);
673 llvm::json::Path P) {
674 llvm::json::ObjectMapper O(Params, P);
679 llvm::json::Path P) {
680 llvm::json::ObjectMapper O(Params, P);
685 llvm::json::Path P) {
686 llvm::json::ObjectMapper O(Params, P);
690 mapOptOrNull(Params,
"forceRebuild", R.
forceRebuild, P);
694 llvm::json::Path P) {
695 if (
auto T = E.getAsInteger()) {
706 llvm::json::Path P) {
707 llvm::json::ObjectMapper O(Params, P);
708 return O && O.map(
"uri", R.
uri) && O.map(
"type", R.
type);
712 llvm::json::Path P) {
713 llvm::json::ObjectMapper O(Params, P);
714 return O && O.map(
"changes", R.
changes);
719 llvm::json::ObjectMapper O(Params, P);
720 return O && O.map(
"range", R.
range) && O.map(
"rangeLength", R.
rangeLength) &&
721 O.map(
"text", R.
text);
725 llvm::json::Path P) {
726 llvm::json::ObjectMapper O(Params, P);
732 llvm::json::ObjectMapper O(Params, P);
734 O.map(
"position", R.
position) && O.map(
"ch", R.
ch);
738 llvm::json::Path P) {
739 llvm::json::ObjectMapper O(Params, P);
744 llvm::json::Path P) {
745 llvm::json::ObjectMapper O(Params, P);
750 return llvm::json::Object{
759 return llvm::json::Object{{
"href", D.
href}};
763 llvm::json::Object Diag{
773 Diag[
"code"] = D.
code;
777 Diag[
"source"] = D.
source;
781 Diag[
"data"] = llvm::json::Object(D.
data);
783 Diag[
"tags"] = llvm::json::Array{D.
tags};
789 llvm::json::Path P) {
790 llvm::json::ObjectMapper O(Params, P);
793 if (
auto *Data = Params.getAsObject()->getObject(
"data"))
795 return O.map(
"range", R.
range) && O.map(
"message", R.
message) &&
796 mapOptOrNull(Params,
"severity", R.
severity, P) &&
797 mapOptOrNull(Params,
"category", R.
category, P) &&
798 mapOptOrNull(Params,
"code", R.
code, P) &&
799 mapOptOrNull(Params,
"source", R.
source, P);
803 llvm::json::Object Result{
808 Result[
"version"] = PDP.
version;
813 llvm::json::Path P) {
814 llvm::json::ObjectMapper O(Params, P);
817 O.map(
"only", R.
only);
822 OS << D.
range <<
" [";
844 llvm::json::Path P) {
845 llvm::json::ObjectMapper O(Params, P);
851 llvm::json::Path P) {
852 llvm::json::ObjectMapper O(Params, P);
853 return O && O.map(
"changes", R.
changes) &&
859 llvm::json::Path P) {
860 llvm::json::ObjectMapper O(Params, P);
861 if (!O || !O.map(
"command", R.
command))
864 const auto *Args = Params.getAsObject()->get(
"arguments");
867 const auto *ArgsArray = Args->getAsArray();
869 P.field(
"arguments").report(
"expected array");
872 if (ArgsArray->size() > 1) {
873 P.field(
"arguments").report(
"Command should have 0 or 1 argument");
876 if (ArgsArray->size() == 1) {
883 llvm::json::Object O{
885 {
"kind",
static_cast<int>(P.
kind)},
890 O[
"score"] = *P.
score;
901 llvm::json::Path P) {
902 llvm::json::ObjectMapper O(Params, P);
903 return O && O.map(
"query", R.
query) &&
904 mapOptOrNull(Params,
"limit", R.
limit, P);
908 auto Cmd = llvm::json::Object{{
"title", C.
title}, {
"command", C.
command}};
910 Cmd[
"arguments"] = llvm::json::Array{C.
argument};
938 llvm::json::Path P) {
939 llvm::json::ObjectMapper O(Params, P);
940 if (!O || !O.map(
"title", CA.
title))
942 O.map(
"kind", CA.
kind);
945 O.map(
"edit", CA.
edit);
948 if (
const auto *Obj = Params.getAsObject()) {
949 if (
const auto *Data = Obj->get(
"data"))
960 llvm::json::Object Result{{
"name", S.
name},
961 {
"kind",
static_cast<int>(S.
kind)},
966 Result[
"detail"] = S.
detail;
970 Result[
"deprecated"] =
true;
976 llvm::json::Object Result;
978 llvm::json::Object FileChanges;
979 for (
auto &Change : *WE.
changes)
980 FileChanges[Change.first] = llvm::json::Array(Change.second);
981 Result[
"changes"] = std::move(FileChanges);
986 llvm::json::Object ChangeAnnotations;
988 ChangeAnnotations[Annotation.first] = Annotation.second;
989 Result[
"changeAnnotations"] = std::move(ChangeAnnotations);
995 llvm::json::Path P) {
996 llvm::json::ObjectMapper O(Params, P);
997 return O && O.map(
"file", A.
file) && O.map(
"selection", A.
selection) &&
1002 return llvm::json::Object{
1007 return llvm::json::Object{{
"edit", Params.
edit}};
1011 llvm::json::Path P) {
1012 llvm::json::ObjectMapper O(Response, P);
1013 return O && O.map(
"applied", R.
applied) &&
1018 llvm::json::Object Result;
1023 Result[
"uri"] = Params.
uri;
1025 Result[
"external"] = *Params.
external;
1027 Result[
"takeFocus"] = *Params.
takeFocus;
1029 Result[
"selection"] = *Params.
selection;
1034 llvm::json::Path P) {
1035 llvm::json::ObjectMapper O(Response, P);
1036 return O && O.map(
"success", R.
success);
1040 llvm::json::Path P) {
1041 llvm::json::ObjectMapper O(Params, P);
1047 llvm::json::Path P) {
1048 llvm::json::ObjectMapper O(Params, P);
1050 if (!O || !O.map(
"triggerKind", TriggerKind) ||
1058 llvm::json::Path P) {
1060 !mapOptOrNull(Params,
"limit", R.
limit, P))
1062 if (
auto *Context = Params.getAsObject()->get(
"context"))
1067static llvm::StringRef toTextKind(
MarkupKind Kind) {
1074 llvm_unreachable(
"Invalid MarkupKind");
1077static MarkupKind fromTextKind(llvm::StringRef Kind) {
1078 if (Kind ==
"plaintext")
1080 if (Kind ==
"markdown")
1082 llvm_unreachable(
"Invalid MarkupKind");
1086 auto Str = V.getAsString();
1088 P.report(
"expected string");
1091 if (*Str ==
"plaintext")
1093 else if (*Str ==
"markdown")
1096 P.report(
"unknown markup kind");
1103 return OS << toTextKind(K);
1107 if (MC.
value.empty())
1110 return llvm::json::Object{
1111 {
"kind", toTextKind(MC.
kind)},
1112 {
"value", MC.
value},
1117 llvm::json::Path P) {
1118 llvm::json::ObjectMapper O(Params, P);
1122 return O.mapOptional(
"value", R.
value);
1135 llvm::json::Path P) {
1136 if (
auto T = E.getAsInteger()) {
1149 auto KindVal =
static_cast<size_t>(Kind);
1151 KindVal <= SupportedCompletionItemKinds.size() &&
1152 SupportedCompletionItemKinds[KindVal])
1169 llvm::json::Path P) {
1170 if (
auto *A = E.getAsArray()) {
1171 for (
size_t I = 0; I < A->size(); ++I) {
1173 if (
fromJSON((*A)[I], KindOut, P.index(I)))
1174 Out.set(
size_t(KindOut));
1182 assert(!CI.
label.empty() &&
"completion item label is required");
1183 llvm::json::Object Result{{
"label", CI.
label}};
1185 Result[
"kind"] =
static_cast<int>(CI.
kind);
1187 Result[
"detail"] = CI.
detail;
1204 Result[
"score"] = CI.
score;
1205 Result[
"data"] = CI.
data;
1210 llvm::json::Path P) {
1211 llvm::json::ObjectMapper O(Params, P);
1213 if (!O.mapOptional(
"kind", Kind))
1217 if (!O.mapOptional(
"insertTextFormat", Kind))
1221 && O.map(
"label", R.
label)
1222 && O.mapOptional(
"detail", R.
detail)
1224 && O.mapOptional(
"sortText", R.
sortText)
1227 && O.mapOptional(
"textEdit", R.
textEdit)
1229 && O.mapOptional(
"data", R.
data)
1244 return llvm::json::Object{
1246 {
"items", llvm::json::Array(L.
items)},
1252 "parameter information label is required");
1253 llvm::json::Object Result;
1265 assert(!SI.
label.empty() &&
"signature information label is required");
1266 llvm::json::Object Result{
1267 {
"label", SI.
label},
1268 {
"parameters", llvm::json::Array(SI.
parameters)},
1283 "Unexpected negative value for number of active signatures.");
1285 "Unexpected negative value for active parameter index");
1286 return llvm::json::Object{
1289 {
"signatures", llvm::json::Array(SH.
signatures)},
1294 llvm::json::Path P) {
1295 llvm::json::ObjectMapper O(Params, P);
1301 return llvm::json::Object{
1303 {
"kind",
static_cast<int>(DH.
kind)},
1308 return llvm::json::Object{
1309 {
"uri", FStatus.
uri},
1310 {
"state", FStatus.
state},
1315static llvm::json::Value encodeTokens(llvm::ArrayRef<SemanticToken> Toks) {
1316 llvm::json::Array Result;
1318 for (
const auto &Tok : Toks) {
1319 Result.push_back(Tok.deltaLine);
1320 Result.push_back(Tok.deltaStart);
1321 Result.push_back(Tok.length);
1322 Result.push_back(Tok.tokenType);
1323 Result.push_back(Tok.tokenModifiers);
1337 return llvm::json::Object{{
"resultId",
Tokens.resultId},
1342 return llvm::json::Object{
1345 {
"data", encodeTokens(Edit.
tokens)}};
1349 llvm::json::Object Result{{
"resultId", TE.
resultId}};
1351 Result[
"edits"] = *TE.
edits;
1353 Result[
"data"] = encodeTokens(*TE.
tokens);
1358 llvm::json::Path P) {
1359 llvm::json::ObjectMapper O(Params, P);
1364 llvm::json::Path P) {
1365 llvm::json::ObjectMapper O(Params, P);
1371 return llvm::json::Object{
1388 llvm::json::ObjectMapper O(Params, P);
1389 return O && O.map(
"settings", CCP.
settings);
1393 llvm::json::Path P) {
1394 llvm::json::ObjectMapper O(Params, P);
1400 llvm::json::Path P) {
1401 llvm::json::ObjectMapper O(Params, P);
1404 return mapOptOrNull(Params,
"compilationDatabaseChanges",
1409 llvm::json::Path P) {
1410 llvm::json::ObjectMapper O(Params, P);
1416 mapOptOrNull(Params,
"fallbackFlags", Opts.
fallbackFlags, P) &&
1417 mapOptOrNull(Params,
"clangdFileStatus", Opts.
FileStatus, P);
1421 llvm::json::Path P) {
1422 auto T = E.getAsInteger();
1433 llvm::json::Path P) {
1434 llvm::json::ObjectMapper O(Params, P);
1437 mapOptOrNull(Params,
"resolve", R.
resolve, P) &&
1438 mapOptOrNull(Params,
"direction", R.
direction, P);
1447 llvm::json::Object Result{};
1449 Result[
"parents"] = RP.
parents;
1454 llvm::json::ObjectMapper O(Params, P);
1455 return O && mapOptOrNull(Params,
"parents", RP.
parents, P);
1459 llvm::json::Object Result{
1460 {
"name", I.
name}, {
"kind",
static_cast<int>(I.
kind)},
1462 {
"uri", I.
uri}, {
"data", I.
data},
1466 Result[
"detail"] = I.
detail;
1471 llvm::json::Path P) {
1472 llvm::json::ObjectMapper O(Params, P);
1475 return O && O.map(
"name", I.
name) && O.map(
"kind", I.
kind) &&
1476 O.map(
"uri", I.
uri) && O.map(
"range", I.
range) &&
1478 mapOptOrNull(Params,
"detail", I.
detail, P) &&
1479 mapOptOrNull(Params,
"deprecated", I.
deprecated, P) &&
1480 mapOptOrNull(Params,
"parents", I.
parents, P) &&
1481 mapOptOrNull(Params,
"children", I.
children, P) &&
1482 mapOptOrNull(Params,
"data", I.
data, P);
1487 llvm::json::ObjectMapper O(Params, P);
1488 return O && O.map(
"item", R.
item) &&
1489 mapOptOrNull(Params,
"resolve", R.
resolve, P) &&
1490 mapOptOrNull(Params,
"direction", R.
direction, P);
1494 llvm::json::Path P) {
1495 llvm::json::ObjectMapper O(Params, P);
1500 llvm::json::Path P) {
1502 llvm::json::ObjectMapper O(Params, P);
1503 return fromJSON(Params, Base, P) && O && O.mapOptional(
"context", R.
context);
1507 return llvm::json::Value{
static_cast<int>(Tag)};
1511 llvm::json::Object Result{{
"name", I.
name},
1512 {
"kind",
static_cast<int>(I.
kind)},
1516 if (!I.
tags.empty())
1517 Result[
"tags"] = I.
tags;
1519 Result[
"detail"] = I.
detail;
1520 if (!I.
data.empty())
1521 Result[
"data"] = I.
data;
1526 llvm::json::Path P) {
1527 llvm::json::ObjectMapper O(Params, P);
1532 return O && O.map(
"name", I.
name) && O.map(
"kind", I.
kind) &&
1533 O.map(
"uri", I.
uri) && O.map(
"range", I.
range) &&
1535 mapOptOrNull(Params,
"data", I.
data, P);
1540 llvm::json::ObjectMapper O(Params, P);
1541 return O.map(
"item", C.
item);
1545 return llvm::json::Object{{
"from", C.
from}, {
"fromRanges", C.
fromRanges}};
1550 llvm::json::ObjectMapper O(Params, P);
1551 return O.map(
"item", C.
item);
1555 return llvm::json::Object{{
"to", C.
to}, {
"fromRanges", C.
fromRanges}};
1559 llvm::json::Path P) {
1560 llvm::json::ObjectMapper O(Params, P);
1573 llvm_unreachable(
"Unknown clang.clangd.InlayHintKind");
1577 llvm::json::Object Result{{
"position", H.
position},
1583 Result[
"kind"] = std::move(K);
1603 return "designator";
1605 llvm_unreachable(
"Unknown clang.clangd.InlayHintKind");
1607 return OS << ToString(Kind);
1621 llvm_unreachable(
"Unknown clang.clangd.OffsetEncoding");
1625 llvm::json::Path P) {
1626 auto Str = V.getAsString();
1629 OE = llvm::StringSwitch<OffsetEncoding>(*Str)
1637 return OS << toString(Enc);
1641 llvm::json::Path P) {
1642 llvm::json::ObjectMapper O(Params, P);
1649 return llvm::json::Object{{
"range", Out.
range},
1652 return llvm::json::Object{{
"range", Out.
range}};
1656 llvm::json::Path P) {
1657 llvm::json::ObjectMapper O(Params, P);
1662 return llvm::json::Object{
1669 llvm::json::Path P) {
1670 llvm::json::ObjectMapper O(Params, P);
1679 llvm::json::Object Result{
1680 {
"startLine",
Range.startLine},
1681 {
"endLine",
Range.endLine},
1683 if (
Range.startCharacter)
1684 Result[
"startCharacter"] =
Range.startCharacter;
1685 if (
Range.endCharacter)
1686 Result[
"endCharacter"] =
Range.endCharacter;
1687 if (!
Range.kind.empty())
1688 Result[
"kind"] =
Range.kind;
1693 llvm::json::Path P) {
1694 llvm::json::ObjectMapper O(Params, P);
1699 llvm::json::Object Result{
1706 Result[
"detail"] = N.
detail;
1708 Result[
"arcana"] = N.
arcana;
1710 Result[
"range"] = *N.
range;
1715 std::function<void(
const ASTNode &,
unsigned)> Print = [&](
const ASTNode &N,
1717 OS.indent(2 * Level) << N.
role <<
": " << N.
kind;
1722 Print(C, Level + 1);
1729 llvm::json::Object R;
1738 return llvm::json::Object{{
"items", N.
items}};
static llvm::Expected< std::string > resolve(const URI &U, llvm::StringRef HintPath="")
static llvm::Expected< URI > parse(llvm::StringRef Uri)
static llvm::Expected< std::string > resolvePath(llvm::StringRef AbsPath, llvm::StringRef HintPath="")
Whether current platform treats paths case insensitively.
std::bitset< SymbolKindMax+1 > SymbolKindBitset
@ Created
The file got created.
@ Deleted
The file got deleted.
@ Info
An information message.
bool fromJSON(const llvm::json::Value &, URIForFile &, llvm::json::Path)
std::variant< TextDocumentEdit, CreateFile, RenameFile, DeleteFile > DocumentChange
constexpr auto CompletionItemKindMin
std::bitset< CompletionItemKindMax+1 > CompletionItemKindBitset
void elog(const char *Fmt, Ts &&...Vals)
llvm::json::Value toJSON(const URIForFile &U)
Serialize/deserialize URIForFile to/from a string URI.
llvm::raw_ostream & operator<<(llvm::raw_ostream &, const Position &)
CompletionItemKind
The kind of a completion entry.
CompletionItemKind adjustKindToCapability(CompletionItemKind Kind, CompletionItemKindBitset &SupportedCompletionItemKinds)
bool operator==(const TextEdit &L, const TextEdit &R)
InlayHintKind
Inlay hint kinds.
constexpr auto SymbolKindMin
constexpr unsigned SemanticTokenEncodingSize
bool operator<(const CompletionItem &, const CompletionItem &)
std::vector< ASTNode > children
Nodes nested within this one, such as the operands of a BinaryOperator.
std::optional< Range > range
TextDocumentIdentifier textDocument
The text document.
std::optional< Range > range
std::optional< std::string > failureReason
Represents an incoming call, e.g. a caller of a method or constructor.
CallHierarchyItem from
The item that makes the call.
std::vector< Range > fromRanges
The parameter of a callHierarchy/incomingCalls request.
URIForFile uri
The resource identifier of this item.
std::vector< SymbolTag > tags
Tags for this item.
std::string detail
More detaill for this item, e.g. the signature of a function.
SymbolKind kind
The kind of this item.
std::string name
The name of this item.
CallHierarchyItem to
The item that is called.
std::vector< Range > fromRanges
The parameter of a callHierarchy/outgoingCalls request.
std::optional< bool > needsConfirmation
std::string workingDirectory
std::vector< std::string > compilationCommand
MarkupKind SignatureHelpDocumentationFormat
bool ChangeAnnotation
The client supports change annotations on text edits,.
bool WorkspaceConfiguration
bool RenamePrepareSupport
bool DocumentChanges
The client supports versioned document changes for WorkspaceEdit.
std::optional< SymbolKindBitset > WorkspaceSymbolKinds
bool TheiaSemanticHighlighting
std::optional< CompletionItemKindBitset > CompletionItemKinds
bool HierarchicalDocumentSymbol
MarkupKind CompletionDocumentationFormat
bool CancelsStaleRequests
bool OffsetsInSignatureHelp
std::optional< std::vector< OffsetEncoding > > offsetEncoding
Supported encodings for LSP character offsets. (clangd extension).
bool ImplicitProgressCreation
bool SemanticTokenRefreshSupport
bool DiagnosticRelatedInformation
MarkupKind HoverContentFormat
std::vector< Diagnostic > diagnostics
std::vector< std::string > only
Range range
The range for which the command was invoked.
TextDocumentIdentifier textDocument
The document in which the command was invoked.
CodeActionContext context
Context carrying additional information.
std::string title
A short, human-readable, title for this code action.
std::optional< std::string > kind
static const llvm::StringLiteral REFACTOR_KIND
std::optional< Command > command
static const llvm::StringLiteral INFO_KIND
std::optional< WorkspaceEdit > edit
The workspace edit this code action performs.
static const llvm::StringLiteral REFACTOR_REWRITE_KIND
std::optional< llvm::json::Value > data
static const llvm::StringLiteral QUICKFIX_KIND
std::optional< std::vector< Diagnostic > > diagnostics
The diagnostics that this code action resolves.
Structure to capture a description for an error code.
std::string href
An URI to open with more information about the diagnostic error.
std::string triggerCharacter
CompletionTriggerKind triggerKind
How the completion was triggered.
bool deprecated
Indicates if this item is deprecated.
std::optional< TextEdit > textEdit
InsertTextFormat insertTextFormat
std::optional< MarkupContent > documentation
A human-readable string that represents a doc-comment.
std::vector< TextEdit > additionalTextEdits
Represents a collection of completion items to be presented in the editor.
std::vector< CompletionItem > items
The completion items.
CompletionContext context
std::optional< int > limit
std::optional< std::string > section
std::optional< URIForFile > scopeUri
std::vector< ConfigurationItem > items
std::map< std::string, ClangdCompileCommand > compilationDatabaseChanges
Options for CreateFile operation.
std::optional< bool > overwrite
Overwrite existing file. Overwrite wins over ignoreIfExists.
std::optional< bool > ignoreIfExists
Ignore if exists.
std::optional< CreateFileOptions > options
Additional options.
std::optional< std::string > annotationId
An optional annotation identifier.
URIForFile uri
The resource to create.
Options for DeleteFile operation.
std::optional< bool > ignoreIfNotExists
Ignore the operation if the file doesn't exist.
std::optional< bool > recursive
Delete the content recursively if a folder is denoted.
URIForFile uri
The file to delete.
std::optional< DeleteFileOptions > options
Delete options.
std::optional< std::string > annotationId
An optional annotation identifier.
std::optional< std::string > category
std::optional< std::vector< CodeAction > > codeActions
llvm::SmallVector< DiagnosticTag, 1 > tags
Additional metadata about the diagnostic.
Range range
The range at which the message applies.
std::string message
The diagnostic's message.
std::optional< std::vector< DiagnosticRelatedInformation > > relatedInformation
std::optional< CodeDescription > codeDescription
An optional property to describe the error code.
std::string code
The diagnostic's code. Can be omitted.
ConfigurationSettings settings
std::optional< bool > wantDiagnostics
std::vector< TextDocumentContentChangeEvent > contentChanges
The actual content changes.
VersionedTextDocumentIdentifier textDocument
std::vector< FileEvent > changes
The actual file events.
TextDocumentIdentifier textDocument
The document that was closed.
TextDocumentItem textDocument
The document that was opened.
TextDocumentIdentifier textDocument
The document that was saved.
Range range
The range this highlight applies to.
DocumentHighlightKind kind
The highlight kind, default is DocumentHighlightKind.Text.
Parameters for the document link request.
TextDocumentIdentifier textDocument
The document to provide document links for.
Range range
The range this link applies to.
URIForFile target
The uri this link points to. If missing a resolve request is sent later.
TextDocumentIdentifier textDocument
SymbolKind kind
The kind of this symbol.
std::vector< DocumentSymbol > children
Children of this symbol, e.g. properties of a class.
std::string name
The name of this symbol.
bool deprecated
Indicates if this symbol is deprecated.
std::string detail
More detail for this symbol, e.g the signature of a function.
llvm::json::Value argument
std::string command
The identifier of the actual command handler.
URIForFile uri
The file's URI.
FileChangeType type
The change type.
URIForFile uri
The text document's URI.
TextDocumentIdentifier textDocument
Stores information about a region of code that can be folded.
static const llvm::StringLiteral IMPORT_KIND
static const llvm::StringLiteral COMMENT_KIND
static const llvm::StringLiteral REGION_KIND
std::optional< Range > range
MarkupContent contents
The hover's content.
TextDocumentIdentifier TextDocument
The textdocument these inactive regions belong to.
std::vector< Range > InactiveRegions
The inactive regions that should be sent.
bool FileStatus
Clients supports show file status for textDocument/clangd.fileStatus.
std::vector< std::string > fallbackFlags
ConfigurationSettings ConfigSettings
std::optional< std::string > compilationDatabasePath
std::optional< std::string > rootPath
llvm::json::Object rawCapabilities
The same data as capabilities, but not parsed (to expose to modules).
InitializationOptions initializationOptions
User-provided initialization options.
std::optional< TraceLevel > trace
The initial trace setting. If omitted trace is disabled ('off').
ClientCapabilities capabilities
The capabilities provided by the client (editor or tool).
std::optional< URIForFile > rootUri
std::optional< int > processId
Position position
The position of this hint.
A parameter literal used in inlay hint requests.
TextDocumentIdentifier textDocument
The text document.
std::optional< Range > range
URIForFile uri
The text document's URI.
int64_t line
Line position in a document (zero-based).
URIForFile uri
The URI for which diagnostic information is reported.
std::optional< int64_t > version
The version number of the document the diagnostics are published for.
std::vector< Diagnostic > diagnostics
An array of diagnostic information items.
Position start
The range's start position.
Position end
The range's end position.
bool includeDeclaration
Include the declaration of the current symbol.
std::optional< std::string > containerName
Options for RenameFile operation.
std::optional< bool > overwrite
Overwrite target if existing. Overwrite wins over ignoreIfExists.
std::optional< bool > ignoreIfExists
Ignores if target exists.
std::optional< RenameFileOptions > options
Rename options.
std::optional< std::string > annotationId
An optional annotation identifier.
URIForFile oldUri
The old (existing) location.
URIForFile newUri
The new location.
std::string newName
The new name of the symbol.
Position position
The position at which this request was sent.
TextDocumentIdentifier textDocument
The document that was opened.
Parameters for the typeHierarchy/resolve request.
TypeHierarchyDirection direction
The direction of the hierarchy levels to resolve.
TypeHierarchyItem item
The item to resolve.
int resolve
The hierarchy levels to resolve. 0 indicates no level.
TextDocumentIdentifier textDocument
The text document.
std::vector< Position > positions
The positions inside the text document.
std::unique_ptr< SelectionRange > parent
unsigned length
the length of the token. A token cannot be multiline
unsigned tokenType
will be looked up in SemanticTokensLegend.tokenTypes
unsigned deltaLine
token line number, relative to the previous token
unsigned tokenModifiers
each set bit will be looked up in SemanticTokensLegend.tokenModifiers
std::string previousResultId
The previous result id.
TextDocumentIdentifier textDocument
The text document.
Describes a replacement of a contiguous range of semanticTokens.
std::vector< SemanticToken > tokens
std::optional< std::vector< SemanticTokensEdit > > edits
Set if we computed edits relative to a previous set of tokens.
std::optional< std::vector< SemanticToken > > tokens
Set if we computed a fresh set of tokens.
Body of textDocument/semanticTokens/full request.
TextDocumentIdentifier textDocument
The text document.
A versioned set of tokens.
URIForFile uri
The document URI to show (for file:// URIs).
std::optional< std::string > externalUri
std::optional< Range > selection
std::optional< bool > takeFocus
std::optional< bool > external
bool success
A boolean indicating if the show was successful.
MessageType type
The message type.
std::string message
The actual message.
Represents the signature of a callable.
int activeSignature
The active signature.
int activeParameter
The active parameter of the active signature.
std::vector< SignatureInformation > signatures
The resulting signatures.
std::string text
The new text of the range/document.
std::optional< Range > range
The range of the document that changed.
std::optional< int > rangeLength
The length of the range that got replaced.
std::vector< TextEdit > edits
VersionedTextDocumentIdentifier textDocument
The text document to change.
URIForFile uri
The text document's URI.
std::string languageId
The text document's language identifier.
std::optional< int64_t > version
std::string text
The content of the opened text document.
URIForFile uri
The text document's URI.
Position position
The position inside the text document.
TextDocumentIdentifier textDocument
The text document.
ChangeAnnotationIdentifier annotationId
std::string tweakID
ID of the tweak that should be executed. Corresponds to Tweak::id().
URIForFile file
A file provided by the client on a textDocument/codeAction request.
Range selection
A selection provided by the client on a textDocument/codeAction request.
Used to resolve a client provided item back.
std::optional< std::vector< ResolveParams > > parents
std::nullopt means parents aren't resolved and empty is no parents.
std::optional< std::vector< TypeHierarchyItem > > children
std::optional< std::string > detail
More detail for this item, e.g. the signature of a function.
SymbolKind kind
The kind of this item.
std::optional< std::vector< TypeHierarchyItem > > parents
This is a clangd exntesion.
URIForFile uri
The resource identifier of this item.
std::string name
The name of this item.
TypeHierarchyDirection direction
static URIForFile canonicalize(llvm::StringRef AbsPath, llvm::StringRef TUPath)
static llvm::Expected< URIForFile > fromURI(const URI &U, llvm::StringRef HintPath)
std::optional< std::int64_t > version
llvm::json::Value token
The token to be used to report progress.
Signals the end of progress reporting.
std::optional< std::string > message
Reporting progress is done using the following payload.
std::optional< bool > cancellable
std::optional< std::string > message
std::optional< unsigned > percentage
std::optional< std::map< std::string, std::vector< TextEdit > > > changes
Holds changes to existing resources.
std::map< std::string, ChangeAnnotation > changeAnnotations
std::optional< std::vector< DocumentChange > > documentChanges
The parameters of a Workspace Symbol Request.
std::optional< int > limit