[clangd] Fix one testcase in XRefsTests.
Summary:
The test didn't test anything actually -- it used "[]" as annotation which should be
"[[]]".
This patch also fixes a bug in XRef where we may return duplicated refs.
Reviewers: ilya-biryukov
Subscribers: MaskRay, jkorous, arphaman, kadircet, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D66349
git-svn-id: https://llvm.org/svn/llvm-project/clang-tools-extra/trunk@369387 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/clangd/XRefs.cpp b/clangd/XRefs.cpp
index fba04bb..5dd5186 100644
--- a/clangd/XRefs.cpp
+++ b/clangd/XRefs.cpp
@@ -370,7 +370,6 @@
class ReferenceFinder : public index::IndexDataConsumer {
public:
struct Reference {
- const Decl *CanonicalTarget;
SourceLocation Loc;
index::SymbolRoleSet Role;
};
@@ -384,17 +383,15 @@
std::vector<Reference> take() && {
llvm::sort(References, [](const Reference &L, const Reference &R) {
- return std::tie(L.Loc, L.CanonicalTarget, L.Role) <
- std::tie(R.Loc, R.CanonicalTarget, R.Role);
+ return std::tie(L.Loc, L.Role) < std::tie(R.Loc, R.Role);
});
// We sometimes see duplicates when parts of the AST get traversed twice.
- References.erase(
- std::unique(References.begin(), References.end(),
- [](const Reference &L, const Reference &R) {
- return std::tie(L.CanonicalTarget, L.Loc, L.Role) ==
- std::tie(R.CanonicalTarget, R.Loc, R.Role);
- }),
- References.end());
+ References.erase(std::unique(References.begin(), References.end(),
+ [](const Reference &L, const Reference &R) {
+ return std::tie(L.Loc, L.Role) ==
+ std::tie(R.Loc, R.Role);
+ }),
+ References.end());
return std::move(References);
}
@@ -407,7 +404,7 @@
const SourceManager &SM = AST.getSourceManager();
Loc = SM.getFileLoc(Loc);
if (isInsideMainFile(Loc, SM) && CanonicalTargets.count(D))
- References.push_back({D, Loc, Roles});
+ References.push_back({Loc, Roles});
return true;
}
@@ -441,6 +438,8 @@
// FIXME: show references to macro within file?
auto References = findRefs(Symbols.Decls, AST);
+ // FIXME: we may get multiple DocumentHighlights with the same location and
+ // different kinds, deduplicate them.
std::vector<DocumentHighlight> Result;
for (const auto &Ref : References) {
if (auto Range =
@@ -951,6 +950,15 @@
// We traverse the AST to find references in the main file.
// TODO: should we handle macros, too?
auto MainFileRefs = findRefs(Symbols.Decls, AST);
+ // We may get multiple refs with the same location and different Roles, as
+ // cross-reference is only interested in locations, we deduplicate them
+ // by the location to avoid emitting duplicated locations.
+ MainFileRefs.erase(std::unique(MainFileRefs.begin(), MainFileRefs.end(),
+ [](const ReferenceFinder::Reference &L,
+ const ReferenceFinder::Reference &R) {
+ return L.Loc == R.Loc;
+ }),
+ MainFileRefs.end());
for (const auto &Ref : MainFileRefs) {
if (auto Range =
getTokenRange(AST.getASTContext().getSourceManager(),
diff --git a/clangd/unittests/XRefsTests.cpp b/clangd/unittests/XRefsTests.cpp
index 4a95a99..1079eea 100644
--- a/clangd/unittests/XRefsTests.cpp
+++ b/clangd/unittests/XRefsTests.cpp
@@ -2037,35 +2037,36 @@
TEST(FindReferences, ExplicitSymbols) {
const char *Tests[] = {
R"cpp(
- struct Foo { Foo* [self]() const; };
+ struct Foo { Foo* [[self]]() const; };
void f() {
- if (Foo* T = foo.[^self]()) {} // Foo member call expr.
+ Foo foo;
+ if (Foo* T = foo.[[^self]]()) {} // Foo member call expr.
}
)cpp",
R"cpp(
struct Foo { Foo(int); };
Foo f() {
- int [b];
- return [^b]; // Foo constructor expr.
+ int [[b]];
+ return [[^b]]; // Foo constructor expr.
}
)cpp",
R"cpp(
struct Foo {};
void g(Foo);
- Foo [f]();
+ Foo [[f]]();
void call() {
- g([^f]()); // Foo constructor expr.
+ g([[^f]]()); // Foo constructor expr.
}
)cpp",
R"cpp(
- void [foo](int);
- void [foo](double);
+ void [[foo]](int);
+ void [[foo]](double);
namespace ns {
- using ::[fo^o];
+ using ::[[fo^o]];
}
)cpp",
};
@@ -2075,6 +2076,7 @@
std::vector<Matcher<Location>> ExpectedLocations;
for (const auto &R : T.ranges())
ExpectedLocations.push_back(RangeIs(R));
+ ASSERT_THAT(ExpectedLocations, Not(IsEmpty()));
EXPECT_THAT(findReferences(AST, T.point(), 0),
ElementsAreArray(ExpectedLocations))
<< Test;