Haojian Wu | c906390 | 2017-10-18 12:10:11 +0000 | [diff] [blame] | 1 | //===-- RenameAliasTest.cpp - unit tests for renaming alias ---------------===// |
| 2 | // |
Chandler Carruth | 2946cd7 | 2019-01-19 08:50:56 +0000 | [diff] [blame] | 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 |
Haojian Wu | c906390 | 2017-10-18 12:10:11 +0000 | [diff] [blame] | 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | |
| 9 | #include "ClangRenameTest.h" |
| 10 | |
| 11 | namespace clang { |
| 12 | namespace clang_rename { |
| 13 | namespace test { |
| 14 | namespace { |
| 15 | |
| 16 | class RenameAliasTest : public ClangRenameTest { |
| 17 | public: |
| 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 | |
| 48 | INSTANTIATE_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 | |
| 195 | TEST_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 | |
| 204 | TEST_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(Expected, After); |
| 215 | } |
| 216 | |
| 217 | TEST_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(Expected, After); |
| 228 | } |
| 229 | |
| 230 | TEST_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(Expected, After); |
| 247 | } |
| 248 | |
| 249 | TEST_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(Expected, After); |
| 264 | } |
| 265 | |
| 266 | TEST_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(Expected, After); |
| 298 | } |
| 299 | |
| 300 | } // anonymous namespace |
| 301 | } // namespace test |
| 302 | } // namespace clang_rename |
| 303 | } // namesdpace clang |