Clang Project

clang_source_code/unittests/Rename/RenameMemberTest.cpp
1//===-- ClangMemberTests.cpp - unit tests for renaming class members ------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "ClangRenameTest.h"
10
11namespace clang {
12namespace clang_rename {
13namespace test {
14namespace {
15
16class RenameMemberTest : public ClangRenameTest {
17public:
18  RenameMemberTest() {
19    AppendToHeader(R"(
20        struct NA {
21          void Foo();
22          void NotFoo();
23          static void SFoo();
24          static void SNotFoo();
25          int Moo;
26        };
27        struct A {
28          virtual void Foo();
29          void NotFoo();
30          static void SFoo();
31          static void SNotFoo();
32          int Moo;
33          int NotMoo;
34          static int SMoo;
35        };
36        struct B : public A {
37          void Foo() override;
38        };
39        template <typename T> struct TA {
40          T* Foo();
41          T* NotFoo();
42          static T* SFoo();
43          static T* NotSFoo();
44        };
45        template <typename T> struct TB : public TA<T> {};
46        namespace ns {
47          template <typename T> struct TA {
48            T* Foo();
49            T* NotFoo();
50            static T* SFoo();
51            static T* NotSFoo();
52            static int SMoo;
53          };
54          template <typename T> struct TB : public TA<T> {};
55          struct A {
56            void Foo();
57            void NotFoo();
58            static void SFoo();
59            static void SNotFoo();
60          };
61          struct B : public A {};
62          struct C {
63            template <class T>
64            void SFoo(const T& t) {}
65            template <class T>
66            void Foo() {}
67          };
68        })");
69  }
70};
71
72INSTANTIATE_TEST_CASE_P(
73    DISABLED_RenameTemplatedClassStaticVariableTest, RenameMemberTest,
74    testing::ValuesIn(std::vector<Case>({
75        // FIXME: support renaming static variables for template classes.
76        {"void f() { ns::TA<int>::SMoo; }",
77         "void f() { ns::TA<int>::SMeh; }""ns::TA::SMoo""ns::TA::SMeh"},
78    })), );
79
80INSTANTIATE_TEST_CASE_P(
81    RenameMemberTest, RenameMemberTest,
82    testing::ValuesIn(std::vector<Case>({
83        // Normal methods and fields.
84        {"void f() { A a; a.Foo(); }""void f() { A a; a.Bar(); }""A::Foo",
85         "A::Bar"},
86        {"void f() { ns::A a; a.Foo(); }""void f() { ns::A a; a.Bar(); }",
87         "ns::A::Foo""ns::A::Bar"},
88        {"void f() { A a; int x = a.Moo; }""void f() { A a; int x = a.Meh; }",
89         "A::Moo""A::Meh"},
90        {"void f() { B b; b.Foo(); }""void f() { B b; b.Bar(); }""B::Foo",
91         "B::Bar"},
92        {"void f() { ns::B b; b.Foo(); }""void f() { ns::B b; b.Bar(); }",
93         "ns::A::Foo""ns::A::Bar"},
94        {"void f() { B b; int x = b.Moo; }""void f() { B b; int x = b.Meh; }",
95         "A::Moo""A::Meh"},
96
97        // Static methods.
98        {"void f() { A::SFoo(); }""void f() { A::SBar(); }""A::SFoo",
99         "A::SBar"},
100        {"void f() { ns::A::SFoo(); }""void f() { ns::A::SBar(); }",
101         "ns::A::SFoo""ns::A::SBar"},
102        {"void f() { TA<int>::SFoo(); }""void f() { TA<int>::SBar(); }",
103         "TA::SFoo""TA::SBar"},
104        {"void f() { ns::TA<int>::SFoo(); }",
105         "void f() { ns::TA<int>::SBar(); }""ns::TA::SFoo""ns::TA::SBar"},
106
107        // Static variables.
108        {"void f() { A::SMoo; }",
109         "void f() { A::SMeh; }""A::SMoo""A::SMeh"},
110
111        // Templated methods.
112        {"void f() { TA<int> a; a.Foo(); }""void f() { TA<int> a; a.Bar(); }",
113         "TA::Foo""TA::Bar"},
114        {"void f() { ns::TA<int> a; a.Foo(); }",
115         "void f() { ns::TA<int> a; a.Bar(); }""ns::TA::Foo""ns::TA::Bar"},
116        {"void f() { TB<int> b; b.Foo(); }""void f() { TB<int> b; b.Bar(); }",
117         "TA::Foo""TA::Bar"},
118        {"void f() { ns::TB<int> b; b.Foo(); }",
119         "void f() { ns::TB<int> b; b.Bar(); }""ns::TA::Foo""ns::TA::Bar"},
120        {"void f() { ns::C c; int x; c.SFoo(x); }",
121         "void f() { ns::C c; int x; c.SBar(x); }""ns::C::SFoo",
122         "ns::C::SBar"},
123        {"void f() { ns::C c; c.Foo<int>(); }",
124         "void f() { ns::C c; c.Bar<int>(); }""ns::C::Foo""ns::C::Bar"},
125
126        // Pointers to methods.
127        {"void f() { auto p = &A::Foo; }""void f() { auto p = &A::Bar; }",
128         "A::Foo""A::Bar"},
129        {"void f() { auto p = &A::SFoo; }""void f() { auto p = &A::SBar; }",
130         "A::SFoo""A::SBar"},
131        {"void f() { auto p = &B::Foo; }""void f() { auto p = &B::Bar; }",
132         "B::Foo""B::Bar"},
133        {"void f() { auto p = &ns::A::Foo; }",
134         "void f() { auto p = &ns::A::Bar; }""ns::A::Foo""ns::A::Bar"},
135        {"void f() { auto p = &ns::A::SFoo; }",
136         "void f() { auto p = &ns::A::SBar; }""ns::A::SFoo""ns::A::SBar"},
137        {"void f() { auto p = &ns::C::SFoo<int>; }",
138         "void f() { auto p = &ns::C::SBar<int>; }""ns::C::SFoo",
139         "ns::C::SBar"},
140
141        // These methods are not declared or overridden in the subclass B, we
142        // have to use the qualified name with parent class A to identify them.
143        {"void f() { auto p = &ns::B::Foo; }",
144         "void f() { auto p = &ns::B::Bar; }""ns::A::Foo""ns::B::Bar"},
145        {"void f() { B::SFoo(); }""void f() { B::SBar(); }""A::SFoo",
146         "B::SBar"},
147        {"void f() { ns::B::SFoo(); }""void f() { ns::B::SBar(); }",
148         "ns::A::SFoo""ns::B::SBar"},
149        {"void f() { auto p = &B::SFoo; }""void f() { auto p = &B::SBar; }",
150         "A::SFoo""B::SBar"},
151        {"void f() { auto p = &ns::B::SFoo; }",
152         "void f() { auto p = &ns::B::SBar; }""ns::A::SFoo""ns::B::SBar"},
153        {"void f() { TB<int>::SFoo(); }""void f() { TB<int>::SBar(); }",
154         "TA::SFoo""TB::SBar"},
155        {"void f() { ns::TB<int>::SFoo(); }",
156         "void f() { ns::TB<int>::SBar(); }""ns::TA::SFoo""ns::TB::SBar"},
157    })), );
158
159TEST_P(RenameMemberTest, RenameMembers) {
160  auto Param = GetParam();
161  assert(!Param.OldName.empty());
162  assert(!Param.NewName.empty());
163  std::string Actual =
164      runClangRenameOnCode(Param.Before, Param.OldName, Param.NewName);
165  CompareSnippets(Param.After, Actual);
166}
167
168TEST_F(RenameMemberTest, RenameMemberInsideClassMethods) {
169  std::string Before = R"(
170      struct X {
171        int Moo;
172        void Baz() { Moo = 1; }
173      };)";
174  std::string Expected = R"(
175      struct X {
176        int Meh;
177        void Baz() { Meh = 1; }
178      };)";
179  std::string After = runClangRenameOnCode(Before"X::Moo""Y::Meh");
180  CompareSnippets(ExpectedAfter);
181}
182
183TEST_F(RenameMemberTest, RenameMethodInsideClassMethods) {
184  std::string Before = R"(
185      struct X {
186        void Foo() {}
187        void Baz() { Foo(); }
188      };)";
189  std::string Expected = R"(
190      struct X {
191        void Bar() {}
192        void Baz() { Bar(); }
193      };)";
194  std::string After = runClangRenameOnCode(Before"X::Foo""X::Bar");
195  CompareSnippets(ExpectedAfter);
196}
197
198TEST_F(RenameMemberTest, RenameCtorInitializer) {
199  std::string Before = R"(
200      class X {
201      public:
202       X();
203       A a;
204       A a2;
205       B b;
206      };
207
208      X::X():a(), b() {}
209      )";
210  std::string Expected = R"(
211      class X {
212      public:
213       X();
214       A bar;
215       A a2;
216       B b;
217      };
218
219      X::X():bar(), b() {}
220      )";
221  std::string After = runClangRenameOnCode(Before"X::a""X::bar");
222  CompareSnippets(ExpectedAfter);
223}
224
225// anonymous namespace
226// namespace test
227// namespace clang_rename
228// namesdpace clang
229