2017-10-25 19:54:45 +08:00
|
|
|
//===-- ClangMemberTests.cpp - unit tests for renaming class members ------===//
|
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2017-10-25 19:54:45 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#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"},
|
|
|
|
|
2018-02-06 21:12:29 +08:00
|
|
|
// These methods are not declared or overridden in the subclass B, we
|
2017-10-25 19:54:45 +08:00
|
|
|
// 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
|