Summary: so that clangd C++ API users (via ClangdServer) can access it.
Reviewers: sammccall
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D70380
void ClangdLSPServer::onReference(const ReferenceParams &Params,
Callback<std::vector<Location>> Reply) {
Server->findReferences(Params.textDocument.uri.file(), Params.position,
- CCOpts.Limit, std::move(Reply));
+ CCOpts.Limit,
+ [Reply = std::move(Reply)](
+ llvm::Expected<ReferencesResult> Refs) mutable {
+ if (!Refs)
+ return Reply(Refs.takeError());
+ return Reply(std::move(Refs->References));
+ });
}
void ClangdLSPServer::onSymbolInfo(const TextDocumentPositionParams &Params,
}
void ClangdServer::findReferences(PathRef File, Position Pos, uint32_t Limit,
- Callback<std::vector<Location>> CB) {
+ Callback<ReferencesResult> CB) {
auto Action = [Pos, Limit, CB = std::move(CB),
this](llvm::Expected<InputsAndAST> InpAST) mutable {
if (!InpAST)
/// Retrieve locations for symbol references.
void findReferences(PathRef File, Position Pos, uint32_t Limit,
- Callback<std::vector<Location>> CB);
+ Callback<ReferencesResult> CB);
/// Run formatting for \p Rng inside \p File with content \p Code.
llvm::Expected<tooling::Replacements> formatRange(StringRef Code,
return HI;
}
-std::vector<Location> findReferences(ParsedAST &AST, Position Pos,
- uint32_t Limit, const SymbolIndex *Index) {
+ReferencesResult findReferences(ParsedAST &AST, Position Pos, uint32_t Limit,
+ const SymbolIndex *Index) {
if (!Limit)
Limit = std::numeric_limits<uint32_t>::max();
- std::vector<Location> Results;
+ ReferencesResult Results;
const SourceManager &SM = AST.getSourceManager();
auto MainFilePath =
getCanonicalPath(SM.getFileEntryForID(SM.getMainFileID()), SM);
Location Result;
Result.range = *Range;
Result.uri = URIForFile::canonicalize(*MainFilePath, *MainFilePath);
- Results.push_back(std::move(Result));
+ Results.References.push_back(std::move(Result));
}
}
-
// Now query the index for references from other files.
- if (Index && Results.size() < Limit) {
+ if (Index && Results.References.size() <= Limit) {
RefsRequest Req;
Req.Limit = Limit;
}
if (Req.IDs.empty())
return Results;
- Index->refs(Req, [&](const Ref &R) {
+ Results.HasMore |= Index->refs(Req, [&](const Ref &R) {
+ // no need to continue process if we reach the limit.
+ if (Results.References.size() > Limit)
+ return;
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 (!LSPLoc || LSPLoc->uri.file() == *MainFilePath)
+ return;
+
+ Results.References.push_back(std::move(*LSPLoc));
});
}
- if (Results.size() > Limit)
- Results.resize(Limit);
+ if (Results.References.size() > Limit) {
+ Results.HasMore = true;
+ Results.References.resize(Limit);
+ }
return Results;
}
format::FormatStyle Style,
const SymbolIndex *Index);
-/// Returns reference locations of the symbol at a specified \p Pos.
+struct ReferencesResult {
+ std::vector<Location> References;
+ bool HasMore = false;
+};
+/// Returns references 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);
+ReferencesResult findReferences(ParsedAST &AST, Position Pos, uint32_t Limit,
+ const SymbolIndex *Index = nullptr);
/// Get info about symbols at \p Pos.
std::vector<SymbolDetails> getSymbolInfo(ParsedAST &AST, Position Pos);
std::vector<Matcher<Location>> ExpectedLocations;
for (const auto &R : T.ranges())
ExpectedLocations.push_back(RangeIs(R));
- EXPECT_THAT(findReferences(AST, T.point(), 0),
+ EXPECT_THAT(findReferences(AST, T.point(), 0).References,
ElementsAreArray(ExpectedLocations))
<< Test;
}
for (const auto &R : T.ranges())
ExpectedLocations.push_back(RangeIs(R));
ASSERT_THAT(ExpectedLocations, Not(IsEmpty()));
- EXPECT_THAT(findReferences(AST, T.point(), 0),
+ EXPECT_THAT(findReferences(AST, T.point(), 0).References,
ElementsAreArray(ExpectedLocations))
<< Test;
}
auto AST = TU.build();
// References in main file are returned without index.
- EXPECT_THAT(findReferences(AST, Main.point(), 0, /*Index=*/nullptr),
- ElementsAre(RangeIs(Main.range())));
+ EXPECT_THAT(
+ findReferences(AST, Main.point(), 0, /*Index=*/nullptr).References,
+ ElementsAre(RangeIs(Main.range())));
Annotations IndexedMain(R"cpp(
int main() { [[f^oo]](); }
)cpp");
IndexedTU.Code = IndexedMain.code();
IndexedTU.Filename = "Indexed.cpp";
IndexedTU.HeaderCode = Header;
- 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());
+ EXPECT_THAT(
+ findReferences(AST, Main.point(), 0, IndexedTU.index().get()).References,
+ ElementsAre(RangeIs(Main.range()), RangeIs(IndexedMain.range())));
+ auto LimitRefs =
+ findReferences(AST, Main.point(), /*Limit*/ 1, IndexedTU.index().get());
+ EXPECT_EQ(1u, LimitRefs.References.size());
+ EXPECT_TRUE(LimitRefs.HasMore);
// 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(), 0, TU.index().get()),
+ EXPECT_THAT(findReferences(AST, Main.point(), 0, TU.index().get()).References,
ElementsAre(RangeIs(Main.range())));
}