usaxena95 created this revision.
usaxena95 added a reviewer: sammccall.
Herald added subscribers: cfe-commits, kadircet, arphaman, jkorous, MaskRay, 
ilya-biryukov.
Herald added a project: clang.

Current implementation of heuristic-based scoring function also contains
computation of derived signals (e.g. whether name contains a word from
context, computing file distances, scope distances.)
This is an attempt to separate out the logic for computation of derived
signals from the scoring function.
This will allow us to have a clean API for scoring functions that will
take only concrete code completion signals as input.

This only refactors Name and ContextWords which are essentially used to
compute whether the name contains a context word or not. If this looks
good then this will be done for other properties that are more of a
utility (used to compute other signals) than a signal themselves.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D79500

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/FindSymbols.cpp
  clang-tools-extra/clangd/Quality.cpp
  clang-tools-extra/clangd/Quality.h
  clang-tools-extra/clangd/XRefs.cpp
  clang-tools-extra/clangd/unittests/QualityTests.cpp

Index: clang-tools-extra/clangd/unittests/QualityTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/QualityTests.cpp
+++ clang-tools-extra/clangd/unittests/QualityTests.cpp
@@ -294,13 +294,17 @@
   EXPECT_LT(InBaseClass.evaluate(), Default.evaluate());
 
   llvm::StringSet<> Words = {"one", "two", "three"};
+
   SymbolRelevanceSignals WithoutMatchingWord;
-  WithoutMatchingWord.ContextWords = &Words;
-  WithoutMatchingWord.Name = "four";
+  WithoutMatchingWord.Util.ContextWords = &Words;
+  WithoutMatchingWord.Util.Name = "four";
+  WithoutMatchingWord.calcNameMatchesContext();
   EXPECT_EQ(WithoutMatchingWord.evaluate(), Default.evaluate());
+
   SymbolRelevanceSignals WithMatchingWord;
-  WithMatchingWord.ContextWords = &Words;
-  WithMatchingWord.Name = "TheTwoTowers";
+  WithMatchingWord.Util.ContextWords = &Words;
+  WithMatchingWord.Util.Name = "TheTwoTowers";
+  WithMatchingWord.calcNameMatchesContext();
   EXPECT_GT(WithMatchingWord.evaluate(), Default.evaluate());
 }
 
Index: clang-tools-extra/clangd/XRefs.cpp
===================================================================
--- clang-tools-extra/clangd/XRefs.cpp
+++ clang-tools-extra/clangd/XRefs.cpp
@@ -427,7 +427,6 @@
     SymbolQualitySignals Quality;
     Quality.merge(Sym);
     SymbolRelevanceSignals Relevance;
-    Relevance.Name = Sym.Name;
     Relevance.Query = SymbolRelevanceSignals::Generic;
     Relevance.merge(Sym);
     auto Score =
Index: clang-tools-extra/clangd/Quality.h
===================================================================
--- clang-tools-extra/clangd/Quality.h
+++ clang-tools-extra/clangd/Quality.h
@@ -85,17 +85,18 @@
 
 /// Attributes of a symbol-query pair that affect how much we like it.
 struct SymbolRelevanceSignals {
-  /// The name of the symbol (for ContextWords). Must be explicitly assigned.
-  llvm::StringRef Name;
+  /// Whether name contains some word in context. Must not be set explicitly.
+  /// Computed by calcNameMatchesContext().
+  bool NameMatchesContext = false;
   /// 0-1+ fuzzy-match score for unqualified name. Must be explicitly assigned.
   float NameMatch = 1;
-  /// Lowercase words relevant to the context (e.g. near the completion point).
-  llvm::StringSet<>* ContextWords = nullptr;
+
   bool Forbidden = false; // Unavailable (e.g const) or inaccessible (private).
   /// Whether fixits needs to be applied for that completion or not.
   bool NeedsFixIts = false;
   bool InBaseClass = false; // A member from base class of the accessed class.
 
+  // FIXME: Move this property to utilites.
   URIDistance *FileProximityMatch = nullptr;
   /// These are used to calculate proximity between the index symbol and the
   /// query.
@@ -105,6 +106,7 @@
   /// Proximity between best declaration and the query. [0-1], 1 is closest.
   float SemaFileProximityScore = 0;
 
+  // FIXME: Move this property to utilites.
   // Scope proximity is only considered (both index and sema) when this is set.
   ScopeDistance *ScopeProximityMatch = nullptr;
   llvm::Optional<llvm::StringRef> SymbolScope;
@@ -136,6 +138,20 @@
   // Whether the item matches the type expected in the completion context.
   bool TypeMatchesPreferred = false;
 
+  // Properties and utilites used to compute derived signals e.g.
+  // IsNameInContext. These are not directly used by the scoring function.
+  struct Utility {
+    /// The name of the symbol (for ContextWords). Must be explicitly assigned.
+    llvm::StringRef Name;
+
+    /// Lowercase words relevant to the context (e.g. near the completion
+    /// point).
+    llvm::StringSet<> *ContextWords = nullptr;
+  } Util;
+
+  // Sets NameMatchesContext to true iff Name contains any of the ContextWords.
+  void calcNameMatchesContext();
+
   void merge(const CodeCompletionResult &SemaResult);
   void merge(const Symbol &IndexResult);
 
Index: clang-tools-extra/clangd/Quality.cpp
===================================================================
--- clang-tools-extra/clangd/Quality.cpp
+++ clang-tools-extra/clangd/Quality.cpp
@@ -348,6 +348,10 @@
   return llvm::None;
 }
 
