1 //===--- CodeComplete.cpp ---------------------------------------*- C++-*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===---------------------------------------------------------------------===// 9 // 10 // AST-based completions are provided using the completion hooks in Sema. 11 // 12 // Signature help works in a similar way as code completion, but it is simpler 13 // as there are typically fewer candidates. 14 // 15 //===---------------------------------------------------------------------===// 16 17 #include "CodeComplete.h" 18 #include "CodeCompletionStrings.h" 19 #include "Compiler.h" 20 #include "FuzzyMatch.h" 21 #include "Logger.h" 22 #include "index/Index.h" 23 #include "clang/Frontend/CompilerInstance.h" 24 #include "clang/Frontend/FrontendActions.h" 25 #include "clang/Sema/CodeCompleteConsumer.h" 26 #include "clang/Sema/Sema.h" 27 #include "llvm/Support/Format.h" 28 #include <queue> 29 30 namespace clang { 31 namespace clangd { 32 namespace { 33 34 CompletionItemKind toCompletionItemKind(CXCursorKind CursorKind) { 35 switch (CursorKind) { 36 case CXCursor_MacroInstantiation: 37 case CXCursor_MacroDefinition: 38 return CompletionItemKind::Text; 39 case CXCursor_CXXMethod: 40 case CXCursor_Destructor: 41 return CompletionItemKind::Method; 42 case CXCursor_FunctionDecl: 43 case CXCursor_FunctionTemplate: 44 return CompletionItemKind::Function; 45 case CXCursor_Constructor: 46 return CompletionItemKind::Constructor; 47 case CXCursor_FieldDecl: 48 return CompletionItemKind::Field; 49 case CXCursor_VarDecl: 50 case CXCursor_ParmDecl: 51 return CompletionItemKind::Variable; 52 // FIXME(ioeric): use LSP struct instead of class when it is suppoted in the 53 // protocol. 54 case CXCursor_StructDecl: 55 case CXCursor_ClassDecl: 56 case CXCursor_UnionDecl: 57 case CXCursor_ClassTemplate: 58 case CXCursor_ClassTemplatePartialSpecialization: 59 return CompletionItemKind::Class; 60 case CXCursor_Namespace: 61 case CXCursor_NamespaceAlias: 62 case CXCursor_NamespaceRef: 63 return CompletionItemKind::Module; 64 case CXCursor_EnumConstantDecl: 65 return CompletionItemKind::Value; 66 case CXCursor_EnumDecl: 67 return CompletionItemKind::Enum; 68 // FIXME(ioeric): figure out whether reference is the right type for aliases. 69 case CXCursor_TypeAliasDecl: 70 case CXCursor_TypeAliasTemplateDecl: 71 case CXCursor_TypedefDecl: 72 case CXCursor_MemberRef: 73 case CXCursor_TypeRef: 74 return CompletionItemKind::Reference; 75 default: 76 return CompletionItemKind::Missing; 77 } 78 } 79 80 CompletionItemKind 81 toCompletionItemKind(CodeCompletionResult::ResultKind ResKind, 82 CXCursorKind CursorKind) { 83 switch (ResKind) { 84 case CodeCompletionResult::RK_Declaration: 85 return toCompletionItemKind(CursorKind); 86 case CodeCompletionResult::RK_Keyword: 87 return CompletionItemKind::Keyword; 88 case CodeCompletionResult::RK_Macro: 89 return CompletionItemKind::Text; // unfortunately, there's no 'Macro' 90 // completion items in LSP. 91 case CodeCompletionResult::RK_Pattern: 92 return CompletionItemKind::Snippet; 93 } 94 llvm_unreachable("Unhandled CodeCompletionResult::ResultKind."); 95 } 96 97 CompletionItemKind toCompletionItemKind(index::SymbolKind Kind) { 98 using SK = index::SymbolKind; 99 switch (Kind) { 100 case SK::Unknown: 101 return CompletionItemKind::Missing; 102 case SK::Module: 103 case SK::Namespace: 104 case SK::NamespaceAlias: 105 return CompletionItemKind::Module; 106 case SK::Macro: 107 return CompletionItemKind::Text; 108 case SK::Enum: 109 return CompletionItemKind::Enum; 110 // FIXME(ioeric): use LSP struct instead of class when it is suppoted in the 111 // protocol. 112 case SK::Struct: 113 case SK::Class: 114 case SK::Protocol: 115 case SK::Extension: 116 case SK::Union: 117 return CompletionItemKind::Class; 118 // FIXME(ioeric): figure out whether reference is the right type for aliases. 119 case SK::TypeAlias: 120 case SK::Using: 121 return CompletionItemKind::Reference; 122 case SK::Function: 123 // FIXME(ioeric): this should probably be an operator. This should be fixed 124 // when `Operator` is support type in the protocol. 125 case SK::ConversionFunction: 126 return CompletionItemKind::Function; 127 case SK::Variable: 128 case SK::Parameter: 129 return CompletionItemKind::Variable; 130 case SK::Field: 131 return CompletionItemKind::Field; 132 // FIXME(ioeric): use LSP enum constant when it is supported in the protocol. 133 case SK::EnumConstant: 134 return CompletionItemKind::Value; 135 case SK::InstanceMethod: 136 case SK::ClassMethod: 137 case SK::StaticMethod: 138 case SK::Destructor: 139 return CompletionItemKind::Method; 140 case SK::InstanceProperty: 141 case SK::ClassProperty: 142 case SK::StaticProperty: 143 return CompletionItemKind::Property; 144 case SK::Constructor: 145 return CompletionItemKind::Constructor; 146 } 147 llvm_unreachable("Unhandled clang::index::SymbolKind."); 148 } 149 150 /// Get the optional chunk as a string. This function is possibly recursive. 151 /// 152 /// The parameter info for each parameter is appended to the Parameters. 153 std::string 154 getOptionalParameters(const CodeCompletionString &CCS, 155 std::vector<ParameterInformation> &Parameters) { 156 std::string Result; 157 for (const auto &Chunk : CCS) { 158 switch (Chunk.Kind) { 159 case CodeCompletionString::CK_Optional: 160 assert(Chunk.Optional && 161 "Expected the optional code completion string to be non-null."); 162 Result += getOptionalParameters(*Chunk.Optional, Parameters); 163 break; 164 case CodeCompletionString::CK_VerticalSpace: 165 break; 166 case CodeCompletionString::CK_Placeholder: 167 // A string that acts as a placeholder for, e.g., a function call 168 // argument. 169 // Intentional fallthrough here. 170 case CodeCompletionString::CK_CurrentParameter: { 171 // A piece of text that describes the parameter that corresponds to 172 // the code-completion location within a function call, message send, 173 // macro invocation, etc. 174 Result += Chunk.Text; 175 ParameterInformation Info; 176 Info.label = Chunk.Text; 177 Parameters.push_back(std::move(Info)); 178 break; 179 } 180 default: 181 Result += Chunk.Text; 182 break; 183 } 184 } 185 return Result; 186 } 187 188 /// A scored code completion result. 189 /// It may be promoted to a CompletionItem if it's among the top-ranked results. 190 /// 191 /// We score candidates by multiplying the symbolScore ("quality" of the result) 192 /// with the filterScore (how well it matched the query). 193 /// This is sensitive to the distribution of both component scores! 194 struct CompletionCandidate { 195 CompletionCandidate(CodeCompletionResult &Result, float FilterScore) 196 : Result(&Result) { 197 Scores.symbolScore = score(Result); // Higher is better. 198 Scores.filterScore = FilterScore; // 0-1, higher is better. 199 Scores.finalScore = Scores.symbolScore * Scores.filterScore; 200 } 201 202 CodeCompletionResult *Result; 203 CompletionItemScores Scores; 204 205 // Comparison reflects rank: better candidates are smaller. 206 bool operator<(const CompletionCandidate &C) const { 207 if (Scores.finalScore != C.Scores.finalScore) 208 return Scores.finalScore > C.Scores.finalScore; 209 return *Result < *C.Result; 210 } 211 212 // Returns a string that sorts in the same order as operator<, for LSP. 213 // Conceptually, this is [-Score, Name]. We convert -Score to an integer, and 214 // hex-encode it for readability. Example: [0.5, "foo"] -> "41000000foo" 215 std::string sortText() const { 216 std::string S, NameStorage; 217 llvm::raw_string_ostream OS(S); 218 write_hex(OS, encodeFloat(-Scores.finalScore), llvm::HexPrintStyle::Lower, 219 /*Width=*/2 * sizeof(Scores.finalScore)); 220 OS << Result->getOrderedName(NameStorage); 221 return OS.str(); 222 } 223 224 private: 225 static float score(const CodeCompletionResult &Result) { 226 // Priority 80 is a really bad score. 227 float Score = 1 - std::min<float>(80, Result.Priority) / 80; 228 229 switch (static_cast<CXAvailabilityKind>(Result.Availability)) { 230 case CXAvailability_Available: 231 // No penalty. 232 break; 233 case CXAvailability_Deprecated: 234 Score *= 0.1f; 235 break; 236 case CXAvailability_NotAccessible: 237 case CXAvailability_NotAvailable: 238 Score = 0; 239 break; 240 } 241 return Score; 242 } 243 244 // Produces an integer that sorts in the same order as F. 245 // That is: a < b <==> encodeFloat(a) < encodeFloat(b). 246 static uint32_t encodeFloat(float F) { 247 static_assert(std::numeric_limits<float>::is_iec559, ""); 248 static_assert(sizeof(float) == sizeof(uint32_t), ""); 249 constexpr uint32_t TopBit = ~(~uint32_t{0} >> 1); 250 251 // Get the bits of the float. Endianness is the same as for integers. 252 uint32_t U; 253 memcpy(&U, &F, sizeof(float)); 254 // IEEE 754 floats compare like sign-magnitude integers. 255 if (U & TopBit) // Negative float. 256 return 0 - U; // Map onto the low half of integers, order reversed. 257 return U + TopBit; // Positive floats map onto the high half of integers. 258 } 259 }; 260 261 /// \brief Information about the scope specifier in the qualified-id code 262 /// completion (e.g. "ns::ab?"). 263 struct SpecifiedScope { 264 /// The scope specifier as written. For example, for completion "ns::ab?", the 265 /// written scope specifier is "ns". 266 std::string Written; 267 // If this scope specifier is recognized in Sema (e.g. as a namespace 268 // context), this will be set to the fully qualfied name of the corresponding 269 // context. 270 std::string Resolved; 271 }; 272 273 /// \brief Information from sema about (parital) symbol names to be completed. 274 /// For example, for completion "ns::ab^", this stores the scope specifier 275 /// "ns::" and the completion filter text "ab". 276 struct NameToComplete { 277 // The partial identifier being completed, without qualifier. 278 std::string Filter; 279 280 /// This is set if the completion is for qualified IDs, e.g. "abc::x^". 281 llvm::Optional<SpecifiedScope> SSInfo; 282 }; 283 284 SpecifiedScope extraCompletionScope(Sema &S, const CXXScopeSpec &SS); 285 286 class CompletionItemsCollector : public CodeCompleteConsumer { 287 public: 288 CompletionItemsCollector(const CodeCompleteOptions &CodeCompleteOpts, 289 CompletionList &Items, NameToComplete &CompletedName) 290 : CodeCompleteConsumer(CodeCompleteOpts.getClangCompleteOpts(), 291 /*OutputIsBinary=*/false), 292 ClangdOpts(CodeCompleteOpts), Items(Items), 293 Allocator(std::make_shared<clang::GlobalCodeCompletionAllocator>()), 294 CCTUInfo(Allocator), CompletedName(CompletedName), 295 EnableSnippets(CodeCompleteOpts.EnableSnippets) {} 296 297 void ProcessCodeCompleteResults(Sema &S, CodeCompletionContext Context, 298 CodeCompletionResult *Results, 299 unsigned NumResults) override final { 300 FuzzyMatcher Filter(S.getPreprocessor().getCodeCompletionFilter()); 301 if (auto SS = Context.getCXXScopeSpecifier()) 302 CompletedName.SSInfo = extraCompletionScope(S, **SS); 303 304 CompletedName.Filter = S.getPreprocessor().getCodeCompletionFilter(); 305 std::priority_queue<CompletionCandidate> Candidates; 306 for (unsigned I = 0; I < NumResults; ++I) { 307 auto &Result = Results[I]; 308 // We drop hidden items, as they cannot be found by the lookup after 309 // inserting the corresponding completion item and only produce noise and 310 // duplicates in the completion list. However, there is one exception. If 311 // Result has a Qualifier which is non-informative, we can refer to an 312 // item by adding that qualifier, so we don't filter out this item. 313 if (Result.Hidden && (!Result.Qualifier || Result.QualifierIsInformative)) 314 continue; 315 if (!ClangdOpts.IncludeIneligibleResults && 316 (Result.Availability == CXAvailability_NotAvailable || 317 Result.Availability == CXAvailability_NotAccessible)) 318 continue; 319 auto FilterScore = fuzzyMatch(S, Context, Filter, Result); 320 if (!FilterScore) 321 continue; 322 Candidates.emplace(Result, *FilterScore); 323 if (ClangdOpts.Limit && Candidates.size() > ClangdOpts.Limit) { 324 Candidates.pop(); 325 Items.isIncomplete = true; 326 } 327 } 328 while (!Candidates.empty()) { 329 auto &Candidate = Candidates.top(); 330 const auto *CCS = Candidate.Result->CreateCodeCompletionString( 331 S, Context, *Allocator, CCTUInfo, 332 CodeCompleteOpts.IncludeBriefComments); 333 assert(CCS && "Expected the CodeCompletionString to be non-null"); 334 Items.items.push_back(ProcessCodeCompleteResult(Candidate, *CCS)); 335 Candidates.pop(); 336 } 337 std::reverse(Items.items.begin(), Items.items.end()); 338 } 339 340 GlobalCodeCompletionAllocator &getAllocator() override { return *Allocator; } 341 342 CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; } 343 344 private: 345 llvm::Optional<float> fuzzyMatch(Sema &S, const CodeCompletionContext &CCCtx, 346 FuzzyMatcher &Filter, 347 CodeCompletionResult Result) { 348 switch (Result.Kind) { 349 case CodeCompletionResult::RK_Declaration: 350 if (auto *ID = Result.Declaration->getIdentifier()) 351 return Filter.match(ID->getName()); 352 break; 353 case CodeCompletionResult::RK_Keyword: 354 return Filter.match(Result.Keyword); 355 case CodeCompletionResult::RK_Macro: 356 return Filter.match(Result.Macro->getName()); 357 case CodeCompletionResult::RK_Pattern: 358 return Filter.match(Result.Pattern->getTypedText()); 359 } 360 auto *CCS = Result.CreateCodeCompletionString( 361 S, CCCtx, *Allocator, CCTUInfo, /*IncludeBriefComments=*/false); 362 return Filter.match(CCS->getTypedText()); 363 } 364 365 CompletionItem 366 ProcessCodeCompleteResult(const CompletionCandidate &Candidate, 367 const CodeCompletionString &CCS) const { 368 369 // Adjust this to InsertTextFormat::Snippet iff we encounter a 370 // CK_Placeholder chunk in SnippetCompletionItemsCollector. 371 CompletionItem Item; 372 373 Item.documentation = getDocumentation(CCS); 374 Item.sortText = Candidate.sortText(); 375 Item.scoreInfo = Candidate.Scores; 376 377 Item.detail = getDetail(CCS); 378 Item.filterText = getFilterText(CCS); 379 getLabelAndInsertText(CCS, &Item.label, &Item.insertText, EnableSnippets); 380 381 Item.insertTextFormat = EnableSnippets ? InsertTextFormat::Snippet 382 : InsertTextFormat::PlainText; 383 384 // Fill in the kind field of the CompletionItem. 385 Item.kind = toCompletionItemKind(Candidate.Result->Kind, 386 Candidate.Result->CursorKind); 387 388 return Item; 389 } 390 391 CodeCompleteOptions ClangdOpts; 392 CompletionList &Items; 393 std::shared_ptr<clang::GlobalCodeCompletionAllocator> Allocator; 394 CodeCompletionTUInfo CCTUInfo; 395 NameToComplete &CompletedName; 396 bool EnableSnippets; 397 }; // CompletionItemsCollector 398 399 class SignatureHelpCollector final : public CodeCompleteConsumer { 400 401 public: 402 SignatureHelpCollector(const clang::CodeCompleteOptions &CodeCompleteOpts, 403 SignatureHelp &SigHelp) 404 : CodeCompleteConsumer(CodeCompleteOpts, /*OutputIsBinary=*/false), 405 SigHelp(SigHelp), 406 Allocator(std::make_shared<clang::GlobalCodeCompletionAllocator>()), 407 CCTUInfo(Allocator) {} 408 409 void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg, 410 OverloadCandidate *Candidates, 411 unsigned NumCandidates) override { 412 SigHelp.signatures.reserve(NumCandidates); 413 // FIXME(rwols): How can we determine the "active overload candidate"? 414 // Right now the overloaded candidates seem to be provided in a "best fit" 415 // order, so I'm not too worried about this. 416 SigHelp.activeSignature = 0; 417 assert(CurrentArg <= (unsigned)std::numeric_limits<int>::max() && 418 "too many arguments"); 419 SigHelp.activeParameter = static_cast<int>(CurrentArg); 420 for (unsigned I = 0; I < NumCandidates; ++I) { 421 const auto &Candidate = Candidates[I]; 422 const auto *CCS = Candidate.CreateSignatureString( 423 CurrentArg, S, *Allocator, CCTUInfo, true); 424 assert(CCS && "Expected the CodeCompletionString to be non-null"); 425 SigHelp.signatures.push_back(ProcessOverloadCandidate(Candidate, *CCS)); 426 } 427 } 428 429 GlobalCodeCompletionAllocator &getAllocator() override { return *Allocator; } 430 431 CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; } 432 433 private: 434 // FIXME(ioeric): consider moving CodeCompletionString logic here to 435 // CompletionString.h. 436 SignatureInformation 437 ProcessOverloadCandidate(const OverloadCandidate &Candidate, 438 const CodeCompletionString &CCS) const { 439 SignatureInformation Result; 440 const char *ReturnType = nullptr; 441 442 Result.documentation = getDocumentation(CCS); 443 444 for (const auto &Chunk : CCS) { 445 switch (Chunk.Kind) { 446 case CodeCompletionString::CK_ResultType: 447 // A piece of text that describes the type of an entity or, 448 // for functions and methods, the return type. 449 assert(!ReturnType && "Unexpected CK_ResultType"); 450 ReturnType = Chunk.Text; 451 break; 452 case CodeCompletionString::CK_Placeholder: 453 // A string that acts as a placeholder for, e.g., a function call 454 // argument. 455 // Intentional fallthrough here. 456 case CodeCompletionString::CK_CurrentParameter: { 457 // A piece of text that describes the parameter that corresponds to 458 // the code-completion location within a function call, message send, 459 // macro invocation, etc. 460 Result.label += Chunk.Text; 461 ParameterInformation Info; 462 Info.label = Chunk.Text; 463 Result.parameters.push_back(std::move(Info)); 464 break; 465 } 466 case CodeCompletionString::CK_Optional: { 467 // The rest of the parameters are defaulted/optional. 468 assert(Chunk.Optional && 469 "Expected the optional code completion string to be non-null."); 470 Result.label += 471 getOptionalParameters(*Chunk.Optional, Result.parameters); 472 break; 473 } 474 case CodeCompletionString::CK_VerticalSpace: 475 break; 476 default: 477 Result.label += Chunk.Text; 478 break; 479 } 480 } 481 if (ReturnType) { 482 Result.label += " -> "; 483 Result.label += ReturnType; 484 } 485 return Result; 486 } 487 488 SignatureHelp &SigHelp; 489 std::shared_ptr<clang::GlobalCodeCompletionAllocator> Allocator; 490 CodeCompletionTUInfo CCTUInfo; 491 492 }; // SignatureHelpCollector 493 494 bool invokeCodeComplete(const Context &Ctx, 495 std::unique_ptr<CodeCompleteConsumer> Consumer, 496 const clang::CodeCompleteOptions &Options, 497 PathRef FileName, 498 const tooling::CompileCommand &Command, 499 PrecompiledPreamble const *Preamble, StringRef Contents, 500 Position Pos, IntrusiveRefCntPtr<vfs::FileSystem> VFS, 501 std::shared_ptr<PCHContainerOperations> PCHs) { 502 std::vector<const char *> ArgStrs; 503 for (const auto &S : Command.CommandLine) 504 ArgStrs.push_back(S.c_str()); 505 506 VFS->setCurrentWorkingDirectory(Command.Directory); 507 508 IgnoreDiagnostics DummyDiagsConsumer; 509 auto CI = createInvocationFromCommandLine( 510 ArgStrs, 511 CompilerInstance::createDiagnostics(new DiagnosticOptions, 512 &DummyDiagsConsumer, false), 513 VFS); 514 assert(CI && "Couldn't create CompilerInvocation"); 515 CI->getFrontendOpts().DisableFree = false; 516 517 std::unique_ptr<llvm::MemoryBuffer> ContentsBuffer = 518 llvm::MemoryBuffer::getMemBufferCopy(Contents, FileName); 519 520 // Attempt to reuse the PCH from precompiled preamble, if it was built. 521 if (Preamble) { 522 auto Bounds = 523 ComputePreambleBounds(*CI->getLangOpts(), ContentsBuffer.get(), 0); 524 if (!Preamble->CanReuse(*CI, ContentsBuffer.get(), Bounds, VFS.get())) 525 Preamble = nullptr; 526 } 527 528 auto Clang = prepareCompilerInstance( 529 std::move(CI), Preamble, std::move(ContentsBuffer), std::move(PCHs), 530 std::move(VFS), DummyDiagsConsumer); 531 auto &DiagOpts = Clang->getDiagnosticOpts(); 532 DiagOpts.IgnoreWarnings = true; 533 534 auto &FrontendOpts = Clang->getFrontendOpts(); 535 FrontendOpts.SkipFunctionBodies = true; 536 FrontendOpts.CodeCompleteOpts = Options; 537 FrontendOpts.CodeCompletionAt.FileName = FileName; 538 FrontendOpts.CodeCompletionAt.Line = Pos.line + 1; 539 FrontendOpts.CodeCompletionAt.Column = Pos.character + 1; 540 541 Clang->setCodeCompletionConsumer(Consumer.release()); 542 543 SyntaxOnlyAction Action; 544 if (!Action.BeginSourceFile(*Clang, Clang->getFrontendOpts().Inputs[0])) { 545 log(Ctx, 546 "BeginSourceFile() failed when running codeComplete for " + FileName); 547 return false; 548 } 549 if (!Action.Execute()) { 550 log(Ctx, "Execute() failed when running codeComplete for " + FileName); 551 return false; 552 } 553 554 Action.EndSourceFile(); 555 556 return true; 557 } 558 559 CompletionItem indexCompletionItem(const Symbol &Sym, llvm::StringRef Filter, 560 const SpecifiedScope &SSInfo, 561 llvm::StringRef DebuggingLabel = "") { 562 CompletionItem Item; 563 Item.kind = toCompletionItemKind(Sym.SymInfo.Kind); 564 // Add DebuggingLabel to the completion results if DebuggingLabel is not 565 // empty. 566 // 567 // For symbols from static index, there are prefix "[G]" in the 568 // results (which is used for debugging purpose). 569 // So completion list will be like: 570 // clang::symbol_from_dynamic_index 571 // [G]clang::symbol_from_static_index 572 // 573 // FIXME: Find out a better way to show the index source. 574 if (!DebuggingLabel.empty()) { 575 llvm::raw_string_ostream Label(Item.label); 576 Label << llvm::format("[%s]%s", DebuggingLabel.str().c_str(), 577 Sym.Name.str().c_str()); 578 } else { 579 Item.label = Sym.Name; 580 } 581 // FIXME(ioeric): support inserting/replacing scope qualifiers. 582 583 // FIXME(ioeric): support snippets. 584 Item.insertText = Sym.CompletionPlainInsertText; 585 Item.insertTextFormat = InsertTextFormat::PlainText; 586 Item.filterText = Sym.Name; 587 588 // FIXME(ioeric): sort symbols appropriately. 589 Item.sortText = ""; 590 591 if (Sym.Detail) { 592 Item.documentation = Sym.Detail->Documentation; 593 Item.detail = Sym.Detail->CompletionDetail; 594 } 595 596 return Item; 597 } 598 599 void completeWithIndex(const Context &Ctx, const SymbolIndex &Index, 600 llvm::StringRef Code, const SpecifiedScope &SSInfo, 601 llvm::StringRef Filter, CompletionList *Items, 602 llvm::StringRef DebuggingLabel = "") { 603 FuzzyFindRequest Req; 604 Req.Query = Filter; 605 // FIXME(ioeric): add more possible scopes based on using namespaces and 606 // containing namespaces. 607 StringRef Scope = SSInfo.Resolved.empty() ? SSInfo.Written : SSInfo.Resolved; 608 Req.Scopes = {Scope.trim(':').str()}; 609 610 Items->isIncomplete |= !Index.fuzzyFind(Ctx, Req, [&](const Symbol &Sym) { 611 Items->items.push_back( 612 indexCompletionItem(Sym, Filter, SSInfo, DebuggingLabel)); 613 }); 614 } 615 616 SpecifiedScope extraCompletionScope(Sema &S, const CXXScopeSpec &SS) { 617 SpecifiedScope Info; 618 auto &SM = S.getSourceManager(); 619 auto SpecifierRange = SS.getRange(); 620 Info.Written = Lexer::getSourceText( 621 CharSourceRange::getCharRange(SpecifierRange), SM, clang::LangOptions()); 622 if (SS.isValid()) { 623 DeclContext *DC = S.computeDeclContext(SS); 624 if (auto *NS = llvm::dyn_cast<NamespaceDecl>(DC)) { 625 Info.Resolved = NS->getQualifiedNameAsString(); 626 } else if (llvm::dyn_cast<TranslationUnitDecl>(DC) != nullptr) { 627 Info.Resolved = "::"; 628 // Sema does not include the suffix "::" in the range of SS, so we add 629 // it back here. 630 Info.Written = "::"; 631 } 632 } 633 return Info; 634 } 635 636 } // namespace 637 638 clang::CodeCompleteOptions CodeCompleteOptions::getClangCompleteOpts() const { 639 clang::CodeCompleteOptions Result; 640 Result.IncludeCodePatterns = EnableSnippets && IncludeCodePatterns; 641 Result.IncludeMacros = IncludeMacros; 642 Result.IncludeGlobals = IncludeGlobals; 643 Result.IncludeBriefComments = IncludeBriefComments; 644 645 // When an is used, Sema is responsible for completing the main file, 646 // the index can provide results from the preamble. 647 // Tell Sema not to deserialize the preamble to look for results. 648 Result.LoadExternal = !Index; 649 650 return Result; 651 } 652 653 CompletionList codeComplete(const Context &Ctx, PathRef FileName, 654 const tooling::CompileCommand &Command, 655 PrecompiledPreamble const *Preamble, 656 StringRef Contents, Position Pos, 657 IntrusiveRefCntPtr<vfs::FileSystem> VFS, 658 std::shared_ptr<PCHContainerOperations> PCHs, 659 CodeCompleteOptions Opts) { 660 CompletionList Results; 661 NameToComplete CompletedName; 662 auto Consumer = 663 llvm::make_unique<CompletionItemsCollector>(Opts, Results, CompletedName); 664 invokeCodeComplete(Ctx, std::move(Consumer), Opts.getClangCompleteOpts(), 665 FileName, Command, Preamble, Contents, Pos, std::move(VFS), 666 std::move(PCHs)); 667 668 // Got scope specifier (ns::f^) for code completion from sema, try to query 669 // global symbols from indexes. 670 // FIXME: merge with Sema results, and respect limits. 671 if (CompletedName.SSInfo && Opts.Index) 672 completeWithIndex(Ctx, *Opts.Index, Contents, *CompletedName.SSInfo, 673 CompletedName.Filter, &Results, /*DebuggingLabel=*/"I"); 674 return Results; 675 } 676 677 SignatureHelp signatureHelp(const Context &Ctx, PathRef FileName, 678 const tooling::CompileCommand &Command, 679 PrecompiledPreamble const *Preamble, 680 StringRef Contents, Position Pos, 681 IntrusiveRefCntPtr<vfs::FileSystem> VFS, 682 std::shared_ptr<PCHContainerOperations> PCHs) { 683 SignatureHelp Result; 684 clang::CodeCompleteOptions Options; 685 Options.IncludeGlobals = false; 686 Options.IncludeMacros = false; 687 Options.IncludeCodePatterns = false; 688 Options.IncludeBriefComments = true; 689 invokeCodeComplete(Ctx, 690 llvm::make_unique<SignatureHelpCollector>(Options, Result), 691 Options, FileName, Command, Preamble, Contents, Pos, 692 std::move(VFS), std::move(PCHs)); 693 return Result; 694 } 695 696 } // namespace clangd 697 } // namespace clang 698