Index: clangd/Quality.cpp =================================================================== --- clangd/Quality.cpp +++ clangd/Quality.cpp @@ -41,6 +41,17 @@ return false; } +static bool hasUsingDeclInMainFile(const CodeCompletionResult &R) { + const auto &Context = R.Declaration->getASTContext(); + const auto &SourceMgr = Context.getSourceManager(); + if (R.ShadowDecl) { + const auto Loc = SourceMgr.getExpansionLoc(R.ShadowDecl->getLocation()); + if (SourceMgr.isWrittenInMainFile(Loc)) + return true; + } + return false; +} + static SymbolQualitySignals::SymbolCategory categorize(const NamedDecl &ND) { class Switch : public ConstDeclVisitor { @@ -231,8 +242,10 @@ // We boost things that have decls in the main file. We give a fixed score // for all other declarations in sema as they are already included in the // translation unit. - float DeclProximity = - hasDeclInMainFile(*SemaCCResult.Declaration) ? 1.0 : 0.6; + float DeclProximity = (hasDeclInMainFile(*SemaCCResult.Declaration) || + hasUsingDeclInMainFile(SemaCCResult)) + ? 1.0 + : 0.6; SemaProximityScore = std::max(DeclProximity, SemaProximityScore); } Index: unittests/clangd/QualityTests.cpp =================================================================== --- unittests/clangd/QualityTests.cpp +++ unittests/clangd/QualityTests.cpp @@ -77,18 +77,31 @@ TEST(QualityTests, SymbolRelevanceSignalExtraction) { TestTU Test; Test.HeaderCode = R"cpp( - int header(); - int header_main(); - )cpp"; + int header(); + int header_main(); + + namespace hdr { class Bar {}; } // namespace hdr + + #define DEFINE_FLAG(X) \ + namespace flags { \ + int FLAGS_##X; \ + } \ + + DEFINE_FLAG(FOO) + )cpp"; Test.Code = R"cpp( - int ::header_main() {} - int main(); + using hdr::Bar; - [[deprecated]] - int deprecated() { return 0; } + using flags::FLAGS_FOO; + + int ::header_main() {} + int main(); - namespace { struct X { void y() { int z; } }; } - struct S{} + [[deprecated]] + int deprecated() { return 0; } + + namespace { struct X { void y() { int z; } }; } + struct S{} )cpp"; auto AST = Test.build(); @@ -111,6 +124,32 @@ EXPECT_FLOAT_EQ(Relevance.SemaProximityScore, 1.0f) << "Current file and header"; + auto constructShadowDeclCompletionResult = [&](const std::string DeclName) { + auto *Shadow = + *dyn_cast( + &findAnyDecl(AST, + [&](const NamedDecl &ND) { + if (const UsingDecl *Using = + dyn_cast(&ND)) + if (Using->shadow_size() && + Using->getQualifiedNameAsString() == DeclName) + return true; + return false; + })) + ->shadow_begin(); + CodeCompletionResult Result(Shadow->getTargetDecl(), 42); + Result.ShadowDecl = Shadow; + return Result; + }; + + Relevance = {}; + Relevance.merge(constructShadowDeclCompletionResult("Bar")); + EXPECT_FLOAT_EQ(Relevance.SemaProximityScore, 1.0f) + << "Using declaration in main file"; + Relevance.merge(constructShadowDeclCompletionResult("FLAGS_FOO")); + EXPECT_FLOAT_EQ(Relevance.SemaProximityScore, 1.0f) + << "Using declaration in main file"; + Relevance = {}; Relevance.merge(CodeCompletionResult(&findAnyDecl(AST, "X"), 42)); EXPECT_EQ(Relevance.Scope, SymbolRelevanceSignals::FileScope); @@ -191,7 +230,8 @@ } TEST(QualityTests, SortText) { - EXPECT_LT(sortText(std::numeric_limits::infinity()), sortText(1000.2f)); + EXPECT_LT(sortText(std::numeric_limits::infinity()), + sortText(1000.2f)); EXPECT_LT(sortText(1000.2f), sortText(1)); EXPECT_LT(sortText(1), sortText(0.3f)); EXPECT_LT(sortText(0.3f), sortText(0));