aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHaojian Wu <hokein@google.com>2019-01-14 18:11:09 +0000
committerHaojian Wu <hokein@google.com>2019-01-14 18:11:09 +0000
commitc34f022bfed27bb608d784f1062709bbed5b710d (patch)
treed57602ac48b8662ef65cb16d761b90103bdcfccd /clang-tools-extra
parent[lldbsuite] Skip two more flaky tests on Windows (diff)
downloadllvm-project-c34f022bfed27bb608d784f1062709bbed5b710d.tar.gz
llvm-project-c34f022bfed27bb608d784f1062709bbed5b710d.tar.bz2
llvm-project-c34f022bfed27bb608d784f1062709bbed5b710d.zip
[clangd] Add Limit parameter for xref.
Reviewers: sammccall Subscribers: ilya-biryukov, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits Differential Revision: https://reviews.llvm.org/D56597 llvm-svn: 351081
Diffstat (limited to 'clang-tools-extra')
-rw-r--r--clang-tools-extra/clangd/ClangdLSPServer.cpp2
-rw-r--r--clang-tools-extra/clangd/ClangdServer.cpp8
-rw-r--r--clang-tools-extra/clangd/ClangdServer.h2
-rw-r--r--clang-tools-extra/clangd/XRefs.cpp46
-rw-r--r--clang-tools-extra/clangd/XRefs.h2
-rw-r--r--clang-tools-extra/clangd/index/Index.h4
-rw-r--r--clang-tools-extra/clangd/index/MemIndex.cpp9
-rw-r--r--clang-tools-extra/clangd/index/Merge.cpp12
-rw-r--r--clang-tools-extra/clangd/index/dex/Dex.cpp9
-rw-r--r--clang-tools-extra/unittests/clangd/DexTests.cpp12
-rw-r--r--clang-tools-extra/unittests/clangd/IndexTests.cpp10
-rw-r--r--clang-tools-extra/unittests/clangd/XRefsTests.cpp16
12 files changed, 92 insertions, 40 deletions
diff --git a/clang-tools-extra/clangd/ClangdLSPServer.cpp b/clang-tools-extra/clangd/ClangdLSPServer.cpp
index e84adebac449..80792eddc69a 100644
--- a/clang-tools-extra/clangd/ClangdLSPServer.cpp
+++ b/clang-tools-extra/clangd/ClangdLSPServer.cpp
@@ -710,7 +710,7 @@ void ClangdLSPServer::onChangeConfiguration(
void ClangdLSPServer::onReference(const ReferenceParams &Params,
Callback<std::vector<Location>> Reply) {
Server->findReferences(Params.textDocument.uri.file(), Params.position,
- std::move(Reply));
+ CCOpts.Limit, std::move(Reply));
}
void ClangdLSPServer::onSymbolInfo(const TextDocumentPositionParams &Params,
diff --git a/clang-tools-extra/clangd/ClangdServer.cpp b/clang-tools-extra/clangd/ClangdServer.cpp
index f799d6bc670e..53a27bdb91d5 100644
--- a/clang-tools-extra/clangd/ClangdServer.cpp
+++ b/clang-tools-extra/clangd/ClangdServer.cpp
@@ -500,13 +500,13 @@ void ClangdServer::documentSymbols(llvm::StringRef File,
Bind(Action, std::move(CB)));
}
-void ClangdServer::findReferences(PathRef File, Position Pos,
+void ClangdServer::findReferences(PathRef File, Position Pos, uint32_t Limit,
Callback<std::vector<Location>> CB) {
- auto Action = [Pos, this](Callback<std::vector<Location>> CB,
- llvm::Expected<InputsAndAST> InpAST) {
+ auto Action = [Pos, Limit, this](Callback<std::vector<Location>> CB,
+ llvm::Expected<InputsAndAST> InpAST) {
if (!InpAST)
return CB(InpAST.takeError());
- CB(clangd::findReferences(InpAST->AST, Pos, Index));
+ CB(clangd::findReferences(InpAST->AST, Pos, Limit, Index));
};
WorkScheduler.runWithAST("References", File, Bind(Action, std::move(CB)));
diff --git a/clang-tools-extra/clangd/ClangdServer.h b/clang-tools-extra/clangd/ClangdServer.h
index 4ce1506dfce6..213f042c83ef 100644
--- a/clang-tools-extra/clangd/ClangdServer.h
+++ b/clang-tools-extra/clangd/ClangdServer.h
@@ -181,7 +181,7 @@ public:
Callback<std::vector<DocumentSymbol>> CB);
/// Retrieve locations for symbol references.
- void findReferences(PathRef File, Position Pos,
+ void findReferences(PathRef File, Position Pos, uint32_t Limit,
Callback<std::vector<Location>> CB);
/// Run formatting for \p Rng inside \p File with content \p Code.
diff --git a/clang-tools-extra/clangd/XRefs.cpp b/clang-tools-extra/clangd/XRefs.cpp
index b07efe9d69da..29561dfe5a53 100644
--- a/clang-tools-extra/clangd/XRefs.cpp
+++ b/clang-tools-extra/clangd/XRefs.cpp
@@ -704,7 +704,9 @@ llvm::Optional<Hover> getHover(ParsedAST &AST, Position Pos) {
}
std::vector<Location> findReferences(ParsedAST &AST, Position Pos,
- const SymbolIndex *Index) {
+ uint32_t Limit, const SymbolIndex *Index) {
+ if (!Limit)
+ Limit = std::numeric_limits<uint32_t>::max();
std::vector<Location> Results;
const SourceManager &SM = AST.getASTContext().getSourceManager();
auto MainFilePath =
@@ -733,26 +735,30 @@ std::vector<Location> findReferences(ParsedAST &AST, Position Pos,
}
// Now query the index for references from other files.
- if (!Index)
- return Results;
- RefsRequest Req;
- for (const Decl *D : TargetDecls) {
- // Not all symbols can be referenced from outside (e.g. function-locals).
- // TODO: we could skip TU-scoped symbols here (e.g. static functions) if
- // we know this file isn't a header. The details might be tricky.
- if (D->getParentFunctionOrMethod())
- continue;
- if (auto ID = getSymbolID(D))
- Req.IDs.insert(*ID);
+ if (Index && Results.size() < Limit) {
+ RefsRequest Req;
+ Req.Limit = Limit;
+
+ for (const Decl *D : TargetDecls) {
+ // Not all symbols can be referenced from outside (e.g. function-locals).
+ // TODO: we could skip TU-scoped symbols here (e.g. static functions) if
+ // we know this file isn't a header. The details might be tricky.
+ if (D->getParentFunctionOrMethod())
+ continue;
+ if (auto ID = getSymbolID(D))
+ Req.IDs.insert(*ID);
+ }
+ if (Req.IDs.empty())
+ return Results;
+ Index->refs(Req, [&](const Ref &R) {
+ auto LSPLoc = toLSPLocation(R.Location, *MainFilePath);
+ // Avoid indexed results for the main file - the AST is authoritative.
+ if (LSPLoc && LSPLoc->uri.file() != *MainFilePath)
+ Results.push_back(std::move(*LSPLoc));
+ });
}
- if (Req.IDs.empty())
- return Results;
- Index->refs(Req, [&](const Ref &R) {
- auto LSPLoc = toLSPLocation(R.Location, *MainFilePath);
- // Avoid indexed results for the main file - the AST is authoritative.
- if (LSPLoc && LSPLoc->uri.file() != *MainFilePath)
- Results.push_back(std::move(*LSPLoc));
- });
+ if (Results.size() > Limit)
+ Results.resize(Limit);
return Results;
}
diff --git a/clang-tools-extra/clangd/XRefs.h b/clang-tools-extra/clangd/XRefs.h
index 77d602489f30..631879d63bf7 100644
--- a/clang-tools-extra/clangd/XRefs.h
+++ b/clang-tools-extra/clangd/XRefs.h
@@ -35,7 +35,9 @@ std::vector<DocumentHighlight> findDocumentHighlights(ParsedAST &AST,
llvm::Optional<Hover> getHover(ParsedAST &AST, Position Pos);
/// Returns reference locations of the symbol at a specified \p Pos.
+/// \p Limit limits the number of results returned (0 means no limit).
std::vector<Location> findReferences(ParsedAST &AST, Position Pos,
+ uint32_t Limit,
const SymbolIndex *Index = nullptr);
/// Get info about symbols at \p Pos.
diff --git a/clang-tools-extra/clangd/index/Index.h b/clang-tools-extra/clangd/index/Index.h
index 3957a7f6830d..cc4cf2a29c9b 100644
--- a/clang-tools-extra/clangd/index/Index.h
+++ b/clang-tools-extra/clangd/index/Index.h
@@ -476,6 +476,10 @@ struct LookupRequest {
struct RefsRequest {
llvm::DenseSet<SymbolID> IDs;
RefKind Filter = RefKind::All;
+ /// If set, limit the number of refers returned from the index. The index may
+ /// choose to return less than this, e.g. it tries to avoid returning stale
+ /// results.
+ llvm::Optional<uint32_t> Limit;
};
/// Interface for symbol indexes that can be used for searching or
diff --git a/clang-tools-extra/clangd/index/MemIndex.cpp b/clang-tools-extra/clangd/index/MemIndex.cpp
index 35352e6e6863..e4dc56c5afa1 100644
--- a/clang-tools-extra/clangd/index/MemIndex.cpp
+++ b/clang-tools-extra/clangd/index/MemIndex.cpp
@@ -69,13 +69,18 @@ void MemIndex::lookup(const LookupRequest &Req,
void MemIndex::refs(const RefsRequest &Req,
llvm::function_ref<void(const Ref &)> Callback) const {
trace::Span Tracer("MemIndex refs");
+ uint32_t Remaining =
+ Req.Limit.getValueOr(std::numeric_limits<uint32_t>::max());
for (const auto &ReqID : Req.IDs) {
auto SymRefs = Refs.find(ReqID);
if (SymRefs == Refs.end())
continue;
- for (const auto &O : SymRefs->second)
- if (static_cast<int>(Req.Filter & O.Kind))
+ for (const auto &O : SymRefs->second) {
+ if (Remaining > 0 && static_cast<int>(Req.Filter & O.Kind)) {
+ --Remaining;
Callback(O);
+ }
+ }
}
}
diff --git a/clang-tools-extra/clangd/index/Merge.cpp b/clang-tools-extra/clangd/index/Merge.cpp
index f599d757aa86..52f54e39dded 100644
--- a/clang-tools-extra/clangd/index/Merge.cpp
+++ b/clang-tools-extra/clangd/index/Merge.cpp
@@ -87,6 +87,8 @@ void MergedIndex::lookup(
void MergedIndex::refs(const RefsRequest &Req,
llvm::function_ref<void(const Ref &)> Callback) const {
trace::Span Tracer("MergedIndex refs");
+ uint32_t Remaining =
+ Req.Limit.getValueOr(std::numeric_limits<uint32_t>::max());
// We don't want duplicated refs from the static/dynamic indexes,
// and we can't reliably duplicate them because offsets may differ slightly.
// We consider the dynamic index authoritative and report all its refs,
@@ -99,10 +101,18 @@ void MergedIndex::refs(const RefsRequest &Req,
Dynamic->refs(Req, [&](const Ref &O) {
DynamicIndexFileURIs.insert(O.Location.FileURI);
Callback(O);
+ --Remaining;
});
+ assert(Remaining >= 0);
+ if (Remaining == 0)
+ return;
+ // We return less than Req.Limit if static index returns more refs for dirty
+ // files.
Static->refs(Req, [&](const Ref &O) {
- if (!DynamicIndexFileURIs.count(O.Location.FileURI))
+ if (Remaining > 0 && !DynamicIndexFileURIs.count(O.Location.FileURI)) {
+ --Remaining;
Callback(O);
+ }
});
}
diff --git a/clang-tools-extra/clangd/index/dex/Dex.cpp b/clang-tools-extra/clangd/index/dex/Dex.cpp
index 157d4668856a..c38706c65ce2 100644
--- a/clang-tools-extra/clangd/index/dex/Dex.cpp
+++ b/clang-tools-extra/clangd/index/dex/Dex.cpp
@@ -236,10 +236,15 @@ void Dex::lookup(const LookupRequest &Req,
void Dex::refs(const RefsRequest &Req,
llvm::function_ref<void(const Ref &)> Callback) const {
trace::Span Tracer("Dex refs");
+ uint32_t Remaining =
+ Req.Limit.getValueOr(std::numeric_limits<uint32_t>::max());
for (const auto &ID : Req.IDs)
- for (const auto &Ref : Refs.lookup(ID))
- if (static_cast<int>(Req.Filter & Ref.Kind))
+ for (const auto &Ref : Refs.lookup(ID)) {
+ if (Remaining > 0 && static_cast<int>(Req.Filter & Ref.Kind)) {
+ --Remaining;
Callback(Ref);
+ }
+ }
}
size_t Dex::estimateMemoryUsage() const {
diff --git a/clang-tools-extra/unittests/clangd/DexTests.cpp b/clang-tools-extra/unittests/clangd/DexTests.cpp
index 6c347b65052e..078bae27bc7b 100644
--- a/clang-tools-extra/unittests/clangd/DexTests.cpp
+++ b/clang-tools-extra/unittests/clangd/DexTests.cpp
@@ -667,18 +667,26 @@ TEST(DexTests, Refs) {
auto Foo = symbol("foo");
auto Bar = symbol("bar");
AddRef(Foo, "foo.h", RefKind::Declaration);
+ AddRef(Foo, "foo.cc", RefKind::Definition);
AddRef(Foo, "reffoo.h", RefKind::Reference);
AddRef(Bar, "bar.h", RefKind::Declaration);
- std::vector<std::string> Files;
RefsRequest Req;
Req.IDs.insert(Foo.ID);
Req.Filter = RefKind::Declaration | RefKind::Definition;
+
+ std::vector<std::string> Files;
Dex(std::vector<Symbol>{Foo, Bar}, Refs).refs(Req, [&](const Ref &R) {
Files.push_back(R.Location.FileURI);
});
+ EXPECT_THAT(Files, UnorderedElementsAre("foo.h", "foo.cc"));
- EXPECT_THAT(Files, ElementsAre("foo.h"));
+ Req.Limit = 1;
+ Files.clear();
+ Dex(std::vector<Symbol>{Foo, Bar}, Refs).refs(Req, [&](const Ref &R) {
+ Files.push_back(R.Location.FileURI);
+ });
+ EXPECT_THAT(Files, ElementsAre(AnyOf("foo.h", "foo.cc")));
}
} // namespace
diff --git a/clang-tools-extra/unittests/clangd/IndexTests.cpp b/clang-tools-extra/unittests/clangd/IndexTests.cpp
index 596366d5ba19..3b7d6ff2b961 100644
--- a/clang-tools-extra/unittests/clangd/IndexTests.cpp
+++ b/clang-tools-extra/unittests/clangd/IndexTests.cpp
@@ -19,6 +19,7 @@
using testing::_;
using testing::AllOf;
+using testing::AnyOf;
using testing::ElementsAre;
using testing::Pair;
using testing::Pointee;
@@ -292,7 +293,6 @@ TEST(MergeIndexTest, Refs) {
Request.IDs = {Foo.ID};
RefSlab::Builder Results;
Merge.refs(Request, [&](const Ref &O) { Results.insert(Foo.ID, O); });
-
EXPECT_THAT(
std::move(Results).build(),
ElementsAre(Pair(
@@ -300,6 +300,14 @@ TEST(MergeIndexTest, Refs) {
FileURI("unittest:///test.cc")),
AllOf(RefRange(Test2Code.range("Foo")),
FileURI("unittest:///test2.cc"))))));
+
+ Request.Limit = 1;
+ RefSlab::Builder Results2;
+ 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"),
+ FileURI("unittest:///test2.cc"))))));
}
MATCHER_P2(IncludeHeaderWithRef, IncludeHeader, References, "") {
diff --git a/clang-tools-extra/unittests/clangd/XRefsTests.cpp b/clang-tools-extra/unittests/clangd/XRefsTests.cpp
index 123049cf1161..88394b6cc512 100644
--- a/clang-tools-extra/unittests/clangd/XRefsTests.cpp
+++ b/clang-tools-extra/unittests/clangd/XRefsTests.cpp
@@ -1219,7 +1219,7 @@ TEST(FindReferences, WithinAST) {
std::vector<Matcher<Location>> ExpectedLocations;
for (const auto &R : T.ranges())
ExpectedLocations.push_back(RangeIs(R));
- EXPECT_THAT(findReferences(AST, T.point()),
+ EXPECT_THAT(findReferences(AST, T.point(), 0),
ElementsAreArray(ExpectedLocations))
<< Test;
}
@@ -1266,7 +1266,7 @@ TEST(FindReferences, ExplicitSymbols) {
std::vector<Matcher<Location>> ExpectedLocations;
for (const auto &R : T.ranges())
ExpectedLocations.push_back(RangeIs(R));
- EXPECT_THAT(findReferences(AST, T.point()),
+ EXPECT_THAT(findReferences(AST, T.point(), 0),
ElementsAreArray(ExpectedLocations))
<< Test;
}
@@ -1281,7 +1281,7 @@ TEST(FindReferences, NeedsIndex) {
auto AST = TU.build();
// References in main file are returned without index.
- EXPECT_THAT(findReferences(AST, Main.point(), /*Index=*/nullptr),
+ EXPECT_THAT(findReferences(AST, Main.point(), 0, /*Index=*/nullptr),
ElementsAre(RangeIs(Main.range())));
Annotations IndexedMain(R"cpp(
int main() { [[f^oo]](); }
@@ -1292,13 +1292,17 @@ TEST(FindReferences, NeedsIndex) {
IndexedTU.Code = IndexedMain.code();
IndexedTU.Filename = "Indexed.cpp";
IndexedTU.HeaderCode = Header;
- EXPECT_THAT(findReferences(AST, Main.point(), IndexedTU.index().get()),
+ EXPECT_THAT(findReferences(AST, Main.point(), 0, IndexedTU.index().get()),
ElementsAre(RangeIs(Main.range()), RangeIs(IndexedMain.range())));
+ EXPECT_EQ(1u, findReferences(AST, Main.point(), /*Limit*/ 1,
+ IndexedTU.index().get())
+ .size());
+
// If the main file is in the index, we don't return duplicates.
// (even if the references are in a different location)
TU.Code = ("\n\n" + Main.code()).str();
- EXPECT_THAT(findReferences(AST, Main.point(), TU.index().get()),
+ EXPECT_THAT(findReferences(AST, Main.point(), 0, TU.index().get()),
ElementsAre(RangeIs(Main.range())));
}
@@ -1328,7 +1332,7 @@ TEST(FindReferences, NoQueryForLocalSymbols) {
Annotations File(T.AnnotatedCode);
RecordingIndex Rec;
auto AST = TestTU::withCode(File.code()).build();
- findReferences(AST, File.point(), &Rec);
+ findReferences(AST, File.point(), 0, &Rec);
if (T.WantQuery)
EXPECT_NE(Rec.RefIDs, None) << T.AnnotatedCode;
else