blob: 59becaef68a10cf6cdbe1c802f371b63694ab694 [file] [log] [blame]
Haojian Wuc9063902017-10-18 12:10:11 +00001//===-- RenameAliasTest.cpp - unit tests for renaming alias ---------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "ClangRenameTest.h"
11
12namespace clang {
13namespace clang_rename {
14namespace test {
15namespace {
16
17class RenameAliasTest : public ClangRenameTest {
18public:
19 RenameAliasTest() {
20 AppendToHeader(R"(
21 #define MACRO(x) x
22 namespace some_ns {
23 class A {
24 public:
25 void foo() {}
26 struct Nested {
27 enum NestedEnum {
28 E1, E2,
29 };
30 };
31 };
32 } // namespace some_ns
33 namespace a {
34 typedef some_ns::A TA;
35 using UA = some_ns::A;
36 } // namespace a
37 namespace b {
38 typedef some_ns::A TA;
39 using UA = some_ns::A;
40 }
41 template <typename T> class ptr {};
42 template <typename T>
43
44 using TPtr = ptr<int>;
45 )");
46 }
47};
48
49INSTANTIATE_TEST_CASE_P(
50 RenameAliasTests, RenameAliasTest,
51 testing::ValuesIn(std::vector<Case>({
52 // basic functions
53 {"void f(a::TA a1) {}", "void f(b::TB a1) {}", "a::TA", "b::TB"},
54 {"void f(a::UA a1) {}", "void f(b::UB a1) {}", "a::UA", "b::UB"},
55 {"void f(a::TA* a1) {}", "void f(b::TB* a1) {}", "a::TA", "b::TB"},
56 {"void f(a::TA** a1) {}", "void f(b::TB** a1) {}", "a::TA", "b::TB"},
57 {"a::TA f() { return a::TA(); }", "b::TB f() { return b::TB(); }",
58 "a::TA", "b::TB"},
59 {"a::TA f() { return a::UA(); }", "b::TB f() { return a::UA(); }",
60 "a::TA", "b::TB"},
61 {"a::TA f() { return a::UA(); }", "a::TA f() { return b::UB(); }",
62 "a::UA", "b::UB"},
63 {"void f() { a::TA a; }", "void f() { b::TB a; }", "a::TA", "b::TB"},
64 {"void f(const a::TA& a1) {}", "void f(const b::TB& a1) {}", "a::TA",
65 "b::TB"},
66 {"void f(const a::UA& a1) {}", "void f(const b::UB& a1) {}", "a::UA",
67 "b::UB"},
68 {"void f(const a::TA* a1) {}", "void f(const b::TB* a1) {}", "a::TA",
69 "b::TB"},
70 {"namespace a { void f(TA a1) {} }",
71 "namespace a { void f(b::TB a1) {} }", "a::TA", "b::TB"},
72 {"void f(MACRO(a::TA) a1) {}", "void f(MACRO(b::TB) a1) {}", "a::TA",
73 "b::TB"},
74 {"void f(MACRO(a::TA a1)) {}", "void f(MACRO(b::TB a1)) {}", "a::TA",
75 "b::TB"},
76
77 // shorten/add namespace.
78 {"namespace b { void f(a::UA a1) {} }",
79 "namespace b {void f(UB a1) {} }", "a::UA", "b::UB"},
80 {"namespace a { void f(UA a1) {} }",
81 "namespace a {void f(b::UB a1) {} }", "a::UA", "b::UB"},
82
83 // use namespace and typedefs
84 {"struct S { using T = a::TA; T a_; };",
85 "struct S { using T = b::TB; T a_; };", "a::TA", "b::TB"},
86 {"using T = a::TA; T gA;", "using T = b::TB; T gA;", "a::TA", "b::TB"},
87 {"using T = a::UA; T gA;", "using T = b::UB; T gA;", "a::UA", "b::UB"},
88 {"typedef a::TA T; T gA;", "typedef b::TB T; T gA;", "a::TA", "b::TB"},
89 {"typedef a::UA T; T gA;", "typedef b::UB T; T gA;", "a::UA", "b::UB"},
90 {"typedef MACRO(a::TA) T; T gA;", "typedef MACRO(b::TB) T; T gA;",
91 "a::TA", "b::TB"},
92
93 // types in using shadows.
94 {"using a::TA; TA gA;", "using b::TB; b::TB gA;", "a::TA", "b::TB"},
95 {"using a::UA; UA gA;", "using b::UB; b::UB gA;", "a::UA", "b::UB"},
96
97 // struct members and other oddities
98 {"struct S : public a::TA {};", "struct S : public b::TB {};", "a::TA",
99 "b::TB"},
100 {"struct S : public a::UA {};", "struct S : public b::UB {};", "a::UA",
101 "b::UB"},
102 {"struct F { void f(a::TA a1) {} };",
103 "struct F { void f(b::TB a1) {} };", "a::TA", "b::TB"},
104 {"struct F { a::TA a_; };", "struct F { b::TB a_; };", "a::TA",
105 "b::TB"},
106 {"struct F { ptr<a::TA> a_; };", "struct F { ptr<b::TB> a_; };",
107 "a::TA", "b::TB"},
108 {"struct F { ptr<a::UA> a_; };", "struct F { ptr<b::UB> a_; };",
109 "a::UA", "b::UB"},
110
111 // types in nested name specifiers
112 {"void f() { a::TA::Nested ne; }", "void f() { b::TB::Nested ne; }",
113 "a::TA", "b::TB"},
114 {"void f() { a::UA::Nested ne; }", "void f() { b::UB::Nested ne; }",
115 "a::UA", "b::UB"},
116 {"void f() { a::TA::Nested::NestedEnum e; }",
117 "void f() { b::TB::Nested::NestedEnum e; }", "a::TA", "b::TB"},
118 {"void f() { auto e = a::TA::Nested::NestedEnum::E1; }",
119 "void f() { auto e = b::TB::Nested::NestedEnum::E1; }", "a::TA",
120 "b::TB"},
121 {"void f() { auto e = a::TA::Nested::E1; }",
122 "void f() { auto e = b::TB::Nested::E1; }", "a::TA", "b::TB"},
123
124 // templates
125 {"template <typename T> struct Foo { T t; }; void f() { Foo<a::TA> "
126 "foo; }",
127 "template <typename T> struct Foo { T t; }; void f() { Foo<b::TB> "
128 "foo; }",
129 "a::TA", "b::TB"},
130 {"template <typename T> struct Foo { a::TA a; };",
131 "template <typename T> struct Foo { b::TB a; };", "a::TA", "b::TB"},
132 {"template <typename T> void f(T t) {} void g() { f<a::TA>(a::TA()); }",
133 "template <typename T> void f(T t) {} void g() { f<b::TB>(b::TB()); }",
134 "a::TA", "b::TB"},
135 {"template <typename T> void f(T t) {} void g() { f<a::UA>(a::UA()); }",
136 "template <typename T> void f(T t) {} void g() { f<b::UB>(b::UB()); }",
137 "a::UA", "b::UB"},
138 {"template <typename T> int f() { return 1; } template <> int "
139 "f<a::TA>() { return 2; } int g() { return f<a::TA>(); }",
140 "template <typename T> int f() { return 1; } template <> int "
141 "f<b::TB>() { return 2; } int g() { return f<b::TB>(); }",
142 "a::TA", "b::TB"},
143 {"struct Foo { template <typename T> T foo(); }; void g() { Foo f; "
144 "auto a = f.template foo<a::TA>(); }",
145 "struct Foo { template <typename T> T foo(); }; void g() { Foo f; "
146 "auto a = f.template foo<b::TB>(); }",
147 "a::TA", "b::TB"},
148 {"struct Foo { template <typename T> T foo(); }; void g() { Foo f; "
149 "auto a = f.template foo<a::UA>(); }",
150 "struct Foo { template <typename T> T foo(); }; void g() { Foo f; "
151 "auto a = f.template foo<b::UB>(); }",
152 "a::UA", "b::UB"},
153
154 // The following two templates are distilled from regressions found in
155 // unique_ptr<> and type_traits.h
156 {"template <typename T> struct outer { typedef T type; type Baz(); }; "
157 "outer<a::TA> g_A;",
158 "template <typename T> struct outer { typedef T type; type Baz(); }; "
159 "outer<b::TB> g_A;",
160 "a::TA", "b::TB"},
161 {"template <typename T> struct nested { typedef T type; }; template "
162 "<typename T> struct outer { typename nested<T>::type Foo(); }; "
163 "outer<a::TA> g_A;",
164 "template <typename T> struct nested { typedef T type; }; template "
165 "<typename T> struct outer { typename nested<T>::type Foo(); }; "
166 "outer<b::TB> g_A;",
167 "a::TA", "b::TB"},
168
169 // macros
170 {"#define FOO(T, t) T t\nvoid f() { FOO(a::TA, a1); FOO(a::TA, a2); }",
171 "#define FOO(T, t) T t\nvoid f() { FOO(b::TB, a1); FOO(b::TB, a2); }",
172 "a::TA", "b::TB"},
173 {"#define FOO(n) a::TA n\nvoid f() { FOO(a1); FOO(a2); }",
174 "#define FOO(n) b::TB n\nvoid f() { FOO(a1); FOO(a2); }", "a::TA",
175 "b::TB"},
176 {"#define FOO(n) a::UA n\nvoid f() { FOO(a1); FOO(a2); }",
177 "#define FOO(n) b::UB n\nvoid f() { FOO(a1); FOO(a2); }", "a::UA",
178 "b::UB"},
179
180 // Pointer to member functions
181 {"auto gA = &a::TA::foo;", "auto gA = &b::TB::foo;", "a::TA", "b::TB"},
182 {"using a::TA; auto gA = &TA::foo;",
183 "using b::TB; auto gA = &b::TB::foo;", "a::TA", "b::TB"},
184 {"typedef a::TA T; auto gA = &T::foo;",
185 "typedef b::TB T; auto gA = &T::foo;", "a::TA", "b::TB"},
186 {"auto gA = &MACRO(a::TA)::foo;", "auto gA = &MACRO(b::TB)::foo;",
187 "a::TA", "b::TB"},
188
189 // templated using alias.
190 {"void f(TPtr<int> p) {}", "void f(NewTPtr<int> p) {}", "TPtr",
191 "NewTPtr"},
192 {"void f(::TPtr<int> p) {}", "void f(::NewTPtr<int> p) {}", "TPtr",
193 "NewTPtr"},
194 })), );
195
196TEST_P(RenameAliasTest, RenameAlias) {
197 auto Param = GetParam();
198 assert(!Param.OldName.empty());
199 assert(!Param.NewName.empty());
200 std::string Actual =
201 runClangRenameOnCode(Param.Before, Param.OldName, Param.NewName);
202 CompareSnippets(Param.After, Actual);
203}
204
205TEST_F(RenameAliasTest, RenameTypedefDefinitions) {
206 std::string Before = R"(
207 class X {};
208 typedef X TOld;
209 )";
210 std::string Expected = R"(
211 class X {};
212 typedef X TNew;
213 )";
214 std::string After = runClangRenameOnCode(Before, "TOld", "TNew");
215 CompareSnippets(Expected, After);
216}
217
218TEST_F(RenameAliasTest, RenameUsingAliasDefinitions) {
219 std::string Before = R"(
220 class X {};
221 using UOld = X;
222 )";
223 std::string Expected = R"(
224 class X {};
225 using UNew = X;
226 )";
227 std::string After = runClangRenameOnCode(Before, "UOld", "UNew");
228 CompareSnippets(Expected, After);
229}
230
231TEST_F(RenameAliasTest, RenameTemplatedAliasDefinitions) {
232 std::string Before = R"(
233 template <typename T>
234 class X { T t; };
235
236 template <typename T>
237 using Old = X<T>;
238 )";
239 std::string Expected = R"(
240 template <typename T>
241 class X { T t; };
242
243 template <typename T>
244 using New = X<T>;
245 )";
246 std::string After = runClangRenameOnCode(Before, "Old", "New");
247 CompareSnippets(Expected, After);
248}
249
250TEST_F(RenameAliasTest, RenameAliasesInNamespaces) {
251 std::string Before = R"(
252 namespace x { class X {}; }
253 namespace ns {
254 using UOld = x::X;
255 }
256 )";
257 std::string Expected = R"(
258 namespace x { class X {}; }
259 namespace ns {
260 using UNew = x::X;
261 }
262 )";
263 std::string After = runClangRenameOnCode(Before, "ns::UOld", "ns::UNew");
264 CompareSnippets(Expected, After);
265}
266
267TEST_F(RenameAliasTest, AliasesInMacros) {
268 std::string Before = R"(
269 namespace x { class Old {}; }
270 namespace ns {
271 #define REF(alias) alias alias_var;
272
273 #define ALIAS(old) \
274 using old##Alias = x::old; \
275 REF(old##Alias);
276
277 ALIAS(Old);
278
279 OldAlias old_alias;
280 }
281 )";
282 std::string Expected = R"(
283 namespace x { class Old {}; }
284 namespace ns {
285 #define REF(alias) alias alias_var;
286
287 #define ALIAS(old) \
288 using old##Alias = x::old; \
289 REF(old##Alias);
290
291 ALIAS(Old);
292
293 NewAlias old_alias;
294 }
295 )";
296 std::string After =
297 runClangRenameOnCode(Before, "ns::OldAlias", "ns::NewAlias");
298 CompareSnippets(Expected, After);
299}
300
301} // anonymous namespace
302} // namespace test
303} // namespace clang_rename
304} // namesdpace clang