Skip to content

Commit e102338

Browse files
authored
Support call hierarchy for fields and non-local variables (#113900)
Fixes clangd/clangd#1308
1 parent 229abcd commit e102338

File tree

2 files changed

+49
-1
lines changed

2 files changed

+49
-1
lines changed

clang-tools-extra/clangd/XRefs.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2238,7 +2238,10 @@ prepareCallHierarchy(ParsedAST &AST, Position Pos, PathRef TUPath) {
22382238
for (const NamedDecl *Decl : getDeclAtPosition(AST, *Loc, {})) {
22392239
if (!(isa<DeclContext>(Decl) &&
22402240
cast<DeclContext>(Decl)->isFunctionOrMethod()) &&
2241-
Decl->getKind() != Decl::Kind::FunctionTemplate)
2241+
Decl->getKind() != Decl::Kind::FunctionTemplate &&
2242+
!(Decl->getKind() == Decl::Kind::Var &&
2243+
!cast<VarDecl>(Decl)->isLocalVarDecl()) &&
2244+
Decl->getKind() != Decl::Kind::Field)
22422245
continue;
22432246
if (auto CHI = declToCallHierarchyItem(*Decl, AST.tuPath()))
22442247
Result.emplace_back(std::move(*CHI));

clang-tools-extra/clangd/unittests/CallHierarchyTests.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,51 @@ TEST(CallHierarchy, CallInLocalVarDecl) {
446446
AllOf(from(withName("caller3")), fromRanges(Source.range("call3")))));
447447
}
448448

449+
TEST(CallHierarchy, HierarchyOnField) {
450+
// Tests that the call hierarchy works on fields.
451+
Annotations Source(R"cpp(
452+
struct Vars {
453+
int v^ar1 = 1;
454+
};
455+
void caller() {
456+
Vars values;
457+
values.$Callee[[var1]];
458+
}
459+
)cpp");
460+
TestTU TU = TestTU::withCode(Source.code());
461+
auto AST = TU.build();
462+
auto Index = TU.index();
463+
464+
std::vector<CallHierarchyItem> Items =
465+
prepareCallHierarchy(AST, Source.point(), testPath(TU.Filename));
466+
ASSERT_THAT(Items, ElementsAre(withName("var1")));
467+
auto IncomingLevel1 = incomingCalls(Items[0], Index.get());
468+
ASSERT_THAT(IncomingLevel1,
469+
ElementsAre(AllOf(from(withName("caller")),
470+
fromRanges(Source.range("Callee")))));
471+
}
472+
473+
TEST(CallHierarchy, HierarchyOnVar) {
474+
// Tests that the call hierarchy works on non-local variables.
475+
Annotations Source(R"cpp(
476+
int v^ar = 1;
477+
void caller() {
478+
$Callee[[var]];
479+
}
480+
)cpp");
481+
TestTU TU = TestTU::withCode(Source.code());
482+
auto AST = TU.build();
483+
auto Index = TU.index();
484+
485+
std::vector<CallHierarchyItem> Items =
486+
prepareCallHierarchy(AST, Source.point(), testPath(TU.Filename));
487+
ASSERT_THAT(Items, ElementsAre(withName("var")));
488+
auto IncomingLevel1 = incomingCalls(Items[0], Index.get());
489+
ASSERT_THAT(IncomingLevel1,
490+
ElementsAre(AllOf(from(withName("caller")),
491+
fromRanges(Source.range("Callee")))));
492+
}
493+
449494
} // namespace
450495
} // namespace clangd
451496
} // namespace clang

0 commit comments

Comments
 (0)