[clangd] go-to-implementation on a base class jumps to all subclasses.

Differential Revision: https://reviews.llvm.org/D92749
This commit is contained in:
Haojian Wu 2020-12-03 09:42:46 +01:00
parent 32733c347d
commit ed3b1f9061
3 changed files with 32 additions and 16 deletions

View File

@ -292,13 +292,14 @@ const NamedDecl *getPreferredDecl(const NamedDecl *D) {
return D;
}
std::vector<LocatedSymbol> findOverrides(llvm::DenseSet<SymbolID> IDs,
const SymbolIndex *Index,
llvm::StringRef MainFilePath) {
std::vector<LocatedSymbol> findImplementors(llvm::DenseSet<SymbolID> IDs,
RelationKind Predicate,
const SymbolIndex *Index,
llvm::StringRef MainFilePath) {
if (IDs.empty())
return {};
RelationsRequest Req;
Req.Predicate = RelationKind::OverriddenBy;
Req.Predicate = Predicate;
Req.Subjects = std::move(IDs);
std::vector<LocatedSymbol> Results;
Index->relations(Req, [&](const SymbolID &Subject, const Symbol &Object) {
@ -458,7 +459,8 @@ locateASTReferent(SourceLocation CurLoc, const syntax::Token *TouchedIdentifier,
});
}
auto Overrides = findOverrides(VirtualMethods, Index, MainFilePath);
auto Overrides = findImplementors(VirtualMethods, RelationKind::OverriddenBy,
Index, MainFilePath);
Result.insert(Result.end(), Overrides.begin(), Overrides.end());
return Result;
}
@ -1239,12 +1241,20 @@ std::vector<LocatedSymbol> findImplementations(ParsedAST &AST, Position Pos,
}
DeclRelationSet Relations =
DeclRelation::TemplatePattern | DeclRelation::Alias;
llvm::DenseSet<SymbolID> VirtualMethods;
for (const NamedDecl *ND : getDeclAtPosition(AST, *CurLoc, Relations))
if (const CXXMethodDecl *CXXMD = llvm::dyn_cast<CXXMethodDecl>(ND))
if (CXXMD->isVirtual())
VirtualMethods.insert(getSymbolID(ND));
return findOverrides(std::move(VirtualMethods), Index, *MainFilePath);
llvm::DenseSet<SymbolID> IDs;
RelationKind QueryKind;
for (const NamedDecl *ND : getDeclAtPosition(AST, *CurLoc, Relations)) {
if (const auto *CXXMD = llvm::dyn_cast<CXXMethodDecl>(ND)) {
if (CXXMD->isVirtual()) {
IDs.insert(getSymbolID(ND));
QueryKind = RelationKind::OverriddenBy;
}
} else if (const auto *RD = dyn_cast<CXXRecordDecl>(ND)) {
IDs.insert(getSymbolID(RD));
QueryKind = RelationKind::BaseOf;
}
}
return findImplementors(std::move(IDs), QueryKind, Index, *MainFilePath);
}
ReferencesResult findReferences(ParsedAST &AST, Position Pos, uint32_t Limit,

View File

@ -83,7 +83,9 @@ struct ReferencesResult {
bool HasMore = false;
};
/// Returns implementations of the virtual function at a specified \p Pos.
/// Returns implementations at a specified \p Pos:
/// - overrides for a virtual method;
/// - subclasses for a base class;
std::vector<LocatedSymbol> findImplementations(ParsedAST &AST, Position Pos,
const SymbolIndex *Index);

View File

@ -1611,11 +1611,11 @@ TEST(LocateSymbol, NearbyIdentifier) {
TEST(FindImplementations, Inheritance) {
llvm::StringRef Test = R"cpp(
struct Base {
struct $0^Base {
virtual void F$1^oo();
void C$4^oncrete();
};
struct Child1 : Base {
struct $0[[Child1]] : Base {
void $1[[Fo$3^o]]() override;
virtual void B$2^ar();
void Concrete(); // No implementations for concrete methods.
@ -1625,7 +1625,7 @@ TEST(FindImplementations, Inheritance) {
void $2[[Bar]]() override;
};
void FromReference() {
Base* B;
$0^Base* B;
B->Fo$1^o();
B->C$4^oncrete();
&Base::Fo$1^o;
@ -1633,12 +1633,16 @@ TEST(FindImplementations, Inheritance) {
C1->B$2^ar();
C1->Fo$3^o();
}
// CRTP should work.
template<typename T>
struct $5^TemplateBase {};
struct $5[[Child3]] : public TemplateBase<Child3> {};
)cpp";
Annotations Code(Test);
auto TU = TestTU::withCode(Code.code());
auto AST = TU.build();
for (const std::string &Label : {"1", "2", "3", "4"}) {
for (StringRef Label : {"0", "1", "2", "3", "4", "5"}) {
for (const auto &Point : Code.points(Label)) {
EXPECT_THAT(findImplementations(AST, Point, TU.index().get()),
UnorderedPointwise(DeclRange(), Code.ranges(Label)))