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