+void SymbolRelevanceSignals::calcNameMatchesContext() {
+  NameMatchesContext = wordMatching(Util.Name, Util.ContextWords).hasValue();
+}
+
 float SymbolRelevanceSignals::evaluate() const {
   float Score = 1;
 
@@ -369,7 +373,7 @@
     Score *=
         SemaSaysInScope ? 2.0 : scopeBoost(*ScopeProximityMatch, SymbolScope);
 
-  if (wordMatching(Name, ContextWords))
+  if (NameMatchesContext)
     Score *= 1.5;
 
   // Symbols like local variables may only be referenced within their scope.
@@ -428,12 +432,12 @@
 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
                               const SymbolRelevanceSignals &S) {
   OS << llvm::formatv("=== Symbol relevance: {0}\n", S.evaluate());
-  OS << llvm::formatv("\tName: {0}\n", S.Name);
+  OS << llvm::formatv("\tName: {0}\n", S.Util.Name);
   OS << llvm::formatv("\tName match: {0}\n", S.NameMatch);
-  if (S.ContextWords)
+  if (S.Util.ContextWords)
     OS << llvm::formatv(
         "\tMatching context word: {0}\n",
-        wordMatching(S.Name, S.ContextWords).getValueOr("<none>"));
+        wordMatching(S.Util.Name, S.Util.ContextWords).getValueOr("<none>"));
   OS << llvm::formatv("\tForbidden: {0}\n", S.Forbidden);
   OS << llvm::formatv("\tNeedsFixIts: {0}\n", S.NeedsFixIts);
   OS << llvm::formatv("\tIsInstanceMember: {0}\n", S.IsInstanceMember);
Index: clang-tools-extra/clangd/FindSymbols.cpp
===================================================================
--- clang-tools-extra/clangd/FindSymbols.cpp
+++ clang-tools-extra/clangd/FindSymbols.cpp
@@ -109,7 +109,6 @@
     SymbolQualitySignals Quality;
     Quality.merge(Sym);
     SymbolRelevanceSignals Relevance;
-    Relevance.Name = Sym.Name;
     Relevance.Query = SymbolRelevanceSignals::Generic;
     if (auto NameMatch = Filter.match(Sym.Name))
       Relevance.NameMatch = *NameMatch;
Index: clang-tools-extra/clangd/CodeComplete.cpp
===================================================================
--- clang-tools-extra/clangd/CodeComplete.cpp
+++ clang-tools-extra/clangd/CodeComplete.cpp
@@ -1612,14 +1612,16 @@
     SymbolQualitySignals Quality;
     SymbolRelevanceSignals Relevance;
     Relevance.Context = CCContextKind;
-    Relevance.Name = Bundle.front().Name;
     Relevance.Query = SymbolRelevanceSignals::CodeComplete;
     Relevance.FileProximityMatch = FileProximity.getPointer();
     if (ScopeProximity)
       Relevance.ScopeProximityMatch = ScopeProximity.getPointer();
     if (PreferredType)
       Relevance.HadContextType = true;
-    Relevance.ContextWords = &ContextWords;
+
+    Relevance.Util.Name = Bundle.front().Name;
+    Relevance.Util.ContextWords = &ContextWords;
+    Relevance.calcNameMatchesContext();
 
     auto &First = Bundle.front();
     if (auto FuzzyScore = fuzzyScore(First))
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to