blob: fb8d5580fb40fc1caf42670c0832fb7f86d6df95 [file] [log] [blame]
//===-- ClangMemberTests.cpp - unit tests for renaming class members ------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "ClangRenameTest.h"
namespace clang {
namespace clang_rename {
namespace test {
namespace {
class RenameMemberTest : public ClangRenameTest {
public:
RenameMemberTest() {
AppendToHeader(R"(
struct NA {
void Foo();
void NotFoo();
static void SFoo();
static void SNotFoo();
int Moo;
};
struct A {
virtual void Foo();
void NotFoo();
static void SFoo();
static void SNotFoo();
int Moo;
int NotMoo;
static int SMoo;
};
struct B : public A {
void Foo() override;
};
template <typename T> struct TA {
T* Foo();
T* NotFoo();
static T* SFoo();
static T* NotSFoo();
};
template <typename T> struct TB : public TA<T> {};
namespace ns {
template <typename T> struct TA {
T* Foo();
T* NotFoo();
static T* SFoo();
static T* NotSFoo();
static int SMoo;
};
template <typename T> struct TB : public TA<T> {};
struct A {
void Foo();
void NotFoo();
static void SFoo();
static void SNotFoo();
};
struct B : public A {};
struct C {
template <class T>
void SFoo(const T& t) {}
template <class T>
void Foo() {}
};
})");
}
};
INSTANTIATE_TEST_CASE_P(
DISABLED_RenameTemplatedClassStaticVariableTest, RenameMemberTest,
testing::ValuesIn(std::vector<Case>({
// FIXME: support renaming static variables for template classes.
{"void f() { ns::TA<int>::SMoo; }",
"void f() { ns::TA<int>::SMeh; }", "ns::TA::SMoo", "ns::TA::SMeh"},
})), );
INSTANTIATE_TEST_CASE_P(
RenameMemberTest, RenameMemberTest,
testing::ValuesIn(std::vector<Case>({
// Normal methods and fields.
{"void f() { A a; a.Foo(); }", "void f() { A a; a.Bar(); }", "A::Foo",
"A::Bar"},
{"void f() { ns::A a; a.Foo(); }", "void f() { ns::A a; a.Bar(); }",
"ns::A::Foo", "ns::A::Bar"},
{"void f() { A a; int x = a.Moo; }", "void f() { A a; int x = a.Meh; }",
"A::Moo", "A::Meh"},
{"void f() { B b; b.Foo(); }", "void f() { B b; b.Bar(); }", "B::Foo",
"B::Bar"},
{"void f() { ns::B b; b.Foo(); }", "void f() { ns::B b; b.Bar(); }",
"ns::A::Foo", "ns::A::Bar"},
{"void f() { B b; int x = b.Moo; }", "void f() { B b; int x = b.Meh; }",
"A::Moo", "A::Meh"},
// Static methods.
{"void f() { A::SFoo(); }", "void f() { A::SBar(); }", "A::SFoo",
"A::SBar"},
{"void f() { ns::A::SFoo(); }", "void f() { ns::A::SBar(); }",
"ns::A::SFoo", "ns::A::SBar"},
{"void f() { TA<int>::SFoo(); }", "void f() { TA<int>::SBar(); }",
"TA::SFoo", "TA::SBar"},
{"void f() { ns::TA<int>::SFoo(); }",
"void f() { ns::TA<int>::SBar(); }", "ns::TA::SFoo", "ns::TA::SBar"},
// Static variables.
{"void f() { A::SMoo; }",
"void f() { A::SMeh; }", "A::SMoo", "A::SMeh"},
// Templated methods.
{"void f() { TA<int> a; a.Foo(); }", "void f() { TA<int> a; a.Bar(); }",
"TA::Foo", "TA::Bar"},
{"void f() { ns::TA<int> a; a.Foo(); }",
"void f() { ns::TA<int> a; a.Bar(); }", "ns::TA::Foo", "ns::TA::Bar"},
{"void f() { TB<int> b; b.Foo(); }", "void f() { TB<int> b; b.Bar(); }",
"TA::Foo", "TA::Bar"},
{"void f() { ns::TB<int> b; b.Foo(); }",
"void f() { ns::TB<int> b; b.Bar(); }", "ns::TA::Foo", "ns::TA::Bar"},
{"void f() { ns::C c; int x; c.SFoo(x); }",
"void f() { ns::C c; int x; c.SBar(x); }", "ns::C::SFoo",
"ns::C::SBar"},
{"void f() { ns::C c; c.Foo<int>(); }",
"void f() { ns::C c; c.Bar<int>(); }", "ns::C::Foo", "ns::C::Bar"},
// Pointers to methods.
{"void f() { auto p = &A::Foo; }", "void f() { auto p = &A::Bar; }",
"A::Foo", "A::Bar"},
{"void f() { auto p = &A::SFoo; }", "void f() { auto p = &A::SBar; }",
"A::SFoo", "A::SBar"},
{"void f() { auto p = &B::Foo; }", "void f() { auto p = &B::Bar; }",
"B::Foo", "B::Bar"},
{"void f() { auto p = &ns::A::Foo; }",
"void f() { auto p = &ns::A::Bar; }", "ns::A::Foo", "ns::A::Bar"},
{"void f() { auto p = &ns::A::SFoo; }",
"void f() { auto p = &ns::A::SBar; }", "ns::A::SFoo", "ns::A::SBar"},
{"void f() { auto p = &ns::C::SFoo<int>; }",
"void f() { auto p = &ns::C::SBar<int>; }", "ns::C::SFoo",
"ns::C::SBar"},
// These methods are not declared or overridden in the subclass B, we
// have to use the qualified name with parent class A to identify them.
{"void f() { auto p = &ns::B::Foo; }",
"void f() { auto p = &ns::B::Bar; }", "ns::A::Foo", "ns::B::Bar"},
{"void f() { B::SFoo(); }", "void f() { B::SBar(); }", "A::SFoo",
"B::SBar"},
{"void f() { ns::B::SFoo(); }", "void f() { ns::B::SBar(); }",
"ns::A::SFoo", "ns::B::SBar"},
{"void f() { auto p = &B::SFoo; }", "void f() { auto p = &B::SBar; }",
"A::SFoo", "B::SBar"},
{"void f() { auto p = &ns::B::SFoo; }",
"void f() { auto p = &ns::B::SBar; }", "ns::A::SFoo", "ns::B::SBar"},
{"void f() { TB<int>::SFoo(); }", "void f() { TB<int>::SBar(); }",
"TA::SFoo", "TB::SBar"},
{"void f() { ns::TB<int>::SFoo(); }",
"void f() { ns::TB<int>::SBar(); }", "ns::TA::SFoo", "ns::TB::SBar"},
})), );
TEST_P(RenameMemberTest, RenameMembers) {
auto Param = GetParam();
assert(!Param.OldName.empty());
assert(!Param.NewName.empty());
std::string Actual =
runClangRenameOnCode(Param.Before, Param.OldName, Param.NewName);
CompareSnippets(Param.After, Actual);
}
TEST_F(RenameMemberTest, RenameMemberInsideClassMethods) {
std::string Before = R"(
struct X {
int Moo;
void Baz() { Moo = 1; }
};)";
std::string Expected = R"(
struct X {
int Meh;
void Baz() { Meh = 1; }
};)";
std::string After = runClangRenameOnCode(Before, "X::Moo", "Y::Meh");
CompareSnippets(Expected, After);
}
TEST_F(RenameMemberTest, RenameMethodInsideClassMethods) {
std::string Before = R"(
struct X {
void Foo() {}
void Baz() { Foo(); }
};)";
std::string Expected = R"(
struct X {
void Bar() {}
void Baz() { Bar(); }
};)";
std::string After = runClangRenameOnCode(Before, "X::Foo", "X::Bar");
CompareSnippets(Expected, After);
}
TEST_F(RenameMemberTest, RenameCtorInitializer) {
std::string Before = R"(
class X {
public:
X();
A a;
A a2;
B b;
};
X::X():a(), b() {}
)";
std::string Expected = R"(
class X {
public:
X();
A bar;
A a2;
B b;
};
X::X():bar(), b() {}
)";
std::string After = runClangRenameOnCode(Before, "X::a", "X::bar");
CompareSnippets(Expected, After);
}
} // anonymous namespace
} // namespace test
} // namespace clang_rename
} // namesdpace clang