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]]> _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits