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 } 387 } 388 if (auto *Rename = TextDocument->getObject("rename")) { 389 if (auto RenameSupport = Rename->getBoolean("prepareSupport")) 390 R.RenamePrepareSupport = *RenameSupport; 391 } 392 } 393 if (auto *Workspace = O->getObject("workspace")) { 394 if (auto *Symbol = Workspace->getObject("symbol")) { 395 if (auto *SymbolKind = Symbol->getObject("symbolKind")) { 396 if (auto *ValueSet = SymbolKind->get("valueSet")) { 397 R.WorkspaceSymbolKinds.emplace(); 398 if (!fromJSON(*ValueSet, *R.WorkspaceSymbolKinds, 399 P.field("workspace") 400 .field("symbol") 401 .field("symbolKind") 402 .field("valueSet"))) 403 return false; 404 } 405 } 406 } 407 if (auto *SemanticTokens = Workspace->getObject("semanticTokens")) { 408 if (auto RefreshSupport = SemanticTokens->getBoolean("refreshSupport")) 409 R.SemanticTokenRefreshSupport = *RefreshSupport; 410 } 411 } 412 if (auto *Window = O->getObject("window")) { 413 if (auto WorkDoneProgress = Window->getBoolean("workDoneProgress")) 414 R.WorkDoneProgress = *WorkDoneProgress; 415 if (auto Implicit = Window->getBoolean("implicitWorkDoneProgressCreate")) 416 R.ImplicitProgressCreation = *Implicit; 417 } 418 if (auto *General = O->getObject("general")) { 419 if (auto *StaleRequestSupport = General->getObject("staleRequestSupport")) { 420 if (auto Cancel = StaleRequestSupport->getBoolean("cancel")) 421 R.CancelsStaleRequests = *Cancel; 422 } 423 } 424 if (auto *OffsetEncoding = O->get("offsetEncoding")) { 425 R.offsetEncoding.emplace(); 426 if (!fromJSON(*OffsetEncoding, *R.offsetEncoding, 427 P.field("offsetEncoding"))) 428 return false; 429 } 430 return true; 431 } 432 433 bool fromJSON(const llvm::json::Value &Params, InitializeParams &R, 434 llvm::json::Path P) { 435 llvm::json::ObjectMapper O(Params, P); 436 if (!O) 437 return false; 438 // We deliberately don't fail if we can't parse individual fields. 439 // Failing to handle a slightly malformed initialize would be a disaster. 440 O.map("processId", R.processId); 441 O.map("rootUri", R.rootUri); 442 O.map("rootPath", R.rootPath); 443 O.map("capabilities", R.capabilities); 444 if (auto *RawCaps = Params.getAsObject()->getObject("capabilities")) 445 R.rawCapabilities = *RawCaps; 446 O.map("trace", R.trace); 447 O.map("initializationOptions", R.initializationOptions); 448 return true; 449 } 450 451 llvm::json::Value toJSON(const WorkDoneProgressCreateParams &P) { 452 return llvm::json::Object{{"token", P.token}}; 453 } 454 455 llvm::json::Value toJSON(const WorkDoneProgressBegin &P) { 456 llvm::json::Object Result{ 457 {"kind", "begin"}, 458 {"title", P.title}, 459 }; 460 if (P.cancellable) 461 Result["cancellable"] = true; 462 if (P.percentage) 463 Result["percentage"] = 0; 464 465 // FIXME: workaround for older gcc/clang 466 return std::move(Result); 467 } 468 469 llvm::json::Value toJSON(const WorkDoneProgressReport &P) { 470 llvm::json::Object Result{{"kind", "report"}}; 471 if (P.cancellable) 472 Result["cancellable"] = *P.cancellable; 473 if (P.message) 474 Result["message"] = *P.message; 475 if (P.percentage) 476 Result["percentage"] = *P.percentage; 477 // FIXME: workaround for older gcc/clang 478 return std::move(Result); 479 } 480 481 llvm::json::Value toJSON(const WorkDoneProgressEnd &P) { 482 llvm::json::Object Result{{"kind", "end"}}; 483 if (P.message) 484 Result["message"] = *P.message; 485 // FIXME: workaround for older gcc/clang 486 return std::move(Result); 487 } 488 489 llvm::json::Value toJSON(const MessageType &R) { 490 return static_cast<int64_t>(R); 491 } 492 493 llvm::json::Value toJSON(const ShowMessageParams &R) { 494 return llvm::json::Object{{"type", R.type}, {"message", R.message}}; 495 } 496 497 bool fromJSON(const llvm::json::Value &Params, DidOpenTextDocumentParams &R, 498 llvm::json::Path P) { 499 llvm::json::ObjectMapper O(Params, P); 500 return O && O.map("textDocument", R.textDocument); 501 } 502 503 bool fromJSON(const llvm::json::Value &Params, DidCloseTextDocumentParams &R, 504 llvm::json::Path P) { 505 llvm::json::ObjectMapper O(Params, P); 506 return O && O.map("textDocument", R.textDocument); 507 } 508 509 bool fromJSON(const llvm::json::Value &Params, DidSaveTextDocumentParams &R, 510 llvm::json::Path P) { 511 llvm::json::ObjectMapper O(Params, P); 512 return O && O.map("textDocument", R.textDocument); 513 } 514 515 bool fromJSON(const llvm::json::Value &Params, DidChangeTextDocumentParams &R, 516 llvm::json::Path P) { 517 llvm::json::ObjectMapper O(Params, P); 518 return O && O.map("textDocument", R.textDocument) && 519 O.map("contentChanges", R.contentChanges) && 520 O.map("wantDiagnostics", R.wantDiagnostics) && 521 mapOptOrNull(Params, "forceRebuild", R.forceRebuild, P); 522 } 523 524 bool fromJSON(const llvm::json::Value &E, FileChangeType &Out, 525 llvm::json::Path P) { 526 if (auto T = E.getAsInteger()) { 527 if (*T < static_cast<int>(FileChangeType::Created) || 528 *T > static_cast<int>(FileChangeType::Deleted)) 529 return false; 530 Out = static_cast<FileChangeType>(*T); 531 return true; 532 } 533 return false; 534 } 535 536 bool fromJSON(const llvm::json::Value &Params, FileEvent &R, 537 llvm::json::Path P) { 538 llvm::json::ObjectMapper O(Params, P); 539 return O && O.map("uri", R.uri) && O.map("type", R.type); 540 } 541 542 bool fromJSON(const llvm::json::Value &Params, DidChangeWatchedFilesParams &R, 543 llvm::json::Path P) { 544 llvm::json::ObjectMapper O(Params, P); 545 return O && O.map("changes", R.changes); 546 } 547 548 bool fromJSON(const llvm::json::Value &Params, 549 TextDocumentContentChangeEvent &R, llvm::json::Path P) { 550 llvm::json::ObjectMapper O(Params, P); 551 return O && O.map("range", R.range) && O.map("rangeLength", R.rangeLength) && 552 O.map("text", R.text); 553 } 554 555 bool fromJSON(const llvm::json::Value &Params, DocumentRangeFormattingParams &R, 556 llvm::json::Path P) { 557 llvm::json::ObjectMapper O(Params, P); 558 return O && O.map("textDocument", R.textDocument) && O.map("range", R.range); 559 } 560 561 bool fromJSON(const llvm::json::Value &Params, 562 DocumentOnTypeFormattingParams &R, llvm::json::Path P) { 563 llvm::json::ObjectMapper O(Params, P); 564 return O && O.map("textDocument", R.textDocument) && 565 O.map("position", R.position) && O.map("ch", R.ch); 566 } 567 568 bool fromJSON(const llvm::json::Value &Params, DocumentFormattingParams &R, 569 llvm::json::Path P) { 570 llvm::json::ObjectMapper O(Params, P); 571 return O && O.map("textDocument", R.textDocument); 572 } 573 574 bool fromJSON(const llvm::json::Value &Params, DocumentSymbolParams &R, 575 llvm::json::Path P) { 576 llvm::json::ObjectMapper O(Params, P); 577 return O && O.map("textDocument", R.textDocument); 578 } 579 580 llvm::json::Value toJSON(const DiagnosticRelatedInformation &DRI) { 581 return llvm::json::Object{ 582 {"location", DRI.location}, 583 {"message", DRI.message}, 584 }; 585 } 586 587 llvm::json::Value toJSON(const Diagnostic &D) { 588 llvm::json::Object Diag{ 589 {"range", D.range}, 590 {"severity", D.severity}, 591 {"message", D.message}, 592 }; 593 if (D.category) 594 Diag["category"] = *D.category; 595 if (D.codeActions) 596 Diag["codeActions"] = D.codeActions; 597 if (!D.code.empty()) 598 Diag["code"] = D.code; 599 if (!D.source.empty()) 600 Diag["source"] = D.source; 601 if (D.relatedInformation) 602 Diag["relatedInformation"] = *D.relatedInformation; 603 if (!D.data.empty()) 604 Diag["data"] = llvm::json::Object(D.data); 605 // FIXME: workaround for older gcc/clang 606 return std::move(Diag); 607 } 608 609 bool fromJSON(const llvm::json::Value &Params, Diagnostic &R, 610 llvm::json::Path P) { 611 llvm::json::ObjectMapper O(Params, P); 612 if (!O) 613 return false; 614 if (auto *Data = Params.getAsObject()->getObject("data")) 615 R.data = *Data; 616 return O.map("range", R.range) && O.map("message", R.message) && 617 mapOptOrNull(Params, "severity", R.severity, P) && 618 mapOptOrNull(Params, "category", R.category, P) && 619 mapOptOrNull(Params, "code", R.code, P) && 620 mapOptOrNull(Params, "source", R.source, P); 621 } 622 623 llvm::json::Value toJSON(const PublishDiagnosticsParams &PDP) { 624 llvm::json::Object Result{ 625 {"uri", PDP.uri}, 626 {"diagnostics", PDP.diagnostics}, 627 }; 628 if (PDP.version) 629 Result["version"] = PDP.version; 630 return std::move(Result); 631 } 632 633 bool fromJSON(const llvm::json::Value &Params, CodeActionContext &R, 634 llvm::json::Path P) { 635 llvm::json::ObjectMapper O(Params, P); 636 if (!O || !O.map("diagnostics", R.diagnostics)) 637 return false; 638 O.map("only", R.only); 639 return true; 640 } 641 642 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Diagnostic &D) { 643 OS << D.range << " ["; 644 switch (D.severity) { 645 case 1: 646 OS << "error"; 647 break; 648 case 2: 649 OS << "warning"; 650 break; 651 case 3: 652 OS << "note"; 653 break; 654 case 4: 655 OS << "remark"; 656 break; 657 default: 658 OS << "diagnostic"; 659 break; 660 } 661 return OS << '(' << D.severity << "): " << D.message << "]"; 662 } 663 664 bool fromJSON(const llvm::json::Value &Params, CodeActionParams &R, 665 llvm::json::Path P) { 666 llvm::json::ObjectMapper O(Params, P); 667 return O && O.map("textDocument", R.textDocument) && 668 O.map("range", R.range) && O.map("context", R.context); 669 } 670 671 bool fromJSON(const llvm::json::Value &Params, WorkspaceEdit &R, 672 llvm::json::Path P) { 673 llvm::json::ObjectMapper O(Params, P); 674 return O && O.map("changes", R.changes); 675 } 676 677 bool fromJSON(const llvm::json::Value &Params, ExecuteCommandParams &R, 678 llvm::json::Path P) { 679 llvm::json::ObjectMapper O(Params, P); 680 if (!O || !O.map("command", R.command)) 681 return false; 682 683 const auto *Args = Params.getAsObject()->get("arguments"); 684 if (!Args) 685 return true; // Missing args is ok, argument is null. 686 const auto *ArgsArray = Args->getAsArray(); 687 if (!ArgsArray) { 688 P.field("arguments").report("expected array"); 689 return false; 690 } 691 if (ArgsArray->size() > 1) { 692 P.field("arguments").report("Command should have 0 or 1 argument"); 693 return false; 694 } else if (ArgsArray->size() == 1) { 695 R.argument = ArgsArray->front(); 696 } 697 return true; 698 } 699 700 llvm::json::Value toJSON(const SymbolInformation &P) { 701 llvm::json::Object O{ 702 {"name", P.name}, 703 {"kind", static_cast<int>(P.kind)}, 704 {"location", P.location}, 705 {"containerName", P.containerName}, 706 }; 707 if (P.score) 708 O["score"] = *P.score; 709 return std::move(O); 710 } 711 712 llvm::raw_ostream &operator<<(llvm::raw_ostream &O, 713 const SymbolInformation &SI) { 714 O << SI.containerName << "::" << SI.name << " - " << toJSON(SI); 715 return O; 716 } 717 718 bool operator==(const SymbolDetails &LHS, const SymbolDetails &RHS) { 719 return LHS.name == RHS.name && LHS.containerName == RHS.containerName && 720 LHS.USR == RHS.USR && LHS.ID == RHS.ID; 721 } 722 723 llvm::json::Value toJSON(const SymbolDetails &P) { 724 llvm::json::Object Result{{"name", llvm::json::Value(nullptr)}, 725 {"containerName", llvm::json::Value(nullptr)}, 726 {"usr", llvm::json::Value(nullptr)}, 727 {"id", llvm::json::Value(nullptr)}}; 728 729 if (!P.name.empty()) 730 Result["name"] = P.name; 731 732 if (!P.containerName.empty()) 733 Result["containerName"] = P.containerName; 734 735 if (!P.USR.empty()) 736 Result["usr"] = P.USR; 737 738 if (P.ID) 739 Result["id"] = P.ID.str(); 740 741 // FIXME: workaround for older gcc/clang 742 return std::move(Result); 743 } 744 745 llvm::raw_ostream &operator<<(llvm::raw_ostream &O, const SymbolDetails &S) { 746 if (!S.containerName.empty()) { 747 O << S.containerName; 748 llvm::StringRef ContNameRef; 749 if (!ContNameRef.endswith("::")) { 750 O << " "; 751 } 752 } 753 O << S.name << " - " << toJSON(S); 754 return O; 755 } 756 757 bool fromJSON(const llvm::json::Value &Params, WorkspaceSymbolParams &R, 758 llvm::json::Path P) { 759 llvm::json::ObjectMapper O(Params, P); 760 return O && O.map("query", R.query) && 761 mapOptOrNull(Params, "limit", R.limit, P); 762 } 763 764 llvm::json::Value toJSON(const Command &C) { 765 auto Cmd = llvm::json::Object{{"title", C.title}, {"command", C.command}}; 766 if (!C.argument.getAsNull()) 767 Cmd["arguments"] = llvm::json::Array{C.argument}; 768 return std::move(Cmd); 769 } 770 771 const llvm::StringLiteral CodeAction::QUICKFIX_KIND = "quickfix"; 772 const llvm::StringLiteral CodeAction::REFACTOR_KIND = "refactor"; 773 const llvm::StringLiteral CodeAction::INFO_KIND = "info"; 774 775 llvm::json::Value toJSON(const CodeAction &CA) { 776 auto CodeAction = llvm::json::Object{{"title", CA.title}}; 777 if (CA.kind) 778 CodeAction["kind"] = *CA.kind; 779 if (CA.diagnostics) 780 CodeAction["diagnostics"] = llvm::json::Array(*CA.diagnostics); 781 if (CA.isPreferred) 782 CodeAction["isPreferred"] = true; 783 if (CA.edit) 784 CodeAction["edit"] = *CA.edit; 785 if (CA.command) 786 CodeAction["command"] = *CA.command; 787 return std::move(CodeAction); 788 } 789 790 llvm::raw_ostream &operator<<(llvm::raw_ostream &O, const DocumentSymbol &S) { 791 return O << S.name << " - " << toJSON(S); 792 } 793 794 llvm::json::Value toJSON(const DocumentSymbol &S) { 795 llvm::json::Object Result{{"name", S.name}, 796 {"kind", static_cast<int>(S.kind)}, 797 {"range", S.range}, 798 {"selectionRange", S.selectionRange}}; 799 800 if (!S.detail.empty()) 801 Result["detail"] = S.detail; 802 if (!S.children.empty()) 803 Result["children"] = S.children; 804 if (S.deprecated) 805 Result["deprecated"] = true; 806 // FIXME: workaround for older gcc/clang 807 return std::move(Result); 808 } 809 810 llvm::json::Value toJSON(const WorkspaceEdit &WE) { 811 if (!WE.changes) 812 return llvm::json::Object{}; 813 llvm::json::Object FileChanges; 814 for (auto &Change : *WE.changes) 815 FileChanges[Change.first] = llvm::json::Array(Change.second); 816 return llvm::json::Object{{"changes", std::move(FileChanges)}}; 817 } 818 819 bool fromJSON(const llvm::json::Value &Params, TweakArgs &A, 820 llvm::json::Path P) { 821 llvm::json::ObjectMapper O(Params, P); 822 return O && O.map("file", A.file) && O.map("selection", A.selection) && 823 O.map("tweakID", A.tweakID); 824 } 825 826 llvm::json::Value toJSON(const TweakArgs &A) { 827 return llvm::json::Object{ 828 {"tweakID", A.tweakID}, {"selection", A.selection}, {"file", A.file}}; 829 } 830 831 llvm::json::Value toJSON(const ApplyWorkspaceEditParams &Params) { 832 return llvm::json::Object{{"edit", Params.edit}}; 833 } 834 835 bool fromJSON(const llvm::json::Value &Response, ApplyWorkspaceEditResponse &R, 836 llvm::json::Path P) { 837 llvm::json::ObjectMapper O(Response, P); 838 return O && O.map("applied", R.applied) && 839 O.map("failureReason", R.failureReason); 840 } 841 842 bool fromJSON(const llvm::json::Value &Params, TextDocumentPositionParams &R, 843 llvm::json::Path P) { 844 llvm::json::ObjectMapper O(Params, P); 845 return O && O.map("textDocument", R.textDocument) && 846 O.map("position", R.position); 847 } 848 849 bool fromJSON(const llvm::json::Value &Params, CompletionContext &R, 850 llvm::json::Path P) { 851 llvm::json::ObjectMapper O(Params, P); 852 int TriggerKind; 853 if (!O || !O.map("triggerKind", TriggerKind) || 854 !mapOptOrNull(Params, "triggerCharacter", R.triggerCharacter, P)) 855 return false; 856 R.triggerKind = static_cast<CompletionTriggerKind>(TriggerKind); 857 return true; 858 } 859 860 bool fromJSON(const llvm::json::Value &Params, CompletionParams &R, 861 llvm::json::Path P) { 862 if (!fromJSON(Params, static_cast<TextDocumentPositionParams &>(R), P) || 863 !mapOptOrNull(Params, "limit", R.limit, P)) 864 return false; 865 if (auto *Context = Params.getAsObject()->get("context")) 866 return fromJSON(*Context, R.context, P.field("context")); 867 return true; 868 } 869 870 static llvm::StringRef toTextKind(MarkupKind Kind) { 871 switch (Kind) { 872 case MarkupKind::PlainText: 873 return "plaintext"; 874 case MarkupKind::Markdown: 875 return "markdown"; 876 } 877 llvm_unreachable("Invalid MarkupKind"); 878 } 879 880 bool fromJSON(const llvm::json::Value &V, MarkupKind &K, llvm::json::Path P) { 881 auto Str = V.getAsString(); 882 if (!Str) { 883 P.report("expected string"); 884 return false; 885 } 886 if (*Str == "plaintext") 887 K = MarkupKind::PlainText; 888 else if (*Str == "markdown") 889 K = MarkupKind::Markdown; 890 else { 891 P.report("unknown markup kind"); 892 return false; 893 } 894 return true; 895 } 896 897 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, MarkupKind K) { 898 return OS << toTextKind(K); 899 } 900 901 llvm::json::Value toJSON(const MarkupContent &MC) { 902 if (MC.value.empty()) 903 return nullptr; 904 905 return llvm::json::Object{ 906 {"kind", toTextKind(MC.kind)}, 907 {"value", MC.value}, 908 }; 909 } 910 911 llvm::json::Value toJSON(const Hover &H) { 912 llvm::json::Object Result{{"contents", toJSON(H.contents)}}; 913 914 if (H.range.hasValue()) 915 Result["range"] = toJSON(*H.range); 916 917 return std::move(Result); 918 } 919 920 bool fromJSON(const llvm::json::Value &E, CompletionItemKind &Out, 921 llvm::json::Path P) { 922 if (auto T = E.getAsInteger()) { 923 if (*T < static_cast<int>(CompletionItemKind::Text) || 924 *T > static_cast<int>(CompletionItemKind::TypeParameter)) 925 return false; 926 Out = static_cast<CompletionItemKind>(*T); 927 return true; 928 } 929 return false; 930 } 931 932 CompletionItemKind 933 adjustKindToCapability(CompletionItemKind Kind, 934 CompletionItemKindBitset &SupportedCompletionItemKinds) { 935 auto KindVal = static_cast<size_t>(Kind); 936 if (KindVal >= CompletionItemKindMin && 937 KindVal <= SupportedCompletionItemKinds.size() && 938 SupportedCompletionItemKinds[KindVal]) 939 return Kind; 940 941 switch (Kind) { 942 // Provide some fall backs for common kinds that are close enough. 943 case CompletionItemKind::Folder: 944 return CompletionItemKind::File; 945 case CompletionItemKind::EnumMember: 946 return CompletionItemKind::Enum; 947 case CompletionItemKind::Struct: 948 return CompletionItemKind::Class; 949 default: 950 return CompletionItemKind::Text; 951 } 952 } 953 954 bool fromJSON(const llvm::json::Value &E, CompletionItemKindBitset &Out, 955 llvm::json::Path P) { 956 if (auto *A = E.getAsArray()) { 957 for (size_t I = 0; I < A->size(); ++I) { 958 CompletionItemKind KindOut; 959 if (fromJSON((*A)[I], KindOut, P.index(I))) 960 Out.set(size_t(KindOut)); 961 } 962 return true; 963 } 964 return false; 965 } 966 967 llvm::json::Value toJSON(const CompletionItem &CI) { 968 assert(!CI.label.empty() && "completion item label is required"); 969 llvm::json::Object Result{{"label", CI.label}}; 970 if (CI.kind != CompletionItemKind::Missing) 971 Result["kind"] = static_cast<int>(CI.kind); 972 if (!CI.detail.empty()) 973 Result["detail"] = CI.detail; 974 if (CI.documentation) 975 Result["documentation"] = CI.documentation; 976 if (!CI.sortText.empty()) 977 Result["sortText"] = CI.sortText; 978 if (!CI.filterText.empty()) 979 Result["filterText"] = CI.filterText; 980 if (!CI.insertText.empty()) 981 Result["insertText"] = CI.insertText; 982 if (CI.insertTextFormat != InsertTextFormat::Missing) 983 Result["insertTextFormat"] = static_cast<int>(CI.insertTextFormat); 984 if (CI.textEdit) 985 Result["textEdit"] = *CI.textEdit; 986 if (!CI.additionalTextEdits.empty()) 987 Result["additionalTextEdits"] = llvm::json::Array(CI.additionalTextEdits); 988 if (CI.deprecated) 989 Result["deprecated"] = CI.deprecated; 990 Result["score"] = CI.score; 991 return std::move(Result); 992 } 993 994 llvm::raw_ostream &operator<<(llvm::raw_ostream &O, const CompletionItem &I) { 995 O << I.label << " - " << toJSON(I); 996 return O; 997 } 998 999 bool operator<(const CompletionItem &L, const CompletionItem &R) { 1000 return (L.sortText.empty() ? L.label : L.sortText) < 1001 (R.sortText.empty() ? R.label : R.sortText); 1002 } 1003 1004 llvm::json::Value toJSON(const CompletionList &L) { 1005 return llvm::json::Object{ 1006 {"isIncomplete", L.isIncomplete}, 1007 {"items", llvm::json::Array(L.items)}, 1008 }; 1009 } 1010 1011 llvm::json::Value toJSON(const ParameterInformation &PI) { 1012 assert((PI.labelOffsets.hasValue() || !PI.labelString.empty()) && 1013 "parameter information label is required"); 1014 llvm::json::Object Result; 1015 if (PI.labelOffsets) 1016 Result["label"] = 1017 llvm::json::Array({PI.labelOffsets->first, PI.labelOffsets->second}); 1018 else 1019 Result["label"] = PI.labelString; 1020 if (!PI.documentation.empty()) 1021 Result["documentation"] = PI.documentation; 1022 return std::move(Result); 1023 } 1024 1025 llvm::json::Value toJSON(const SignatureInformation &SI) { 1026 assert(!SI.label.empty() && "signature information label is required"); 1027 llvm::json::Object Result{ 1028 {"label", SI.label}, 1029 {"parameters", llvm::json::Array(SI.parameters)}, 1030 }; 1031 if (!SI.documentation.empty()) 1032 Result["documentation"] = SI.documentation; 1033 return std::move(Result); 1034 } 1035 1036 llvm::raw_ostream &operator<<(llvm::raw_ostream &O, 1037 const SignatureInformation &I) { 1038 O << I.label << " - " << toJSON(I); 1039 return O; 1040 } 1041 1042 llvm::json::Value toJSON(const SignatureHelp &SH) { 1043 assert(SH.activeSignature >= 0 && 1044 "Unexpected negative value for number of active signatures."); 1045 assert(SH.activeParameter >= 0 && 1046 "Unexpected negative value for active parameter index"); 1047 return llvm::json::Object{ 1048 {"activeSignature", SH.activeSignature}, 1049 {"activeParameter", SH.activeParameter}, 1050 {"signatures", llvm::json::Array(SH.signatures)}, 1051 }; 1052 } 1053 1054 bool fromJSON(const llvm::json::Value &Params, RenameParams &R, 1055 llvm::json::Path P) { 1056 llvm::json::ObjectMapper O(Params, P); 1057 return O && O.map("textDocument", R.textDocument) && 1058 O.map("position", R.position) && O.map("newName", R.newName); 1059 } 1060 1061 llvm::json::Value toJSON(const DocumentHighlight &DH) { 1062 return llvm::json::Object{ 1063 {"range", toJSON(DH.range)}, 1064 {"kind", static_cast<int>(DH.kind)}, 1065 }; 1066 } 1067 1068 llvm::json::Value toJSON(const FileStatus &FStatus) { 1069 return llvm::json::Object{ 1070 {"uri", FStatus.uri}, 1071 {"state", FStatus.state}, 1072 }; 1073 } 1074 1075 constexpr unsigned SemanticTokenEncodingSize = 5; 1076 static llvm::json::Value encodeTokens(llvm::ArrayRef<SemanticToken> Toks) { 1077 llvm::json::Array Result; 1078 for (const auto &Tok : Toks) { 1079 Result.push_back(Tok.deltaLine); 1080 Result.push_back(Tok.deltaStart); 1081 Result.push_back(Tok.length); 1082 Result.push_back(Tok.tokenType); 1083 Result.push_back(Tok.tokenModifiers); 1084 } 1085 assert(Result.size() == SemanticTokenEncodingSize * Toks.size()); 1086 return std::move(Result); 1087 } 1088 1089 bool operator==(const SemanticToken &L, const SemanticToken &R) { 1090 return std::tie(L.deltaLine, L.deltaStart, L.length, L.tokenType, 1091 L.tokenModifiers) == std::tie(R.deltaLine, R.deltaStart, 1092 R.length, R.tokenType, 1093 R.tokenModifiers); 1094 } 1095 1096 llvm::json::Value toJSON(const SemanticTokens &Tokens) { 1097 return llvm::json::Object{{"resultId", Tokens.resultId}, 1098 {"data", encodeTokens(Tokens.tokens)}}; 1099 } 1100 1101 llvm::json::Value toJSON(const SemanticTokensEdit &Edit) { 1102 return llvm::json::Object{ 1103 {"start", SemanticTokenEncodingSize * Edit.startToken}, 1104 {"deleteCount", SemanticTokenEncodingSize * Edit.deleteTokens}, 1105 {"data", encodeTokens(Edit.tokens)}}; 1106 } 1107 1108 llvm::json::Value toJSON(const SemanticTokensOrDelta &TE) { 1109 llvm::json::Object Result{{"resultId", TE.resultId}}; 1110 if (TE.edits) 1111 Result["edits"] = *TE.edits; 1112 if (TE.tokens) 1113 Result["data"] = encodeTokens(*TE.tokens); 1114 return std::move(Result); 1115 } 1116 1117 bool fromJSON(const llvm::json::Value &Params, SemanticTokensParams &R, 1118 llvm::json::Path P) { 1119 llvm::json::ObjectMapper O(Params, P); 1120 return O && O.map("textDocument", R.textDocument); 1121 } 1122 1123 bool fromJSON(const llvm::json::Value &Params, SemanticTokensDeltaParams &R, 1124 llvm::json::Path P) { 1125 llvm::json::ObjectMapper O(Params, P); 1126 return O && O.map("textDocument", R.textDocument) && 1127 O.map("previousResultId", R.previousResultId); 1128 } 1129 1130 llvm::raw_ostream &operator<<(llvm::raw_ostream &O, 1131 const DocumentHighlight &V) { 1132 O << V.range; 1133 if (V.kind == DocumentHighlightKind::Read) 1134 O << "(r)"; 1135 if (V.kind == DocumentHighlightKind::Write) 1136 O << "(w)"; 1137 return O; 1138 } 1139 1140 bool fromJSON(const llvm::json::Value &Params, 1141 DidChangeConfigurationParams &CCP, llvm::json::Path P) { 1142 llvm::json::ObjectMapper O(Params, P); 1143 return O && O.map("settings", CCP.settings); 1144 } 1145 1146 bool fromJSON(const llvm::json::Value &Params, ClangdCompileCommand &CDbUpdate, 1147 llvm::json::Path P) { 1148 llvm::json::ObjectMapper O(Params, P); 1149 return O && O.map("workingDirectory", CDbUpdate.workingDirectory) && 1150 O.map("compilationCommand", CDbUpdate.compilationCommand); 1151 } 1152 1153 bool fromJSON(const llvm::json::Value &Params, ConfigurationSettings &S, 1154 llvm::json::Path P) { 1155 llvm::json::ObjectMapper O(Params, P); 1156 if (!O) 1157 return true; // 'any' type in LSP. 1158 return mapOptOrNull(Params, "compilationDatabaseChanges", 1159 S.compilationDatabaseChanges, P); 1160 } 1161 1162 bool fromJSON(const llvm::json::Value &Params, InitializationOptions &Opts, 1163 llvm::json::Path P) { 1164 llvm::json::ObjectMapper O(Params, P); 1165 if (!O) 1166 return true; // 'any' type in LSP. 1167 1168 return fromJSON(Params, Opts.ConfigSettings, P) && 1169 O.map("compilationDatabasePath", Opts.compilationDatabasePath) && 1170 mapOptOrNull(Params, "fallbackFlags", Opts.fallbackFlags, P) && 1171 mapOptOrNull(Params, "clangdFileStatus", Opts.FileStatus, P); 1172 } 1173 1174 bool fromJSON(const llvm::json::Value &E, TypeHierarchyDirection &Out, 1175 llvm::json::Path P) { 1176 auto T = E.getAsInteger(); 1177 if (!T) 1178 return false; 1179 if (*T < static_cast<int>(TypeHierarchyDirection::Children) || 1180 *T > static_cast<int>(TypeHierarchyDirection::Both)) 1181 return false; 1182 Out = static_cast<TypeHierarchyDirection>(*T); 1183 return true; 1184 } 1185 1186 bool fromJSON(const llvm::json::Value &Params, TypeHierarchyParams &R, 1187 llvm::json::Path P) { 1188 llvm::json::ObjectMapper O(Params, P); 1189 return O && O.map("textDocument", R.textDocument) && 1190 O.map("position", R.position) && O.map("resolve", R.resolve) && 1191 O.map("direction", R.direction); 1192 } 1193 1194 llvm::raw_ostream &operator<<(llvm::raw_ostream &O, 1195 const TypeHierarchyItem &I) { 1196 return O << I.name << " - " << toJSON(I); 1197 } 1198 1199 llvm::json::Value toJSON(const TypeHierarchyItem &I) { 1200 llvm::json::Object Result{{"name", I.name}, 1201 {"kind", static_cast<int>(I.kind)}, 1202 {"range", I.range}, 1203 {"selectionRange", I.selectionRange}, 1204 {"uri", I.uri}}; 1205 1206 if (I.detail) 1207 Result["detail"] = I.detail; 1208 if (I.deprecated) 1209 Result["deprecated"] = I.deprecated; 1210 if (I.parents) 1211 Result["parents"] = I.parents; 1212 if (I.children) 1213 Result["children"] = I.children; 1214 if (I.data) 1215 Result["data"] = I.data; 1216 return std::move(Result); 1217 } 1218 1219 bool fromJSON(const llvm::json::Value &Params, TypeHierarchyItem &I, 1220 llvm::json::Path P) { 1221 llvm::json::ObjectMapper O(Params, P); 1222 1223 // Required fields. 1224 return O && O.map("name", I.name) && O.map("kind", I.kind) && 1225 O.map("uri", I.uri) && O.map("range", I.range) && 1226 O.map("selectionRange", I.selectionRange) && 1227 mapOptOrNull(Params, "detail", I.detail, P) && 1228 mapOptOrNull(Params, "deprecated", I.deprecated, P) && 1229 mapOptOrNull(Params, "parents", I.parents, P) && 1230 mapOptOrNull(Params, "children", I.children, P) && 1231 mapOptOrNull(Params, "data", I.data, P); 1232 } 1233 1234 bool fromJSON(const llvm::json::Value &Params, 1235 ResolveTypeHierarchyItemParams &R, llvm::json::Path P) { 1236 llvm::json::ObjectMapper O(Params, P); 1237 return O && O.map("item", R.item) && O.map("resolve", R.resolve) && 1238 O.map("direction", R.direction); 1239 } 1240 1241 bool fromJSON(const llvm::json::Value &Params, ReferenceContext &R, 1242 llvm::json::Path P) { 1243 llvm::json::ObjectMapper O(Params, P); 1244 return O && O.mapOptional("includeDeclaration", R.includeDeclaration); 1245 } 1246 1247 bool fromJSON(const llvm::json::Value &Params, ReferenceParams &R, 1248 llvm::json::Path P) { 1249 TextDocumentPositionParams &Base = R; 1250 llvm::json::ObjectMapper O(Params, P); 1251 return fromJSON(Params, Base, P) && O && O.mapOptional("context", R.context); 1252 } 1253 1254 llvm::json::Value toJSON(SymbolTag Tag) { 1255 return llvm::json::Value{static_cast<int>(Tag)}; 1256 } 1257 1258 llvm::json::Value toJSON(const CallHierarchyItem &I) { 1259 llvm::json::Object Result{{"name", I.name}, 1260 {"kind", static_cast<int>(I.kind)}, 1261 {"range", I.range}, 1262 {"selectionRange", I.selectionRange}, 1263 {"uri", I.uri}}; 1264 if (!I.tags.empty()) 1265 Result["tags"] = I.tags; 1266 if (!I.detail.empty()) 1267 Result["detail"] = I.detail; 1268 if (!I.data.empty()) 1269 Result["data"] = I.data; 1270 return std::move(Result); 1271 } 1272 1273 bool fromJSON(const llvm::json::Value &Params, CallHierarchyItem &I, 1274 llvm::json::Path P) { 1275 llvm::json::ObjectMapper O(Params, P); 1276 1277 // Populate the required fields only. We don't care about the 1278 // optional fields `Tags` and `Detail` for the purpose of 1279 // client --> server communication. 1280 return O && O.map("name", I.name) && O.map("kind", I.kind) && 1281 O.map("uri", I.uri) && O.map("range", I.range) && 1282 O.map("selectionRange", I.selectionRange) && 1283 mapOptOrNull(Params, "data", I.data, P); 1284 } 1285 1286 bool fromJSON(const llvm::json::Value &Params, 1287 CallHierarchyIncomingCallsParams &C, llvm::json::Path P) { 1288 llvm::json::ObjectMapper O(Params, P); 1289 return O.map("item", C.item); 1290 } 1291 1292 llvm::json::Value toJSON(const CallHierarchyIncomingCall &C) { 1293 return llvm::json::Object{{"from", C.from}, {"fromRanges", C.fromRanges}}; 1294 } 1295 1296 bool fromJSON(const llvm::json::Value &Params, 1297 CallHierarchyOutgoingCallsParams &C, llvm::json::Path P) { 1298 llvm::json::ObjectMapper O(Params, P); 1299 return O.map("item", C.item); 1300 } 1301 1302 llvm::json::Value toJSON(const CallHierarchyOutgoingCall &C) { 1303 return llvm::json::Object{{"to", C.to}, {"fromRanges", C.fromRanges}}; 1304 } 1305 1306 bool fromJSON(const llvm::json::Value &Params, InlayHintsParams &R, 1307 llvm::json::Path P) { 1308 llvm::json::ObjectMapper O(Params, P); 1309 return O && O.map("textDocument", R.textDocument); 1310 } 1311 1312 llvm::json::Value toJSON(InlayHintKind K) { 1313 switch (K) { 1314 case InlayHintKind::ParameterHint: 1315 return "parameter"; 1316 } 1317 llvm_unreachable("Unknown clang.clangd.InlayHintKind"); 1318 } 1319 1320 llvm::json::Value toJSON(const InlayHint &H) { 1321 return llvm::json::Object{ 1322 {"range", H.range}, {"kind", H.kind}, {"label", H.label}}; 1323 } 1324 1325 static const char *toString(OffsetEncoding OE) { 1326 switch (OE) { 1327 case OffsetEncoding::UTF8: 1328 return "utf-8"; 1329 case OffsetEncoding::UTF16: 1330 return "utf-16"; 1331 case OffsetEncoding::UTF32: 1332 return "utf-32"; 1333 case OffsetEncoding::UnsupportedEncoding: 1334 return "unknown"; 1335 } 1336 llvm_unreachable("Unknown clang.clangd.OffsetEncoding"); 1337 } 1338 llvm::json::Value toJSON(const OffsetEncoding &OE) { return toString(OE); } 1339 bool fromJSON(const llvm::json::Value &V, OffsetEncoding &OE, 1340 llvm::json::Path P) { 1341 auto Str = V.getAsString(); 1342 if (!Str) 1343 return false; 1344 OE = llvm::StringSwitch<OffsetEncoding>(*Str) 1345 .Case("utf-8", OffsetEncoding::UTF8) 1346 .Case("utf-16", OffsetEncoding::UTF16) 1347 .Case("utf-32", OffsetEncoding::UTF32) 1348 .Default(OffsetEncoding::UnsupportedEncoding); 1349 return true; 1350 } 1351 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, OffsetEncoding Enc) { 1352 return OS << toString(Enc); 1353 } 1354 1355 bool fromJSON(const llvm::json::Value &Params, SelectionRangeParams &S, 1356 llvm::json::Path P) { 1357 llvm::json::ObjectMapper O(Params, P); 1358 return O && O.map("textDocument", S.textDocument) && 1359 O.map("positions", S.positions); 1360 } 1361 1362 llvm::json::Value toJSON(const SelectionRange &Out) { 1363 if (Out.parent) { 1364 return llvm::json::Object{{"range", Out.range}, 1365 {"parent", toJSON(*Out.parent)}}; 1366 } 1367 return llvm::json::Object{{"range", Out.range}}; 1368 } 1369 1370 bool fromJSON(const llvm::json::Value &Params, DocumentLinkParams &R, 1371 llvm::json::Path P) { 1372 llvm::json::ObjectMapper O(Params, P); 1373 return O && O.map("textDocument", R.textDocument); 1374 } 1375 1376 llvm::json::Value toJSON(const DocumentLink &DocumentLink) { 1377 return llvm::json::Object{ 1378 {"range", DocumentLink.range}, 1379 {"target", DocumentLink.target}, 1380 }; 1381 } 1382 1383 bool fromJSON(const llvm::json::Value &Params, FoldingRangeParams &R, 1384 llvm::json::Path P) { 1385 llvm::json::ObjectMapper O(Params, P); 1386 return O && O.map("textDocument", R.textDocument); 1387 } 1388 1389 llvm::json::Value toJSON(const FoldingRange &Range) { 1390 llvm::json::Object Result{ 1391 {"startLine", Range.startLine}, 1392 {"endLine", Range.endLine}, 1393 }; 1394 if (Range.startCharacter) 1395 Result["startCharacter"] = Range.startCharacter; 1396 if (Range.endCharacter) 1397 Result["endCharacter"] = Range.endCharacter; 1398 if (Range.kind) 1399 Result["kind"] = *Range.kind; 1400 return Result; 1401 } 1402 1403 llvm::json::Value toJSON(const MemoryTree &MT) { 1404 llvm::json::Object Out; 1405 int64_t Total = MT.self(); 1406 Out["_self"] = Total; 1407 for (const auto &Entry : MT.children()) { 1408 auto Child = toJSON(Entry.getSecond()); 1409 Total += *Child.getAsObject()->getInteger("_total"); 1410 Out[Entry.first] = std::move(Child); 1411 } 1412 Out["_total"] = Total; 1413 return Out; 1414 } 1415 1416 bool fromJSON(const llvm::json::Value &Params, ASTParams &R, 1417 llvm::json::Path P) { 1418 llvm::json::ObjectMapper O(Params, P); 1419 return O && O.map("textDocument", R.textDocument) && O.map("range", R.range); 1420 } 1421 1422 llvm::json::Value toJSON(const ASTNode &N) { 1423 llvm::json::Object Result{ 1424 {"role", N.role}, 1425 {"kind", N.kind}, 1426 }; 1427 if (!N.children.empty()) 1428 Result["children"] = N.children; 1429 if (!N.detail.empty()) 1430 Result["detail"] = N.detail; 1431 if (!N.arcana.empty()) 1432 Result["arcana"] = N.arcana; 1433 if (N.range) 1434 Result["range"] = *N.range; 1435 return Result; 1436 } 1437 1438 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const ASTNode &Root) { 1439 std::function<void(const ASTNode &, unsigned)> Print = [&](const ASTNode &N, 1440 unsigned Level) { 1441 OS.indent(2 * Level) << N.role << ": " << N.kind; 1442 if (!N.detail.empty()) 1443 OS << " - " << N.detail; 1444 OS << "\n"; 1445 for (const ASTNode &C : N.children) 1446 Print(C, Level + 1); 1447 }; 1448 Print(Root, 0); 1449 return OS; 1450 } 1451 1452 } // namespace clangd 1453 } // namespace clang 1454