[clang-tools-extra] abfcb60 - [clangd] Add support for within-file rename of complicated fields
Kirill Bobyrev via cfe-commits
cfe-commits at lists.llvm.org
Thu Nov 26 18:59:46 PST 2020
Author: Kirill Bobyrev
Date: 2020-11-27T03:59:28+01:00
New Revision: abfcb606c2f86da6dbf25bc260e4d716bc87eaf0
URL: https://github.com/llvm/llvm-project/commit/abfcb606c2f86da6dbf25bc260e4d716bc87eaf0
DIFF: https://github.com/llvm/llvm-project/commit/abfcb606c2f86da6dbf25bc260e4d716bc87eaf0.diff
LOG: [clangd] Add support for within-file rename of complicated fields
This was originally a part of D71880 but is separated for simplicity and ease
of reviewing.
Fixes: https://github.com/clangd/clangd/issues/582
Reviewed By: hokein
Differential Revision: https://reviews.llvm.org/D91952
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 78aaa9930cd4..946daaf6d158 100644
--- a/clang-tools-extra/clangd/refactor/Rename.cpp
+++ b/clang-tools-extra/clangd/refactor/Rename.cpp
@@ -124,6 +124,28 @@ const NamedDecl *canonicalRenameDecl(const NamedDecl *D) {
if (const auto *Function = dyn_cast<FunctionDecl>(D))
if (const FunctionTemplateDecl *Template = Function->getPrimaryTemplate())
return canonicalRenameDecl(Template);
+ if (const auto *Field = dyn_cast<FieldDecl>(D)) {
+ // This is a hacky way to do something like
+ // CXXMethodDecl::getInstantiatedFromMemberFunction for the field because
+ // Clang AST does not store relevant information about the field that is
+ // instantiated.
+ const auto *FieldParent = dyn_cast<CXXRecordDecl>(Field->getParent());
+ if (!FieldParent)
+ return Field->getCanonicalDecl();
+ FieldParent = FieldParent->getTemplateInstantiationPattern();
+ // Field is not instantiation.
+ if (!FieldParent || Field->getParent() == FieldParent)
+ return Field->getCanonicalDecl();
+ for (const FieldDecl *Candidate : FieldParent->fields())
+ if (Field->getDeclName() == Candidate->getDeclName())
+ return Candidate->getCanonicalDecl();
+ elog("FieldParent should have field with the same name as Field.");
+ }
+ if (const auto *VD = dyn_cast<VarDecl>(D)) {
+ if (const VarDecl *OriginalVD = VD->getInstantiatedFromStaticDataMember())
+ VD = OriginalVD;
+ return VD->getCanonicalDecl();
+ }
return dyn_cast<NamedDecl>(D->getCanonicalDecl());
}
diff --git a/clang-tools-extra/clangd/unittests/RenameTests.cpp b/clang-tools-extra/clangd/unittests/RenameTests.cpp
index c67339ff2be4..2382dba19659 100644
--- a/clang-tools-extra/clangd/unittests/RenameTests.cpp
+++ b/clang-tools-extra/clangd/unittests/RenameTests.cpp
@@ -540,6 +540,94 @@ TEST(RenameTest, WithinFileRename) {
}
)cpp",
+ // Fields in classes & partial and full specialiations.
+ R"cpp(
+ template<typename T>
+ struct Foo {
+ T [[Vari^able]] = 42;
+ };
+
+ void foo() {
+ Foo<int> f;
+ f.[[Varia^ble]] = 9000;
+ }
+ )cpp",
+ R"cpp(
+ template<typename T, typename U>
+ struct Foo {
+ T Variable[42];
+ U Another;
+
+ void bar() {}
+ };
+
+ template<typename T>
+ struct Foo<T, bool> {
+ T [[Var^iable]];
+ void bar() { ++[[Var^iable]]; }
+ };
+
+ void foo() {
+ Foo<unsigned, bool> f;
+ f.[[Var^iable]] = 9000;
+ }
+ )cpp",
+ R"cpp(
+ template<typename T, typename U>
+ struct Foo {
+ T Variable[42];
+ U Another;
+
+ void bar() {}
+ };
+
+ template<typename T>
+ struct Foo<T, bool> {
+ T Variable;
+ void bar() { ++Variable; }
+ };
+
+ template<>
+ struct Foo<unsigned, bool> {
+ unsigned [[Var^iable]];
+ void bar() { ++[[Var^iable]]; }
+ };
+
+ void foo() {
+ Foo<unsigned, bool> f;
+ f.[[Var^iable]] = 9000;
+ }
+ )cpp",
+ // Static fields.
+ R"cpp(
+ struct Foo {
+ static int [[Var^iable]];
+ };
+
+ int Foo::[[Var^iable]] = 42;
+
+ void foo() {
+ int LocalInt = Foo::[[Var^iable]];
+ }
+ )cpp",
+ R"cpp(
+ template<typename T>
+ struct Foo {
+ static T [[Var^iable]];
+ };
+
+ template <>
+ int Foo<int>::[[Var^iable]] = 42;
+
+ template <>
+ bool Foo<bool>::[[Var^iable]] = true;
+
+ void foo() {
+ int LocalInt = Foo<int>::[[Var^iable]];
+ bool LocalBool = Foo<bool>::[[Var^iable]];
+ }
+ )cpp",
+
// Template parameters.
R"cpp(
template <typename [[^T]]>
More information about the cfe-commits
mailing list