Index: clangd/CodeComplete.cpp =================================================================== --- clangd/CodeComplete.cpp +++ clangd/CodeComplete.cpp @@ -24,6 +24,7 @@ #include "CodeCompletionStrings.h" #include "Compiler.h" #include "Diagnostics.h" +#include "ExpectedTypes.h" #include "FileDistance.h" #include "FuzzyMatch.h" #include "Headers.h" @@ -1225,6 +1226,7 @@ std::vector QueryScopes; // Initialized once Sema runs. // Initialized once QueryScopes is initialized, if there are scopes. Optional ScopeProximity; + llvm::Optional PreferredType; // Initialized once Sema runs. // Whether to query symbols from any scope. Initialized once Sema runs. bool AllScopes = false; // Include-insertion and proximity scoring rely on the include structure. @@ -1354,6 +1356,12 @@ getQueryScopes(Recorder->CCContext, *Recorder->CCSema, Opts); if (!QueryScopes.empty()) ScopeProximity.emplace(QueryScopes); + PreferredType = + OpaqueType::fromType(Recorder->CCSema->getASTContext(), + Recorder->CCContext.getPreferredType()); + if (PreferredType) + vlog("Added an expected type for {1}", + Recorder->CCContext.getPreferredType().getAsString()); // Sema provides the needed context to query the index. // FIXME: in addition to querying for extra/overlapping symbols, we should // explicitly request symbols corresponding to Sema results. @@ -1506,10 +1514,24 @@ Relevance.merge(*Candidate.IndexResult); Origin |= Candidate.IndexResult->Origin; FromIndex = true; + if (PreferredType && + PreferredType->raw() == Candidate.IndexResult->Type) { + vlog("Types matched in index for {0}", Candidate.Name); + Relevance.TypeMatchesPreferred = true; + } } if (Candidate.SemaResult) { Quality.merge(*Candidate.SemaResult); Relevance.merge(*Candidate.SemaResult); + if (PreferredType) { + if (auto CompletionType = OpaqueType::fromCompletionResult( + Recorder->CCSema->getASTContext(), *Candidate.SemaResult)) { + if (PreferredType == CompletionType) { + vlog("Types matched in index for {0}", Candidate.Name); + Relevance.TypeMatchesPreferred = true; + } + } + } Origin |= SymbolOrigin::AST; } } Index: clangd/Quality.h =================================================================== --- clangd/Quality.h +++ clangd/Quality.h @@ -28,6 +28,7 @@ #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_QUALITY_H #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_QUALITY_H +#include "ExpectedTypes.h" #include "FileDistance.h" #include "clang/Sema/CodeCompleteConsumer.h" #include "llvm/ADT/ArrayRef.h" @@ -122,6 +123,9 @@ // Whether symbol is an instance member of a class. bool IsInstanceMember = false; + /// Whether the item matches the type expected in the completion context. + bool TypeMatchesPreferred = false; + void merge(const CodeCompletionResult &SemaResult); void merge(const Symbol &IndexResult); Index: clangd/Quality.cpp =================================================================== --- clangd/Quality.cpp +++ clangd/Quality.cpp @@ -369,6 +369,9 @@ } } + if (TypeMatchesPreferred) + Score *= 5.0; + // Penalize non-instance members when they are accessed via a class instance. if (!IsInstanceMember && (Context == CodeCompletionContext::CCC_DotMemberAccess ||