1 //===-- RenameFunctionTest.cpp - unit tests for renaming functions --------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "ClangRenameTest.h"
12 namespace clang_rename
{
16 class RenameFunctionTest
: public ClangRenameTest
{
18 RenameFunctionTest() {
27 static int Eric(int x);
34 void ToInt64NanoSeconds();
39 TEST_F(RenameFunctionTest
, RefactorsAFoo
) {
40 std::string Before
= R
"(
45 std::string Expected
= R
"(
51 std::string After
= runClangRenameOnCode(Before
, "A::Foo", "A::Bar");
52 CompareSnippets(Expected
, After
);
55 TEST_F(RenameFunctionTest
, RefactorsNonCallingAFoo
) {
56 std::string Before
= R
"(
57 bool g(bool (*func)()) {
62 auto *ref2 = ::A::Foo;
65 std::string Expected
= R
"(
66 bool g(bool (*func)()) {
71 auto *ref2 = ::A::Bar;
74 std::string After
= runClangRenameOnCode(Before
, "A::Foo", "A::Bar");
75 CompareSnippets(Expected
, After
);
78 TEST_F(RenameFunctionTest
, RefactorsEric
) {
79 std::string Before
= R
"(
81 if (Eric(3)==4) ::Eric(2);
83 std::string Expected
= R
"(
85 if (Larry(3)==4) ::Larry(2);
87 std::string After
= runClangRenameOnCode(Before
, "Eric", "Larry");
88 CompareSnippets(Expected
, After
);
91 TEST_F(RenameFunctionTest
, RefactorsNonCallingEric
) {
92 std::string Before
= R
"(
93 int g(int (*func)(int)) {
100 std::string Expected
= R
"(
101 int g(int (*func)(int)) {
108 std::string After
= runClangRenameOnCode(Before
, "Eric", "Larry");
109 CompareSnippets(Expected
, After
);
112 TEST_F(RenameFunctionTest
, DoesNotRefactorBFoo
) {
113 std::string Before
= R
"(
117 std::string After
= runClangRenameOnCode(Before
, "A::Foo", "A::Bar");
118 CompareSnippets(Before
, After
);
121 TEST_F(RenameFunctionTest
, DoesNotRefactorBEric
) {
122 std::string Before
= R
"(
126 std::string After
= runClangRenameOnCode(Before
, "Eric", "Larry");
127 CompareSnippets(Before
, After
);
130 TEST_F(RenameFunctionTest
, DoesNotRefactorCEric
) {
131 std::string Before
= R
"(
132 namespace C { int Eric(int x); }
134 if (C::Eric(3)==4) ::C::Eric(2);
136 std::string Expected
= R
"(
137 namespace C { int Eric(int x); }
139 if (C::Eric(3)==4) ::C::Eric(2);
141 std::string After
= runClangRenameOnCode(Before
, "Eric", "Larry");
142 CompareSnippets(Expected
, After
);
145 TEST_F(RenameFunctionTest
, DoesNotRefactorEricInNamespaceC
) {
146 std::string Before
= R
"(
150 if (Eric(3)==4) Eric(2);
153 std::string After
= runClangRenameOnCode(Before
, "Eric", "Larry");
154 CompareSnippets(Before
, After
);
157 TEST_F(RenameFunctionTest
, NamespaceQualified
) {
158 std::string Before
= R
"(
160 base::ToNanoSeconds();
161 ::base::ToNanoSeconds();
164 using base::ToNanoSeconds;
165 base::ToNanoSeconds();
166 ::base::ToNanoSeconds();
171 void ToNanoSeconds();
173 base::ToNanoSeconds();
177 ::base::ToNanoSeconds();
180 std::string Expected
= R
"(
182 base::ToInt64NanoSeconds();
183 ::base::ToInt64NanoSeconds();
186 using base::ToInt64NanoSeconds;
187 base::ToInt64NanoSeconds();
188 ::base::ToInt64NanoSeconds();
189 base::ToInt64NanoSeconds();
193 void ToNanoSeconds();
195 base::ToNanoSeconds();
199 ::base::ToInt64NanoSeconds();
202 std::string After
= runClangRenameOnCode(Before
, "base::ToNanoSeconds",
203 "base::ToInt64NanoSeconds");
204 CompareSnippets(Expected
, After
);
207 TEST_F(RenameFunctionTest
, RenameFunctionDecls
) {
208 std::string Before
= R
"(
213 std::string Expected
= R
"(
218 std::string After
= runClangRenameOnCode(Before
, "na::X", "na::Y");
219 CompareSnippets(Expected
, After
);
222 TEST_F(RenameFunctionTest
, RenameTemplateFunctions
) {
223 std::string Before
= R
"(
225 template<typename T> T X();
227 namespace na { void f() { X<int>(); } }
228 namespace nb { void g() { na::X <int>(); } }
230 std::string Expected
= R
"(
232 template<typename T> T Y();
234 namespace na { void f() { nb::Y<int>(); } }
235 namespace nb { void g() { Y<int>(); } }
237 std::string After
= runClangRenameOnCode(Before
, "na::X", "nb::Y");
238 CompareSnippets(Expected
, After
);
241 TEST_F(RenameFunctionTest
, RenameOutOfLineFunctionDecls
) {
242 std::string Before
= R
"(
248 std::string Expected
= R
"(
254 std::string After
= runClangRenameOnCode(Before
, "na::X", "na::Y");
255 CompareSnippets(Expected
, After
);
258 TEST_F(RenameFunctionTest
, NewNamespaceWithoutLeadingDotDot
) {
259 std::string Before
= R
"(
264 // Assume that the reference is in another file.
265 void f() { old_ns::X(); }
266 namespace old_ns { void g() { X(); } }
267 namespace new_ns { void h() { ::old_ns::X(); } }
269 std::string Expected
= R
"(
274 // Assume that the reference is in another file.
275 void f() { new_ns::Y(); }
276 namespace old_ns { void g() { new_ns::Y(); } }
277 namespace new_ns { void h() { Y(); } }
279 std::string After
= runClangRenameOnCode(Before
, "::old_ns::X", "new_ns::Y");
280 CompareSnippets(Expected
, After
);
283 TEST_F(RenameFunctionTest
, NewNamespaceWithLeadingDotDot
) {
284 std::string Before
= R
"(
289 // Assume that the reference is in another file.
290 void f() { old_ns::X(); }
291 namespace old_ns { void g() { X(); } }
292 namespace new_ns { void h() { ::old_ns::X(); } }
294 std::string Expected
= R
"(
299 // Assume that the reference is in another file.
300 void f() { ::new_ns::Y(); }
301 namespace old_ns { void g() { ::new_ns::Y(); } }
302 namespace new_ns { void h() { Y(); } }
305 runClangRenameOnCode(Before
, "::old_ns::X", "::new_ns::Y");
306 CompareSnippets(Expected
, After
);
309 TEST_F(RenameFunctionTest
, DontRenameSymbolsDefinedInAnonymousNamespace
) {
310 std::string Before
= R
"(
320 std::string Expected
= R
"(
331 runClangRenameOnCode(Before
, "::old_ns::X", "::old_ns::Y");
332 CompareSnippets(Expected
, After
);
335 TEST_F(RenameFunctionTest
, NewNestedNamespace
) {
336 std::string Before
= R
"(
341 // Assume that the reference is in another file.
346 std::string Expected
= R
"(
351 // Assume that the reference is in another file.
353 void f() { older_ns::X(); }
357 runClangRenameOnCode(Before
, "::old_ns::X", "::old_ns::older_ns::X");
358 CompareSnippets(Expected
, After
);
361 TEST_F(RenameFunctionTest
, MoveFromGlobalToNamespaceWithoutLeadingDotDot
) {
362 std::string Before
= R
"(
366 // Assume that the reference is in another file.
371 std::string Expected
= R
"(
375 // Assume that the reference is in another file.
377 void f() { ns::X(); }
381 runClangRenameOnCode(Before
, "::X", "ns::X");
382 CompareSnippets(Expected
, After
);
385 TEST_F(RenameFunctionTest
, MoveFromGlobalToNamespaceWithLeadingDotDot
) {
386 std::string Before
= R
"(
389 // Assume that the reference is in another file.
394 std::string Expected
= R
"(
397 // Assume that the reference is in another file.
399 void f() { ::ns::Y(); }
403 runClangRenameOnCode(Before
, "::Y", "::ns::Y");
404 CompareSnippets(Expected
, After
);
407 // FIXME: the rename of overloaded operator is not fully supported yet.
408 TEST_F(RenameFunctionTest
, DISABLED_DoNotRenameOverloadedOperatorCalls
) {
409 std::string Before
= R
"(
411 class T { public: int x; };
412 bool operator==(const T& lhs, const T& rhs) {
413 return lhs.x == rhs.x;
415 } // namespace old_ns
417 // Assume that the reference is in another file.
419 auto eq = old_ns::operator==;
421 old_ns::operator==(t1, t2);
425 std::string Expected
= R
"(
427 class T { public: int x; };
428 bool operator==(const T& lhs, const T& rhs) {
429 return lhs.x == rhs.x;
431 } // namespace old_ns
433 // Assume that the reference is in another file.
435 auto eq = new_ns::operator==;
437 new_ns::operator==(t1, t2);
442 runClangRenameOnCode(Before
, "old_ns::operator==", "new_ns::operator==");
443 CompareSnippets(Expected
, After
);
446 TEST_F(RenameFunctionTest
, FunctionRefAsTemplate
) {
447 std::string Before
= R
"(
450 // Assume that the reference is in another file.
452 template <void (*Func)(void)>
455 template <void (*Func)(void)>
458 typedef TIterator<Func> IterType;
459 using TI = TIterator<Func>;
463 TIterator<Func> iter;
468 void f() { T<X> tx; tx.g(); }
469 } // namespace some_ns
471 std::string Expected
= R
"(
474 // Assume that the reference is in another file.
476 template <void (*Func)(void)>
479 template <void (*Func)(void)>
482 typedef TIterator<Func> IterType;
483 using TI = TIterator<Func>;
487 TIterator<Func> iter;
492 void f() { T<ns::X> tx; tx.g(); }
493 } // namespace some_ns
495 std::string After
= runClangRenameOnCode(Before
, "::X", "ns::X");
496 CompareSnippets(Expected
, After
);
499 TEST_F(RenameFunctionTest
, RenameFunctionInUsingDecl
) {
500 std::string Before
= R
"(
501 using base::ToNanoSeconds;
503 using base::ToNanoSeconds;
505 using base::ToNanoSeconds;
509 std::string Expected
= R
"(
510 using base::ToInt64NanoSeconds;
512 using base::ToInt64NanoSeconds;
514 using base::ToInt64NanoSeconds;
518 std::string After
= runClangRenameOnCode(Before
, "base::ToNanoSeconds",
519 "base::ToInt64NanoSeconds");
520 CompareSnippets(Expected
, After
);
523 // FIXME: Fix the complex the case where the symbol being renamed is located in
524 // `std::function<decltype<renamed_symbol>>`.
525 TEST_F(ClangRenameTest
, DISABLED_ReferencesInLambdaFunctionParameters
) {
526 std::string Before
= R
"(
529 template <class R, class... ArgTypes>
530 class function<R(ArgTypes...)> {
532 template <typename Functor>
533 function(Functor f) {}
537 R operator()(ArgTypes...) const {}
543 function<decltype(Old)> func;
546 std::string Expected
= R
"(
549 template <class R, class... ArgTypes>
550 class function<R(ArgTypes...)> {
552 template <typename Functor>
553 function(Functor f) {}
557 R operator()(ArgTypes...) const {}
563 function<decltype(::new_ns::New)> func;
566 std::string After
= runClangRenameOnCode(Before
, "ns::Old", "::new_ns::New");
567 CompareSnippets(Expected
, After
);
570 } // anonymous namespace
572 } // namespace clang_rename
573 } // namesdpace clang