[llvm-branch-commits] [clang-tools-extra] 63ec9e4 - [clangd] Go-to-definition on pure virtual method decls jumps to all overrides.
Haojian Wu via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Dec 14 00:04:20 PST 2020
Author: Haojian Wu
Date: 2020-12-14T08:56:24+01:00
New Revision: 63ec9e40d10056b0f85605d585e7db0b4146851e
URL: https://github.com/llvm/llvm-project/commit/63ec9e40d10056b0f85605d585e7db0b4146851e
DIFF: https://github.com/llvm/llvm-project/commit/63ec9e40d10056b0f85605d585e7db0b4146851e.diff
LOG: [clangd] Go-to-definition on pure virtual method decls jumps to all overrides.
Reviewed By: usaxena95
Differential Revision: https://reviews.llvm.org/D92299
Added:
Modified:
clang-tools-extra/clangd/XRefs.cpp
clang-tools-extra/clangd/unittests/XRefsTests.cpp
Removed:
################################################################################
diff --git a/clang-tools-extra/clangd/XRefs.cpp b/clang-tools-extra/clangd/XRefs.cpp
index 8a85507ff14c..ac4543026a9f 100644
--- a/clang-tools-extra/clangd/XRefs.cpp
+++ b/clang-tools-extra/clangd/XRefs.cpp
@@ -292,6 +292,35 @@ const NamedDecl *getPreferredDecl(const NamedDecl *D) {
return D;
}
+std::vector<LocatedSymbol> findOverrides(llvm::DenseSet<SymbolID> IDs,
+ const SymbolIndex *Index,
+ llvm::StringRef MainFilePath) {
+ if (IDs.empty())
+ return {};
+ RelationsRequest Req;
+ Req.Predicate = RelationKind::OverriddenBy;
+ Req.Subjects = std::move(IDs);
+ std::vector<LocatedSymbol> Results;
+ Index->relations(Req, [&](const SymbolID &Subject, const Symbol &Object) {
+ auto DeclLoc =
+ indexToLSPLocation(Object.CanonicalDeclaration, MainFilePath);
+ if (!DeclLoc) {
+ elog("Find overrides: {0}", DeclLoc.takeError());
+ return;
+ }
+ Results.emplace_back();
+ Results.back().Name = Object.Name.str();
+ Results.back().PreferredDeclaration = *DeclLoc;
+ auto DefLoc = indexToLSPLocation(Object.Definition, MainFilePath);
+ if (!DefLoc) {
+ elog("Failed to convert location: {0}", DefLoc.takeError());
+ return;
+ }
+ Results.back().Definition = *DefLoc;
+ });
+ return Results;
+}
+
// Decls are more complicated.
// The AST contains at least a declaration, maybe a definition.
// These are up-to-date, and so generally preferred over index results.
@@ -330,10 +359,19 @@ locateASTReferent(SourceLocation CurLoc, const syntax::Token *TouchedIdentifier,
DeclRelation::TemplatePattern | DeclRelation::Alias;
auto Candidates =
getDeclAtPositionWithRelations(AST, CurLoc, Relations, NodeKind);
+ llvm::DenseSet<SymbolID> VirtualMethods;
for (const auto &E : Candidates) {
const NamedDecl *D = E.first;
- // Special case: void foo() ^override: jump to the overridden method.
if (const auto *CMD = llvm::dyn_cast<CXXMethodDecl>(D)) {
+ // Special case: virtual void ^method() = 0: jump to all overrides.
+ // FIXME: extend it to ^virtual, unfortunately, virtual location is not
+ // saved in the AST.
+ if (CMD->isPure()) {
+ if (TouchedIdentifier && SM.getSpellingLoc(CMD->getLocation()) ==
+ TouchedIdentifier->location())
+ VirtualMethods.insert(getSymbolID(CMD));
+ }
+ // Special case: void foo() ^override: jump to the overridden method.
const InheritableAttr *Attr = D->getAttr<OverrideAttr>();
if (!Attr)
Attr = D->getAttr<FinalAttr>();
@@ -420,6 +458,8 @@ locateASTReferent(SourceLocation CurLoc, const syntax::Token *TouchedIdentifier,
});
}
+ auto Overrides = findOverrides(VirtualMethods, Index, MainFilePath);
+ Result.insert(Result.end(), Overrides.begin(), Overrides.end());
return Result;
}
@@ -1145,36 +1185,14 @@ std::vector<LocatedSymbol> findImplementations(ParsedAST &AST, Position Pos,
CurLoc.takeError());
return {};
}
- std::vector<LocatedSymbol> Results;
DeclRelationSet Relations =
DeclRelation::TemplatePattern | DeclRelation::Alias;
- RelationsRequest Req;
- Req.Predicate = RelationKind::OverriddenBy;
+ llvm::DenseSet<SymbolID> VirtualMethods;
for (const NamedDecl *ND : getDeclAtPosition(AST, *CurLoc, Relations))
if (const CXXMethodDecl *CXXMD = llvm::dyn_cast<CXXMethodDecl>(ND))
if (CXXMD->isVirtual())
- Req.Subjects.insert(getSymbolID(ND));
-
- if (Req.Subjects.empty())
- return Results;
- Index->relations(Req, [&](const SymbolID &Subject, const Symbol &Object) {
- auto DeclLoc =
- indexToLSPLocation(Object.CanonicalDeclaration, *MainFilePath);
- if (!DeclLoc) {
- elog("Find implementation: {0}", DeclLoc.takeError());
- return;
- }
- LocatedSymbol Loc;
- Loc.Name = Object.Name.str();
- Loc.PreferredDeclaration = *DeclLoc;
- auto DefLoc = indexToLSPLocation(Object.Definition, *MainFilePath);
- if (DefLoc)
- Loc.Definition = *DefLoc;
- else
- llvm::consumeError(DefLoc.takeError());
- Results.push_back(Loc);
- });
- return Results;
+ VirtualMethods.insert(getSymbolID(ND));
+ return findOverrides(std::move(VirtualMethods), Index, *MainFilePath);
}
ReferencesResult findReferences(ParsedAST &AST, Position Pos, uint32_t Limit,
diff --git a/clang-tools-extra/clangd/unittests/XRefsTests.cpp b/clang-tools-extra/clangd/unittests/XRefsTests.cpp
index 5b0ceb1cc200..dfe1f6ce6ccc 100644
--- a/clang-tools-extra/clangd/unittests/XRefsTests.cpp
+++ b/clang-tools-extra/clangd/unittests/XRefsTests.cpp
@@ -349,6 +349,22 @@ TEST(LocateSymbol, WithIndex) {
ElementsAre(Sym("Forward", SymbolHeader.range("forward"), Test.range())));
}
+TEST(LocateSymbol, FindOverrides) {
+ auto Code = Annotations(R"cpp(
+ class Foo {
+ virtual void $1[[fo^o]]() = 0;
+ };
+ class Bar : public Foo {
+ void $2[[foo]]() override;
+ };
+ )cpp");
+ TestTU TU = TestTU::withCode(Code.code());
+ auto AST = TU.build();
+ EXPECT_THAT(locateSymbolAt(AST, Code.point(), TU.index().get()),
+ UnorderedElementsAre(Sym("foo", Code.range("1"), llvm::None),
+ Sym("foo", Code.range("2"), llvm::None)));
+}
+
TEST(LocateSymbol, WithIndexPreferredLocation) {
Annotations SymbolHeader(R"cpp(
class $p[[Proto]] {};
More information about the llvm-branch-commits
mailing list