usaxena95 updated this revision to Diff 294281.
usaxena95 added a comment.
Moved DF evaluation to Quality.cpp
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D88281/new/
https://reviews.llvm.org/D88281
Files:
clang-tools-extra/clangd/CodeComplete.cpp
clang-tools-extra/clangd/CodeComplete.h
clang-tools-extra/clangd/Quality.cpp
clang-tools-extra/clangd/Quality.h
clang-tools-extra/clangd/tool/ClangdMain.cpp
Index: clang-tools-extra/clangd/tool/ClangdMain.cpp
===================================================================
--- clang-tools-extra/clangd/tool/ClangdMain.cpp
+++ clang-tools-extra/clangd/tool/ClangdMain.cpp
@@ -167,6 +167,18 @@
Hidden,
};
+opt<CodeCompleteOptions::CodeCompletionRankingModel> RankingModel{
+ "ranking-model",
+ cat(Features),
+ desc("Model to use to rank code-completion items"),
+ values(clEnumValN(CodeCompleteOptions::Heuristics, "heuristic",
+ "Use hueristics to rank code completion items"),
+ clEnumValN(CodeCompleteOptions::DecisionForest, "df",
+ "Use Decision Forest model to rank completion items")),
+ init(CodeCompleteOptions().RankingModel),
+ Hidden,
+};
+
// FIXME: also support "plain" style where signatures are always omitted.
enum CompletionStyleFlag { Detailed, Bundled };
opt<CompletionStyleFlag> CompletionStyle{
@@ -739,6 +751,7 @@
CCOpts.EnableFunctionArgSnippets = EnableFunctionArgSnippets;
CCOpts.AllScopes = AllScopesCompletion;
CCOpts.RunParser = CodeCompletionParse;
+ CCOpts.RankingModel = RankingModel;
RealThreadsafeFS TFS;
std::vector<std::unique_ptr<config::Provider>> ProviderStack;
Index: clang-tools-extra/clangd/Quality.h
===================================================================
--- clang-tools-extra/clangd/Quality.h
+++ clang-tools-extra/clangd/Quality.h
@@ -136,6 +136,10 @@
// Whether the item matches the type expected in the completion context.
bool TypeMatchesPreferred = false;
+ /// Length of the unqualified partial name of Symbol typed in
+ /// CompletionPrefix.
+ unsigned FilterLength = 0;
+
/// Set of derived signals computed by calculateDerivedSignals(). Must not be
/// set explicitly.
struct DerivedSignals {
@@ -161,6 +165,8 @@
/// Combine symbol quality and relevance into a single score.
float evaluateSymbolAndRelevance(float SymbolQuality, float SymbolRelevance);
+float evaluateDecisionForest(const SymbolQualitySignals &Quality,
+ const SymbolRelevanceSignals &Relevance);
/// TopN<T> is a lossy container that preserves only the "best" N elements.
template <typename T, typename Compare = std::greater<T>> class TopN {
public:
Index: clang-tools-extra/clangd/Quality.cpp
===================================================================
--- clang-tools-extra/clangd/Quality.cpp
+++ clang-tools-extra/clangd/Quality.cpp
@@ -8,6 +8,7 @@
#include "Quality.h"
#include "AST.h"
+#include "CompletionModel.h"
#include "FileDistance.h"
#include "SourceCode.h"
#include "URI.h"
@@ -486,6 +487,33 @@
return SymbolQuality * SymbolRelevance;
}
+float evaluateDecisionForest(const SymbolQualitySignals &Quality,
+ const SymbolRelevanceSignals &Relevance) {
+ Example E;
+ E.setIsDeprecated(Quality.Deprecated);
+ E.setIsReservedName(Quality.ReservedName);
+ E.setIsImplementationDetail(Quality.ImplementationDetail);
+ E.setNumReferences(Quality.References);
+ E.setSymbolCategory(Quality.Category);
+
+ SymbolRelevanceSignals::DerivedSignals Derived =
+ Relevance.calculateDerivedSignals();
+ E.setIsNameInContext(Derived.NameMatchesContext);
+ E.setIsForbidden(Relevance.Forbidden);
+ E.setIsInBaseClass(Relevance.InBaseClass);
+ E.setFileProximityDistance(Derived.FileProximityDistance);
+ E.setSemaFileProximityScore(Relevance.SemaFileProximityScore);
+ E.setSymbolScopeDistance(Derived.ScopeProximityDistance);
+ E.setSemaSaysInScope(Relevance.SemaSaysInScope);
+ E.setScope(Relevance.Scope);
+ E.setContextKind(Relevance.Context);
+ E.setIsInstanceMember(Relevance.IsInstanceMember);
+ E.setHadContextType(Relevance.HadContextType);
+ E.setHadSymbolType(Relevance.HadSymbolType);
+ E.setTypeMatchesPreferred(Relevance.TypeMatchesPreferred);
+ E.setFilterLength(Relevance.FilterLength);
+ return Evaluate(E);
+}
// Produces an integer that sorts in the same order as F.
// That is: a < b <==> encodeFloat(a) < encodeFloat(b).
static uint32_t encodeFloat(float F) {
Index: clang-tools-extra/clangd/CodeComplete.h
===================================================================
--- clang-tools-extra/clangd/CodeComplete.h
+++ clang-tools-extra/clangd/CodeComplete.h
@@ -147,6 +147,12 @@
std::function<void(const CodeCompletion &, const SymbolQualitySignals &,
const SymbolRelevanceSignals &, float Score)>
RecordCCResult;
+
+ /// Model to use for ranking code completion candidates.
+ enum CodeCompletionRankingModel {
+ Heuristics,
+ DecisionForest,
+ } RankingModel = Heuristics;
};
// Semi-structured representation of a code-complete suggestion for our C++ API.
Index: clang-tools-extra/clangd/CodeComplete.cpp
===================================================================
--- clang-tools-extra/clangd/CodeComplete.cpp
+++ clang-tools-extra/clangd/CodeComplete.cpp
@@ -1625,6 +1625,39 @@
return Filter->match(C.Name);
}
+ CodeCompletion::Scores
+ evaluateCompletion(const SymbolQualitySignals &Quality,
+ const SymbolRelevanceSignals &Relevance) {
+ using RM = CodeCompleteOptions::CodeCompletionRankingModel;
+ CodeCompletion::Scores Scores;
+ switch (Opts.RankingModel) {
+ case RM::Heuristics:
+ Scores.Quality = Quality.evaluate();
+ Scores.Relevance = Relevance.evaluate();
+ Scores.Total =
+ evaluateSymbolAndRelevance(Scores.Quality, Scores.Relevance);
+ // NameMatch is in fact a multiplier on total score, so rescoring is
+ // sound.
+ Scores.ExcludingName = Relevance.NameMatch
+ ? Scores.Total / Relevance.NameMatch
+ : Scores.Quality;
+ return Scores;
+
+ case RM::DecisionForest:
+ Scores.Quality = 0;
+ Scores.Relevance = 0;
+ Scores.ExcludingName = exp(evaluateDecisionForest(Quality, Relevance));
+ // NeedsFixIts is not part of the DecisionForest as generating training
+ // data that needs fixits is not-feasible.
+ if (Relevance.NeedsFixIts)
+ Scores.ExcludingName *= 0.5;
+ // NameMatch should be a multiplier on total score to support rescoring.
+ Scores.Total = Relevance.NameMatch * Scores.ExcludingName;
+ return Scores;
+ }
+ llvm_unreachable("Unhandled CodeCompletion ranking model.");
+ }
+
// Scores a candidate and adds it to the TopN structure.
void addCandidate(TopN<ScoredBundle, ScoredBundleGreater> &Candidates,
CompletionCandidate::Bundle Bundle) {
@@ -1632,6 +1665,7 @@
SymbolRelevanceSignals Relevance;
Relevance.Context = CCContextKind;
Relevance.Name = Bundle.front().Name;
+ Relevance.FilterLength = HeuristicPrefix.Name.size();
Relevance.Query = SymbolRelevanceSignals::CodeComplete;
Relevance.FileProximityMatch = FileProximity.getPointer();
if (ScopeProximity)
@@ -1680,15 +1714,7 @@
}
}
- CodeCompletion::Scores Scores;
- Scores.Quality = Quality.evaluate();
- Scores.Relevance = Relevance.evaluate();
- Scores.Total = evaluateSymbolAndRelevance(Scores.Quality, Scores.Relevance);
- // NameMatch is in fact a multiplier on total score, so rescoring is sound.
- Scores.ExcludingName = Relevance.NameMatch
- ? Scores.Total / Relevance.NameMatch
- : Scores.Quality;
-
+ CodeCompletion::Scores Scores = evaluateCompletion(Quality, Relevance);
if (Opts.RecordCCResult)
Opts.RecordCCResult(toCodeCompletion(Bundle), Quality, Relevance,
Scores.Total);
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits