diff --git a/clang-tools-extra/clangd/index/Index.h b/clang-tools-extra/clangd/index/Index.h --- a/clang-tools-extra/clangd/index/Index.h +++ b/clang-tools-extra/clangd/index/Index.h @@ -107,7 +107,9 @@ /// /// Results should be returned in arbitrary order. /// The returned result must be deep-copied if it's used outside Callback. - virtual void refs(const RefsRequest &Req, + /// + /// Returns true if there will be more results (limited by Req.Limit); + virtual bool refs(const RefsRequest &Req, llvm::function_ref Callback) const = 0; /// Finds all relations (S, P, O) stored in the index such that S is among @@ -136,7 +138,7 @@ llvm::function_ref) const override; void lookup(const LookupRequest &, llvm::function_ref) const override; - void refs(const RefsRequest &, + bool refs(const RefsRequest &, llvm::function_ref) const override; void relations(const RelationsRequest &, llvm::function_ref) diff --git a/clang-tools-extra/clangd/index/Index.cpp b/clang-tools-extra/clangd/index/Index.cpp --- a/clang-tools-extra/clangd/index/Index.cpp +++ b/clang-tools-extra/clangd/index/Index.cpp @@ -65,7 +65,7 @@ llvm::function_ref CB) const { return snapshot()->lookup(R, CB); } -void SwapIndex::refs(const RefsRequest &R, +bool SwapIndex::refs(const RefsRequest &R, llvm::function_ref CB) const { return snapshot()->refs(R, CB); } diff --git a/clang-tools-extra/clangd/index/MemIndex.h b/clang-tools-extra/clangd/index/MemIndex.h --- a/clang-tools-extra/clangd/index/MemIndex.h +++ b/clang-tools-extra/clangd/index/MemIndex.h @@ -55,7 +55,7 @@ void lookup(const LookupRequest &Req, llvm::function_ref Callback) const override; - void refs(const RefsRequest &Req, + bool refs(const RefsRequest &Req, llvm::function_ref Callback) const override; void relations(const RelationsRequest &Req, diff --git a/clang-tools-extra/clangd/index/MemIndex.cpp b/clang-tools-extra/clangd/index/MemIndex.cpp --- a/clang-tools-extra/clangd/index/MemIndex.cpp +++ b/clang-tools-extra/clangd/index/MemIndex.cpp @@ -67,22 +67,30 @@ } } -void MemIndex::refs(const RefsRequest &Req, +bool MemIndex::refs(const RefsRequest &Req, llvm::function_ref Callback) const { trace::Span Tracer("MemIndex refs"); uint32_t Remaining = Req.Limit.getValueOr(std::numeric_limits::max()); + bool More = false; for (const auto &ReqID : Req.IDs) { auto SymRefs = Refs.find(ReqID); if (SymRefs == Refs.end()) continue; for (const auto &O : SymRefs->second) { - if (Remaining > 0 && static_cast(Req.Filter & O.Kind)) { + if (!static_cast(Req.Filter & O.Kind)) + continue; + if (Remaining == 0) { + More = true; + break; + } + if (Remaining > 0) { --Remaining; Callback(O); } } } + return More; } void MemIndex::relations( diff --git a/clang-tools-extra/clangd/index/Merge.h b/clang-tools-extra/clangd/index/Merge.h --- a/clang-tools-extra/clangd/index/Merge.h +++ b/clang-tools-extra/clangd/index/Merge.h @@ -40,7 +40,7 @@ llvm::function_ref) const override; void lookup(const LookupRequest &, llvm::function_ref) const override; - void refs(const RefsRequest &, + bool refs(const RefsRequest &, llvm::function_ref) const override; void relations(const RelationsRequest &, llvm::function_ref) diff --git a/clang-tools-extra/clangd/index/Merge.cpp b/clang-tools-extra/clangd/index/Merge.cpp --- a/clang-tools-extra/clangd/index/Merge.cpp +++ b/clang-tools-extra/clangd/index/Merge.cpp @@ -89,9 +89,10 @@ Callback(*Sym); } -void MergedIndex::refs(const RefsRequest &Req, +bool MergedIndex::refs(const RefsRequest &Req, llvm::function_ref Callback) const { trace::Span Tracer("MergedIndex refs"); + bool More = false; uint32_t Remaining = Req.Limit.getValueOr(std::numeric_limits::max()); // We don't want duplicated refs from the static/dynamic indexes, @@ -103,21 +104,26 @@ // refs were removed (we will report stale ones from the static index). // Ultimately we should explicit check which index has the file instead. llvm::StringSet<> DynamicIndexFileURIs; - Dynamic->refs(Req, [&](const Ref &O) { + More |= Dynamic->refs(Req, [&](const Ref &O) { DynamicIndexFileURIs.insert(O.Location.FileURI); Callback(O); --Remaining; }); - if (Remaining == 0) - return; + if (Remaining == 0 && More) + return More; // We return less than Req.Limit if static index returns more refs for dirty // files. - Static->refs(Req, [&](const Ref &O) { - if (Remaining > 0 && !DynamicIndexFileURIs.count(O.Location.FileURI)) { + More |= Static->refs(Req, [&](const Ref &O) { + if (DynamicIndexFileURIs.count(O.Location.FileURI)) + return; // ignore refs that have been seen from dynamic index. + if (Remaining == 0) + More = true; + if (Remaining > 0) { --Remaining; Callback(O); } }); + return More; } void MergedIndex::relations( diff --git a/clang-tools-extra/clangd/index/dex/Dex.h b/clang-tools-extra/clangd/index/dex/Dex.h --- a/clang-tools-extra/clangd/index/dex/Dex.h +++ b/clang-tools-extra/clangd/index/dex/Dex.h @@ -77,7 +77,7 @@ void lookup(const LookupRequest &Req, llvm::function_ref Callback) const override; - void refs(const RefsRequest &Req, + bool refs(const RefsRequest &Req, llvm::function_ref Callback) const override; void relations(const RelationsRequest &Req, diff --git a/clang-tools-extra/clangd/index/dex/Dex.cpp b/clang-tools-extra/clangd/index/dex/Dex.cpp --- a/clang-tools-extra/clangd/index/dex/Dex.cpp +++ b/clang-tools-extra/clangd/index/dex/Dex.cpp @@ -249,18 +249,26 @@ } } -void Dex::refs(const RefsRequest &Req, +bool Dex::refs(const RefsRequest &Req, llvm::function_ref Callback) const { trace::Span Tracer("Dex refs"); uint32_t Remaining = Req.Limit.getValueOr(std::numeric_limits::max()); + bool More = false; for (const auto &ID : Req.IDs) for (const auto &Ref : Refs.lookup(ID)) { - if (Remaining > 0 && static_cast(Req.Filter & Ref.Kind)) { + if (!static_cast(Req.Filter & Ref.Kind)) + continue; + if (Remaining == 0) { + More = true; + break; + } + if (Remaining > 0) { --Remaining; Callback(Ref); } } + return More; } void Dex::relations( diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp --- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp +++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp @@ -1193,8 +1193,10 @@ void lookup(const LookupRequest &, llvm::function_ref) const override {} - void refs(const RefsRequest &, - llvm::function_ref) const override {} + bool refs(const RefsRequest &, + llvm::function_ref) const override { + return false; + } void relations(const RelationsRequest &, llvm::function_ref) diff --git a/clang-tools-extra/clangd/unittests/DexTests.cpp b/clang-tools-extra/clangd/unittests/DexTests.cpp --- a/clang-tools-extra/clangd/unittests/DexTests.cpp +++ b/clang-tools-extra/clangd/unittests/DexTests.cpp @@ -687,14 +687,18 @@ Req.Filter = RefKind::Declaration | RefKind::Definition; std::vector Files; - Dex(std::vector{Foo, Bar}, Refs, RelationSlab()) - .refs(Req, [&](const Ref &R) { Files.push_back(R.Location.FileURI); }); + EXPECT_FALSE(Dex(std::vector{Foo, Bar}, Refs, RelationSlab()) + .refs(Req, [&](const Ref &R) { + Files.push_back(R.Location.FileURI); + })); EXPECT_THAT(Files, UnorderedElementsAre("foo.h", "foo.cc")); Req.Limit = 1; Files.clear(); - Dex(std::vector{Foo, Bar}, Refs, RelationSlab()) - .refs(Req, [&](const Ref &R) { Files.push_back(R.Location.FileURI); }); + EXPECT_TRUE(Dex(std::vector{Foo, Bar}, Refs, RelationSlab()) + .refs(Req, [&](const Ref &R) { + Files.push_back(R.Location.FileURI); + })); EXPECT_THAT(Files, ElementsAre(AnyOf("foo.h", "foo.cc"))); } diff --git a/clang-tools-extra/clangd/unittests/IndexTests.cpp b/clang-tools-extra/clangd/unittests/IndexTests.cpp --- a/clang-tools-extra/clangd/unittests/IndexTests.cpp +++ b/clang-tools-extra/clangd/unittests/IndexTests.cpp @@ -389,7 +389,8 @@ RefsRequest Request; Request.IDs = {Foo.ID}; RefSlab::Builder Results; - Merge.refs(Request, [&](const Ref &O) { Results.insert(Foo.ID, O); }); + EXPECT_FALSE( + Merge.refs(Request, [&](const Ref &O) { Results.insert(Foo.ID, O); })); EXPECT_THAT( std::move(Results).build(), ElementsAre(Pair( @@ -400,7 +401,8 @@ Request.Limit = 1; RefSlab::Builder Results2; - Merge.refs(Request, [&](const Ref &O) { Results2.insert(Foo.ID, O); }); + EXPECT_TRUE( + Merge.refs(Request, [&](const Ref &O) { Results2.insert(Foo.ID, O); })); EXPECT_THAT(std::move(Results2).build(), ElementsAre(Pair( _, ElementsAre(AnyOf(FileURI("unittest:///test.cc"), diff --git a/clang-tools-extra/clangd/unittests/XRefsTests.cpp b/clang-tools-extra/clangd/unittests/XRefsTests.cpp --- a/clang-tools-extra/clangd/unittests/XRefsTests.cpp +++ b/clang-tools-extra/clangd/unittests/XRefsTests.cpp @@ -2161,9 +2161,10 @@ TEST(FindReferences, NoQueryForLocalSymbols) { struct RecordingIndex : public MemIndex { mutable Optional> RefIDs; - void refs(const RefsRequest &Req, + bool refs(const RefsRequest &Req, llvm::function_ref) const override { RefIDs = Req.IDs; + return false; } };