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