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