43 #include "clang/AST/Decl.h"
44 #include "clang/AST/DeclBase.h"
45 #include "clang/Basic/CharInfo.h"
46 #include "clang/Basic/LangOptions.h"
47 #include "clang/Basic/SourceLocation.h"
48 #include "clang/Basic/TokenKinds.h"
49 #include "clang/Format/Format.h"
50 #include "clang/Frontend/CompilerInstance.h"
51 #include "clang/Frontend/FrontendActions.h"
52 #include "clang/Lex/ExternalPreprocessorSource.h"
53 #include "clang/Lex/Lexer.h"
54 #include "clang/Lex/Preprocessor.h"
55 #include "clang/Lex/PreprocessorOptions.h"
56 #include "clang/Sema/CodeCompleteConsumer.h"
57 #include "clang/Sema/DeclSpec.h"
58 #include "clang/Sema/Sema.h"
59 #include "llvm/ADT/ArrayRef.h"
60 #include "llvm/ADT/SmallVector.h"
61 #include "llvm/ADT/StringExtras.h"
62 #include "llvm/ADT/StringRef.h"
63 #include "llvm/Support/Casting.h"
64 #include "llvm/Support/Compiler.h"
65 #include "llvm/Support/Debug.h"
66 #include "llvm/Support/Error.h"
67 #include "llvm/Support/FormatVariadic.h"
68 #include "llvm/Support/ScopedPrinter.h"
76 #define DEBUG_TYPE "CodeComplete"
81 #if CLANGD_DECISION_FOREST
99 case SK::NamespaceAlias:
123 case SK::ConversionFunction:
127 case SK::NonTypeTemplateParm:
131 case SK::EnumConstant:
133 case SK::InstanceMethod:
134 case SK::ClassMethod:
135 case SK::StaticMethod:
138 case SK::InstanceProperty:
139 case SK::ClassProperty:
140 case SK::StaticProperty:
142 case SK::Constructor:
144 case SK::TemplateTypeParm:
145 case SK::TemplateTemplateParm:
150 llvm_unreachable(
"Unhandled clang::index::SymbolKind.");
154 toCompletionItemKind(CodeCompletionResult::ResultKind ResKind,
155 const NamedDecl *
Decl,
159 if (CtxKind == CodeCompletionContext::CCC_IncludedFile)
162 case CodeCompletionResult::RK_Declaration:
163 llvm_unreachable(
"RK_Declaration without Decl");
164 case CodeCompletionResult::RK_Keyword:
166 case CodeCompletionResult::RK_Macro:
169 case CodeCompletionResult::RK_Pattern:
172 llvm_unreachable(
"Unhandled CodeCompletionResult::ResultKind.");
176 MarkupContent renderDoc(
const markup::Document &Doc,
MarkupKind Kind) {
177 MarkupContent Result;
181 Result.value.append(Doc.asPlainText());
184 Result.value.append(Doc.asMarkdown());
192 return Symbol::IncludeDirective::Include;
197 struct RawIdentifier {
204 struct CompletionCandidate {
205 llvm::StringRef
Name;
214 size_t overloadSet(
const CodeCompleteOptions &Opts, llvm::StringRef
FileName,
215 IncludeInserter *Inserter)
const {
216 if (!Opts.BundleOverloads.value_or(
false))
222 std::string HeaderForHash;
224 if (
auto Header = headerToInsertIfAllowed(Opts)) {
227 Inserter->calculateIncludePath(*HeaderFile,
FileName))
228 HeaderForHash = *Spelled;
230 vlog(
"Code completion header path manipulation failed {0}",
231 HeaderFile.takeError());
236 llvm::SmallString<256> Scratch;
239 case index::SymbolKind::ClassMethod:
240 case index::SymbolKind::InstanceMethod:
241 case index::SymbolKind::StaticMethod:
243 llvm_unreachable(
"Don't expect members from index in code completion");
247 case index::SymbolKind::Function:
250 return llvm::hash_combine(
260 if (!
D || !
D->isFunctionOrFunctionTemplate())
263 llvm::raw_svector_ostream
OS(Scratch);
264 D->printQualifiedName(
OS);
266 return llvm::hash_combine(Scratch, HeaderForHash);
273 std::optional<llvm::StringRef>
274 headerToInsertIfAllowed(
const CodeCompleteOptions &Opts)
const {
281 auto &SM =
SemaResult->Declaration->getASTContext().getSourceManager();
283 if (SM.isInMainFile(SM.getExpansionLoc(RD->getBeginLoc())))
293 using Bundle = llvm::SmallVector<CompletionCandidate, 4>;
296 std::pair<CompletionCandidate::Bundle, CodeCompletion::Scores>;
297 struct ScoredBundleGreater {
298 bool operator()(
const ScoredBundle &L,
const ScoredBundle &R) {
299 if (L.second.Total != R.second.Total)
300 return L.second.Total > R.second.Total;
301 return L.first.front().Name <
302 R.first.front().Name;
313 struct CodeCompletionBuilder {
314 CodeCompletionBuilder(ASTContext *ASTCtx,
const CompletionCandidate &
C,
315 CodeCompletionString *SemaCCS,
316 llvm::ArrayRef<std::string> QueryScopes,
317 const IncludeInserter &Includes,
320 const CodeCompleteOptions &Opts,
321 bool IsUsingDeclaration, tok::TokenKind NextTokenKind)
323 EnableFunctionArgSnippets(Opts.EnableFunctionArgSnippets),
324 IsUsingDeclaration(IsUsingDeclaration), NextTokenKind(NextTokenKind) {
325 Completion.Deprecated =
true;
330 Completion.Name = std::string(llvm::StringRef(SemaCCS->getTypedText()));
331 Completion.FilterText = SemaCCS->getAllTypedText();
332 if (Completion.Scope.empty()) {
333 if ((
C.SemaResult->Kind == CodeCompletionResult::RK_Declaration) ||
334 (
C.SemaResult->Kind == CodeCompletionResult::RK_Pattern))
335 if (
const auto *
D =
C.SemaResult->getDeclaration())
336 if (
const auto *ND = dyn_cast<NamedDecl>(
D))
337 Completion.Scope = std::string(
340 Completion.Kind = toCompletionItemKind(
341 C.SemaResult->Kind,
C.SemaResult->Declaration, ContextKind);
345 Completion.Name.back() ==
'/')
347 for (
const auto &
FixIt :
C.SemaResult->FixIts) {
349 FixIt, ASTCtx->getSourceManager(), ASTCtx->getLangOpts()));
351 llvm::sort(Completion.FixIts, [](
const TextEdit &
X,
const TextEdit &Y) {
352 return std::tie(X.range.start.line, X.range.start.character) <
353 std::tie(Y.range.start.line, Y.range.start.character);
357 Completion.Origin |=
C.IndexResult->Origin;
358 if (Completion.Scope.empty())
359 Completion.Scope = std::string(
C.IndexResult->Scope);
361 Completion.Kind = toCompletionItemKind(
C.IndexResult->SymInfo.Kind);
362 if (Completion.Name.empty())
363 Completion.Name = std::string(
C.IndexResult->Name);
364 if (Completion.FilterText.empty())
365 Completion.FilterText = Completion.Name;
368 if (Completion.RequiredQualifier.empty() && !
C.SemaResult) {
369 llvm::StringRef ShortestQualifier =
C.IndexResult->Scope;
370 for (llvm::StringRef Scope : QueryScopes) {
371 llvm::StringRef Qualifier =
C.IndexResult->Scope;
372 if (Qualifier.consume_front(Scope) &&
373 Qualifier.size() < ShortestQualifier.size())
374 ShortestQualifier = Qualifier;
376 Completion.RequiredQualifier = std::string(ShortestQualifier);
379 if (
C.IdentifierResult) {
382 Completion.Name = std::string(
C.IdentifierResult->Name);
383 Completion.FilterText = Completion.Name;
387 auto Inserted = [&](llvm::StringRef Header)
389 auto ResolvedDeclaring =
391 if (!ResolvedDeclaring)
392 return ResolvedDeclaring.takeError();
394 if (!ResolvedInserted)
395 return ResolvedInserted.takeError();
396 auto Spelled = Includes.calculateIncludePath(*ResolvedInserted,
FileName);
398 return error(
"Header not on include path");
399 return std::make_pair(
401 Includes.shouldInsertInclude(*ResolvedDeclaring, *ResolvedInserted));
403 bool ShouldInsert =
C.headerToInsertIfAllowed(Opts).has_value();
406 for (
const auto &Inc :
C.RankedIncludeHeaders) {
410 if (
auto ToInclude = Inserted(Inc.Header)) {
411 CodeCompletion::IncludeCandidate Include;
412 Include.Header = ToInclude->first;
413 if (ToInclude->second && ShouldInsert)
414 Include.Insertion = Includes.insert(
416 ? tooling::IncludeDirective::Import
417 : tooling::IncludeDirective::Include);
418 Completion.Includes.push_back(std::move(Include));
420 log(
"Failed to generate include insertion edits for adding header "
421 "(FileURI='{0}', IncludeHeader='{1}') into {2}: {3}",
422 C.IndexResult->CanonicalDeclaration.FileURI, Inc.Header,
FileName,
423 ToInclude.takeError());
426 std::stable_partition(Completion.Includes.begin(),
427 Completion.Includes.end(),
428 [](
const CodeCompletion::IncludeCandidate &I) {
429 return !I.Insertion.has_value();
433 void add(
const CompletionCandidate &
C, CodeCompletionString *SemaCCS) {
434 assert(
bool(
C.SemaResult) ==
bool(SemaCCS));
435 Bundled.emplace_back();
436 BundledEntry &S = Bundled.back();
438 bool IsPattern =
C.SemaResult->Kind == CodeCompletionResult::RK_Pattern;
440 &Completion.RequiredQualifier, IsPattern);
441 if (!
C.SemaResult->FunctionCanBeCall)
442 S.SnippetSuffix.clear();
444 }
else if (
C.IndexResult) {
445 S.Signature = std::string(
C.IndexResult->Signature);
446 S.SnippetSuffix = std::string(
C.IndexResult->CompletionSnippetSuffix);
447 S.ReturnType = std::string(
C.IndexResult->ReturnType);
449 if (!Completion.Documentation) {
450 auto SetDoc = [&](llvm::StringRef Doc) {
452 Completion.Documentation.emplace();
457 SetDoc(
C.IndexResult->Documentation);
458 }
else if (
C.SemaResult) {
464 if (Completion.Deprecated) {
466 Completion.Deprecated &=
467 C.SemaResult->Availability == CXAvailability_Deprecated;
469 Completion.Deprecated &=
474 CodeCompletion build() {
475 Completion.ReturnType = summarizeReturnType();
476 Completion.Signature = summarizeSignature();
477 Completion.SnippetSuffix = summarizeSnippet();
478 Completion.BundleSize = Bundled.size();
479 return std::move(Completion);
483 struct BundledEntry {
490 template <std::
string BundledEntry::*Member>
491 const std::string *onlyValue()
const {
492 auto B = Bundled.begin(),
E = Bundled.end();
493 for (
auto *I =
B + 1; I !=
E; ++I)
494 if (I->*Member !=
B->*Member)
496 return &(
B->*Member);
499 template <
bool BundledEntry::*Member>
const bool *onlyValue()
const {
500 auto B = Bundled.begin(),
E = Bundled.end();
501 for (
auto *I =
B + 1; I !=
E; ++I)
502 if (I->*Member !=
B->*Member)
504 return &(
B->*Member);
507 std::string summarizeReturnType()
const {
508 if (
auto *RT = onlyValue<&BundledEntry::ReturnType>())
513 std::string summarizeSnippet()
const {
514 if (IsUsingDeclaration)
516 auto *
Snippet = onlyValue<&BundledEntry::SnippetSuffix>();
534 if (MayHaveArgList) {
538 if (NextTokenKind == tok::less &&
Snippet->front() ==
'<')
541 if (NextTokenKind == tok::l_paren) {
551 else if (
Snippet->at(I) ==
'<')
554 }
while (Balance > 0);
560 if (EnableFunctionArgSnippets)
564 if (MayHaveArgList) {
573 bool EmptyArgs = llvm::StringRef(*Snippet).endswith(
"()");
575 return EmptyArgs ?
"<$1>()$0" :
"<$1>($0)";
577 return EmptyArgs ?
"()" :
"($0)";
588 if (llvm::StringRef(*Snippet).endswith(
"<>"))
595 std::string summarizeSignature()
const {
596 if (
auto *
Signature = onlyValue<&BundledEntry::Signature>())
604 CodeCompletion Completion;
605 llvm::SmallVector<BundledEntry, 1> Bundled;
606 bool EnableFunctionArgSnippets;
609 bool IsUsingDeclaration;
610 tok::TokenKind NextTokenKind;
616 case CodeCompletionResult::RK_Declaration:
617 case CodeCompletionResult::RK_Pattern: {
623 case CodeCompletionResult::RK_Macro:
625 case CodeCompletionResult::RK_Keyword:
628 llvm_unreachable(
"unknown CodeCompletionResult kind");
633 struct SpecifiedScope {
661 std::vector<std::string> scopesForIndexQuery() {
673 std::pair<std::vector<std::string>,
bool>
675 const CompletionPrefix &HeuristicPrefix,
676 const CodeCompleteOptions &Opts) {
677 SpecifiedScope Scopes;
678 for (
auto *Context :
CCContext.getVisitedContexts()) {
679 if (isa<TranslationUnitDecl>(Context))
680 Scopes.AccessibleScopes.push_back(
"");
681 else if (isa<NamespaceDecl>(Context))
685 const CXXScopeSpec *SemaSpecifier =
686 CCContext.getCXXScopeSpecifier().value_or(
nullptr);
688 if (!SemaSpecifier) {
691 if (!HeuristicPrefix.
Qualifier.empty()) {
692 vlog(
"Sema said no scope specifier, but we saw {0} in the source code",
694 StringRef SpelledSpecifier = HeuristicPrefix.
Qualifier;
695 if (SpelledSpecifier.consume_front(
"::"))
696 Scopes.AccessibleScopes = {
""};
697 Scopes.UnresolvedQualifier = std::string(SpelledSpecifier);
698 return {Scopes.scopesForIndexQuery(),
false};
701 std::vector<std::string> EnclosingAtFront;
703 EnclosingAtFront.push_back(EnclosingScope);
704 for (
auto &S : Scopes.scopesForIndexQuery()) {
705 if (EnclosingScope != S)
706 EnclosingAtFront.push_back(std::move(S));
709 return {EnclosingAtFront, Opts.
AllScopes};
712 if (SemaSpecifier && SemaSpecifier->isValid())
713 return {Scopes.scopesForIndexQuery(),
false};
716 Scopes.AccessibleScopes.push_back(
"");
718 CharSourceRange::getCharRange(SemaSpecifier->getRange()),
719 CCSema.SourceMgr, clang::LangOptions());
720 if (SpelledSpecifier.consume_front(
"::"))
721 Scopes.AccessibleScopes = {
""};
722 Scopes.UnresolvedQualifier = std::string(SpelledSpecifier);
724 if (!Scopes.UnresolvedQualifier->empty())
725 *Scopes.UnresolvedQualifier +=
"::";
727 return {Scopes.scopesForIndexQuery(),
false};
734 case CodeCompletionContext::CCC_TopLevel:
735 case CodeCompletionContext::CCC_ObjCInterface:
736 case CodeCompletionContext::CCC_ObjCImplementation:
737 case CodeCompletionContext::CCC_ObjCIvarList:
738 case CodeCompletionContext::CCC_ClassStructUnion:
739 case CodeCompletionContext::CCC_Statement:
740 case CodeCompletionContext::CCC_Expression:
741 case CodeCompletionContext::CCC_ObjCMessageReceiver:
742 case CodeCompletionContext::CCC_EnumTag:
743 case CodeCompletionContext::CCC_UnionTag:
744 case CodeCompletionContext::CCC_ClassOrStructTag:
745 case CodeCompletionContext::CCC_ObjCProtocolName:
746 case CodeCompletionContext::CCC_Namespace:
747 case CodeCompletionContext::CCC_Type:
748 case CodeCompletionContext::CCC_ParenthesizedExpression:
749 case CodeCompletionContext::CCC_ObjCInterfaceName:
750 case CodeCompletionContext::CCC_Symbol:
751 case CodeCompletionContext::CCC_SymbolOrNewName:
753 case CodeCompletionContext::CCC_OtherWithMacros:
754 case CodeCompletionContext::CCC_DotMemberAccess:
755 case CodeCompletionContext::CCC_ArrowMemberAccess:
756 case CodeCompletionContext::CCC_ObjCCategoryName:
757 case CodeCompletionContext::CCC_ObjCPropertyAccess:
758 case CodeCompletionContext::CCC_MacroName:
759 case CodeCompletionContext::CCC_MacroNameUse:
760 case CodeCompletionContext::CCC_PreprocessorExpression:
761 case CodeCompletionContext::CCC_PreprocessorDirective:
762 case CodeCompletionContext::CCC_SelectorName:
763 case CodeCompletionContext::CCC_TypeQualifiers:
764 case CodeCompletionContext::CCC_ObjCInstanceMessage:
765 case CodeCompletionContext::CCC_ObjCClassMessage:
766 case CodeCompletionContext::CCC_IncludedFile:
767 case CodeCompletionContext::CCC_Attribute:
769 case CodeCompletionContext::CCC_Other:
770 case CodeCompletionContext::CCC_NaturalLanguage:
771 case CodeCompletionContext::CCC_Recovery:
772 case CodeCompletionContext::CCC_NewName:
775 llvm_unreachable(
"unknown code completion context");
778 static bool isInjectedClass(
const NamedDecl &
D) {
779 if (
auto *R = dyn_cast_or_null<RecordDecl>(&
D))
780 if (R->isInjectedClassName())
786 static bool isExcludedMember(
const NamedDecl &
D) {
789 if (
D.getKind() == Decl::CXXDestructor)
792 if (isInjectedClass(
D))
795 auto NameKind =
D.getDeclName().getNameKind();
796 if (NameKind == DeclarationName::CXXOperatorName ||
797 NameKind == DeclarationName::CXXLiteralOperatorName ||
798 NameKind == DeclarationName::CXXConversionFunctionName)
809 struct CompletionRecorder :
public CodeCompleteConsumer {
810 CompletionRecorder(
const CodeCompleteOptions &Opts,
811 llvm::unique_function<
void()> ResultsCallback)
812 : CodeCompleteConsumer(Opts.getClangCompleteOpts()),
813 CCContext(CodeCompletionContext::CCC_Other), Opts(Opts),
814 CCAllocator(std::make_shared<GlobalCodeCompletionAllocator>()),
815 CCTUInfo(CCAllocator), ResultsCallback(std::move(ResultsCallback)) {
816 assert(this->ResultsCallback);
824 void ProcessCodeCompleteResults(
class Sema &S, CodeCompletionContext Context,
825 CodeCompletionResult *InResults,
826 unsigned NumResults)
final {
835 if (Context.getKind() == CodeCompletionContext::CCC_Recovery) {
836 log(
"Code complete: Ignoring sema code complete callback with Recovery "
843 if (NumResults == 0 && !contextAllowsIndex(Context.getKind()))
846 log(
"Multiple code complete callbacks (parser backtracked?). "
847 "Dropping results from context {0}, keeping results from {1}.",
848 getCompletionKindString(Context.getKind()),
849 getCompletionKindString(this->CCContext.getKind()));
857 for (
unsigned I = 0; I < NumResults; ++I) {
858 auto &Result = InResults[I];
860 if (Result.Hidden && Result.Declaration &&
861 Result.Declaration->isCXXClassMember())
863 if (!Opts.IncludeIneligibleResults &&
864 (Result.Availability == CXAvailability_NotAvailable ||
865 Result.Availability == CXAvailability_NotAccessible))
867 if (Result.Declaration &&
868 !Context.getBaseType().isNull()
869 && isExcludedMember(*Result.Declaration))
873 if (Result.Declaration && !Context.getCXXScopeSpecifier() &&
874 isInjectedClass(*Result.Declaration))
877 Result.StartsNestedNameSpecifier =
false;
883 CodeCompletionAllocator &getAllocator()
override {
return *CCAllocator; }
884 CodeCompletionTUInfo &getCodeCompletionTUInfo()
override {
return CCTUInfo; }
888 llvm::StringRef
getName(
const CodeCompletionResult &Result) {
889 switch (Result.Kind) {
890 case CodeCompletionResult::RK_Declaration:
891 if (
auto *
ID = Result.Declaration->getIdentifier())
892 return ID->getName();
894 case CodeCompletionResult::RK_Keyword:
895 return Result.Keyword;
896 case CodeCompletionResult::RK_Macro:
897 return Result.Macro->getName();
898 case CodeCompletionResult::RK_Pattern:
901 auto *CCS = codeCompletionString(Result);
902 const CodeCompletionString::Chunk *OnlyText =
nullptr;
903 for (
auto &
C : *CCS) {
904 if (
C.Kind != CodeCompletionString::CK_TypedText)
907 return CCAllocator->CopyString(CCS->getAllTypedText());
910 return OnlyText ? OnlyText->Text : llvm::StringRef();
915 CodeCompletionString *codeCompletionString(
const CodeCompletionResult &R) {
917 return const_cast<CodeCompletionResult &
>(R).CreateCodeCompletionString(
923 CodeCompleteOptions Opts;
924 std::shared_ptr<GlobalCodeCompletionAllocator> CCAllocator;
926 llvm::unique_function<void()> ResultsCallback;
929 struct ScoredSignature {
942 int paramIndexForArg(
const CodeCompleteConsumer::OverloadCandidate &
Candidate,
944 int NumParams =
Candidate.getNumParams();
945 if (
auto *T =
Candidate.getFunctionType()) {
946 if (
auto *Proto = T->getAs<FunctionProtoType>()) {
947 if (Proto->isVariadic())
951 return std::min(Arg, std::max(NumParams - 1, 0));
954 class SignatureHelpCollector final :
public CodeCompleteConsumer {
956 SignatureHelpCollector(
const clang::CodeCompleteOptions &CodeCompleteOpts,
958 const SymbolIndex *
Index, SignatureHelp &SigHelp)
959 : CodeCompleteConsumer(CodeCompleteOpts), SigHelp(SigHelp),
960 Allocator(std::make_shared<
clang::GlobalCodeCompletionAllocator>()),
962 DocumentationFormat(DocumentationFormat) {}
964 void ProcessOverloadCandidates(Sema &S,
unsigned CurrentArg,
965 OverloadCandidate *Candidates,
966 unsigned NumCandidates,
967 SourceLocation OpenParLoc,
968 bool Braced)
override {
969 assert(!OpenParLoc.isInvalid());
970 SourceManager &SrcMgr = S.getSourceManager();
971 OpenParLoc = SrcMgr.getFileLoc(OpenParLoc);
972 if (SrcMgr.isInMainFile(OpenParLoc))
975 elog(
"Location oustide main file in signature help: {0}",
976 OpenParLoc.printToString(SrcMgr));
978 std::vector<ScoredSignature> ScoredSignatures;
979 SigHelp.signatures.reserve(NumCandidates);
980 ScoredSignatures.reserve(NumCandidates);
984 SigHelp.activeSignature = 0;
985 assert(CurrentArg <= (
unsigned)std::numeric_limits<int>::max() &&
986 "too many arguments");
988 SigHelp.activeParameter =
static_cast<int>(CurrentArg);
990 for (
unsigned I = 0; I < NumCandidates; ++I) {
991 OverloadCandidate
Candidate = Candidates[I];
995 if (
auto *Func =
Candidate.getFunction()) {
996 if (
auto *Pattern = Func->getTemplateInstantiationPattern())
999 if (
static_cast<int>(I) == SigHelp.activeSignature) {
1004 SigHelp.activeParameter =
1005 paramIndexForArg(
Candidate, SigHelp.activeParameter);
1008 const auto *CCS =
Candidate.CreateSignatureString(
1011 assert(CCS &&
"Expected the CodeCompletionString to be non-null");
1012 ScoredSignatures.push_back(processOverloadCandidate(
1021 llvm::DenseMap<SymbolID, std::string> FetchedDocs;
1023 LookupRequest IndexRequest;
1024 for (
const auto &S : ScoredSignatures) {
1027 IndexRequest.IDs.insert(S.IDForDoc);
1029 Index->lookup(IndexRequest, [&](
const Symbol &S) {
1030 if (!S.Documentation.empty())
1031 FetchedDocs[S.ID] = std::string(S.Documentation);
1033 vlog(
"SigHelp: requested docs for {0} symbols from the index, got {1} "
1034 "symbols with non-empty docs in the response",
1035 IndexRequest.IDs.size(), FetchedDocs.size());
1038 llvm::sort(ScoredSignatures, [](
const ScoredSignature &L,
1039 const ScoredSignature &R) {
1046 if (L.Quality.NumberOfParameters != R.Quality.NumberOfParameters)
1047 return L.Quality.NumberOfParameters < R.Quality.NumberOfParameters;
1048 if (L.Quality.NumberOfOptionalParameters !=
1049 R.Quality.NumberOfOptionalParameters)
1050 return L.Quality.NumberOfOptionalParameters <
1051 R.Quality.NumberOfOptionalParameters;
1052 if (L.Quality.Kind != R.Quality.Kind) {
1053 using OC = CodeCompleteConsumer::OverloadCandidate;
1054 auto KindPriority = [&](OC::CandidateKind K) {
1056 case OC::CK_Aggregate:
1058 case OC::CK_Function:
1060 case OC::CK_FunctionType:
1062 case OC::CK_FunctionProtoTypeLoc:
1064 case OC::CK_FunctionTemplate:
1066 case OC::CK_Template:
1069 llvm_unreachable(
"Unknown overload candidate type.");
1071 return KindPriority(L.Quality.Kind) < KindPriority(R.Quality.Kind);
1073 if (L.Signature.label.size() != R.Signature.label.size())
1074 return L.Signature.label.size() < R.Signature.label.size();
1075 return L.Signature.label < R.Signature.label;
1078 for (
auto &SS : ScoredSignatures) {
1080 SS.IDForDoc ? FetchedDocs.find(SS.IDForDoc) : FetchedDocs.end();
1081 if (IndexDocIt != FetchedDocs.end()) {
1082 markup::Document SignatureComment;
1084 SS.Signature.documentation =
1085 renderDoc(SignatureComment, DocumentationFormat);
1088 SigHelp.signatures.push_back(std::move(SS.Signature));
1092 GlobalCodeCompletionAllocator &getAllocator()
override {
return *
Allocator; }
1094 CodeCompletionTUInfo &getCodeCompletionTUInfo()
override {
return CCTUInfo; }
1097 void processParameterChunk(llvm::StringRef ChunkText,
1098 SignatureInformation &
Signature)
const {
1101 unsigned ParamEndOffset = ParamStartOffset +
lspLength(ChunkText);
1106 ParameterInformation
Info;
1107 Info.labelOffsets.emplace(ParamStartOffset, ParamEndOffset);
1109 Info.labelString = std::string(ChunkText);
1111 Signature.parameters.push_back(std::move(Info));
1114 void processOptionalChunk(
const CodeCompletionString &CCS,
1116 SignatureQualitySignals &Signal)
const {
1117 for (
const auto &Chunk : CCS) {
1118 switch (Chunk.Kind) {
1119 case CodeCompletionString::CK_Optional:
1120 assert(Chunk.Optional &&
1121 "Expected the optional code completion string to be non-null.");
1122 processOptionalChunk(*Chunk.Optional,
Signature, Signal);
1124 case CodeCompletionString::CK_VerticalSpace:
1126 case CodeCompletionString::CK_CurrentParameter:
1127 case CodeCompletionString::CK_Placeholder:
1128 processParameterChunk(Chunk.Text,
Signature);
1129 Signal.NumberOfOptionalParameters++;
1140 ScoredSignature processOverloadCandidate(
const OverloadCandidate &
Candidate,
1141 const CodeCompletionString &CCS,
1142 llvm::StringRef DocComment)
const {
1144 SignatureQualitySignals Signal;
1147 markup::Document OverloadComment;
1149 Signature.documentation = renderDoc(OverloadComment, DocumentationFormat);
1152 for (
const auto &Chunk : CCS) {
1153 switch (Chunk.Kind) {
1154 case CodeCompletionString::CK_ResultType:
1157 assert(!
ReturnType &&
"Unexpected CK_ResultType");
1160 case CodeCompletionString::CK_CurrentParameter:
1161 case CodeCompletionString::CK_Placeholder:
1162 processParameterChunk(Chunk.Text,
Signature);
1163 Signal.NumberOfParameters++;
1165 case CodeCompletionString::CK_Optional: {
1167 assert(Chunk.Optional &&
1168 "Expected the optional code completion string to be non-null.");
1169 processOptionalChunk(*Chunk.Optional,
Signature, Signal);
1172 case CodeCompletionString::CK_VerticalSpace:
1184 ScoredSignature Result;
1185 Result.Signature = std::move(
Signature);
1186 Result.Quality = Signal;
1187 const FunctionDecl *Func =
Candidate.getFunction();
1188 if (Func && Result.Signature.documentation.value.empty()) {
1196 SignatureHelp &SigHelp;
1197 std::shared_ptr<clang::GlobalCodeCompletionAllocator>
Allocator;
1199 const SymbolIndex *
Index;
1205 class ParamNameCollector final :
public CodeCompleteConsumer {
1207 ParamNameCollector(
const clang::CodeCompleteOptions &CodeCompleteOpts,
1208 std::set<std::string> &ParamNames)
1209 : CodeCompleteConsumer(CodeCompleteOpts),
1210 Allocator(std::make_shared<
clang::GlobalCodeCompletionAllocator>()),
1213 void ProcessOverloadCandidates(Sema &S,
unsigned CurrentArg,
1214 OverloadCandidate *Candidates,
1215 unsigned NumCandidates,
1216 SourceLocation OpenParLoc,
1217 bool Braced)
override {
1218 assert(CurrentArg <= (
unsigned)std::numeric_limits<int>::max() &&
1219 "too many arguments");
1221 for (
unsigned I = 0; I < NumCandidates; ++I) {
1222 if (
const NamedDecl *ND = Candidates[I].getParamDecl(CurrentArg))
1223 if (
const auto *II = ND->getIdentifier())
1224 ParamNames.emplace(II->getName());
1229 GlobalCodeCompletionAllocator &getAllocator()
override {
return *
Allocator; }
1231 CodeCompletionTUInfo &getCodeCompletionTUInfo()
override {
return CCTUInfo; }
1233 std::shared_ptr<clang::GlobalCodeCompletionAllocator>
Allocator;
1235 std::set<std::string> &ParamNames;
1238 struct SemaCompleteInput {
1242 const std::optional<PreamblePatch>
Patch;
1246 void loadMainFilePreambleMacros(
const Preprocessor &
PP,
1247 const PreambleData &Preamble) {
1251 ExternalPreprocessorSource *PreambleMacros =
PP.getExternalSource();
1254 const auto &ITable =
PP.getIdentifierTable();
1255 IdentifierInfoLookup *PreambleIdentifiers =
1256 ITable.getExternalIdentifierLookup();
1258 if (!PreambleIdentifiers || !PreambleMacros)
1261 if (ITable.find(MacroName.getKey()) != ITable.end())
1263 if (
auto *II = PreambleIdentifiers->get(MacroName.getKey()))
1264 if (II->isOutOfDate())
1265 PreambleMacros->updateOutOfDateIdentifier(*II);
1271 bool semaCodeComplete(std::unique_ptr<CodeCompleteConsumer> Consumer,
1272 const clang::CodeCompleteOptions &Options,
1273 const SemaCompleteInput &Input,
1274 IncludeStructure *Includes =
nullptr) {
1275 trace::Span
Tracer(
"Sema completion");
1280 elog(
"Couldn't create CompilerInvocation");
1283 auto &FrontendOpts =
CI->getFrontendOpts();
1284 FrontendOpts.SkipFunctionBodies =
true;
1286 CI->getLangOpts()->SpellChecking =
false;
1290 CI->getLangOpts()->DelayedTemplateParsing =
false;
1292 FrontendOpts.CodeCompleteOpts = Options;
1293 FrontendOpts.CodeCompletionAt.FileName = std::string(Input.FileName);
1294 std::tie(FrontendOpts.CodeCompletionAt.Line,
1295 FrontendOpts.CodeCompletionAt.Column) =
1298 std::unique_ptr<llvm::MemoryBuffer> ContentsBuffer =
1299 llvm::MemoryBuffer::getMemBuffer(Input.ParseInput.Contents,
1302 CI->getDiagnosticOpts().IgnoreWarnings =
true;
1309 PreambleBounds PreambleRegion =
1310 ComputePreambleBounds(*
CI->getLangOpts(), *ContentsBuffer, 0);
1311 bool CompletingInPreamble = Input.Offset < PreambleRegion.Size ||
1312 (!PreambleRegion.PreambleEndsAtStartOfLine &&
1313 Input.Offset == PreambleRegion.Size);
1315 Input.Patch->apply(*
CI);
1318 llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS =
1319 Input.ParseInput.TFS->view(Input.ParseInput.CompileCommand.Directory);
1320 if (Input.Preamble.StatCache)
1321 VFS = Input.Preamble.StatCache->getConsumingFS(std::move(VFS));
1323 std::move(
CI), !CompletingInPreamble ? &Input.Preamble.Preamble :
nullptr,
1324 std::move(ContentsBuffer), std::move(VFS),
IgnoreDiags);
1325 Clang->getPreprocessorOpts().SingleFileParseMode = CompletingInPreamble;
1326 Clang->setCodeCompletionConsumer(Consumer.release());
1330 log(
"BeginSourceFile() failed when running codeComplete for {0}",
1340 loadMainFilePreambleMacros(
Clang->getPreprocessor(), Input.Preamble);
1343 if (llvm::Error Err =
Action.Execute()) {
1344 log(
"Execute() failed when running codeComplete for {0}: {1}",
1345 Input.FileName,
toString(std::move(Err)));
1354 bool allowIndex(CodeCompletionContext &
CC) {
1355 if (!contextAllowsIndex(
CC.getKind()))
1358 auto Scope =
CC.getCXXScopeSpecifier();
1361 NestedNameSpecifier *NameSpec = (*Scope)->getScopeRep();
1366 switch (NameSpec->getKind()) {
1367 case NestedNameSpecifier::Global:
1368 case NestedNameSpecifier::Namespace:
1369 case NestedNameSpecifier::NamespaceAlias:
1371 case NestedNameSpecifier::Super:
1372 case NestedNameSpecifier::TypeSpec:
1373 case NestedNameSpecifier::TypeSpecWithTemplate:
1375 case NestedNameSpecifier::Identifier:
1378 llvm_unreachable(
"invalid NestedNameSpecifier kind");
1384 const Symbol &Sym) {
1388 if (Sym.SymInfo.Kind == index::SymbolKind::Protocol &&
1389 Sym.SymInfo.Lang == index::SymbolLanguage::ObjC)
1390 return Kind == CodeCompletionContext::CCC_ObjCProtocolName;
1391 else if (
Kind == CodeCompletionContext::CCC_ObjCProtocolName)
1397 std::future<std::pair<bool, SymbolSlab>>
1398 startAsyncFuzzyFind(
const SymbolIndex &
Index,
const FuzzyFindRequest &Req) {
1399 return runAsync<std::pair<bool, SymbolSlab>>([&
Index, Req]() {
1400 trace::Span
Tracer(
"Async fuzzyFind");
1403 Index.
fuzzyFind(Req, [&Syms](
const Symbol &Sym) { Syms.insert(Sym); });
1404 return std::make_pair(Incomplete, std::move(Syms).build());
1411 FuzzyFindRequest speculativeFuzzyFindRequestForCompletion(
1412 FuzzyFindRequest CachedReq,
const CompletionPrefix &HeuristicPrefix) {
1413 CachedReq.Query = std::string(HeuristicPrefix.
Name);
1446 class CodeCompleteFlow {
1448 IncludeStructure Includes;
1449 SpeculativeFuzzyFind *SpecFuzzyFind;
1450 const CodeCompleteOptions &Opts;
1453 CompletionRecorder *Recorder =
nullptr;
1455 bool IsUsingDeclaration =
false;
1459 tok::TokenKind NextTokenKind = tok::eof;
1461 int NSema = 0, NIndex = 0, NSemaAndIndex = 0, NIdent = 0;
1462 bool Incomplete =
false;
1463 CompletionPrefix HeuristicPrefix;
1464 std::optional<FuzzyMatcher> Filter;
1465 Range ReplacedRange;
1466 std::vector<std::string> QueryScopes;
1468 std::optional<ScopeDistance> ScopeProximity;
1469 std::optional<OpaqueType> PreferredType;
1471 bool AllScopes =
false;
1472 llvm::StringSet<> ContextWords;
1475 std::optional<IncludeInserter> Inserter;
1476 std::optional<URIDistance> FileProximity;
1481 std::optional<FuzzyFindRequest> SpecReq;
1486 SpeculativeFuzzyFind *SpecFuzzyFind,
1487 const CodeCompleteOptions &Opts)
1491 CodeCompleteResult run(
const SemaCompleteInput &SemaCCInput) && {
1492 trace::Span
Tracer(
"CodeCompleteFlow");
1494 SemaCCInput.Offset);
1495 populateContextWords(SemaCCInput.ParseInput.Contents);
1496 if (Opts.Index && SpecFuzzyFind && SpecFuzzyFind->CachedReq) {
1497 assert(!SpecFuzzyFind->Result.valid());
1498 SpecReq = speculativeFuzzyFindRequestForCompletion(
1499 *SpecFuzzyFind->CachedReq, HeuristicPrefix);
1500 SpecFuzzyFind->Result = startAsyncFuzzyFind(*Opts.Index, *SpecReq);
1506 CodeCompleteResult
Output;
1507 auto RecorderOwner = std::make_unique<CompletionRecorder>(Opts, [&]() {
1508 assert(Recorder &&
"Recorder is not set");
1509 CCContextKind = Recorder->CCContext.getKind();
1510 IsUsingDeclaration = Recorder->CCContext.isUsingDeclaration();
1512 SemaCCInput.ParseInput.Contents,
1513 *SemaCCInput.ParseInput.TFS);
1514 const auto NextToken = Lexer::findNextToken(
1515 Recorder->CCSema->getPreprocessor().getCodeCompletionLoc(),
1516 Recorder->CCSema->getSourceManager(), Recorder->CCSema->LangOpts);
1518 NextTokenKind = NextToken->getKind();
1522 SemaCCInput.FileName, SemaCCInput.ParseInput.Contents, Style,
1523 SemaCCInput.ParseInput.CompileCommand.Directory,
1524 &Recorder->CCSema->getPreprocessor().getHeaderSearchInfo());
1525 for (
const auto &Inc : Includes.MainFileIncludes)
1526 Inserter->addExisting(Inc);
1532 FileDistanceOptions ProxOpts{};
1533 const auto &SM = Recorder->CCSema->getSourceManager();
1534 llvm::StringMap<SourceParams> ProxSources;
1536 Includes.getID(SM.getFileEntryForID(SM.getMainFileID()));
1538 for (
auto &HeaderIDAndDepth : Includes.includeDepth(*MainFileID)) {
1540 ProxSources[Includes.getRealPath(HeaderIDAndDepth.getFirst())];
1541 Source.Cost = HeaderIDAndDepth.getSecond() * ProxOpts.IncludeCost;
1545 if (HeaderIDAndDepth.getSecond() > 0)
1546 Source.MaxUpTraversals = 1;
1548 FileProximity.emplace(ProxSources, ProxOpts);
1553 getCompletionKindString(CCContextKind));
1554 log(
"Code complete: sema context {0}, query scopes [{1}] (AnyScope={2}), "
1555 "expected type {3}{4}",
1556 getCompletionKindString(CCContextKind),
1557 llvm::join(QueryScopes.begin(), QueryScopes.end(),
","), AllScopes,
1558 PreferredType ? Recorder->CCContext.getPreferredType().getAsString()
1560 IsUsingDeclaration ?
", inside using declaration" :
"");
1563 Recorder = RecorderOwner.get();
1565 semaCodeComplete(std::move(RecorderOwner), Opts.getClangCompleteOpts(),
1566 SemaCCInput, &Includes);
1571 void logResults(
const CodeCompleteResult &
Output,
const trace::Span &
Tracer) {
1578 log(
"Code complete: {0} results from Sema, {1} from Index, "
1579 "{2} matched, {3} from identifiers, {4} returned{5}.",
1580 NSema, NIndex, NSemaAndIndex, NIdent,
Output.Completions.size(),
1581 Output.HasMore ?
" (incomplete)" :
"");
1582 assert(!Opts.Limit ||
Output.Completions.size() <= Opts.Limit);
1587 CodeCompleteResult runWithoutSema(llvm::StringRef Content,
size_t Offset,
1588 const ThreadsafeFS &TFS) && {
1589 trace::Span
Tracer(
"CodeCompleteWithoutSema");
1592 populateContextWords(Content);
1593 CCContextKind = CodeCompletionContext::CCC_Recovery;
1594 IsUsingDeclaration =
false;
1595 Filter = FuzzyMatcher(HeuristicPrefix.Name);
1597 ReplacedRange.start = ReplacedRange.end =
Pos;
1598 ReplacedRange.start.character -= HeuristicPrefix.Name.size();
1600 llvm::StringMap<SourceParams> ProxSources;
1602 FileProximity.emplace(ProxSources);
1606 Inserter.emplace(
FileName, Content, Style,
1610 std::vector<RawIdentifier> IdentifierResults;
1611 for (
const auto &IDAndCount : Identifiers) {
1613 ID.Name = IDAndCount.first();
1614 ID.References = IDAndCount.second;
1616 if (
ID.Name == HeuristicPrefix.Name)
1618 if (
ID.References > 0)
1619 IdentifierResults.push_back(std::move(
ID));
1625 SpecifiedScope Scopes;
1627 Content.take_front(
Offset), format::getFormattingLangOpts(Style));
1628 for (std::string &S : Scopes.AccessibleScopes)
1631 if (HeuristicPrefix.Qualifier.empty())
1632 AllScopes = Opts.AllScopes;
1633 else if (HeuristicPrefix.Qualifier.startswith(
"::")) {
1634 Scopes.AccessibleScopes = {
""};
1635 Scopes.UnresolvedQualifier =
1636 std::string(HeuristicPrefix.Qualifier.drop_front(2));
1638 Scopes.UnresolvedQualifier = std::string(HeuristicPrefix.Qualifier);
1640 QueryScopes = Scopes.scopesForIndexQuery();
1641 ScopeProximity.emplace(QueryScopes);
1643 SymbolSlab IndexResults = Opts.Index ? queryIndex() : SymbolSlab();
1645 CodeCompleteResult
Output = toCodeCompleteResult(mergeResults(
1646 {}, IndexResults, IdentifierResults));
1647 Output.RanParser =
false;
1653 void populateContextWords(llvm::StringRef Content) {
1655 unsigned RangeEnd = HeuristicPrefix.Qualifier.begin() - Content.data(),
1656 RangeBegin = RangeEnd;
1657 for (
size_t I = 0; I < 3 && RangeBegin > 0; ++I) {
1658 auto PrevNL = Content.rfind(
'\n', RangeBegin);
1659 if (PrevNL == StringRef::npos) {
1663 RangeBegin = PrevNL;
1666 ContextWords =
collectWords(Content.slice(RangeBegin, RangeEnd));
1667 dlog(
"Completion context words: {0}",
1673 CodeCompleteResult runWithSema() {
1674 const auto &CodeCompletionRange = CharSourceRange::getCharRange(
1675 Recorder->CCSema->getPreprocessor().getCodeCompletionTokenRange());
1681 if (CodeCompletionRange.isValid()) {
1683 CodeCompletionRange);
1686 Recorder->CCSema->getSourceManager(),
1687 Recorder->CCSema->getPreprocessor().getCodeCompletionLoc());
1688 ReplacedRange.start = ReplacedRange.end =
Pos;
1690 Filter = FuzzyMatcher(
1691 Recorder->CCSema->getPreprocessor().getCodeCompletionFilter());
1692 std::tie(QueryScopes, AllScopes) = getQueryScopes(
1693 Recorder->CCContext, *Recorder->CCSema, HeuristicPrefix, Opts);
1694 if (!QueryScopes.empty())
1695 ScopeProximity.emplace(QueryScopes);
1698 Recorder->CCContext.getPreferredType());
1704 auto IndexResults = (Opts.Index && allowIndex(Recorder->CCContext))
1707 trace::Span
Tracer(
"Populate CodeCompleteResult");
1710 mergeResults(Recorder->Results, IndexResults, {});
1711 return toCodeCompleteResult(Top);
1715 toCodeCompleteResult(
const std::vector<ScoredBundle> &Scored) {
1716 CodeCompleteResult
Output;
1719 for (
auto &
C : Scored) {
1720 Output.Completions.push_back(toCodeCompletion(
C.first));
1721 Output.Completions.back().Score =
C.second;
1722 Output.Completions.back().CompletionTokenRange = ReplacedRange;
1724 Output.HasMore = Incomplete;
1725 Output.Context = CCContextKind;
1726 Output.CompletionRange = ReplacedRange;
1730 SymbolSlab queryIndex() {
1731 trace::Span
Tracer(
"Query index");
1735 FuzzyFindRequest Req;
1737 Req.Limit = Opts.Limit;
1738 Req.Query = std::string(Filter->pattern());
1739 Req.RestrictForCodeCompletion =
true;
1740 Req.Scopes = QueryScopes;
1741 Req.AnyScope = AllScopes;
1743 Req.ProximityPaths.push_back(std::string(
FileName));
1745 Req.PreferredTypes.push_back(std::string(PreferredType->raw()));
1746 vlog(
"Code complete: fuzzyFind({0:2})",
toJSON(Req));
1749 SpecFuzzyFind->NewReq = Req;
1750 if (SpecFuzzyFind && SpecFuzzyFind->Result.valid() && (*SpecReq == Req)) {
1751 vlog(
"Code complete: speculative fuzzy request matches the actual index "
1752 "request. Waiting for the speculative index results.");
1755 trace::Span WaitSpec(
"Wait speculative results");
1756 auto SpecRes = SpecFuzzyFind->Result.get();
1757 Incomplete |= SpecRes.first;
1758 return std::move(SpecRes.second);
1765 Incomplete |= Opts.Index->fuzzyFind(
1766 Req, [&](
const Symbol &Sym) { ResultsBuilder.insert(Sym); });
1767 return std::move(ResultsBuilder).build();
1775 std::vector<ScoredBundle>
1776 mergeResults(
const std::vector<CodeCompletionResult> &SemaResults,
1777 const SymbolSlab &IndexResults,
1778 const std::vector<RawIdentifier> &IdentifierResults) {
1779 trace::Span
Tracer(
"Merge and score results");
1780 std::vector<CompletionCandidate::Bundle> Bundles;
1781 llvm::DenseMap<size_t, size_t> BundleLookup;
1782 auto AddToBundles = [&](
const CodeCompletionResult *
SemaResult,
1785 CompletionCandidate
C;
1789 if (
C.IndexResult) {
1792 }
else if (
C.SemaResult) {
1798 if (
auto OverloadSet =
1799 C.overloadSet(Opts,
FileName, Inserter ? &*Inserter :
nullptr)) {
1800 auto Ret = BundleLookup.try_emplace(OverloadSet, Bundles.size());
1802 Bundles.emplace_back();
1803 Bundles[Ret.first->second].push_back(std::move(
C));
1805 Bundles.emplace_back();
1806 Bundles.back().push_back(std::move(
C));
1809 llvm::DenseSet<const Symbol *> UsedIndexResults;
1810 auto CorrespondingIndexResult =
1811 [&](
const CodeCompletionResult &
SemaResult) ->
const Symbol * {
1814 auto I = IndexResults.find(SymID);
1815 if (I != IndexResults.end()) {
1816 UsedIndexResults.insert(&*I);
1829 if (!includeSymbolFromIndex(CCContextKind,
IndexResult))
1834 for (
const auto &Ident : IdentifierResults)
1835 AddToBundles(
nullptr,
nullptr, &Ident);
1837 TopN<ScoredBundle, ScoredBundleGreater> Top(
1838 Opts.Limit == 0 ? std::numeric_limits<size_t>::max() : Opts.Limit);
1839 for (
auto &Bundle : Bundles)
1840 addCandidate(Top, std::move(Bundle));
1841 return std::move(Top).items();
1844 std::optional<float> fuzzyScore(
const CompletionCandidate &
C) {
1846 if (((
C.SemaResult &&
1847 C.SemaResult->Kind == CodeCompletionResult::RK_Macro) ||
1849 C.IndexResult->SymInfo.Kind == index::SymbolKind::Macro)) &&
1850 !
C.Name.startswith_insensitive(Filter->pattern()))
1851 return std::nullopt;
1852 return Filter->match(
C.Name);
1855 CodeCompletion::Scores
1856 evaluateCompletion(
const SymbolQualitySignals &
Quality,
1857 const SymbolRelevanceSignals &Relevance) {
1859 CodeCompletion::Scores Scores;
1860 switch (Opts.RankingModel) {
1861 case RM::Heuristics:
1862 Scores.Quality =
Quality.evaluateHeuristics();
1863 Scores.Relevance = Relevance.evaluateHeuristics();
1868 Scores.ExcludingName =
1869 Relevance.NameMatch > std::numeric_limits<float>::epsilon()
1870 ? Scores.Total / Relevance.NameMatch
1874 case RM::DecisionForest:
1875 DecisionForestScores DFScores = Opts.DecisionForestScorer(
1876 Quality, Relevance, Opts.DecisionForestBase);
1877 Scores.ExcludingName = DFScores.ExcludingName;
1878 Scores.Total = DFScores.Total;
1881 llvm_unreachable(
"Unhandled CodeCompletion ranking model.");
1885 void addCandidate(TopN<ScoredBundle, ScoredBundleGreater> &Candidates,
1886 CompletionCandidate::Bundle Bundle) {
1888 SymbolRelevanceSignals Relevance;
1889 Relevance.Context = CCContextKind;
1890 Relevance.Name = Bundle.front().Name;
1891 Relevance.FilterLength = HeuristicPrefix.Name.size();
1893 Relevance.FileProximityMatch = &*FileProximity;
1895 Relevance.ScopeProximityMatch = &*ScopeProximity;
1897 Relevance.HadContextType =
true;
1898 Relevance.ContextWords = &ContextWords;
1899 Relevance.MainFileSignals = Opts.MainFileSignals;
1901 auto &First = Bundle.front();
1902 if (
auto FuzzyScore = fuzzyScore(First))
1903 Relevance.NameMatch = *FuzzyScore;
1907 bool FromIndex =
false;
1911 Relevance.merge(*
Candidate.IndexResult);
1912 Origin |=
Candidate.IndexResult->Origin;
1914 if (!
Candidate.IndexResult->Type.empty())
1915 Relevance.HadSymbolType |=
true;
1916 if (PreferredType &&
1917 PreferredType->raw() ==
Candidate.IndexResult->Type) {
1918 Relevance.TypeMatchesPreferred =
true;
1924 if (PreferredType) {
1926 Recorder->CCSema->getASTContext(), *
Candidate.SemaResult)) {
1927 Relevance.HadSymbolType |=
true;
1928 if (PreferredType == CompletionType)
1929 Relevance.TypeMatchesPreferred =
true;
1941 CodeCompletion::Scores Scores = evaluateCompletion(
Quality, Relevance);
1942 if (Opts.RecordCCResult)
1943 Opts.RecordCCResult(toCodeCompletion(Bundle),
Quality, Relevance,
1946 dlog(
"CodeComplete: {0} ({1}) = {2}\n{3}{4}\n", First.Name,
1947 llvm::to_string(Origin), Scores.Total, llvm::to_string(
Quality),
1948 llvm::to_string(Relevance));
1951 NIndex += FromIndex;
1954 if (Candidates.push({std::move(Bundle), Scores}))
1958 CodeCompletion toCodeCompletion(
const CompletionCandidate::Bundle &Bundle) {
1959 std::optional<CodeCompletionBuilder>
Builder;
1960 for (
const auto &Item : Bundle) {
1961 CodeCompletionString *SemaCCS =
1962 Item.SemaResult ? Recorder->codeCompletionString(*Item.SemaResult)
1965 Builder.emplace(Recorder ? &Recorder->CCSema->getASTContext() :
nullptr,
1966 Item, SemaCCS, QueryScopes, *Inserter,
FileName,
1967 CCContextKind, Opts, IsUsingDeclaration, NextTokenKind);
1977 clang::CodeCompleteOptions CodeCompleteOptions::getClangCompleteOpts()
const {
1978 clang::CodeCompleteOptions Result;
1979 Result.IncludeCodePatterns = EnableSnippets;
1980 Result.IncludeMacros =
true;
1981 Result.IncludeGlobals =
true;
1986 Result.IncludeBriefComments =
false;
1991 Result.LoadExternal = !
Index;
1992 Result.IncludeFixIts = IncludeFixIts;
1999 assert(
Offset <= Content.size());
2000 StringRef Rest = Content.take_front(
Offset);
2005 while (!Rest.empty() && isAsciiIdentifierContinue(Rest.back()))
2006 Rest = Rest.drop_back();
2007 Result.Name = Content.slice(Rest.size(),
Offset);
2010 while (Rest.consume_back(
"::") && !Rest.endswith(
":"))
2011 while (!Rest.empty() && isAsciiIdentifierContinue(Rest.back()))
2012 Rest = Rest.drop_back();
2014 Content.slice(Rest.size(), Result.Name.begin() - Content.begin());
2023 llvm::StringRef Prefix,
2029 clang::CodeCompleteOptions Options;
2030 Options.IncludeGlobals =
false;
2031 Options.IncludeMacros =
false;
2032 Options.IncludeCodePatterns =
false;
2033 Options.IncludeBriefComments =
false;
2034 std::set<std::string> ParamNames;
2038 std::make_unique<ParamNameCollector>(Options, ParamNames), Options,
2042 if (ParamNames.empty())
2046 Range CompletionRange;
2050 CompletionRange.
end =
2052 Result.CompletionRange = CompletionRange;
2053 Result.Context = CodeCompletionContext::CCC_NaturalLanguage;
2054 for (llvm::StringRef
Name : ParamNames) {
2055 if (!
Name.startswith(Prefix))
2063 Result.Completions.push_back(Item);
2072 std::optional<unsigned>
2074 while (!Content.empty() && isAsciiIdentifierContinue(Content.back()))
2075 Content = Content.drop_back();
2076 Content = Content.rtrim();
2077 if (Content.endswith(
"/*"))
2078 return Content.size() - 2;
2079 return std::nullopt;
2089 elog(
"Code completion position was invalid {0}",
Offset.takeError());
2100 auto CommentPrefix = Content.substr(*OffsetBeforeComment + 2).trim();
2105 auto Flow = CodeCompleteFlow(
2107 SpecFuzzyFind, Opts);
2108 return (!
Preamble || Opts.RunParser == CodeCompleteOptions::NeverParse)
2113 PreamblePatch::createMacroPatch(
2124 elog(
"Signature help position was invalid {0}",
Offset.takeError());
2128 clang::CodeCompleteOptions Options;
2129 Options.IncludeGlobals =
false;
2130 Options.IncludeMacros =
false;
2131 Options.IncludeCodePatterns =
false;
2132 Options.IncludeBriefComments =
false;
2134 std::make_unique<SignatureHelpCollector>(Options, DocumentationFormat,
2137 {FileName, *Offset, Preamble,
2138 PreamblePatch::createFullPatch(FileName, ParseInput, Preamble),
2144 auto InTopLevelScope = [](
const NamedDecl &ND) {
2145 switch (ND.getDeclContext()->getDeclKind()) {
2146 case Decl::TranslationUnit:
2147 case Decl::Namespace:
2148 case Decl::LinkageSpec:
2155 auto InClassScope = [](
const NamedDecl &ND) {
2156 return ND.getDeclContext()->getDeclKind() == Decl::CXXRecord;
2167 if (llvm::isa<ObjCCategoryDecl>(&ND) || llvm::isa<ObjCCategoryImplDecl>(&ND))
2170 if (InTopLevelScope(ND))
2176 if (
const auto *EnumDecl = dyn_cast<clang::EnumDecl>(ND.getDeclContext()))
2177 return (InTopLevelScope(*EnumDecl) || InClassScope(*EnumDecl));
2184 const auto *InsertInclude = Includes.empty() ? nullptr : &Includes[0];
2185 LSP.
label = ((InsertInclude && InsertInclude->Insertion)
2186 ? Opts.IncludeIndicator.Insert
2187 : Opts.IncludeIndicator.NoInsert) +
2188 (Opts.ShowOrigins ?
"[" + llvm::to_string(Origin) +
"]" :
"") +
2192 LSP.
detail = BundleSize > 1
2193 ? std::string(llvm::formatv(
"[{0} overloads]", BundleSize))
2198 if (InsertInclude || Documentation) {
2203 Doc.
append(*Documentation);
2204 LSP.
documentation = renderDoc(Doc, Opts.DocumentationFormat);
2208 LSP.
textEdit = {CompletionTokenRange, RequiredQualifier +
Name};
2216 for (
const auto &
FixIt : FixIts) {
2224 if (Opts.EnableSnippets)
2235 : InsertTextFormat::PlainText;
2236 if (InsertInclude && InsertInclude->Insertion)
2252 <<
" (" << getCompletionKindString(R.
Context) <<
")"
2262 if (!
Line.consume_front(
"#"))
2265 if (!(
Line.consume_front(
"include_next") ||
Line.consume_front(
"include") ||
2266 Line.consume_front(
"import")))
2269 if (
Line.consume_front(
"<"))
2270 return Line.count(
'>') == 0;
2271 if (
Line.consume_front(
"\""))
2272 return Line.count(
'"') == 0;
2278 Content = Content.take_front(
Offset);
2279 auto Pos = Content.rfind(
'\n');
2280 if (
Pos != llvm::StringRef::npos)
2281 Content = Content.substr(
Pos + 1);
2284 if (Content.endswith(
".") || Content.endswith(
"->") ||
2285 Content.endswith(
"::") || Content.endswith(
"/*"))
2288 if ((Content.endswith(
"<") || Content.endswith(
"\"") ||
2289 Content.endswith(
"/")) &&
2294 return !Content.empty() && (isAsciiIdentifierContinue(Content.back()) ||
2295 !llvm::isASCII(Content.back()));