[clangd] Add type boosting in code completion
Reviewers: sammccall, ioeric Reviewed By: sammccall Subscribers: MaskRay, jkorous, arphaman, kadircet, cfe-commits Differential Revision: https://reviews.llvm.org/D52276 llvm-svn: 347562
This commit is contained in:
parent
f94c8f0d1b
commit
647da3e8a5
|
@ -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 @@ class CodeCompleteFlow {
|
|||
std::vector<std::string> QueryScopes; // Initialized once Sema runs.
|
||||
// Initialized once QueryScopes is initialized, if there are scopes.
|
||||
Optional<ScopeDistance> ScopeProximity;
|
||||
llvm::Optional<OpaqueType> 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.
|
||||
|
@ -1302,9 +1304,12 @@ public:
|
|||
Inserter.reset(); // Make sure this doesn't out-live Clang.
|
||||
SPAN_ATTACH(Tracer, "sema_completion_kind",
|
||||
getCompletionKindString(Recorder->CCContext.getKind()));
|
||||
log("Code complete: sema context {0}, query scopes [{1}] (AnyScope={2})",
|
||||
log("Code complete: sema context {0}, query scopes [{1}] (AnyScope={2}), "
|
||||
"expected type {3}",
|
||||
getCompletionKindString(Recorder->CCContext.getKind()),
|
||||
join(QueryScopes.begin(), QueryScopes.end(), ","), AllScopes);
|
||||
join(QueryScopes.begin(), QueryScopes.end(), ","), AllScopes,
|
||||
PreferredType ? Recorder->CCContext.getPreferredType().getAsString()
|
||||
: "<none>");
|
||||
});
|
||||
|
||||
Recorder = RecorderOwner.get();
|
||||
|
@ -1354,6 +1359,9 @@ private:
|
|||
getQueryScopes(Recorder->CCContext, *Recorder->CCSema, Opts);
|
||||
if (!QueryScopes.empty())
|
||||
ScopeProximity.emplace(QueryScopes);
|
||||
PreferredType =
|
||||
OpaqueType::fromType(Recorder->CCSema->getASTContext(),
|
||||
Recorder->CCContext.getPreferredType());
|
||||
// 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.
|
||||
|
@ -1492,6 +1500,8 @@ private:
|
|||
Relevance.FileProximityMatch = FileProximity.getPointer();
|
||||
if (ScopeProximity)
|
||||
Relevance.ScopeProximityMatch = ScopeProximity.getPointer();
|
||||
if (PreferredType)
|
||||
Relevance.HadContextType = true;
|
||||
|
||||
auto &First = Bundle.front();
|
||||
if (auto FuzzyScore = fuzzyScore(First))
|
||||
|
@ -1506,10 +1516,24 @@ private:
|
|||
Relevance.merge(*Candidate.IndexResult);
|
||||
Origin |= Candidate.IndexResult->Origin;
|
||||
FromIndex = true;
|
||||
if (!Candidate.IndexResult->Type.empty())
|
||||
Relevance.HadSymbolType |= true;
|
||||
if (PreferredType &&
|
||||
PreferredType->raw() == Candidate.IndexResult->Type) {
|
||||
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)) {
|
||||
Relevance.HadSymbolType |= true;
|
||||
if (PreferredType == CompletionType)
|
||||
Relevance.TypeMatchesPreferred = true;
|
||||
}
|
||||
}
|
||||
Origin |= SymbolOrigin::AST;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -369,6 +369,9 @@ float SymbolRelevanceSignals::evaluate() const {
|
|||
}
|
||||
}
|
||||
|
||||
if (TypeMatchesPreferred)
|
||||
Score *= 5.0;
|
||||
|
||||
// Penalize non-instance members when they are accessed via a class instance.
|
||||
if (!IsInstanceMember &&
|
||||
(Context == CodeCompletionContext::CCC_DotMemberAccess ||
|
||||
|
@ -412,6 +415,10 @@ raw_ostream &operator<<(raw_ostream &OS, const SymbolRelevanceSignals &S) {
|
|||
OS << formatv("\tIndex scope boost: {0}\n",
|
||||
scopeBoost(*S.ScopeProximityMatch, S.SymbolScope));
|
||||
|
||||
OS << formatv(
|
||||
"\tType matched preferred: {0} (Context type: {1}, Symbol type: {2}\n",
|
||||
S.TypeMatchesPreferred, S.HadContextType, S.HadSymbolType);
|
||||
|
||||
return OS;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,13 @@ struct SymbolRelevanceSignals {
|
|||
// Whether symbol is an instance member of a class.
|
||||
bool IsInstanceMember = false;
|
||||
|
||||
// Whether clang provided a preferred type in the completion context.
|
||||
bool HadContextType = false;
|
||||
// Whether a source completion item or a symbol had a type information.
|
||||
bool HadSymbolType = 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);
|
||||
|
||||
|
|
|
@ -494,6 +494,8 @@ struct FuzzyFindRequest {
|
|||
/// Paths should be absolute.
|
||||
std::vector<std::string> ProximityPaths;
|
||||
|
||||
// FIXME(ibiryukov): add expected type to the request.
|
||||
|
||||
bool operator==(const FuzzyFindRequest &Req) const {
|
||||
return std::tie(Query, Scopes, Limit, RestrictForCodeCompletion,
|
||||
ProximityPaths) ==
|
||||
|
|
Loading…
Reference in New Issue