Index: clangd/Quality.h =================================================================== --- clangd/Quality.h +++ clangd/Quality.h @@ -87,6 +87,7 @@ 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. URIDistance *FileProximityMatch = nullptr; /// These are used to calculate proximity between the index symbol and the Index: clangd/Quality.cpp =================================================================== --- clangd/Quality.cpp +++ clangd/Quality.cpp @@ -299,6 +299,7 @@ : 0.6; SemaFileProximityScore = std::max(DeclProximity, SemaFileProximityScore); IsInstanceMember |= isInstanceMember(SemaCCResult.Declaration); + InBaseClass |= SemaCCResult.InBaseClass; } // Declarations are scoped, others (like macros) are assumed global. @@ -375,6 +376,9 @@ Score *= 0.5; } + if (InBaseClass) + Score *= 0.7; + // Penalize for FixIts. if (NeedsFixIts) Score *= 0.5; Index: unittests/clangd/QualityTests.cpp =================================================================== --- unittests/clangd/QualityTests.cpp +++ unittests/clangd/QualityTests.cpp @@ -184,7 +184,13 @@ // The injected class name is treated as the outer class name. Relevance = {}; Relevance.merge(CodeCompletionResult(&findDecl(AST, "S::S"), 42)); - EXPECT_EQ(Relevance.Scope, SymbolRelevanceSignals::GlobalScope); + + Relevance = {}; + EXPECT_FALSE(Relevance.InBaseClass); + auto BaseMember = CodeCompletionResult(&findAnyDecl(AST, "y"), 42); + BaseMember.InBaseClass = true; + Relevance.merge(Member); + EXPECT_TRUE(Relevance.InBaseClass); } // Do the signals move the scores in the direction we expect? @@ -276,6 +282,10 @@ EXPECT_LT(Instance.evaluate(), Default.evaluate()); Instance.IsInstanceMember = true; EXPECT_EQ(Instance.evaluate(), Default.evaluate()); + + SymbolRelevanceSignals InBaseClass; + InBaseClass.InBaseClass = true; + EXPECT_LT(InBaseClass.evaluate(), Default.evaluate()); } TEST(QualityTests, ScopeProximity) {