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