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 cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits