[clang-tools-extra] 8019b46 - [clangd] Support renaming virtual methods
Sam McCall via cfe-commits
cfe-commits at lists.llvm.org
Wed Sep 7 04:16:03 PDT 2022
Author: Tom Praschan
Date: 2022-09-07T13:15:50+02:00
New Revision: 8019b46bc70b15cf5551ffcf494c6df17d1e7437
URL: https://github.com/llvm/llvm-project/commit/8019b46bc70b15cf5551ffcf494c6df17d1e7437
DIFF: https://github.com/llvm/llvm-project/commit/8019b46bc70b15cf5551ffcf494c6df17d1e7437.diff
LOG: [clangd] Support renaming virtual methods
Fixes https://github.com/clangd/clangd/issues/706
Differential Revision: https://reviews.llvm.org/D132797
Added:
Modified:
clang-tools-extra/clangd/refactor/Rename.cpp
clang-tools-extra/clangd/unittests/RenameTests.cpp
Removed:
################################################################################
diff --git a/clang-tools-extra/clangd/refactor/Rename.cpp b/clang-tools-extra/clangd/refactor/Rename.cpp
index af454f0a372b..6358a05667bd 100644
--- a/clang-tools-extra/clangd/refactor/Rename.cpp
+++ b/clang-tools-extra/clangd/refactor/Rename.cpp
@@ -214,13 +214,6 @@ llvm::Optional<ReasonToReject> renameable(const NamedDecl &RenameDecl,
IsMainFileOnly))
return ReasonToReject::NonIndexable;
-
- // FIXME: Renaming virtual methods requires to rename all overridens in
- // subclasses, our index doesn't have this information.
- if (const auto *S = llvm::dyn_cast<CXXMethodDecl>(&RenameDecl)) {
- if (S->isVirtual())
- return ReasonToReject::UnsupportedSymbol;
- }
return None;
}
@@ -551,6 +544,26 @@ Range toRange(const SymbolLocation &L) {
return R;
}
+// Walk down from a virtual method to overriding methods, we rename them as a
+// group. Note that canonicalRenameDecl() ensures we're starting from the base
+// method.
+void insertTransitiveOverrides(SymbolID Base, llvm::DenseSet<SymbolID> &IDs,
+ const SymbolIndex &Index) {
+ RelationsRequest Req;
+ Req.Predicate = RelationKind::OverriddenBy;
+
+ llvm::DenseSet<SymbolID> Pending = {Base};
+ while (!Pending.empty()) {
+ Req.Subjects = std::move(Pending);
+ Pending.clear();
+
+ Index.relations(Req, [&](const SymbolID &, const Symbol &Override) {
+ if (IDs.insert(Override.ID).second)
+ Pending.insert(Override.ID);
+ });
+ }
+}
+
// Return all rename occurrences (using the index) outside of the main file,
// grouped by the absolute file path.
llvm::Expected<llvm::StringMap<std::vector<Range>>>
@@ -561,6 +574,10 @@ findOccurrencesOutsideFile(const NamedDecl &RenameDecl,
RefsRequest RQuest;
RQuest.IDs.insert(getSymbolID(&RenameDecl));
+ if (const auto *MethodDecl = llvm::dyn_cast<CXXMethodDecl>(&RenameDecl))
+ if (MethodDecl->isVirtual())
+ insertTransitiveOverrides(*RQuest.IDs.begin(), RQuest.IDs, Index);
+
// Absolute file path => rename occurrences in that file.
llvm::StringMap<std::vector<Range>> AffectedFiles;
bool HasMore = Index.refs(RQuest, [&](const Ref &R) {
diff --git a/clang-tools-extra/clangd/unittests/RenameTests.cpp b/clang-tools-extra/clangd/unittests/RenameTests.cpp
index 70b0bbc8f073..451ec3723469 100644
--- a/clang-tools-extra/clangd/unittests/RenameTests.cpp
+++ b/clang-tools-extra/clangd/unittests/RenameTests.cpp
@@ -886,12 +886,6 @@ TEST(RenameTest, Renameable) {
@end
)cpp",
"not a supported kind", HeaderFile},
- {R"cpp(// FIXME: rename virtual/override methods is not supported yet.
- struct A {
- virtual void f^oo() {}
- };
- )cpp",
- "not a supported kind", !HeaderFile},
{R"cpp(
void foo(int);
void foo(char);
@@ -1490,6 +1484,48 @@ TEST(CrossFileRenameTests, WithUpToDateIndex) {
}
)cpp",
},
+ {
+ // virtual methods.
+ R"cpp(
+ class Base {
+ virtual void [[foo]]();
+ };
+ class Derived1 : public Base {
+ void [[f^oo]]() override;
+ };
+ class NotDerived {
+ void foo() {};
+ }
+ )cpp",
+ R"cpp(
+ #include "foo.h"
+ void Base::[[foo]]() {}
+ void Derived1::[[foo]]() {}
+
+ class Derived2 : public Derived1 {
+ void [[foo]]() override {};
+ };
+
+ void func(Base* b, Derived1* d1,
+ Derived2* d2, NotDerived* nd) {
+ b->[[foo]]();
+ d1->[[foo]]();
+ d2->[[foo]]();
+ nd->foo();
+ }
+ )cpp",
+ },
+ // FIXME: triggers an assertion failure due to a bug in canonicalization.
+ // See https://reviews.llvm.org/D132797
+#if 0
+ {
+ // virtual templated method
+ R"cpp(
+ template <typename> class Foo { virtual void [[m]](); };
+ class Bar : Foo<int> { void [[^m]]() override; };
+ )cpp", ""
+ },
+#endif
{
// rename on constructor and destructor.
R"cpp(
More information about the cfe-commits
mailing list