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