1 //===--- Protocol.cpp - Language Server Protocol Implementation -----------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file contains the serialization code for the LSP structs. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "Protocol.h" 14 #include "URI.h" 15 #include "support/Logger.h" 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" 24 25 namespace clang { 26 namespace clangd { 27 namespace { 28 29 // Helper that doesn't treat `null` and absent fields as failures. 30 template <typename T> 31 bool mapOptOrNull(const llvm::json::Value &Params, llvm::StringLiteral Prop, 32 T &Out, llvm::json::Path P) { 33 auto *O = Params.getAsObject(); 34 assert(O); 35 auto *V = O->get(Prop); 36 // Field is missing or null. 37 if (!V || V->getAsNull()) 38 return true; 39 return fromJSON(*V, Out, P.field(Prop)); 40 } 41 } // namespace 42 43 char LSPError::ID; 44 45 URIForFile URIForFile::canonicalize(llvm::StringRef AbsPath, 46 llvm::StringRef TUPath) { 47 assert(llvm::sys::path::is_absolute(AbsPath) && "the path is relative"); 48 auto Resolved = URI::resolvePath(AbsPath, TUPath); 49 if (!Resolved) { 50 elog("URIForFile: failed to resolve path {0} with TU path {1}: " 51 "{2}.\nUsing unresolved path.", 52 AbsPath, TUPath, Resolved.takeError()); 53 return URIForFile(std::string(AbsPath)); 54 } 55 return URIForFile(std::move(*Resolved)); 56 } 57 58 llvm::Expected<URIForFile> URIForFile::fromURI(const URI &U, 59 llvm::StringRef HintPath) { 60 auto Resolved = URI::resolve(U, HintPath); 61 if (!Resolved) 62 return Resolved.takeError(); 63 return URIForFile(std::move(*Resolved)); 64 } 65 66 bool fromJSON(const llvm::json::Value &E, URIForFile &R, llvm::json::Path P) { 67 if (auto S = E.getAsString()) { 68 auto Parsed = URI::parse(*S); 69 if (!Parsed) { 70 consumeError(Parsed.takeError()); 71 P.report("failed to parse URI"); 72 return false; 73 } 74 if (Parsed->scheme() != "file" && Parsed->scheme() != "test") { 75 P.report("clangd only supports 'file' URI scheme for workspace files"); 76 return false; 77 } 78 // "file" and "test" schemes do not require hint path. 79 auto U = URIForFile::fromURI(*Parsed, /*HintPath=*/""); 80 if (!U) { 81 P.report("unresolvable URI"); 82 consumeError(U.takeError()); 83 return false; 84 } 85 R = std::move(*U); 86 return true; 87 } 88 return false; 89 } 90 91 llvm::json::Value toJSON(const URIForFile &U) { return U.uri(); } 92 93 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const URIForFile &U) { 94 return OS << U.uri(); 95 } 96 97 llvm::json::Value toJSON(const TextDocumentIdentifier &R) { 98 return llvm::json::Object{{"uri", R.uri}}; 99 } 100 101 bool fromJSON(const llvm::json::Value &Params, TextDocumentIdentifier &R, 102 llvm::json::Path P) { 103 llvm::json::ObjectMapper O(Params, P); 104 return O && O.map("uri", R.uri); 105 } 106 107 llvm::json::Value toJSON(const VersionedTextDocumentIdentifier &R) { 108 auto Result = toJSON(static_cast<const TextDocumentIdentifier &>(R)); 109 Result.getAsObject()->try_emplace("version", R.version); 110 return Result; 111 } 112 113 bool fromJSON(const llvm::json::Value &Params, 114 VersionedTextDocumentIdentifier &R, llvm::json::Path P) { 115 llvm::json::ObjectMapper O(Params, P); 116 return fromJSON(Params, static_cast<TextDocumentIdentifier &>(R), P) && O && 117 O.map("version", R.version); 118 } 119 120 bool fromJSON(const llvm::json::Value &Params, Position &R, 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); 124 } 125 126 llvm::json::Value toJSON(const Position &P) { 127 return llvm::json::Object{ 128 {"line", P.line}, 129 {"character", P.character}, 130 }; 131 } 132 133 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Position &P) { 134 return OS << P.line << ':' << P.character; 135 } 136 137 bool 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); 140 } 141 142 llvm::json::Value toJSON(const Range &P) { 143 return llvm::json::Object{ 144 {"start", P.start}, 145 {"end", P.end}, 146 }; 147 } 148 149 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Range &R) { 150 return OS << R.start << '-' << R.end; 151 } 152 153 llvm::json::Value toJSON(const Location &P) { 154 return llvm::json::Object{ 155 {"uri", P.uri}, 156 {"range", P.range}, 157 }; 158 } 159 160 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Location &L) { 161 return OS << L.range << '@' << L.uri; 162 } 163 164 bool fromJSON(const llvm::json::Value &Params, TextDocumentItem &R, 165 llvm::json::Path P) { 166 llvm::json::ObjectMapper O(Params, P); 167 return O && O.map("uri", R.uri) && O.map("languageId", R.languageId) && 168 O.map("version", R.version) && O.map("text", R.text); 169 } 170 171 bool fromJSON(const llvm::json::Value &Params, TextEdit &R, 172 llvm::json::Path P) { 173 llvm::json::ObjectMapper O(Params, P); 174 return O && O.map("range", R.range) && O.map("newText", R.newText); 175 } 176 177 llvm::json::Value toJSON(const TextEdit &P) { 178 return llvm::json::Object{ 179 {"range", P.range}, 180 {"newText", P.newText}, 181 }; 182 } 183 184 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const TextEdit &TE) { 185 OS << TE.range << " => \""; 186 llvm::printEscapedString(TE.newText, OS); 187 return OS << '"'; 188 } 189 190 bool fromJSON(const llvm::json::Value &E, TraceLevel &Out, llvm::json::Path P) { 191 if (auto S = E.getAsString()) { 192 if (*S == "off") { 193 Out = TraceLevel::Off; 194 return true; 195 } 196 if (*S == "messages") { 197 Out = TraceLevel::Messages; 198 return true; 199 } 200 if (*S == "verbose") { 201 Out = TraceLevel::Verbose; 202 return true; 203 } 204 } 205 return false; 206 } 207 208 bool fromJSON(const llvm::json::Value &E, SymbolKind &Out, llvm::json::Path P) { 209 if (auto T = E.getAsInteger()) { 210 if (*T < static_cast<int>(SymbolKind::File) || 211 *T > static_cast<int>(SymbolKind::TypeParameter)) 212 return false; 213 Out = static_cast<SymbolKind>(*T); 214 return true; 215 } 216 return false; 217 } 218 219 bool fromJSON(const llvm::json::Value &E, SymbolKindBitset &Out, 220 llvm::json::Path P) { 221 if (auto *A = E.getAsArray()) { 222 for (size_t I = 0; I < A->size(); ++I) { 223 SymbolKind KindOut; 224 if (fromJSON((*A)[I], KindOut, P.index(I))) 225 Out.set(size_t(KindOut)); 226 } 227 return true; 228 } 229 return false; 230 } 231 232 SymbolKind adjustKindToCapability(SymbolKind Kind, 233 SymbolKindBitset &SupportedSymbolKinds) { 234 auto KindVal = static_cast<size_t>(Kind); 235 if (KindVal >= SymbolKindMin && KindVal <= SupportedSymbolKinds.size() && 236 SupportedSymbolKinds[KindVal]) 237 return Kind; 238 239 switch (Kind) { 240 // Provide some fall backs for common kinds that are close enough. 241 case SymbolKind::Struct: 242 return SymbolKind::Class; 243 case SymbolKind::EnumMember: 244 return SymbolKind::Enum; 245 default: 246 return SymbolKind::String; 247 } 248 } 249 250 SymbolKind indexSymbolKindToSymbolKind(index::SymbolKind Kind) { 251 switch (Kind) { 252 case index::SymbolKind::Unknown: 253 return SymbolKind::Variable; 254 case index::SymbolKind::Module: 255 return SymbolKind::Module; 256 case index::SymbolKind::Namespace: 257 return SymbolKind::Namespace; 258 case index::SymbolKind::NamespaceAlias: 259 return SymbolKind::Namespace; 260 case index::SymbolKind::Macro: 261 return SymbolKind::String; 262 case index::SymbolKind::Enum: 263 return SymbolKind::Enum; 264 case index::SymbolKind::Struct: 265 return SymbolKind::Struct; 266 case index::SymbolKind::Class: 267 return SymbolKind::Class; 268 case index::SymbolKind::Protocol: 269 return SymbolKind::Interface; 270 case index::SymbolKind::Extension: 271 return SymbolKind::Interface; 272 case index::SymbolKind::Union: 273 return SymbolKind::Class; 274 case index::SymbolKind::TypeAlias: 275 return SymbolKind::Class; 276 case index::SymbolKind::Function: 277 return SymbolKind::Function; 278 case index::SymbolKind::Variable: 279 return SymbolKind::Variable; 280 case index::SymbolKind::Field: 281 return SymbolKind::Field; 282 case index::SymbolKind::EnumConstant: 283 return SymbolKind::EnumMember; 284 case index::SymbolKind::InstanceMethod: 285 case index::SymbolKind::ClassMethod: 286 case index::SymbolKind::StaticMethod: 287 return SymbolKind::Method; 288 case index::SymbolKind::InstanceProperty: 289 case index::SymbolKind::ClassProperty: 290 case index::SymbolKind::StaticProperty: 291 return SymbolKind::Property; 292 case index::SymbolKind::Constructor: 293 case index::SymbolKind::Destructor: 294 return SymbolKind::Constructor; 295 case index::SymbolKind::ConversionFunction: 296 return SymbolKind::Function; 297 case index::SymbolKind::Parameter: 298 case index::SymbolKind::NonTypeTemplateParm: 299 return SymbolKind::Variable; 300 case index::SymbolKind::Using: 301 return SymbolKind::Namespace; 302 case index::SymbolKind::TemplateTemplateParm: 303 case index::SymbolKind::TemplateTypeParm: 304 return SymbolKind::TypeParameter; 305 case index::SymbolKind::Concept: 306 return SymbolKind::Interface; 307 } 308 llvm_unreachable("invalid symbol kind"); 309 } 310 311 bool fromJSON(const llvm::json::Value &Params, ClientCapabilities &R, 312 llvm::json::Path P) { 313 const llvm::json::Object *O = Params.getAsObject(); 314 if (!O) { 315 P.report("expected object"); 316 return false; 317 } 318 if (auto *TextDocument = O->getObject("textDocument")) { 319 if (auto *SemanticHighlighting = 320 TextDocument->getObject("semanticHighlightingCapabilities")) { 321 if (auto SemanticHighlightingSupport = 322 SemanticHighlighting->getBoolean("semanticHighlighting")) 323 R.TheiaSemanticHighlighting = *SemanticHighlightingSupport; 324 } 325 if (TextDocument->getObject("semanticTokens")) 326 R.SemanticTokens = true; 327 if (auto *Diagnostics = TextDocument->getObject("publishDiagnostics")) { 328 if (auto CategorySupport = Diagnostics->getBoolean("categorySupport")) 329 R.DiagnosticCategory = *CategorySupport; 330 if (auto CodeActions = Diagnostics->getBoolean("codeActionsInline")) 331 R.DiagnosticFixes = *CodeActions; 332 if (auto RelatedInfo = Diagnostics->getBoolean("relatedInformation")) 333 R.DiagnosticRelatedInformation = *RelatedInfo; 334 } 335 if (auto *Completion = TextDocument->getObject("completion")) { 336 if (auto *Item = Completion->getObject("completionItem")) { 337 if (auto SnippetSupport = Item->getBoolean("snippetSupport")) 338 R.CompletionSnippets = *SnippetSupport; 339 if (const auto *DocumentationFormat = 340 Item->getArray("documentationFormat")) { 341 for (const auto &Format : *DocumentationFormat) { 342 if (fromJSON(Format, R.CompletionDocumentationFormat, P)) 343 break; 344 } 345 } 346 } 347 if (auto *ItemKind = Completion->getObject("completionItemKind")) { 348 if (auto *ValueSet = ItemKind->get("valueSet")) { 349 R.CompletionItemKinds.emplace(); 350 if (!fromJSON(*ValueSet, *R.CompletionItemKinds, 351 P.field("textDocument") 352 .field("completion") 353 .field("completionItemKind") 354 .field("valueSet"))) 355 return false; 356 } 357 } 358 if (auto EditsNearCursor = Completion->getBoolean("editsNearCursor")) 359 R.CompletionFixes = *EditsNearCursor; 360 } 361 if (auto *CodeAction = TextDocument->getObject("codeAction")) { 362 if (CodeAction->getObject("codeActionLiteralSupport")) 363 R.CodeActionStructure = true; 364 } 365 if (auto *DocumentSymbol = TextDocument->getObject("documentSymbol")) { 366 if (auto HierarchicalSupport = 367 DocumentSymbol->getBoolean("hierarchicalDocumentSymbolSupport")) 368 R.HierarchicalDocumentSymbol = *HierarchicalSupport; 369 } 370 if (auto *Hover = TextDocument->getObject("hover")) { 371 if (auto *ContentFormat = Hover->getArray("contentFormat")) { 372 for (const auto &Format : *ContentFormat) { 373 if (fromJSON(Format, R.HoverContentFormat, P)) 374 break; 375 } 376 } 377 } 378 if (auto *Help = TextDocument->getObject("signatureHelp")) { 379 R.HasSignatureHelp = true; 380 if (auto *Info = Help->getObject("signatureInformation")) { 381 if (auto *Parameter = Info->getObject("parameterInformation")) { 382 if (auto OffsetSupport = Parameter->getBoolean("labelOffsetSupport")) 383 R.OffsetsInSignatureHelp = *OffsetSupport; 384 } 385 if (const auto *DocumentationFormat = 386 Info->getArray("documentationFormat")) { 387 for (const auto &Format : *DocumentationFormat) { 388 if (fromJSON(Format, R.SignatureHelpDocumentationFormat, P)) 389 break; 390 } 391 } 392 } 393 } 394 if (auto *Rename = TextDocument->getObject("rename")) { 395 if (auto RenameSupport = Rename->getBoolean("prepareSupport")) 396 R.RenamePrepareSupport = *RenameSupport; 397 } 398 } 399 if (auto *Workspace = O->getObject("workspace")) { 400 if (auto *Symbol = Workspace->getObject("symbol")) { 401 if (auto *SymbolKind = Symbol->getObject("symbolKind")) { 402 if (auto *ValueSet = SymbolKind->get("valueSet")) { 403 R.WorkspaceSymbolKinds.emplace(); 404 if (!fromJSON(*ValueSet, *R.WorkspaceSymbolKinds, 405 P.field("workspace") 406 .field("symbol") 407 .field("symbolKind") 408 .field("valueSet"))) 409 return false; 410 } 411 } 412 } 413 if (auto *SemanticTokens = Workspace->getObject("semanticTokens")) { 414 if (auto RefreshSupport = SemanticTokens->getBoolean("refreshSupport")) 415 R.SemanticTokenRefreshSupport = *RefreshSupport; 416 } 417 } 418 if (auto *Window = O->getObject("window")) { 419 if (auto WorkDoneProgress = Window->getBoolean("workDoneProgress")) 420 R.WorkDoneProgress = *WorkDoneProgress; 421 if (auto Implicit = Window->getBoolean("implicitWorkDoneProgressCreate")) 422 R.ImplicitProgressCreation = *Implicit; 423 } 424 if (auto *General = O->getObject("general")) { 425 if (auto *StaleRequestSupport = General->getObject("staleRequestSupport")) { 426 if (auto Cancel = StaleRequestSupport->getBoolean("cancel")) 427 R.CancelsStaleRequests = *Cancel; 428 } 429 } 430 if (auto *OffsetEncoding = O->get("offsetEncoding")) { 431 R.offsetEncoding.emplace(); 432 if (!fromJSON(*OffsetEncoding, *R.offsetEncoding, 433 P.field("offsetEncoding"))) 434 return false; 435 } 436 return true; 437 } 438 439 bool fromJSON(const llvm::json::Value &Params, InitializeParams &R, 440 llvm::json::Path P) { 441 llvm::json::ObjectMapper O(Params, P); 442 if (!O) 443 return false; 444 // We deliberately don't fail if we can't parse individual fields. 445 // Failing to handle a slightly malformed initialize would be a disaster. 446 O.map("processId", R.processId); 447 O.map("rootUri", R.rootUri); 448 O.map("rootPath", R.rootPath); 449 O.map("capabilities", R.capabilities); 450 if (auto *RawCaps = Params.getAsObject()->getObject("capabilities")) 451 R.rawCapabilities = *RawCaps; 452 O.map("trace", R.trace); 453 O.map("initializationOptions", R.initializationOptions); 454 return true; 455 } 456 457 llvm::json::Value toJSON(const WorkDoneProgressCreateParams &P) { 458 return llvm::json::Object{{"token", P.token}}; 459 } 460 461 llvm::json::Value toJSON(const WorkDoneProgressBegin &P) { 462 llvm::json::Object Result{ 463 {"kind", "begin"}, 464 {"title", P.title}, 465 }; 466 if (P.cancellable) 467 Result["cancellable"] = true; 468 if (P.percentage) 469 Result["percentage"] = 0; 470 471 // FIXME: workaround for older gcc/clang 472 return std::move(Result); 473 } 474 475 llvm::json::Value toJSON(const WorkDoneProgressReport &P) { 476 llvm::json::Object Result{{"kind", "report"}}; 477 if (P.cancellable) 478 Result["cancellable"] = *P.cancellable; 479 if (P.message) 480 Result["message"] = *P.message; 481 if (P.percentage) 482 Result["percentage"] = *P.percentage; 483 // FIXME: workaround for older gcc/clang 484 return std::move(Result); 485 } 486 487 llvm::json::Value toJSON(const WorkDoneProgressEnd &P) { 488 llvm::json::Object Result{{"kind", "end"}}; 489 if (P.message) 490 Result["message"] = *P.message; 491 // FIXME: workaround for older gcc/clang 492 return std::move(Result); 493 } 494 495 llvm::json::Value toJSON(const MessageType &R) { 496 return static_cast<int64_t>(R); 497 } 498 499 llvm::json::Value toJSON(const ShowMessageParams &R) { 500 return llvm::json::Object{{"type", R.type}, {"message", R.message}}; 501 } 502 503 bool fromJSON(const llvm::json::Value &Params, DidOpenTextDocumentParams &R, 504 llvm::json::Path P) { 505 llvm::json::ObjectMapper O(Params, P); 506 return O && O.map("textDocument", R.textDocument); 507 } 508 509 bool fromJSON(const llvm::json::Value &Params, DidCloseTextDocumentParams &R, 510 llvm::json::Path P) { 511 llvm::json::ObjectMapper O(Params, P); 512 return O && O.map("textDocument", R.textDocument); 513 } 514 515 bool fromJSON(const llvm::json::Value &Params, DidSaveTextDocumentParams &R, 516 llvm::json::Path P) { 517 llvm::json::ObjectMapper O(Params, P); 518 return O && O.map("textDocument", R.textDocument); 519 } 520 521 bool fromJSON(const llvm::json::Value &Params, DidChangeTextDocumentParams &R, 522 llvm::json::Path P) { 523 llvm::json::ObjectMapper O(Params, P); 524 return O && O.map("textDocument", R.textDocument) && 525 O.map("contentChanges", R.contentChanges) && 526 O.map("wantDiagnostics", R.wantDiagnostics) && 527 mapOptOrNull(Params, "forceRebuild", R.forceRebuild, P); 528 } 529 530 bool fromJSON(const llvm::json::Value &E, FileChangeType &Out, 531 llvm::json::Path P) { 532 if (auto T = E.getAsInteger()) { 533 if (*T < static_cast<int>(FileChangeType::Created) || 534 *T > static_cast<int>(FileChangeType::Deleted)) 535 return false; 536 Out = static_cast<FileChangeType>(*T); 537 return true; 538 } 539 return false; 540 } 541 542 bool fromJSON(const llvm::json::Value &Params, FileEvent &R, 543 llvm::json::Path P) { 544 llvm::json::ObjectMapper O(Params, P); 545 return O && O.map("uri", R.uri) && O.map("type", R.type); 546 } 547 548 bool fromJSON(const llvm::json::Value &Params, DidChangeWatchedFilesParams &R, 549 llvm::json::Path P) { 550 llvm::json::ObjectMapper O(Params, P); 551 return O && O.map("changes", R.changes); 552 } 553 554 bool fromJSON(const llvm::json::Value &Params, 555 TextDocumentContentChangeEvent &R, llvm::json::Path P) { 556 llvm::json::ObjectMapper O(Params, P); 557 return O && O.map("range", R.range) && O.map("rangeLength", R.rangeLength) && 558 O.map("text", R.text); 559 } 560 561 bool fromJSON(const llvm::json::Value &Params, DocumentRangeFormattingParams &R, 562 llvm::json::Path P) { 563 llvm::json::ObjectMapper O(Params, P); 564 return O && O.map("textDocument", R.textDocument) && O.map("range", R.range); 565 } 566 567 bool fromJSON(const llvm::json::Value &Params, 568 DocumentOnTypeFormattingParams &R, llvm::json::Path P) { 569 llvm::json::ObjectMapper O(Params, P); 570 return O && O.map("textDocument", R.textDocument) && 571 O.map("position", R.position) && O.map("ch", R.ch); 572 } 573 574 bool fromJSON(const llvm::json::Value &Params, DocumentFormattingParams &R, 575 llvm::json::Path P) { 576 llvm::json::ObjectMapper O(Params, P); 577 return O && O.map("textDocument", R.textDocument); 578 } 579 580 bool fromJSON(const llvm::json::Value &Params, DocumentSymbolParams &R, 581 llvm::json::Path P) { 582 llvm::json::ObjectMapper O(Params, P); 583 return O && O.map("textDocument", R.textDocument); 584 } 585 586 llvm::json::Value toJSON(const DiagnosticRelatedInformation &DRI) { 587 return llvm::json::Object{ 588 {"location", DRI.location}, 589 {"message", DRI.message}, 590 }; 591 } 592 593 llvm::json::Value toJSON(DiagnosticTag Tag) { return static_cast<int>(Tag); } 594 595 llvm::json::Value toJSON(const CodeDescription &D) { 596 return llvm::json::Object{{"href", D.href}}; 597 } 598 599 llvm::json::Value toJSON(const Diagnostic &D) { 600 llvm::json::Object Diag{ 601 {"range", D.range}, 602 {"severity", D.severity}, 603 {"message", D.message}, 604 }; 605 if (D.category) 606 Diag["category"] = *D.category; 607 if (D.codeActions) 608 Diag["codeActions"] = D.codeActions; 609 if (!D.code.empty()) 610 Diag["code"] = D.code; 611 if (D.codeDescription) 612 Diag["codeDescription"] = *D.codeDescription; 613 if (!D.source.empty()) 614 Diag["source"] = D.source; 615 if (D.relatedInformation) 616 Diag["relatedInformation"] = *D.relatedInformation; 617 if (!D.data.empty()) 618 Diag["data"] = llvm::json::Object(D.data); 619 if (!D.tags.empty()) 620 Diag["tags"] = llvm::json::Array{D.tags}; 621 // FIXME: workaround for older gcc/clang 622 return std::move(Diag); 623 } 624 625 bool fromJSON(const llvm::json::Value &Params, Diagnostic &R, 626 llvm::json::Path P) { 627 llvm::json::ObjectMapper O(Params, P); 628 if (!O) 629 return false; 630 if (auto *Data = Params.getAsObject()->getObject("data")) 631 R.data = *Data; 632 return O.map("range", R.range) && O.map("message", R.message) && 633 mapOptOrNull(Params, "severity", R.severity, P) && 634 mapOptOrNull(Params, "category", R.category, P) && 635 mapOptOrNull(Params, "code", R.code, P) && 636 mapOptOrNull(Params, "source", R.source, P); 637 } 638 639 llvm::json::Value toJSON(const PublishDiagnosticsParams &PDP) { 640 llvm::json::Object Result{ 641 {"uri", PDP.uri}, 642 {"diagnostics", PDP.diagnostics}, 643 }; 644 if (PDP.version) 645 Result["version"] = PDP.version; 646 return std::move(Result); 647 } 648 649 bool fromJSON(const llvm::json::Value &Params, CodeActionContext &R, 650 llvm::json::Path P) { 651 llvm::json::ObjectMapper O(Params, P); 652 if (!O || !O.map("diagnostics", R.diagnostics)) 653 return false; 654 O.map("only", R.only); 655 return true; 656 } 657 658 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Diagnostic &D) { 659 OS << D.range << " ["; 660 switch (D.severity) { 661 case 1: 662 OS << "error"; 663 break; 664 case 2: 665 OS << "warning"; 666 break; 667 case 3: 668 OS << "note"; 669 break; 670 case 4: 671 OS << "remark"; 672 break; 673 default: 674 OS << "diagnostic"; 675 break; 676 } 677 return OS << '(' << D.severity << "): " << D.message << "]"; 678 } 679 680 bool fromJSON(const llvm::json::Value &Params, CodeActionParams &R, 681 llvm::json::Path P) { 682 llvm::json::ObjectMapper O(Params, P); 683 return O && O.map("textDocument", R.textDocument) && 684 O.map("range", R.range) && O.map("context", R.context); 685 } 686 687 bool fromJSON(const llvm::json::Value &Params, WorkspaceEdit &R, 688 llvm::json::Path P) { 689 llvm::json::ObjectMapper O(Params, P); 690 return O && O.map("changes", R.changes); 691 } 692 693 bool fromJSON(const llvm::json::Value &Params, ExecuteCommandParams &R, 694 llvm::json::Path P) { 695 llvm::json::ObjectMapper O(Params, P); 696 if (!O || !O.map("command", R.command)) 697 return false; 698 699 const auto *Args = Params.getAsObject()->get("arguments"); 700 if (!Args) 701 return true; // Missing args is ok, argument is null. 702 const auto *ArgsArray = Args->getAsArray(); 703 if (!ArgsArray) { 704 P.field("arguments").report("expected array"); 705 return false; 706 } 707 if (ArgsArray->size() > 1) { 708 P.field("arguments").report("Command should have 0 or 1 argument"); 709 return false; 710 } 711 if (ArgsArray->size() == 1) { 712 R.argument = ArgsArray->front(); 713 } 714 return true; 715 } 716 717 llvm::json::Value toJSON(const SymbolInformation &P) { 718 llvm::json::Object O{ 719 {"name", P.name}, 720 {"kind", static_cast<int>(P.kind)}, 721 {"location", P.location}, 722 {"containerName", P.containerName}, 723 }; 724 if (P.score) 725 O["score"] = *P.score; 726 return std::move(O); 727 } 728 729 llvm::raw_ostream &operator<<(llvm::raw_ostream &O, 730 const SymbolInformation &SI) { 731 O << SI.containerName << "::" << SI.name << " - " << toJSON(SI); 732 return O; 733 } 734 735 bool operator==(const SymbolDetails &LHS, const SymbolDetails &RHS) { 736 return LHS.name == RHS.name && LHS.containerName == RHS.containerName && 737 LHS.USR == RHS.USR && LHS.ID == RHS.ID; 738 } 739 740 llvm::json::Value toJSON(const SymbolDetails &P) { 741 llvm::json::Object Result{{"name", llvm::json::Value(nullptr)}, 742 {"containerName", llvm::json::Value(nullptr)}, 743 {"usr", llvm::json::Value(nullptr)}, 744 {"id", llvm::json::Value(nullptr)}}; 745 746 if (!P.name.empty()) 747 Result["name"] = P.name; 748 749 if (!P.containerName.empty()) 750 Result["containerName"] = P.containerName; 751 752 if (!P.USR.empty()) 753 Result["usr"] = P.USR; 754 755 if (P.ID) 756 Result["id"] = P.ID.str(); 757 758 // FIXME: workaround for older gcc/clang 759 return std::move(Result); 760 } 761 762 llvm::raw_ostream &operator<<(llvm::raw_ostream &O, const SymbolDetails &S) { 763 if (!S.containerName.empty()) { 764 O << S.containerName; 765 llvm::StringRef ContNameRef; 766 if (!ContNameRef.endswith("::")) { 767 O << " "; 768 } 769 } 770 O << S.name << " - " << toJSON(S); 771 return O; 772 } 773 774 bool fromJSON(const llvm::json::Value &Params, WorkspaceSymbolParams &R, 775 llvm::json::Path P) { 776 llvm::json::ObjectMapper O(Params, P); 777 return O && O.map("query", R.query) && 778 mapOptOrNull(Params, "limit", R.limit, P); 779 } 780 781 llvm::json::Value toJSON(const Command &C) { 782 auto Cmd = llvm::json::Object{{"title", C.title}, {"command", C.command}}; 783 if (!C.argument.getAsNull()) 784 Cmd["arguments"] = llvm::json::Array{C.argument}; 785 return std::move(Cmd); 786 } 787 788 const llvm::StringLiteral CodeAction::QUICKFIX_KIND = "quickfix"; 789 const llvm::StringLiteral CodeAction::REFACTOR_KIND = "refactor"; 790 const llvm::StringLiteral CodeAction::INFO_KIND = "info"; 791 792 llvm::json::Value toJSON(const CodeAction &CA) { 793 auto CodeAction = llvm::json::Object{{"title", CA.title}}; 794 if (CA.kind) 795 CodeAction["kind"] = *CA.kind; 796 if (CA.diagnostics) 797 CodeAction["diagnostics"] = llvm::json::Array(*CA.diagnostics); 798 if (CA.isPreferred) 799 CodeAction["isPreferred"] = true; 800 if (CA.edit) 801 CodeAction["edit"] = *CA.edit; 802 if (CA.command) 803 CodeAction["command"] = *CA.command; 804 return std::move(CodeAction); 805 } 806 807 llvm::raw_ostream &operator<<(llvm::raw_ostream &O, const DocumentSymbol &S) { 808 return O << S.name << " - " << toJSON(S); 809 } 810 811 llvm::json::Value toJSON(const DocumentSymbol &S) { 812 llvm::json::Object Result{{"name", S.name}, 813 {"kind", static_cast<int>(S.kind)}, 814 {"range", S.range}, 815 {"selectionRange", S.selectionRange}}; 816 817 if (!S.detail.empty()) 818 Result["detail"] = S.detail; 819 if (!S.children.empty()) 820 Result["children"] = S.children; 821 if (S.deprecated) 822 Result["deprecated"] = true; 823 // FIXME: workaround for older gcc/clang 824 return std::move(Result); 825 } 826 827 llvm::json::Value toJSON(const WorkspaceEdit &WE) { 828 llvm::json::Object FileChanges; 829 for (auto &Change : WE.changes) 830 FileChanges[Change.first] = llvm::json::Array(Change.second); 831 return llvm::json::Object{{"changes", std::move(FileChanges)}}; 832 } 833 834 bool fromJSON(const llvm::json::Value &Params, TweakArgs &A, 835 llvm::json::Path P) { 836 llvm::json::ObjectMapper O(Params, P); 837 return O && O.map("file", A.file) && O.map("selection", A.selection) && 838 O.map("tweakID", A.tweakID); 839 } 840 841 llvm::json::Value toJSON(const TweakArgs &A) { 842 return llvm::json::Object{ 843 {"tweakID", A.tweakID}, {"selection", A.selection}, {"file", A.file}}; 844 } 845 846 llvm::json::Value toJSON(const ApplyWorkspaceEditParams &Params) { 847 return llvm::json::Object{{"edit", Params.edit}}; 848 } 849 850 bool fromJSON(const llvm::json::Value &Response, ApplyWorkspaceEditResponse &R, 851 llvm::json::Path P) { 852 llvm::json::ObjectMapper O(Response, P); 853 return O && O.map("applied", R.applied) && 854 O.map("failureReason", R.failureReason); 855 } 856 857 bool fromJSON(const llvm::json::Value &Params, TextDocumentPositionParams &R, 858 llvm::json::Path P) { 859 llvm::json::ObjectMapper O(Params, P); 860 return O && O.map("textDocument", R.textDocument) && 861 O.map("position", R.position); 862 } 863 864 bool fromJSON(const llvm::json::Value &Params, CompletionContext &R, 865 llvm::json::Path P) { 866 llvm::json::ObjectMapper O(Params, P); 867 int TriggerKind; 868 if (!O || !O.map("triggerKind", TriggerKind) || 869 !mapOptOrNull(Params, "triggerCharacter", R.triggerCharacter, P)) 870 return false; 871 R.triggerKind = static_cast<CompletionTriggerKind>(TriggerKind); 872 return true; 873 } 874 875 bool fromJSON(const llvm::json::Value &Params, CompletionParams &R, 876 llvm::json::Path P) { 877 if (!fromJSON(Params, static_cast<TextDocumentPositionParams &>(R), P) || 878 !mapOptOrNull(Params, "limit", R.limit, P)) 879 return false; 880 if (auto *Context = Params.getAsObject()->get("context")) 881 return fromJSON(*Context, R.context, P.field("context")); 882 return true; 883 } 884 885 static llvm::StringRef toTextKind(MarkupKind Kind) { 886 switch (Kind) { 887 case MarkupKind::PlainText: 888 return "plaintext"; 889 case MarkupKind::Markdown: 890 return "markdown"; 891 } 892 llvm_unreachable("Invalid MarkupKind"); 893 } 894 895 bool fromJSON(const llvm::json::Value &V, MarkupKind &K, llvm::json::Path P) { 896 auto Str = V.getAsString(); 897 if (!Str) { 898 P.report("expected string"); 899 return false; 900 } 901 if (*Str == "plaintext") 902 K = MarkupKind::PlainText; 903 else if (*Str == "markdown") 904 K = MarkupKind::Markdown; 905 else { 906 P.report("unknown markup kind"); 907 return false; 908 } 909 return true; 910 } 911 912 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, MarkupKind K) { 913 return OS << toTextKind(K); 914 } 915 916 llvm::json::Value toJSON(const MarkupContent &MC) { 917 if (MC.value.empty()) 918 return nullptr; 919 920 return llvm::json::Object{ 921 {"kind", toTextKind(MC.kind)}, 922 {"value", MC.value}, 923 }; 924 } 925 926 llvm::json::Value toJSON(const Hover &H) { 927 llvm::json::Object Result{{"contents", toJSON(H.contents)}}; 928 929 if (H.range) 930 Result["range"] = toJSON(*H.range); 931 932 return std::move(Result); 933 } 934 935 bool fromJSON(const llvm::json::Value &E, CompletionItemKind &Out, 936 llvm::json::Path P) { 937 if (auto T = E.getAsInteger()) { 938 if (*T < static_cast<int>(CompletionItemKind::Text) || 939 *T > static_cast<int>(CompletionItemKind::TypeParameter)) 940 return false; 941 Out = static_cast<CompletionItemKind>(*T); 942 return true; 943 } 944 return false; 945 } 946 947 CompletionItemKind 948 adjustKindToCapability(CompletionItemKind Kind, 949 CompletionItemKindBitset &SupportedCompletionItemKinds) { 950 auto KindVal = static_cast<size_t>(Kind); 951 if (KindVal >= CompletionItemKindMin && 952 KindVal <= SupportedCompletionItemKinds.size() && 953 SupportedCompletionItemKinds[KindVal]) 954 return Kind; 955 956 switch (Kind) { 957 // Provide some fall backs for common kinds that are close enough. 958 case CompletionItemKind::Folder: 959 return CompletionItemKind::File; 960 case CompletionItemKind::EnumMember: 961 return CompletionItemKind::Enum; 962 case CompletionItemKind::Struct: 963 return CompletionItemKind::Class; 964 default: 965 return CompletionItemKind::Text; 966 } 967 } 968 969 bool fromJSON(const llvm::json::Value &E, CompletionItemKindBitset &Out, 970 llvm::json::Path P) { 971 if (auto *A = E.getAsArray()) { 972 for (size_t I = 0; I < A->size(); ++I) { 973 CompletionItemKind KindOut; 974 if (fromJSON((*A)[I], KindOut, P.index(I))) 975 Out.set(size_t(KindOut)); 976 } 977 return true; 978 } 979 return false; 980 } 981 982 llvm::json::Value toJSON(const CompletionItem &CI) { 983 assert(!CI.label.empty() && "completion item label is required"); 984 llvm::json::Object Result{{"label", CI.label}}; 985 if (CI.kind != CompletionItemKind::Missing) 986 Result["kind"] = static_cast<int>(CI.kind); 987 if (!CI.detail.empty()) 988 Result["detail"] = CI.detail; 989 if (CI.documentation) 990 Result["documentation"] = CI.documentation; 991 if (!CI.sortText.empty()) 992 Result["sortText"] = CI.sortText; 993 if (!CI.filterText.empty()) 994 Result["filterText"] = CI.filterText; 995 if (!CI.insertText.empty()) 996 Result["insertText"] = CI.insertText; 997 if (CI.insertTextFormat != InsertTextFormat::Missing) 998 Result["insertTextFormat"] = static_cast<int>(CI.insertTextFormat); 999 if (CI.textEdit) 1000 Result["textEdit"] = *CI.textEdit; 1001 if (!CI.additionalTextEdits.empty()) 1002 Result["additionalTextEdits"] = llvm::json::Array(CI.additionalTextEdits); 1003 if (CI.deprecated) 1004 Result["deprecated"] = CI.deprecated; 1005 Result["score"] = CI.score; 1006 return std::move(Result); 1007 } 1008 1009 llvm::raw_ostream &operator<<(llvm::raw_ostream &O, const CompletionItem &I) { 1010 O << I.label << " - " << toJSON(I); 1011 return O; 1012 } 1013 1014 bool operator<(const CompletionItem &L, const CompletionItem &R) { 1015 return (L.sortText.empty() ? L.label : L.sortText) < 1016 (R.sortText.empty() ? R.label : R.sortText); 1017 } 1018 1019 llvm::json::Value toJSON(const CompletionList &L) { 1020 return llvm::json::Object{ 1021 {"isIncomplete", L.isIncomplete}, 1022 {"items", llvm::json::Array(L.items)}, 1023 }; 1024 } 1025 1026 llvm::json::Value toJSON(const ParameterInformation &PI) { 1027 assert((PI.labelOffsets || !PI.labelString.empty()) && 1028 "parameter information label is required"); 1029 llvm::json::Object Result; 1030 if (PI.labelOffsets) 1031 Result["label"] = 1032 llvm::json::Array({PI.labelOffsets->first, PI.labelOffsets->second}); 1033 else 1034 Result["label"] = PI.labelString; 1035 if (!PI.documentation.empty()) 1036 Result["documentation"] = PI.documentation; 1037 return std::move(Result); 1038 } 1039 1040 llvm::json::Value toJSON(const SignatureInformation &SI) { 1041 assert(!SI.label.empty() && "signature information label is required"); 1042 llvm::json::Object Result{ 1043 {"label", SI.label}, 1044 {"parameters", llvm::json::Array(SI.parameters)}, 1045 }; 1046 if (!SI.documentation.value.empty()) 1047 Result["documentation"] = SI.documentation; 1048 return std::move(Result); 1049 } 1050 1051 llvm::raw_ostream &operator<<(llvm::raw_ostream &O, 1052 const SignatureInformation &I) { 1053 O << I.label << " - " << toJSON(I); 1054 return O; 1055 } 1056 1057 llvm::json::Value toJSON(const SignatureHelp &SH) { 1058 assert(SH.activeSignature >= 0 && 1059 "Unexpected negative value for number of active signatures."); 1060 assert(SH.activeParameter >= 0 && 1061 "Unexpected negative value for active parameter index"); 1062 return llvm::json::Object{ 1063 {"activeSignature", SH.activeSignature}, 1064 {"activeParameter", SH.activeParameter}, 1065 {"signatures", llvm::json::Array(SH.signatures)}, 1066 }; 1067 } 1068 1069 bool fromJSON(const llvm::json::Value &Params, RenameParams &R, 1070 llvm::json::Path P) { 1071 llvm::json::ObjectMapper O(Params, P); 1072 return O && O.map("textDocument", R.textDocument) && 1073 O.map("position", R.position) && O.map("newName", R.newName); 1074 } 1075 1076 llvm::json::Value toJSON(const DocumentHighlight &DH) { 1077 return llvm::json::Object{ 1078 {"range", toJSON(DH.range)}, 1079 {"kind", static_cast<int>(DH.kind)}, 1080 }; 1081 } 1082 1083 llvm::json::Value toJSON(const FileStatus &FStatus) { 1084 return llvm::json::Object{ 1085 {"uri", FStatus.uri}, 1086 {"state", FStatus.state}, 1087 }; 1088 } 1089 1090 constexpr unsigned SemanticTokenEncodingSize = 5; 1091 static llvm::json::Value encodeTokens(llvm::ArrayRef<SemanticToken> Toks) { 1092 llvm::json::Array Result; 1093 Result.reserve(SemanticTokenEncodingSize * Toks.size()); 1094 for (const auto &Tok : Toks) { 1095 Result.push_back(Tok.deltaLine); 1096 Result.push_back(Tok.deltaStart); 1097 Result.push_back(Tok.length); 1098 Result.push_back(Tok.tokenType); 1099 Result.push_back(Tok.tokenModifiers); 1100 } 1101 assert(Result.size() == SemanticTokenEncodingSize * Toks.size()); 1102 return std::move(Result); 1103 } 1104 1105 bool operator==(const SemanticToken &L, const SemanticToken &R) { 1106 return std::tie(L.deltaLine, L.deltaStart, L.length, L.tokenType, 1107 L.tokenModifiers) == std::tie(R.deltaLine, R.deltaStart, 1108 R.length, R.tokenType, 1109 R.tokenModifiers); 1110 } 1111 1112 llvm::json::Value toJSON(const SemanticTokens &Tokens) { 1113 return llvm::json::Object{{"resultId", Tokens.resultId}, 1114 {"data", encodeTokens(Tokens.tokens)}}; 1115 } 1116 1117 llvm::json::Value toJSON(const SemanticTokensEdit &Edit) { 1118 return llvm::json::Object{ 1119 {"start", SemanticTokenEncodingSize * Edit.startToken}, 1120 {"deleteCount", SemanticTokenEncodingSize * Edit.deleteTokens}, 1121 {"data", encodeTokens(Edit.tokens)}}; 1122 } 1123 1124 llvm::json::Value toJSON(const SemanticTokensOrDelta &TE) { 1125 llvm::json::Object Result{{"resultId", TE.resultId}}; 1126 if (TE.edits) 1127 Result["edits"] = *TE.edits; 1128 if (TE.tokens) 1129 Result["data"] = encodeTokens(*TE.tokens); 1130 return std::move(Result); 1131 } 1132 1133 bool fromJSON(const llvm::json::Value &Params, SemanticTokensParams &R, 1134 llvm::json::Path P) { 1135 llvm::json::ObjectMapper O(Params, P); 1136 return O && O.map("textDocument", R.textDocument); 1137 } 1138 1139 bool fromJSON(const llvm::json::Value &Params, SemanticTokensDeltaParams &R, 1140 llvm::json::Path P) { 1141 llvm::json::ObjectMapper O(Params, P); 1142 return O && O.map("textDocument", R.textDocument) && 1143 O.map("previousResultId", R.previousResultId); 1144 } 1145 1146 llvm::raw_ostream &operator<<(llvm::raw_ostream &O, 1147 const DocumentHighlight &V) { 1148 O << V.range; 1149 if (V.kind == DocumentHighlightKind::Read) 1150 O << "(r)"; 1151 if (V.kind == DocumentHighlightKind::Write) 1152 O << "(w)"; 1153 return O; 1154 } 1155 1156 bool fromJSON(const llvm::json::Value &Params, 1157 DidChangeConfigurationParams &CCP, llvm::json::Path P) { 1158 llvm::json::ObjectMapper O(Params, P); 1159 return O && O.map("settings", CCP.settings); 1160 } 1161 1162 bool fromJSON(const llvm::json::Value &Params, ClangdCompileCommand &CDbUpdate, 1163 llvm::json::Path P) { 1164 llvm::json::ObjectMapper O(Params, P); 1165 return O && O.map("workingDirectory", CDbUpdate.workingDirectory) && 1166 O.map("compilationCommand", CDbUpdate.compilationCommand); 1167 } 1168 1169 bool fromJSON(const llvm::json::Value &Params, ConfigurationSettings &S, 1170 llvm::json::Path P) { 1171 llvm::json::ObjectMapper O(Params, P); 1172 if (!O) 1173 return true; // 'any' type in LSP. 1174 return mapOptOrNull(Params, "compilationDatabaseChanges", 1175 S.compilationDatabaseChanges, P); 1176 } 1177 1178 bool fromJSON(const llvm::json::Value &Params, InitializationOptions &Opts, 1179 llvm::json::Path P) { 1180 llvm::json::ObjectMapper O(Params, P); 1181 if (!O) 1182 return true; // 'any' type in LSP. 1183 1184 return fromJSON(Params, Opts.ConfigSettings, P) && 1185 O.map("compilationDatabasePath", Opts.compilationDatabasePath) && 1186 mapOptOrNull(Params, "fallbackFlags", Opts.fallbackFlags, P) && 1187 mapOptOrNull(Params, "clangdFileStatus", Opts.FileStatus, P); 1188 } 1189 1190 bool fromJSON(const llvm::json::Value &E, TypeHierarchyDirection &Out, 1191 llvm::json::Path P) { 1192 auto T = E.getAsInteger(); 1193 if (!T) 1194 return false; 1195 if (*T < static_cast<int>(TypeHierarchyDirection::Children) || 1196 *T > static_cast<int>(TypeHierarchyDirection::Both)) 1197 return false; 1198 Out = static_cast<TypeHierarchyDirection>(*T); 1199 return true; 1200 } 1201 1202 bool fromJSON(const llvm::json::Value &Params, TypeHierarchyParams &R, 1203 llvm::json::Path P) { 1204 llvm::json::ObjectMapper O(Params, P); 1205 return O && O.map("textDocument", R.textDocument) && 1206 O.map("position", R.position) && O.map("resolve", R.resolve) && 1207 O.map("direction", R.direction); 1208 } 1209 1210 llvm::raw_ostream &operator<<(llvm::raw_ostream &O, 1211 const TypeHierarchyItem &I) { 1212 return O << I.name << " - " << toJSON(I); 1213 } 1214 1215 llvm::json::Value toJSON(const TypeHierarchyItem &I) { 1216 llvm::json::Object Result{{"name", I.name}, 1217 {"kind", static_cast<int>(I.kind)}, 1218 {"range", I.range}, 1219 {"selectionRange", I.selectionRange}, 1220 {"uri", I.uri}}; 1221 1222 if (I.detail) 1223 Result["detail"] = I.detail; 1224 if (I.deprecated) 1225 Result["deprecated"] = I.deprecated; 1226 if (I.parents) 1227 Result["parents"] = I.parents; 1228 if (I.children) 1229 Result["children"] = I.children; 1230 if (I.data) 1231 Result["data"] = I.data; 1232 return std::move(Result); 1233 } 1234 1235 bool fromJSON(const llvm::json::Value &Params, TypeHierarchyItem &I, 1236 llvm::json::Path P) { 1237 llvm::json::ObjectMapper O(Params, P); 1238 1239 // Required fields. 1240 return O && O.map("name", I.name) && O.map("kind", I.kind) && 1241 O.map("uri", I.uri) && O.map("range", I.range) && 1242 O.map("selectionRange", I.selectionRange) && 1243 mapOptOrNull(Params, "detail", I.detail, P) && 1244 mapOptOrNull(Params, "deprecated", I.deprecated, P) && 1245 mapOptOrNull(Params, "parents", I.parents, P) && 1246 mapOptOrNull(Params, "children", I.children, P) && 1247 mapOptOrNull(Params, "data", I.data, P); 1248 } 1249 1250 bool fromJSON(const llvm::json::Value &Params, 1251 ResolveTypeHierarchyItemParams &R, llvm::json::Path P) { 1252 llvm::json::ObjectMapper O(Params, P); 1253 return O && O.map("item", R.item) && O.map("resolve", R.resolve) && 1254 O.map("direction", R.direction); 1255 } 1256 1257 bool fromJSON(const llvm::json::Value &Params, ReferenceContext &R, 1258 llvm::json::Path P) { 1259 llvm::json::ObjectMapper O(Params, P); 1260 return O && O.mapOptional("includeDeclaration", R.includeDeclaration); 1261 } 1262 1263 bool fromJSON(const llvm::json::Value &Params, ReferenceParams &R, 1264 llvm::json::Path P) { 1265 TextDocumentPositionParams &Base = R; 1266 llvm::json::ObjectMapper O(Params, P); 1267 return fromJSON(Params, Base, P) && O && O.mapOptional("context", R.context); 1268 } 1269 1270 llvm::json::Value toJSON(SymbolTag Tag) { 1271 return llvm::json::Value{static_cast<int>(Tag)}; 1272 } 1273 1274 llvm::json::Value toJSON(const CallHierarchyItem &I) { 1275 llvm::json::Object Result{{"name", I.name}, 1276 {"kind", static_cast<int>(I.kind)}, 1277 {"range", I.range}, 1278 {"selectionRange", I.selectionRange}, 1279 {"uri", I.uri}}; 1280 if (!I.tags.empty()) 1281 Result["tags"] = I.tags; 1282 if (!I.detail.empty()) 1283 Result["detail"] = I.detail; 1284 if (!I.data.empty()) 1285 Result["data"] = I.data; 1286 return std::move(Result); 1287 } 1288 1289 bool fromJSON(const llvm::json::Value &Params, CallHierarchyItem &I, 1290 llvm::json::Path P) { 1291 llvm::json::ObjectMapper O(Params, P); 1292 1293 // Populate the required fields only. We don't care about the 1294 // optional fields `Tags` and `Detail` for the purpose of 1295 // client --> server communication. 1296 return O && O.map("name", I.name) && O.map("kind", I.kind) && 1297 O.map("uri", I.uri) && O.map("range", I.range) && 1298 O.map("selectionRange", I.selectionRange) && 1299 mapOptOrNull(Params, "data", I.data, P); 1300 } 1301 1302 bool fromJSON(const llvm::json::Value &Params, 1303 CallHierarchyIncomingCallsParams &C, llvm::json::Path P) { 1304 llvm::json::ObjectMapper O(Params, P); 1305 return O.map("item", C.item); 1306 } 1307 1308 llvm::json::Value toJSON(const CallHierarchyIncomingCall &C) { 1309 return llvm::json::Object{{"from", C.from}, {"fromRanges", C.fromRanges}}; 1310 } 1311 1312 bool fromJSON(const llvm::json::Value &Params, 1313 CallHierarchyOutgoingCallsParams &C, llvm::json::Path P) { 1314 llvm::json::ObjectMapper O(Params, P); 1315 return O.map("item", C.item); 1316 } 1317 1318 llvm::json::Value toJSON(const CallHierarchyOutgoingCall &C) { 1319 return llvm::json::Object{{"to", C.to}, {"fromRanges", C.fromRanges}}; 1320 } 1321 1322 bool fromJSON(const llvm::json::Value &Params, InlayHintsParams &R, 1323 llvm::json::Path P) { 1324 llvm::json::ObjectMapper O(Params, P); 1325 return O && O.map("textDocument", R.textDocument) && O.map("range", R.range); 1326 } 1327 1328 llvm::json::Value toJSON(const InlayHintKind &Kind) { 1329 switch (Kind) { 1330 case InlayHintKind::Type: 1331 return 1; 1332 case InlayHintKind::Parameter: 1333 return 2; 1334 case InlayHintKind::Designator: // This is an extension, don't serialize. 1335 return nullptr; 1336 } 1337 llvm_unreachable("Unknown clang.clangd.InlayHintKind"); 1338 } 1339 1340 llvm::json::Value toJSON(const InlayHint &H) { 1341 llvm::json::Object Result{{"position", H.position}, 1342 {"label", H.label}, 1343 {"paddingLeft", H.paddingLeft}, 1344 {"paddingRight", H.paddingRight}}; 1345 auto K = toJSON(H.kind); 1346 if (!K.getAsNull()) 1347 Result["kind"] = std::move(K); 1348 return std::move(Result); 1349 } 1350 bool operator==(const InlayHint &A, const InlayHint &B) { 1351 return std::tie(A.position, A.range, A.kind, A.label) == 1352 std::tie(B.position, B.range, B.kind, B.label); 1353 } 1354 bool operator<(const InlayHint &A, const InlayHint &B) { 1355 return std::tie(A.position, A.range, A.kind, A.label) < 1356 std::tie(B.position, B.range, B.kind, B.label); 1357 } 1358 1359 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, InlayHintKind Kind) { 1360 auto ToString = [](InlayHintKind K) { 1361 switch (K) { 1362 case InlayHintKind::Parameter: 1363 return "parameter"; 1364 case InlayHintKind::Type: 1365 return "type"; 1366 case InlayHintKind::Designator: 1367 return "designator"; 1368 } 1369 llvm_unreachable("Unknown clang.clangd.InlayHintKind"); 1370 }; 1371 return OS << ToString(Kind); 1372 } 1373 1374 static const char *toString(OffsetEncoding OE) { 1375 switch (OE) { 1376 case OffsetEncoding::UTF8: 1377 return "utf-8"; 1378 case OffsetEncoding::UTF16: 1379 return "utf-16"; 1380 case OffsetEncoding::UTF32: 1381 return "utf-32"; 1382 case OffsetEncoding::UnsupportedEncoding: 1383 return "unknown"; 1384 } 1385 llvm_unreachable("Unknown clang.clangd.OffsetEncoding"); 1386 } 1387 llvm::json::Value toJSON(const OffsetEncoding &OE) { return toString(OE); } 1388 bool fromJSON(const llvm::json::Value &V, OffsetEncoding &OE, 1389 llvm::json::Path P) { 1390 auto Str = V.getAsString(); 1391 if (!Str) 1392 return false; 1393 OE = llvm::StringSwitch<OffsetEncoding>(*Str) 1394 .Case("utf-8", OffsetEncoding::UTF8) 1395 .Case("utf-16", OffsetEncoding::UTF16) 1396 .Case("utf-32", OffsetEncoding::UTF32) 1397 .Default(OffsetEncoding::UnsupportedEncoding); 1398 return true; 1399 } 1400 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, OffsetEncoding Enc) { 1401 return OS << toString(Enc); 1402 } 1403 1404 bool fromJSON(const llvm::json::Value &Params, SelectionRangeParams &S, 1405 llvm::json::Path P) { 1406 llvm::json::ObjectMapper O(Params, P); 1407 return O && O.map("textDocument", S.textDocument) && 1408 O.map("positions", S.positions); 1409 } 1410 1411 llvm::json::Value toJSON(const SelectionRange &Out) { 1412 if (Out.parent) { 1413 return llvm::json::Object{{"range", Out.range}, 1414 {"parent", toJSON(*Out.parent)}}; 1415 } 1416 return llvm::json::Object{{"range", Out.range}}; 1417 } 1418 1419 bool fromJSON(const llvm::json::Value &Params, DocumentLinkParams &R, 1420 llvm::json::Path P) { 1421 llvm::json::ObjectMapper O(Params, P); 1422 return O && O.map("textDocument", R.textDocument); 1423 } 1424 1425 llvm::json::Value toJSON(const DocumentLink &DocumentLink) { 1426 return llvm::json::Object{ 1427 {"range", DocumentLink.range}, 1428 {"target", DocumentLink.target}, 1429 }; 1430 } 1431 1432 bool fromJSON(const llvm::json::Value &Params, FoldingRangeParams &R, 1433 llvm::json::Path P) { 1434 llvm::json::ObjectMapper O(Params, P); 1435 return O && O.map("textDocument", R.textDocument); 1436 } 1437 1438 llvm::json::Value toJSON(const FoldingRange &Range) { 1439 llvm::json::Object Result{ 1440 {"startLine", Range.startLine}, 1441 {"endLine", Range.endLine}, 1442 }; 1443 if (Range.startCharacter) 1444 Result["startCharacter"] = Range.startCharacter; 1445 if (Range.endCharacter) 1446 Result["endCharacter"] = Range.endCharacter; 1447 if (Range.kind) 1448 Result["kind"] = *Range.kind; 1449 return Result; 1450 } 1451 1452 llvm::json::Value toJSON(const MemoryTree &MT) { 1453 llvm::json::Object Out; 1454 int64_t Total = MT.self(); 1455 Out["_self"] = Total; 1456 for (const auto &Entry : MT.children()) { 1457 auto Child = toJSON(Entry.getSecond()); 1458 Total += *Child.getAsObject()->getInteger("_total"); 1459 Out[Entry.first] = std::move(Child); 1460 } 1461 Out["_total"] = Total; 1462 return Out; 1463 } 1464 1465 bool fromJSON(const llvm::json::Value &Params, ASTParams &R, 1466 llvm::json::Path P) { 1467 llvm::json::ObjectMapper O(Params, P); 1468 return O && O.map("textDocument", R.textDocument) && O.map("range", R.range); 1469 } 1470 1471 llvm::json::Value toJSON(const ASTNode &N) { 1472 llvm::json::Object Result{ 1473 {"role", N.role}, 1474 {"kind", N.kind}, 1475 }; 1476 if (!N.children.empty()) 1477 Result["children"] = N.children; 1478 if (!N.detail.empty()) 1479 Result["detail"] = N.detail; 1480 if (!N.arcana.empty()) 1481 Result["arcana"] = N.arcana; 1482 if (N.range) 1483 Result["range"] = *N.range; 1484 return Result; 1485 } 1486 1487 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const ASTNode &Root) { 1488 std::function<void(const ASTNode &, unsigned)> Print = [&](const ASTNode &N, 1489 unsigned Level) { 1490 OS.indent(2 * Level) << N.role << ": " << N.kind; 1491 if (!N.detail.empty()) 1492 OS << " - " << N.detail; 1493 OS << "\n"; 1494 for (const ASTNode &C : N.children) 1495 Print(C, Level + 1); 1496 }; 1497 Print(Root, 0); 1498 return OS; 1499 } 1500 1501 } // namespace clangd 1502 } // namespace clang 1503