Clang Project

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