16#include "clang/Basic/LLVM.h"
17#include "clang/Index/IndexSymbol.h"
18#include "llvm/ADT/StringRef.h"
19#include "llvm/ADT/StringSwitch.h"
20#include "llvm/Support/ErrorHandling.h"
21#include "llvm/Support/JSON.h"
22#include "llvm/Support/Path.h"
23#include "llvm/Support/raw_ostream.h"
31bool mapOptOrNull(
const llvm::json::Value &Params, llvm::StringLiteral Prop,
32 T &
Out, llvm::json::Path P) {
33 auto *O = Params.getAsObject();
35 auto *V = O->get(Prop);
37 if (!V || V->getAsNull())
46 llvm::StringRef TUPath) {
47 assert(llvm::sys::path::is_absolute(AbsPath) &&
"the path is relative");
50 elog(
"URIForFile: failed to resolve path {0} with TU path {1}: "
51 "{2}.\nUsing unresolved path.",
52 AbsPath, TUPath, Resolved.takeError());
59 llvm::StringRef HintPath) {
62 return Resolved.takeError();
67 if (
auto S =
E.getAsString()) {
70 consumeError(Parsed.takeError());
71 P.report(
"failed to parse URI");
74 if (Parsed->scheme() !=
"file" && Parsed->scheme() !=
"test") {
75 P.report(
"clangd only supports 'file' URI scheme for workspace files");
81 P.report(
"unresolvable URI");
82 consumeError(U.takeError());
98 return llvm::json::Object{{
"uri", R.
uri}};
102 llvm::json::Path P) {
103 llvm::json::ObjectMapper O(Params, P);
104 return O && O.map(
"uri", R.
uri);
109 Result.getAsObject()->try_emplace(
"version", R.
version);
115 llvm::json::ObjectMapper O(Params, P);
121 llvm::json::Path P) {
122 llvm::json::ObjectMapper O(Params, P);
123 return O && O.map(
"line", R.
line) && O.map(
"character", R.
character);
127 return llvm::json::Object{
137bool fromJSON(
const llvm::json::Value &Params,
Range &R, llvm::json::Path P) {
138 llvm::json::ObjectMapper O(Params, P);
139 return O && O.map(
"start", R.
start) && O.map(
"end", R.
end);
143 return llvm::json::Object{
154 return llvm::json::Object{
161 return OS << L.range <<
'@' << L.uri;
165 llvm::json::Object Result{
176 return OS << L.range <<
'@' << L.uri <<
" (container: " << L.containerName
181 llvm::json::Path P) {
182 llvm::json::ObjectMapper O(Params, P);
183 return O && O.map(
"uri", R.
uri) && O.map(
"languageId", R.
languageId) &&
184 O.map(
"version", R.
version) && O.map(
"text", R.
text);
188 llvm::json::Path P) {
189 llvm::json::ObjectMapper O(Params, P);
190 return O && O.map(
"range", R.
range) && O.map(
"newText", R.
newText);
194 return llvm::json::Object{
202 llvm::printEscapedString(TE.
newText,
OS);
207 if (
auto S =
E.getAsString()) {
212 if (*S ==
"messages") {
216 if (*S ==
"verbose") {
225 if (
auto T =
E.getAsInteger()) {
226 if (*T <
static_cast<int>(SymbolKind::File) ||
227 *T >
static_cast<int>(SymbolKind::TypeParameter))
236 llvm::json::Path P) {
237 if (
auto *A =
E.getAsArray()) {
238 for (
size_t I = 0; I < A->size(); ++I) {
240 if (
fromJSON((*A)[I], KindOut, P.index(I)))
241 Out.set(
size_t(KindOut));
250 auto KindVal =
static_cast<size_t>(
Kind);
251 if (KindVal >=
SymbolKindMin && KindVal <= SupportedSymbolKinds.size() &&
252 SupportedSymbolKinds[KindVal])
257 case SymbolKind::Struct:
258 return SymbolKind::Class;
259 case SymbolKind::EnumMember:
260 return SymbolKind::Enum;
262 return SymbolKind::String;
268 case index::SymbolKind::Unknown:
269 return SymbolKind::Variable;
270 case index::SymbolKind::Module:
271 return SymbolKind::Module;
272 case index::SymbolKind::Namespace:
273 return SymbolKind::Namespace;
274 case index::SymbolKind::NamespaceAlias:
275 return SymbolKind::Namespace;
276 case index::SymbolKind::Macro:
277 return SymbolKind::String;
278 case index::SymbolKind::Enum:
279 return SymbolKind::Enum;
280 case index::SymbolKind::Struct:
281 return SymbolKind::Struct;
282 case index::SymbolKind::Class:
283 return SymbolKind::Class;
284 case index::SymbolKind::Protocol:
285 return SymbolKind::Interface;
286 case index::SymbolKind::Extension:
287 return SymbolKind::Interface;
288 case index::SymbolKind::Union:
289 return SymbolKind::Class;
290 case index::SymbolKind::TypeAlias:
291 return SymbolKind::Class;
292 case index::SymbolKind::Function:
293 return SymbolKind::Function;
294 case index::SymbolKind::Variable:
295 return SymbolKind::Variable;
296 case index::SymbolKind::Field:
297 return SymbolKind::Field;
298 case index::SymbolKind::EnumConstant:
299 return SymbolKind::EnumMember;
300 case index::SymbolKind::InstanceMethod:
301 case index::SymbolKind::ClassMethod:
302 case index::SymbolKind::StaticMethod:
303 return SymbolKind::Method;
304 case index::SymbolKind::InstanceProperty:
305 case index::SymbolKind::ClassProperty:
306 case index::SymbolKind::StaticProperty:
307 return SymbolKind::Property;
308 case index::SymbolKind::Constructor:
309 case index::SymbolKind::Destructor:
310 return SymbolKind::Constructor;
311 case index::SymbolKind::ConversionFunction:
312 return SymbolKind::Function;
313 case index::SymbolKind::Parameter:
314 case index::SymbolKind::NonTypeTemplateParm:
315 return SymbolKind::Variable;
316 case index::SymbolKind::Using:
317 return SymbolKind::Namespace;
318 case index::SymbolKind::TemplateTemplateParm:
319 case index::SymbolKind::TemplateTypeParm:
320 return SymbolKind::TypeParameter;
321 case index::SymbolKind::Concept:
322 return SymbolKind::Interface;
324 llvm_unreachable(
"invalid symbol kind");
328 llvm::json::Path P) {
329 const llvm::json::Object *O = Params.getAsObject();
331 P.report(
"expected object");
334 if (
auto *TextDocument = O->getObject(
"textDocument")) {
335 if (
auto *SemanticHighlighting =
336 TextDocument->getObject(
"semanticHighlightingCapabilities")) {
337 if (
auto SemanticHighlightingSupport =
338 SemanticHighlighting->getBoolean(
"semanticHighlighting"))
341 if (TextDocument->getObject(
"semanticTokens"))
343 if (
auto *
Diagnostics = TextDocument->getObject(
"publishDiagnostics")) {
344 if (
auto CategorySupport =
Diagnostics->getBoolean(
"categorySupport"))
346 if (
auto CodeActions =
Diagnostics->getBoolean(
"codeActionsInline"))
348 if (
auto RelatedInfo =
Diagnostics->getBoolean(
"relatedInformation"))
351 if (
auto *
References = TextDocument->getObject(
"references"))
352 if (
auto ContainerSupport =
References->getBoolean(
"container"))
354 if (
auto *Completion = TextDocument->getObject(
"completion")) {
355 if (
auto *Item = Completion->getObject(
"completionItem")) {
356 if (
auto SnippetSupport = Item->getBoolean(
"snippetSupport"))
358 if (
const auto *DocumentationFormat =
359 Item->getArray(
"documentationFormat")) {
360 for (
const auto &Format : *DocumentationFormat) {
366 if (
auto *ItemKind = Completion->getObject(
"completionItemKind")) {
367 if (
auto *ValueSet = ItemKind->get(
"valueSet")) {
370 P.field(
"textDocument")
372 .field(
"completionItemKind")
377 if (
auto EditsNearCursor = Completion->getBoolean(
"editsNearCursor"))
380 if (
auto *
CodeAction = TextDocument->getObject(
"codeAction")) {
381 if (
CodeAction->getObject(
"codeActionLiteralSupport"))
384 if (
auto *
DocumentSymbol = TextDocument->getObject(
"documentSymbol")) {
385 if (
auto HierarchicalSupport =
389 if (
auto *
Hover = TextDocument->getObject(
"hover")) {
390 if (
auto *ContentFormat =
Hover->getArray(
"contentFormat")) {
391 for (
const auto &Format : *ContentFormat) {
397 if (
auto *Help = TextDocument->getObject(
"signatureHelp")) {
399 if (
auto *
Info = Help->getObject(
"signatureInformation")) {
400 if (
auto *
Parameter =
Info->getObject(
"parameterInformation")) {
401 if (
auto OffsetSupport =
Parameter->getBoolean(
"labelOffsetSupport"))
404 if (
const auto *DocumentationFormat =
405 Info->getArray(
"documentationFormat")) {
406 for (
const auto &Format : *DocumentationFormat) {
413 if (
auto *Folding = TextDocument->getObject(
"foldingRange")) {
414 if (
auto LineFolding = Folding->getBoolean(
"lineFoldingOnly"))
417 if (
auto *Rename = TextDocument->getObject(
"rename")) {
418 if (
auto RenameSupport = Rename->getBoolean(
"prepareSupport"))
422 if (
auto *Workspace = O->getObject(
"workspace")) {
423 if (
auto *
Symbol = Workspace->getObject(
"symbol")) {
425 if (
auto *ValueSet =
SymbolKind->get(
"valueSet")) {
436 if (
auto *
SemanticTokens = Workspace->getObject(
"semanticTokens")) {
437 if (
auto RefreshSupport =
SemanticTokens->getBoolean(
"refreshSupport"))
441 if (
auto *Window = O->getObject(
"window")) {
442 if (
auto WorkDoneProgress = Window->getBoolean(
"workDoneProgress"))
444 if (
auto Implicit = Window->getBoolean(
"implicitWorkDoneProgressCreate"))
447 if (
auto *General = O->getObject(
"general")) {
448 if (
auto *StaleRequestSupport = General->getObject(
"staleRequestSupport")) {
449 if (
auto Cancel = StaleRequestSupport->getBoolean(
"cancel"))
456 P.field(
"offsetEncoding")))
463 llvm::json::Path P) {
464 llvm::json::ObjectMapper O(Params, P);
473 if (
auto *RawCaps = Params.getAsObject()->getObject(
"capabilities"))
475 O.map(
"trace", R.
trace);
481 return llvm::json::Object{{
"token", P.
token}};
485 llvm::json::Object Result{
490 Result[
"cancellable"] =
true;
492 Result[
"percentage"] = 0;
495 return std::move(Result);
499 llvm::json::Object Result{{
"kind",
"report"}};
503 Result[
"message"] = *P.
message;
507 return std::move(Result);
511 llvm::json::Object Result{{
"kind",
"end"}};
513 Result[
"message"] = *P.
message;
515 return std::move(Result);
519 return static_cast<int64_t
>(R);
523 return llvm::json::Object{{
"type", R.
type}, {
"message", R.
message}};
527 llvm::json::Path P) {
528 llvm::json::ObjectMapper O(Params, P);
533 llvm::json::Path P) {
534 llvm::json::ObjectMapper O(Params, P);
539 llvm::json::Path P) {
540 llvm::json::ObjectMapper O(Params, P);
545 llvm::json::Path P) {
546 llvm::json::ObjectMapper O(Params, P);
550 mapOptOrNull(Params,
"forceRebuild", R.
forceRebuild, P);
554 llvm::json::Path P) {
555 if (
auto T =
E.getAsInteger()) {
566 llvm::json::Path P) {
567 llvm::json::ObjectMapper O(Params, P);
568 return O && O.map(
"uri", R.
uri) && O.map(
"type", R.
type);
572 llvm::json::Path P) {
573 llvm::json::ObjectMapper O(Params, P);
574 return O && O.map(
"changes", R.
changes);
579 llvm::json::ObjectMapper O(Params, P);
580 return O && O.map(
"range", R.
range) && O.map(
"rangeLength", R.
rangeLength) &&
581 O.map(
"text", R.
text);
585 llvm::json::Path P) {
586 llvm::json::ObjectMapper O(Params, P);
592 llvm::json::ObjectMapper O(Params, P);
594 O.map(
"position", R.
position) && O.map(
"ch", R.
ch);
598 llvm::json::Path P) {
599 llvm::json::ObjectMapper O(Params, P);
604 llvm::json::Path P) {
605 llvm::json::ObjectMapper O(Params, P);
610 return llvm::json::Object{
619 return llvm::json::Object{{
"href", D.href}};
623 llvm::json::Object
Diag{
625 {
"severity", D.severity},
626 {
"message", D.message},
629 Diag[
"category"] = *D.category;
631 Diag[
"codeActions"] = D.codeActions;
633 Diag[
"code"] = D.code;
634 if (D.codeDescription)
635 Diag[
"codeDescription"] = *D.codeDescription;
636 if (!D.source.empty())
637 Diag[
"source"] = D.source;
638 if (D.relatedInformation)
639 Diag[
"relatedInformation"] = *D.relatedInformation;
641 Diag[
"data"] = llvm::json::Object(D.data);
643 Diag[
"tags"] = llvm::json::Array{D.tags};
645 return std::move(
Diag);
649 llvm::json::Path P) {
650 llvm::json::ObjectMapper O(Params, P);
653 if (
auto *Data = Params.getAsObject()->getObject(
"data"))
655 return O.map(
"range", R.
range) && O.map(
"message", R.
message) &&
656 mapOptOrNull(Params,
"severity", R.
severity, P) &&
657 mapOptOrNull(Params,
"category", R.
category, P) &&
658 mapOptOrNull(Params,
"code", R.
code, P) &&
659 mapOptOrNull(Params,
"source", R.
source, P);
663 llvm::json::Object Result{
668 Result[
"version"] = PDP.
version;
669 return std::move(Result);
673 llvm::json::Path P) {
674 llvm::json::ObjectMapper O(Params, P);
677 O.map(
"only", R.
only);
682 OS << D.range <<
" [";
683 switch (D.severity) {
700 return OS <<
'(' << D.severity <<
"): " << D.message <<
"]";
704 llvm::json::Path P) {
705 llvm::json::ObjectMapper O(Params, P);
711 llvm::json::Path P) {
712 llvm::json::ObjectMapper O(Params, P);
713 return O && O.map(
"changes", R.
changes);
717 llvm::json::Path P) {
718 llvm::json::ObjectMapper O(Params, P);
719 if (!O || !O.map(
"command", R.
command))
722 const auto *
Args = Params.getAsObject()->get(
"arguments");
725 const auto *ArgsArray =
Args->getAsArray();
727 P.field(
"arguments").report(
"expected array");
730 if (ArgsArray->size() > 1) {
731 P.field(
"arguments").report(
"Command should have 0 or 1 argument");
734 if (ArgsArray->size() == 1) {
741 llvm::json::Object O{
743 {
"kind",
static_cast<int>(P.
kind)},
748 O[
"score"] = *P.
score;
766 llvm::json::Object Result{{
"name", llvm::json::Value(
nullptr)},
767 {
"containerName", llvm::json::Value(
nullptr)},
768 {
"usr", llvm::json::Value(
nullptr)},
769 {
"id", llvm::json::Value(
nullptr)}};
772 Result[
"name"] = P.
name;
778 Result[
"usr"] = P.
USR;
781 Result[
"id"] = P.
ID.
str();
790 return std::move(Result);
796 llvm::StringRef ContNameRef;
797 if (!ContNameRef.endswith(
"::")) {
806 llvm::json::Path P) {
807 llvm::json::ObjectMapper O(Params, P);
808 return O && O.map(
"query", R.
query) &&
809 mapOptOrNull(Params,
"limit", R.
limit, P);
813 auto Cmd = llvm::json::Object{{
"title",
C.title}, {
"command",
C.command}};
814 if (!
C.argument.getAsNull())
815 Cmd[
"arguments"] = llvm::json::Array{
C.argument};
816 return std::move(Cmd);
843 llvm::json::Object Result{{
"name", S.
name},
844 {
"kind",
static_cast<int>(S.
kind)},
849 Result[
"detail"] = S.
detail;
853 Result[
"deprecated"] =
true;
855 return std::move(Result);
859 llvm::json::Object FileChanges;
860 for (
auto &Change : WE.
changes)
861 FileChanges[Change.first] = llvm::json::Array(Change.second);
862 return llvm::json::Object{{
"changes", std::move(FileChanges)}};
866 llvm::json::Path P) {
867 llvm::json::ObjectMapper O(Params, P);
868 return O && O.map(
"file", A.file) && O.map(
"selection", A.selection) &&
869 O.map(
"tweakID", A.tweakID);
873 return llvm::json::Object{
874 {
"tweakID", A.tweakID}, {
"selection", A.selection}, {
"file", A.file}};
878 return llvm::json::Object{{
"edit", Params.
edit}};
882 llvm::json::Path P) {
883 llvm::json::ObjectMapper O(Response, P);
884 return O && O.map(
"applied", R.
applied) &&
889 llvm::json::Path P) {
890 llvm::json::ObjectMapper O(Params, P);
896 llvm::json::Path P) {
897 llvm::json::ObjectMapper O(Params, P);
899 if (!O || !O.map(
"triggerKind", TriggerKind) ||
907 llvm::json::Path P) {
909 !mapOptOrNull(Params,
"limit", R.
limit, P))
911 if (
auto *
Context = Params.getAsObject()->
get(
"context"))
923 llvm_unreachable(
"Invalid MarkupKind");
927 auto Str = V.getAsString();
929 P.report(
"expected string");
932 if (*Str ==
"plaintext")
934 else if (*Str ==
"markdown")
937 P.report(
"unknown markup kind");
948 if (MC.
value.empty())
951 return llvm::json::Object{
958 llvm::json::Object Result{{
"contents",
toJSON(H.contents)}};
961 Result[
"range"] =
toJSON(*H.range);
963 return std::move(Result);
967 llvm::json::Path P) {
968 if (
auto T =
E.getAsInteger()) {
981 auto KindVal =
static_cast<size_t>(
Kind);
983 KindVal <= SupportedCompletionItemKinds.size() &&
984 SupportedCompletionItemKinds[KindVal])
1001 llvm::json::Path P) {
1002 if (
auto *A =
E.getAsArray()) {
1003 for (
size_t I = 0; I < A->size(); ++I) {
1005 if (
fromJSON((*A)[I], KindOut, P.index(I)))
1006 Out.set(
size_t(KindOut));
1014 assert(!
CI.label.empty() &&
"completion item label is required");
1015 llvm::json::Object Result{{
"label",
CI.label}};
1017 Result[
"kind"] =
static_cast<int>(
CI.kind);
1018 if (!
CI.detail.empty())
1019 Result[
"detail"] =
CI.detail;
1020 if (
CI.documentation)
1021 Result[
"documentation"] =
CI.documentation;
1022 if (!
CI.sortText.empty())
1023 Result[
"sortText"] =
CI.sortText;
1024 if (!
CI.filterText.empty())
1025 Result[
"filterText"] =
CI.filterText;
1026 if (!
CI.insertText.empty())
1027 Result[
"insertText"] =
CI.insertText;
1029 Result[
"insertTextFormat"] =
static_cast<int>(
CI.insertTextFormat);
1031 Result[
"textEdit"] = *
CI.textEdit;
1032 if (!
CI.additionalTextEdits.empty())
1033 Result[
"additionalTextEdits"] = llvm::json::Array(
CI.additionalTextEdits);
1035 Result[
"deprecated"] =
CI.deprecated;
1036 Result[
"score"] =
CI.score;
1037 return std::move(Result);
1046 return (L.sortText.empty() ? L.label : L.sortText) <
1051 return llvm::json::Object{
1052 {
"isIncomplete", L.isIncomplete},
1053 {
"items", llvm::json::Array(L.items)},
1059 "parameter information label is required");
1060 llvm::json::Object Result;
1068 return std::move(Result);
1072 assert(!SI.
label.empty() &&
"signature information label is required");
1073 llvm::json::Object Result{
1074 {
"label", SI.
label},
1075 {
"parameters", llvm::json::Array(SI.
parameters)},
1079 return std::move(Result);
1090 "Unexpected negative value for number of active signatures.");
1092 "Unexpected negative value for active parameter index");
1093 return llvm::json::Object{
1096 {
"signatures", llvm::json::Array(SH.
signatures)},
1101 llvm::json::Path P) {
1102 llvm::json::ObjectMapper O(Params, P);
1108 return llvm::json::Object{
1110 {
"kind",
static_cast<int>(DH.
kind)},
1115 return llvm::json::Object{
1116 {
"uri", FStatus.
uri},
1117 {
"state", FStatus.
state},
1123 llvm::json::Array Result;
1125 for (
const auto &Tok : Toks) {
1126 Result.push_back(Tok.deltaLine);
1127 Result.push_back(Tok.deltaStart);
1128 Result.push_back(Tok.length);
1129 Result.push_back(Tok.tokenType);
1130 Result.push_back(Tok.tokenModifiers);
1133 return std::move(Result);
1137 return std::tie(L.deltaLine, L.deltaStart, L.length, L.tokenType,
1144 return llvm::json::Object{{
"resultId", Tokens.resultId},
1149 return llvm::json::Object{
1156 llvm::json::Object Result{{
"resultId", TE.
resultId}};
1158 Result[
"edits"] = *TE.
edits;
1161 return std::move(Result);
1165 llvm::json::Path P) {
1166 llvm::json::ObjectMapper O(Params, P);
1171 llvm::json::Path P) {
1172 llvm::json::ObjectMapper O(Params, P);
1189 llvm::json::ObjectMapper O(Params, P);
1190 return O && O.map(
"settings", CCP.
settings);
1194 llvm::json::Path P) {
1195 llvm::json::ObjectMapper O(Params, P);
1201 llvm::json::Path P) {
1202 llvm::json::ObjectMapper O(Params, P);
1205 return mapOptOrNull(Params,
"compilationDatabaseChanges",
1210 llvm::json::Path P) {
1211 llvm::json::ObjectMapper O(Params, P);
1215 return fromJSON(Params, Opts.ConfigSettings, P) &&
1216 O.map(
"compilationDatabasePath", Opts.compilationDatabasePath) &&
1217 mapOptOrNull(Params,
"fallbackFlags", Opts.fallbackFlags, P) &&
1218 mapOptOrNull(Params,
"clangdFileStatus", Opts.FileStatus, P);
1222 llvm::json::Path P) {
1223 auto T =
E.getAsInteger();
1234 llvm::json::Path P) {
1235 llvm::json::ObjectMapper O(Params, P);
1238 mapOptOrNull(Params,
"resolve", R.
resolve, P) &&
1239 mapOptOrNull(Params,
"direction", R.
direction, P);
1248 llvm::json::Object Result{{
"symbolID", RP.
symbolID}};
1250 Result[
"parents"] = RP.
parents;
1251 return std::move(Result);
1255 llvm::json::ObjectMapper O(Params, P);
1256 return O && O.map(
"symbolID", RP.
symbolID) &&
1257 mapOptOrNull(Params,
"parents", RP.
parents, P);
1261 llvm::json::Object Result{
1262 {
"name", I.
name}, {
"kind",
static_cast<int>(I.
kind)},
1264 {
"uri", I.
uri}, {
"data", I.
data},
1268 Result[
"detail"] = I.
detail;
1269 return std::move(Result);
1273 llvm::json::Path P) {
1274 llvm::json::ObjectMapper O(Params, P);
1277 return O && O.map(
"name", I.
name) && O.map(
"kind", I.
kind) &&
1278 O.map(
"uri", I.
uri) && O.map(
"range", I.
range) &&
1280 mapOptOrNull(Params,
"detail", I.
detail, P) &&
1281 mapOptOrNull(Params,
"deprecated", I.
deprecated, P) &&
1282 mapOptOrNull(Params,
"parents", I.
parents, P) &&
1283 mapOptOrNull(Params,
"children", I.
children, P) &&
1284 mapOptOrNull(Params,
"data", I.
data, P);
1289 llvm::json::ObjectMapper O(Params, P);
1290 return O && O.map(
"item", R.
item) &&
1291 mapOptOrNull(Params,
"resolve", R.
resolve, P) &&
1292 mapOptOrNull(Params,
"direction", R.
direction, P);
1296 llvm::json::Path P) {
1297 llvm::json::ObjectMapper O(Params, P);
1302 llvm::json::Path P) {
1304 llvm::json::ObjectMapper O(Params, P);
1305 return fromJSON(Params, Base, P) && O && O.mapOptional(
"context", R.
context);
1309 return llvm::json::Value{
static_cast<int>(
Tag)};
1313 llvm::json::Object Result{{
"name", I.
name},
1314 {
"kind",
static_cast<int>(I.
kind)},
1318 if (!I.
tags.empty())
1319 Result[
"tags"] = I.
tags;
1321 Result[
"detail"] = I.
detail;
1322 if (!I.
data.empty())
1323 Result[
"data"] = I.
data;
1324 return std::move(Result);
1328 llvm::json::Path P) {
1329 llvm::json::ObjectMapper O(Params, P);
1334 return O && O.map(
"name", I.
name) && O.map(
"kind", I.
kind) &&
1335 O.map(
"uri", I.
uri) && O.map(
"range", I.
range) &&
1337 mapOptOrNull(Params,
"data", I.
data, P);
1342 llvm::json::ObjectMapper O(Params, P);
1343 return O.map(
"item",
C.item);
1347 return llvm::json::Object{{
"from",
C.from}, {
"fromRanges",
C.fromRanges}};
1352 llvm::json::ObjectMapper O(Params, P);
1353 return O.map(
"item",
C.item);
1357 return llvm::json::Object{{
"to",
C.to}, {
"fromRanges",
C.fromRanges}};
1361 llvm::json::Path P) {
1362 llvm::json::ObjectMapper O(Params, P);
1375 llvm_unreachable(
"Unknown clang.clangd.InlayHintKind");
1379 llvm::json::Object Result{{
"position", H.position},
1381 {
"paddingLeft", H.paddingLeft},
1382 {
"paddingRight", H.paddingRight}};
1385 Result[
"kind"] = std::move(
K);
1386 return std::move(Result);
1389 return std::tie(A.position, A.range, A.kind, A.label) ==
1390 std::tie(B.position, B.range, B.kind, B.label);
1393 return std::tie(A.position, A.range, A.kind, A.label) <
1394 std::tie(B.position, B.range, B.kind, B.label);
1405 return "designator";
1407 llvm_unreachable(
"Unknown clang.clangd.InlayHintKind");
1409 return OS << ToString(
Kind);
1423 llvm_unreachable(
"Unknown clang.clangd.OffsetEncoding");
1427 llvm::json::Path P) {
1428 auto Str = V.getAsString();
1431 OE = llvm::StringSwitch<OffsetEncoding>(*Str)
1443 llvm::json::Path P) {
1444 llvm::json::ObjectMapper O(Params, P);
1451 return llvm::json::Object{{
"range",
Out.range},
1454 return llvm::json::Object{{
"range",
Out.range}};
1458 llvm::json::Path P) {
1459 llvm::json::ObjectMapper O(Params, P);
1464 return llvm::json::Object{
1471 llvm::json::Path P) {
1472 llvm::json::ObjectMapper O(Params, P);
1481 llvm::json::Object Result{
1482 {
"startLine",
Range.startLine},
1483 {
"endLine",
Range.endLine},
1485 if (
Range.startCharacter)
1486 Result[
"startCharacter"] =
Range.startCharacter;
1487 if (
Range.endCharacter)
1488 Result[
"endCharacter"] =
Range.endCharacter;
1489 if (!
Range.kind.empty())
1490 Result[
"kind"] =
Range.kind;
1495 llvm::json::Object
Out;
1500 Total += *Child.getAsObject()->getInteger(
"_total");
1501 Out[
Entry.first] = std::move(Child);
1508 llvm::json::Path P) {
1509 llvm::json::ObjectMapper O(Params, P);
1514 llvm::json::Object Result{
1521 Result[
"detail"] = N.
detail;
1523 Result[
"arcana"] = N.
arcana;
1525 Result[
"range"] = *N.
range;
1530 std::function<void(
const ASTNode &,
unsigned)> Print = [&](
const ASTNode &N,
1532 OS.indent(2 * Level) << N.
role <<
": " << N.
kind;
1537 Print(
C, Level + 1);
1544 auto Str =
E.getAsString();
1546 P.report(
"expected a string");
1551 elog(
"Malformed symbolid: {0}", ID.takeError());
1552 P.report(
"malformed symbolid");
CompiledFragmentImpl & Out
std::unique_ptr< CompilerInvocation > CI
WantDiagnostics Diagnostics
llvm::raw_string_ostream OS
A context is an immutable container for per-request data that must be propagated through layers that ...
const Type * get(const Key< Type > &Key) const
Get data stored for a typed Key.
static llvm::Expected< SymbolID > fromStr(llvm::StringRef)
A URI describes the location of a source file.
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...
static llvm::Expected< std::string > resolve(const URI &U, llvm::StringRef HintPath="")
Resolves the absolute path of U.
static llvm::Expected< URI > parse(llvm::StringRef Uri)
Parse a URI string "<scheme>:[//<authority>/]<path>".
@ Created
The file got created.
@ Deleted
The file got deleted.
@ Info
An information message.
std::bitset< SymbolKindMax+1 > SymbolKindBitset
constexpr auto CompletionItemKindMin
constexpr auto SymbolKindMin
CompletionItemKind
The kind of a completion entry.
static const char * toString(OffsetEncoding OE)
bool operator==(const Inclusion &LHS, const Inclusion &RHS)
constexpr unsigned SemanticTokenEncodingSize
llvm::raw_ostream & operator<<(llvm::raw_ostream &OS, const CodeCompletion &C)
llvm::json::Value toJSON(const FuzzyFindRequest &Request)
SymbolKind adjustKindToCapability(SymbolKind Kind, SymbolKindBitset &SupportedSymbolKinds)
bool operator<(const Ref &L, const Ref &R)
SymbolKind indexSymbolKindToSymbolKind(index::SymbolKind Kind)
static llvm::StringRef toTextKind(MarkupKind Kind)
InlayHintKind
Inlay hint kinds.
@ Parameter
An inlay hint that is for a parameter.
@ Type
An inlay hint that for a type annotation.
@ Designator
A hint before an element of an aggregate braced initializer list, indicating what it is initializing.
static llvm::json::Value encodeTokens(llvm::ArrayRef< SemanticToken > Toks)
std::bitset< CompletionItemKindMax+1 > CompletionItemKindBitset
void elog(const char *Fmt, Ts &&... Vals)
bool fromJSON(const llvm::json::Value &Parameters, FuzzyFindRequest &Request, llvm::json::Path P)
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Simplified description of a clang AST node.
std::optional< Range > range
The range of the original source file covered by this node.
std::vector< ASTNode > children
Nodes nested within this one, such as the operands of a BinaryOperator.
std::string role
The general kind of node, such as "expression" Corresponds to the base AST node type such as Expr.
std::string kind
The specific kind of node this is, such as "BinaryOperator".
std::string detail
Brief additional information, such as "||" for the particular operator.
std::string arcana
A one-line dump of detailed information about the node.
Payload for textDocument/ast request.
std::optional< Range > range
The position of the node to be dumped.
TextDocumentIdentifier textDocument
The text document.
std::optional< std::string > failureReason
Represents an incoming call, e.g. a caller of a method or constructor.
The parameter of a callHierarchy/incomingCalls request.
Represents programming constructs like functions or constructors in the context of call hierarchy.
std::string name
The name of this item.
URIForFile uri
The resource identifier of this item.
Range range
The range enclosing this symbol not including leading / trailing whitespace but everything else,...
SymbolKind kind
The kind of this item.
std::vector< SymbolTag > tags
Tags for this item.
std::string data
An optional 'data' field, which can be used to identify a call hierarchy item in an incomingCalls or ...
std::string detail
More detaill for this item, e.g. the signature of a function.
Range selectionRange
The range that should be selected and revealed when this symbol is being picked, e....
Represents an outgoing call, e.g.
The parameter of a callHierarchy/outgoingCalls request.
Clangd extension that's used in the 'compilationDatabaseChanges' in workspace/didChangeConfiguration ...
std::string workingDirectory
std::vector< std::string > compilationCommand
bool HierarchicalDocumentSymbol
Client supports hierarchical document symbols.
bool WorkDoneProgress
The client supports progress notifications.
bool DiagnosticCategory
Whether the client accepts diagnostics with category attached to it using the "category" extension.
MarkupKind HoverContentFormat
The content format that should be used for Hover requests.
bool CodeActionStructure
Client supports CodeAction return value for textDocument/codeAction.
bool OffsetsInSignatureHelp
Client supports processing label offsets instead of a simple label string.
bool DiagnosticFixes
Whether the client accepts diagnostics with codeActions attached inline.
bool HasSignatureHelp
Client supports signature help.
bool TheiaSemanticHighlighting
Client supports Theia semantic highlighting extension.
bool SemanticTokenRefreshSupport
Whether the client implementation supports a refresh request sent from the server to the client.
bool ImplicitProgressCreation
The client supports implicit $/progress work-done progress streams, without a preceding window/workDo...
MarkupKind SignatureHelpDocumentationFormat
The documentation format that should be used for textDocument/signatureHelp.
bool DiagnosticRelatedInformation
Whether the client accepts diagnostics with related locations.
bool CompletionFixes
Client supports completions with additionalTextEdit near the cursor.
bool RenamePrepareSupport
The client supports testing for validity of rename operations before execution.
bool CancelsStaleRequests
Whether the client claims to cancel stale requests.
std::optional< CompletionItemKindBitset > CompletionItemKinds
The supported set of CompletionItemKinds for textDocument/completion.
bool CompletionSnippets
Client supports snippets as insert text.
MarkupKind CompletionDocumentationFormat
The documentation format that should be used for textDocument/completion.
bool SemanticTokens
Client advertises support for the semanticTokens feature.
bool LineFoldingOnly
Client signals that it only supports folding complete lines.
std::optional< SymbolKindBitset > WorkspaceSymbolKinds
The supported set of SymbolKinds for workspace/symbol.
std::optional< std::vector< OffsetEncoding > > offsetEncoding
Supported encodings for LSP character offsets. (clangd extension).
bool ReferenceContainer
Client supports displaying a container string for results of textDocument/reference (clangd extension...
std::vector< Diagnostic > diagnostics
An array of diagnostics known on the client side overlapping the range provided to the textDocument/c...
std::vector< std::string > only
Requested kind of actions to return.
CodeActionContext context
Context carrying additional information.
TextDocumentIdentifier textDocument
The document in which the command was invoked.
Range range
The range for which the command was invoked.
A code action represents a change that can be performed in code, e.g.
static const llvm::StringLiteral INFO_KIND
bool isPreferred
Marks this as a preferred action.
static const llvm::StringLiteral REFACTOR_KIND
std::optional< std::vector< Diagnostic > > diagnostics
The diagnostics that this code action resolves.
static const llvm::StringLiteral QUICKFIX_KIND
std::optional< WorkspaceEdit > edit
The workspace edit this code action performs.
std::optional< Command > command
A command this code action executes.
std::optional< std::string > kind
The kind of the code action.
std::string title
A short, human-readable, title for this code action.
Structure to capture a description for an error code.
CompletionTriggerKind triggerKind
How the completion was triggered.
std::string triggerCharacter
The trigger character (a single character) that has trigger code complete.
std::string sortText
A string that should be used when comparing this item with other items.
std::string label
The label of this completion item.
Represents a collection of completion items to be presented in the editor.
std::optional< int > limit
Max results to return, overriding global default.
CompletionContext context
Clangd extension: parameters configurable at any time, via the workspace/didChangeConfiguration notif...
std::map< std::string, ClangdCompileCommand > compilationDatabaseChanges
A top-level diagnostic that may have Notes and Fixes.
llvm::json::Object data
A data entry field that is preserved between a textDocument/publishDiagnostics notification and textD...
std::string code
The diagnostic's code. Can be omitted.
Range range
The range at which the message applies.
std::string source
A human-readable string describing the source of this diagnostic, e.g.
std::string message
The diagnostic's message.
int severity
The diagnostic's severity.
std::optional< std::string > category
The diagnostic's category.
ConfigurationSettings settings
bool forceRebuild
Force a complete rebuild of the file, ignoring all cached state.
VersionedTextDocumentIdentifier textDocument
The document that did change.
std::optional< bool > wantDiagnostics
Forces diagnostics to be generated, or to not be generated, for this version of the file.
std::vector< TextDocumentContentChangeEvent > contentChanges
The actual content changes.
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.
A document highlight is a range inside a text document which deserves special attention.
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.
A range in a text document that links to an internal or external resource, like another text document...
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
Represents programming constructs like variables, classes, interfaces etc.
Range selectionRange
The range that should be selected and revealed when this symbol is being picked, e....
std::vector< DocumentSymbol > children
Children of this symbol, e.g. properties of a class.
std::string detail
More detail for this symbol, e.g the signature of a function.
std::string name
The name of this symbol.
Range range
The range enclosing this symbol not including leading/trailing whitespace but everything else like co...
bool deprecated
Indicates if this symbol is deprecated.
SymbolKind kind
The kind of this symbol.
A set of edits generated for a single file.
llvm::json::Value argument
std::string command
The identifier of the actual command handler.
FileChangeType type
The change type.
URIForFile uri
The file's URI.
Clangd extension: indicates the current state of the file in clangd, sent from server via the textDoc...
URIForFile uri
The text document's URI.
std::string state
The human-readable string presents the current state of the file, can be shown in the UI (e....
TextDocumentIdentifier textDocument
Stores information about a region of code that can be folded.
static const llvm::StringLiteral REGION_KIND
static const llvm::StringLiteral COMMENT_KIND
static const llvm::StringLiteral IMPORT_KIND
Clangd extension: parameters configurable at initialize time.
llvm::json::Object rawCapabilities
The same data as capabilities, but not parsed (to expose to modules).
InitializationOptions initializationOptions
User-provided initialization options.
ClientCapabilities capabilities
The capabilities provided by the client (editor or tool)
std::optional< TraceLevel > trace
The initial trace setting. If omitted trace is disabled ('off').
std::optional< int > processId
The process Id of the parent process that started the server.
std::optional< std::string > rootPath
The rootPath of the workspace.
std::optional< URIForFile > rootUri
The rootUri of the workspace.
A parameter literal used in inlay hint requests.
std::optional< Range > range
The visible document range for which inlay hints should be computed.
TextDocumentIdentifier textDocument
The text document.
URIForFile uri
The text document's URI.
A tree that can be used to represent memory usage of nested components while preserving the hierarchy...
const llvm::DenseMap< llvm::StringRef, MemoryTree > & children() const
Returns edges to direct children of this node.
size_t self() const
Returns total number of bytes used by this node only.
int line
Line position in a document (zero-based).
int character
Character offset on a line in a document (zero-based).
std::vector< Diagnostic > diagnostics
An array of diagnostic information items.
std::optional< int64_t > version
The version number of the document the diagnostics are published for.
URIForFile uri
The URI for which diagnostic information is reported.
Position start
The range's start position.
Position end
The range's end position.
bool includeDeclaration
Include the declaration of the current symbol.
Extends Locations returned by textDocument/references with extra info.
std::optional< std::string > containerName
clangd extension: contains the name of the function or class in which the reference occurs
TextDocumentIdentifier textDocument
The document that was opened.
Position position
The position at which this request was sent.
std::string newName
The new name of the symbol.
Parameters for the typeHierarchy/resolve request.
TypeHierarchyItem item
The item to resolve.
int resolve
The hierarchy levels to resolve. 0 indicates no level.
TypeHierarchyDirection direction
The direction of the hierarchy levels to resolve.
TextDocumentIdentifier textDocument
The text document.
std::vector< Position > positions
The positions inside the text document.
Specifies a single semantic token in the document.
unsigned length
the length of the token. A token cannot be multiline
unsigned deltaStart
token start character, relative to the previous token (relative to 0 or the previous token's start if...
unsigned deltaLine
token line number, relative to the previous token
unsigned tokenType
will be looked up in SemanticTokensLegend.tokenTypes
unsigned tokenModifiers
each set bit will be looked up in SemanticTokensLegend.tokenModifiers
Body of textDocument/semanticTokens/full/delta request.
TextDocumentIdentifier textDocument
The text document.
std::string previousResultId
The previous result id.
Describes a replacement of a contiguous range of semanticTokens.
This models LSP SemanticTokensDelta | SemanticTokens, which is the result of textDocument/semanticTok...
std::optional< std::vector< SemanticToken > > tokens
Set if we computed a fresh set of tokens.
std::optional< std::vector< SemanticTokensEdit > > edits
Set if we computed edits relative to a previous set of tokens.
Body of textDocument/semanticTokens/full request.
TextDocumentIdentifier textDocument
The text document.
A versioned set of tokens.
The show message notification is sent from a server to a client to ask the client to display a partic...
MessageType type
The message type.
std::string message
The actual message.
Represents the signature of a callable.
int activeSignature
The active signature.
std::vector< SignatureInformation > signatures
The resulting signatures.
int activeParameter
The active parameter of the active signature.
Represents information about identifier.
std::optional< Location > definitionRange
std::string containerName
std::optional< Location > declarationRange
std::string USR
Unified Symbol Resolution identifier This is an opaque string uniquely identifying a symbol.
The class presents a C++ symbol, e.g.
std::optional< Range > range
The range of the document that changed.
std::string text
The new text of the range/document.
std::optional< int > rangeLength
The length of the range that got replaced.
URIForFile uri
The text document's URI.
std::string languageId
The text document's language identifier.
std::optional< int64_t > version
The version number of this document (it will strictly increase after each change, including undo/redo...
URIForFile uri
The text document's URI.
std::string text
The content of the opened text document.
TextDocumentIdentifier textDocument
The text document.
Position position
The position inside the text document.
std::string newText
The string to be inserted.
Range range
The range of the text document to be manipulated.
Arguments for the 'applyTweak' command.
Used to resolve a client provided item back.
std::optional< std::vector< ResolveParams > > parents
None means parents aren't resolved and empty is no parents.
Range range
The range enclosing this symbol not including leading/trailing whitespace but everything else,...
URIForFile uri
The resource identifier of this item.
Range selectionRange
The range that should be selected and revealed when this symbol is being picked, e....
SymbolKind kind
The kind of this item.
std::optional< std::vector< TypeHierarchyItem > > children
If this type hierarchy item is resolved, it contains the direct children of the current item.
std::optional< std::vector< TypeHierarchyItem > > parents
This is a clangd exntesion.
bool deprecated
true if the hierarchy item is deprecated.
std::optional< std::string > detail
More detail for this item, e.g. the signature of a function.
ResolveParams data
A data entry field that is preserved between a type hierarchy prepare and supertypes or subtypes requ...
std::string name
The name of this item.
The type hierarchy params is an extension of the TextDocumentPositionsParams with optional properties...
int resolve
The hierarchy levels to resolve.
TypeHierarchyDirection direction
The direction of the hierarchy levels to resolve.
static llvm::Expected< URIForFile > fromURI(const URI &U, llvm::StringRef HintPath)
static URIForFile canonicalize(llvm::StringRef AbsPath, llvm::StringRef TUPath)
Canonicalizes AbsPath via URI.
std::optional< std::int64_t > version
The version number of this document.
To start progress reporting a $/progress notification with the following payload must be sent.
bool percentage
Optional progress percentage to display (value 100 is considered 100%).
bool cancellable
Controls if a cancel button should show to allow the user to cancel the long-running operation.
std::string title
Mandatory title of the progress operation.
llvm::json::Value token
The token to be used to report progress.
Signals the end of progress reporting.
std::optional< std::string > message
Optional, a final message indicating to for example indicate the outcome of the operation.
Reporting progress is done using the following payload.
std::optional< unsigned > percentage
Optional progress percentage to display (value 100 is considered 100%).
std::optional< bool > cancellable
Controls enablement state of a cancel button.
std::optional< std::string > message
Optional, more detailed associated progress message.
std::map< std::string, std::vector< TextEdit > > changes
Holds changes to existing resources.
The parameters of a Workspace Symbol Request.
std::string query
A query string to filter symbols by.
std::optional< int > limit
Max results to return, overriding global default.