Imported Upstream version 6.10.0.49

Former-commit-id: 1d6753294b2993e1fbf92de9366bb9544db4189b
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2020-01-16 16:38:04 +00:00
parent d94e79959b
commit 468663ddbb
48518 changed files with 2789335 additions and 61176 deletions

View File

@ -0,0 +1,27 @@
set(LLVM_LINK_COMPONENTS
support
)
# We'd like clang/unittests/Tooling/RewriterTestContext.h in the test.
include_directories(${CLANG_SOURCE_DIR})
add_clang_unittest(ClangRenameTests
RenameClassTest.cpp
RenameEnumTest.cpp
RenameAliasTest.cpp
RenameMemberTest.cpp
RenameFunctionTest.cpp
)
target_link_libraries(ClangRenameTests
PRIVATE
clangAST
clangASTMatchers
clangBasic
clangFormat
clangFrontend
clangRewrite
clangTooling
clangToolingCore
clangToolingRefactor
)

View File

@ -0,0 +1,112 @@
//===-- ClangRenameTests.cpp - clang-rename unit tests --------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "unittests/Tooling/RewriterTestContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/FileSystemOptions.h"
#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Format/Format.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/PCHContainerOperations.h"
#include "clang/Tooling/Refactoring.h"
#include "clang/Tooling/Refactoring/Rename/RenamingAction.h"
#include "clang/Tooling/Refactoring/Rename/USRFindingAction.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/MemoryBuffer.h"
#include "gtest/gtest.h"
#include <memory>
#include <string>
#include <vector>
namespace clang {
namespace clang_rename {
namespace test {
struct Case {
std::string Before;
std::string After;
std::string OldName;
std::string NewName;
};
class ClangRenameTest : public testing::Test,
public testing::WithParamInterface<Case> {
protected:
void AppendToHeader(StringRef Code) { HeaderContent += Code.str(); }
std::string runClangRenameOnCode(llvm::StringRef Code,
llvm::StringRef OldName,
llvm::StringRef NewName) {
std::string NewCode;
llvm::raw_string_ostream(NewCode) << llvm::format(
"#include \"%s\"\n%s", HeaderName.c_str(), Code.str().c_str());
tooling::FileContentMappings FileContents = {{HeaderName, HeaderContent},
{CCName, NewCode}};
clang::RewriterTestContext Context;
Context.createInMemoryFile(HeaderName, HeaderContent);
clang::FileID InputFileID = Context.createInMemoryFile(CCName, NewCode);
tooling::USRFindingAction FindingAction({}, {OldName}, false);
std::unique_ptr<tooling::FrontendActionFactory> USRFindingActionFactory =
tooling::newFrontendActionFactory(&FindingAction);
if (!tooling::runToolOnCodeWithArgs(
USRFindingActionFactory->create(), NewCode, {"-std=c++11"}, CCName,
"clang-rename", std::make_shared<PCHContainerOperations>(),
FileContents))
return "";
const std::vector<std::vector<std::string>> &USRList =
FindingAction.getUSRList();
std::vector<std::string> NewNames = {NewName};
std::map<std::string, tooling::Replacements> FileToReplacements;
tooling::QualifiedRenamingAction RenameAction(NewNames, USRList,
FileToReplacements);
auto RenameActionFactory = tooling::newFrontendActionFactory(&RenameAction);
if (!tooling::runToolOnCodeWithArgs(
RenameActionFactory->create(), NewCode, {"-std=c++11"}, CCName,
"clang-rename", std::make_shared<PCHContainerOperations>(),
FileContents))
return "";
formatAndApplyAllReplacements(FileToReplacements, Context.Rewrite, "llvm");
return Context.getRewrittenText(InputFileID);
}
void CompareSnippets(StringRef Expected, StringRef Actual) {
std::string ExpectedCode;
llvm::raw_string_ostream(ExpectedCode) << llvm::format(
"#include \"%s\"\n%s", HeaderName.c_str(), Expected.str().c_str());
EXPECT_EQ(format(ExpectedCode), format(Actual));
}
std::string format(llvm::StringRef Code) {
tooling::Replacements Replaces = format::reformat(
format::getLLVMStyle(), Code, {tooling::Range(0, Code.size())});
auto ChangedCode = tooling::applyAllReplacements(Code, Replaces);
EXPECT_TRUE(static_cast<bool>(ChangedCode));
if (!ChangedCode) {
llvm::errs() << llvm::toString(ChangedCode.takeError());
return "";
}
return *ChangedCode;
}
std::string HeaderContent;
std::string HeaderName = "header.h";
std::string CCName = "input.cc";
};
} // namespace test
} // namespace clang_rename
} // namesdpace clang

View File

@ -0,0 +1,304 @@
//===-- RenameAliasTest.cpp - unit tests for renaming alias ---------------===//
//
// 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 RenameAliasTest : public ClangRenameTest {
public:
RenameAliasTest() {
AppendToHeader(R"(
#define MACRO(x) x
namespace some_ns {
class A {
public:
void foo() {}
struct Nested {
enum NestedEnum {
E1, E2,
};
};
};
} // namespace some_ns
namespace a {
typedef some_ns::A TA;
using UA = some_ns::A;
} // namespace a
namespace b {
typedef some_ns::A TA;
using UA = some_ns::A;
}
template <typename T> class ptr {};
template <typename T>
using TPtr = ptr<int>;
)");
}
};
INSTANTIATE_TEST_CASE_P(
RenameAliasTests, RenameAliasTest,
testing::ValuesIn(std::vector<Case>({
// basic functions
{"void f(a::TA a1) {}", "void f(b::TB a1) {}", "a::TA", "b::TB"},
{"void f(a::UA a1) {}", "void f(b::UB a1) {}", "a::UA", "b::UB"},
{"void f(a::TA* a1) {}", "void f(b::TB* a1) {}", "a::TA", "b::TB"},
{"void f(a::TA** a1) {}", "void f(b::TB** a1) {}", "a::TA", "b::TB"},
{"a::TA f() { return a::TA(); }", "b::TB f() { return b::TB(); }",
"a::TA", "b::TB"},
{"a::TA f() { return a::UA(); }", "b::TB f() { return a::UA(); }",
"a::TA", "b::TB"},
{"a::TA f() { return a::UA(); }", "a::TA f() { return b::UB(); }",
"a::UA", "b::UB"},
{"void f() { a::TA a; }", "void f() { b::TB a; }", "a::TA", "b::TB"},
{"void f(const a::TA& a1) {}", "void f(const b::TB& a1) {}", "a::TA",
"b::TB"},
{"void f(const a::UA& a1) {}", "void f(const b::UB& a1) {}", "a::UA",
"b::UB"},
{"void f(const a::TA* a1) {}", "void f(const b::TB* a1) {}", "a::TA",
"b::TB"},
{"namespace a { void f(TA a1) {} }",
"namespace a { void f(b::TB a1) {} }", "a::TA", "b::TB"},
{"void f(MACRO(a::TA) a1) {}", "void f(MACRO(b::TB) a1) {}", "a::TA",
"b::TB"},
{"void f(MACRO(a::TA a1)) {}", "void f(MACRO(b::TB a1)) {}", "a::TA",
"b::TB"},
// shorten/add namespace.
{"namespace b { void f(a::UA a1) {} }",
"namespace b {void f(UB a1) {} }", "a::UA", "b::UB"},
{"namespace a { void f(UA a1) {} }",
"namespace a {void f(b::UB a1) {} }", "a::UA", "b::UB"},
// use namespace and typedefs
{"struct S { using T = a::TA; T a_; };",
"struct S { using T = b::TB; T a_; };", "a::TA", "b::TB"},
{"using T = a::TA; T gA;", "using T = b::TB; T gA;", "a::TA", "b::TB"},
{"using T = a::UA; T gA;", "using T = b::UB; T gA;", "a::UA", "b::UB"},
{"typedef a::TA T; T gA;", "typedef b::TB T; T gA;", "a::TA", "b::TB"},
{"typedef a::UA T; T gA;", "typedef b::UB T; T gA;", "a::UA", "b::UB"},
{"typedef MACRO(a::TA) T; T gA;", "typedef MACRO(b::TB) T; T gA;",
"a::TA", "b::TB"},
// types in using shadows.
{"using a::TA; TA gA;", "using b::TB; b::TB gA;", "a::TA", "b::TB"},
{"using a::UA; UA gA;", "using b::UB; b::UB gA;", "a::UA", "b::UB"},
// struct members and other oddities
{"struct S : public a::TA {};", "struct S : public b::TB {};", "a::TA",
"b::TB"},
{"struct S : public a::UA {};", "struct S : public b::UB {};", "a::UA",
"b::UB"},
{"struct F { void f(a::TA a1) {} };",
"struct F { void f(b::TB a1) {} };", "a::TA", "b::TB"},
{"struct F { a::TA a_; };", "struct F { b::TB a_; };", "a::TA",
"b::TB"},
{"struct F { ptr<a::TA> a_; };", "struct F { ptr<b::TB> a_; };",
"a::TA", "b::TB"},
{"struct F { ptr<a::UA> a_; };", "struct F { ptr<b::UB> a_; };",
"a::UA", "b::UB"},
// types in nested name specifiers
{"void f() { a::TA::Nested ne; }", "void f() { b::TB::Nested ne; }",
"a::TA", "b::TB"},
{"void f() { a::UA::Nested ne; }", "void f() { b::UB::Nested ne; }",
"a::UA", "b::UB"},
{"void f() { a::TA::Nested::NestedEnum e; }",
"void f() { b::TB::Nested::NestedEnum e; }", "a::TA", "b::TB"},
{"void f() { auto e = a::TA::Nested::NestedEnum::E1; }",
"void f() { auto e = b::TB::Nested::NestedEnum::E1; }", "a::TA",
"b::TB"},
{"void f() { auto e = a::TA::Nested::E1; }",
"void f() { auto e = b::TB::Nested::E1; }", "a::TA", "b::TB"},
// templates
{"template <typename T> struct Foo { T t; }; void f() { Foo<a::TA> "
"foo; }",
"template <typename T> struct Foo { T t; }; void f() { Foo<b::TB> "
"foo; }",
"a::TA", "b::TB"},
{"template <typename T> struct Foo { a::TA a; };",
"template <typename T> struct Foo { b::TB a; };", "a::TA", "b::TB"},
{"template <typename T> void f(T t) {} void g() { f<a::TA>(a::TA()); }",
"template <typename T> void f(T t) {} void g() { f<b::TB>(b::TB()); }",
"a::TA", "b::TB"},
{"template <typename T> void f(T t) {} void g() { f<a::UA>(a::UA()); }",
"template <typename T> void f(T t) {} void g() { f<b::UB>(b::UB()); }",
"a::UA", "b::UB"},
{"template <typename T> int f() { return 1; } template <> int "
"f<a::TA>() { return 2; } int g() { return f<a::TA>(); }",
"template <typename T> int f() { return 1; } template <> int "
"f<b::TB>() { return 2; } int g() { return f<b::TB>(); }",
"a::TA", "b::TB"},
{"struct Foo { template <typename T> T foo(); }; void g() { Foo f; "
"auto a = f.template foo<a::TA>(); }",
"struct Foo { template <typename T> T foo(); }; void g() { Foo f; "
"auto a = f.template foo<b::TB>(); }",
"a::TA", "b::TB"},
{"struct Foo { template <typename T> T foo(); }; void g() { Foo f; "
"auto a = f.template foo<a::UA>(); }",
"struct Foo { template <typename T> T foo(); }; void g() { Foo f; "
"auto a = f.template foo<b::UB>(); }",
"a::UA", "b::UB"},
// The following two templates are distilled from regressions found in
// unique_ptr<> and type_traits.h
{"template <typename T> struct outer { typedef T type; type Baz(); }; "
"outer<a::TA> g_A;",
"template <typename T> struct outer { typedef T type; type Baz(); }; "
"outer<b::TB> g_A;",
"a::TA", "b::TB"},
{"template <typename T> struct nested { typedef T type; }; template "
"<typename T> struct outer { typename nested<T>::type Foo(); }; "
"outer<a::TA> g_A;",
"template <typename T> struct nested { typedef T type; }; template "
"<typename T> struct outer { typename nested<T>::type Foo(); }; "
"outer<b::TB> g_A;",
"a::TA", "b::TB"},
// macros
{"#define FOO(T, t) T t\nvoid f() { FOO(a::TA, a1); FOO(a::TA, a2); }",
"#define FOO(T, t) T t\nvoid f() { FOO(b::TB, a1); FOO(b::TB, a2); }",
"a::TA", "b::TB"},
{"#define FOO(n) a::TA n\nvoid f() { FOO(a1); FOO(a2); }",
"#define FOO(n) b::TB n\nvoid f() { FOO(a1); FOO(a2); }", "a::TA",
"b::TB"},
{"#define FOO(n) a::UA n\nvoid f() { FOO(a1); FOO(a2); }",
"#define FOO(n) b::UB n\nvoid f() { FOO(a1); FOO(a2); }", "a::UA",
"b::UB"},
// Pointer to member functions
{"auto gA = &a::TA::foo;", "auto gA = &b::TB::foo;", "a::TA", "b::TB"},
{"using a::TA; auto gA = &TA::foo;",
"using b::TB; auto gA = &b::TB::foo;", "a::TA", "b::TB"},
{"typedef a::TA T; auto gA = &T::foo;",
"typedef b::TB T; auto gA = &T::foo;", "a::TA", "b::TB"},
{"auto gA = &MACRO(a::TA)::foo;", "auto gA = &MACRO(b::TB)::foo;",
"a::TA", "b::TB"},
// templated using alias.
{"void f(TPtr<int> p) {}", "void f(NewTPtr<int> p) {}", "TPtr",
"NewTPtr"},
{"void f(::TPtr<int> p) {}", "void f(::NewTPtr<int> p) {}", "TPtr",
"NewTPtr"},
})), );
TEST_P(RenameAliasTest, RenameAlias) {
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(RenameAliasTest, RenameTypedefDefinitions) {
std::string Before = R"(
class X {};
typedef X TOld;
)";
std::string Expected = R"(
class X {};
typedef X TNew;
)";
std::string After = runClangRenameOnCode(Before, "TOld", "TNew");
CompareSnippets(Expected, After);
}
TEST_F(RenameAliasTest, RenameUsingAliasDefinitions) {
std::string Before = R"(
class X {};
using UOld = X;
)";
std::string Expected = R"(
class X {};
using UNew = X;
)";
std::string After = runClangRenameOnCode(Before, "UOld", "UNew");
CompareSnippets(Expected, After);
}
TEST_F(RenameAliasTest, RenameTemplatedAliasDefinitions) {
std::string Before = R"(
template <typename T>
class X { T t; };
template <typename T>
using Old = X<T>;
)";
std::string Expected = R"(
template <typename T>
class X { T t; };
template <typename T>
using New = X<T>;
)";
std::string After = runClangRenameOnCode(Before, "Old", "New");
CompareSnippets(Expected, After);
}
TEST_F(RenameAliasTest, RenameAliasesInNamespaces) {
std::string Before = R"(
namespace x { class X {}; }
namespace ns {
using UOld = x::X;
}
)";
std::string Expected = R"(
namespace x { class X {}; }
namespace ns {
using UNew = x::X;
}
)";
std::string After = runClangRenameOnCode(Before, "ns::UOld", "ns::UNew");
CompareSnippets(Expected, After);
}
TEST_F(RenameAliasTest, AliasesInMacros) {
std::string Before = R"(
namespace x { class Old {}; }
namespace ns {
#define REF(alias) alias alias_var;
#define ALIAS(old) \
using old##Alias = x::old; \
REF(old##Alias);
ALIAS(Old);
OldAlias old_alias;
}
)";
std::string Expected = R"(
namespace x { class Old {}; }
namespace ns {
#define REF(alias) alias alias_var;
#define ALIAS(old) \
using old##Alias = x::old; \
REF(old##Alias);
ALIAS(Old);
NewAlias old_alias;
}
)";
std::string After =
runClangRenameOnCode(Before, "ns::OldAlias", "ns::NewAlias");
CompareSnippets(Expected, After);
}
} // anonymous namespace
} // namespace test
} // namespace clang_rename
} // namesdpace clang

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,189 @@
#include "ClangRenameTest.h"
namespace clang {
namespace clang_rename {
namespace test {
namespace {
class RenameEnumTest : public ClangRenameTest {
public:
RenameEnumTest() {
AppendToHeader(R"(
#define MACRO(x) x
namespace a {
enum A1 { Red };
enum class A2 { Blue };
struct C {
enum NestedEnum { White };
enum class NestedScopedEnum { Black };
};
namespace d {
enum A3 { Orange };
} // namespace d
enum A4 { Pink };
} // namespace a
enum A5 { Green };)");
}
};
INSTANTIATE_TEST_CASE_P(
RenameEnumTests, RenameEnumTest,
testing::ValuesIn(std::vector<Case>({
{"void f(a::A2 arg) { a::A2 t = a::A2::Blue; }",
"void f(b::B2 arg) { b::B2 t = b::B2::Blue; }", "a::A2", "b::B2"},
{"void f() { a::A1* t1; }", "void f() { b::B1* t1; }", "a::A1",
"b::B1"},
{"void f() { a::A2* t1; }", "void f() { b::B2* t1; }", "a::A2",
"b::B2"},
{"void f() { enum a::A2 t = a::A2::Blue; }",
"void f() { enum b::B2 t = b::B2::Blue; }", "a::A2", "b::B2"},
{"void f() { enum a::A2 t = a::A2::Blue; }",
"void f() { enum b::B2 t = b::B2::Blue; }", "a::A2", "b::B2"},
{"void f() { a::A1 t = a::Red; }", "void f() { b::B1 t = b::B1::Red; }",
"a::A1", "b::B1"},
{"void f() { a::A1 t = a::A1::Red; }",
"void f() { b::B1 t = b::B1::Red; }", "a::A1", "b::B1"},
{"void f() { auto t = a::Red; }", "void f() { auto t = b::B1::Red; }",
"a::A1", "b::B1"},
{"namespace b { void f() { a::A1 t = a::Red; } }",
"namespace b { void f() { B1 t = B1::Red; } }", "a::A1", "b::B1"},
{"void f() { a::d::A3 t = a::d::Orange; }",
"void f() { a::b::B3 t = a::b::B3::Orange; }", "a::d::A3", "a::b::B3"},
{"namespace a { void f() { a::d::A3 t = a::d::Orange; } }",
"namespace a { void f() { b::B3 t = b::B3::Orange; } }", "a::d::A3",
"a::b::B3"},
{"void f() { A5 t = Green; }", "void f() { B5 t = Green; }", "A5",
"B5"},
// FIXME: the new namespace qualifier should be added to the unscoped
// enum constant.
{"namespace a { void f() { auto t = Green; } }",
"namespace a { void f() { auto t = Green; } }", "a::A1", "b::B1"},
// namespace qualifiers
{"namespace a { void f(A1 a1) {} }",
"namespace a { void f(b::B1 a1) {} }", "a::A1", "b::B1"},
{"namespace a { void f(A2 a2) {} }",
"namespace a { void f(b::B2 a2) {} }", "a::A2", "b::B2"},
{"namespace b { void f(a::A1 a1) {} }",
"namespace b { void f(B1 a1) {} }", "a::A1", "b::B1"},
{"namespace b { void f(a::A2 a2) {} }",
"namespace b { void f(B2 a2) {} }", "a::A2", "b::B2"},
// nested enums
{"void f() { a::C::NestedEnum t = a::C::White; }",
"void f() { a::C::NewNestedEnum t = a::C::NewNestedEnum::White; }",
"a::C::NestedEnum", "a::C::NewNestedEnum"},
{"void f() { a::C::NestedScopedEnum t = a::C::NestedScopedEnum::Black; "
"}",
"void f() { a::C::NewNestedScopedEnum t = "
"a::C::NewNestedScopedEnum::Black; }",
"a::C::NestedScopedEnum", "a::C::NewNestedScopedEnum"},
// macros
{"void f(MACRO(a::A1) a1) {}", "void f(MACRO(b::B1) a1) {}", "a::A1",
"b::B1"},
{"void f(MACRO(a::A2) a2) {}", "void f(MACRO(b::B2) a2) {}", "a::A2",
"b::B2"},
{"#define FOO(T, t) T t\nvoid f() { FOO(a::A1, a1); }",
"#define FOO(T, t) T t\nvoid f() { FOO(b::B1, a1); }", "a::A1",
"b::B1"},
{"#define FOO(T, t) T t\nvoid f() { FOO(a::A2, a2); }",
"#define FOO(T, t) T t\nvoid f() { FOO(b::B2, a2); }", "a::A2",
"b::B2"},
{"#define FOO(n) a::A1 n\nvoid f() { FOO(a1); FOO(a2); }",
"#define FOO(n) b::B1 n\nvoid f() { FOO(a1); FOO(a2); }", "a::A1",
"b::B1"},
// using and type alias
{"using a::A1; A1 gA;", "using b::B1; b::B1 gA;", "a::A1", "b::B1"},
{"using a::A2; A2 gA;", "using b::B2; b::B2 gA;", "a::A2", "b::B2"},
{"struct S { using T = a::A1; T a_; };",
"struct S { using T = b::B1; T a_; };", "a::A1", "b::B1"},
{"using T = a::A1; T gA;", "using T = b::B1; T gA;", "a::A1", "b::B1"},
{"using T = a::A2; T gA;", "using T = b::B2; T gA;", "a::A2", "b::B2"},
{"typedef a::A1 T; T gA;", "typedef b::B1 T; T gA;", "a::A1", "b::B1"},
{"typedef a::A2 T; T gA;", "typedef b::B2 T; T gA;", "a::A2", "b::B2"},
{"typedef MACRO(a::A1) T; T gA;", "typedef MACRO(b::B1) T; T gA;",
"a::A1", "b::B1"},
// templates
{"template<typename T> struct Foo { T t; }; void f() { Foo<a::A1> "
"foo1; }",
"template<typename T> struct Foo { T t; }; void f() { Foo<b::B1> "
"foo1; }",
"a::A1", "b::B1"},
{"template<typename T> struct Foo { T t; }; void f() { Foo<a::A2> "
"foo2; }",
"template<typename T> struct Foo { T t; }; void f() { Foo<b::B2> "
"foo2; }",
"a::A2", "b::B2"},
{"template<typename T> struct Foo { a::A1 a1; };",
"template<typename T> struct Foo { b::B1 a1; };", "a::A1", "b::B1"},
{"template<typename T> struct Foo { a::A2 a2; };",
"template<typename T> struct Foo { b::B2 a2; };", "a::A2", "b::B2"},
{"template<typename T> int f() { return 1; } template<> int f<a::A1>() "
"{ return 2; } int g() { return f<a::A1>(); }",
"template<typename T> int f() { return 1; } template<> int f<b::B1>() "
"{ return 2; } int g() { return f<b::B1>(); }",
"a::A1", "b::B1"},
{"template<typename T> int f() { return 1; } template<> int f<a::A2>() "
"{ return 2; } int g() { return f<a::A2>(); }",
"template<typename T> int f() { return 1; } template<> int f<b::B2>() "
"{ return 2; } int g() { return f<b::B2>(); }",
"a::A2", "b::B2"},
{"struct Foo { template <typename T> T foo(); }; void g() { Foo f; "
"f.foo<a::A1>(); }",
"struct Foo { template <typename T> T foo(); }; void g() { Foo f; "
"f.foo<b::B1>(); }",
"a::A1", "b::B1"},
{"struct Foo { template <typename T> T foo(); }; void g() { Foo f; "
"f.foo<a::A2>(); }",
"struct Foo { template <typename T> T foo(); }; void g() { Foo f; "
"f.foo<b::B2>(); }",
"a::A2", "b::B2"},
})), );
TEST_P(RenameEnumTest, RenameEnums) {
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(RenameEnumTest, RenameEnumDecl) {
std::string Before = R"(
namespace ns {
enum Old1 { Blue };
}
)";
std::string Expected = R"(
namespace ns {
enum New1 { Blue };
}
)";
std::string After = runClangRenameOnCode(Before, "ns::Old1", "ns::New1");
CompareSnippets(Expected, After);
}
TEST_F(RenameEnumTest, RenameScopedEnumDecl) {
std::string Before = R"(
namespace ns {
enum class Old1 { Blue };
}
)";
std::string Expected = R"(
namespace ns {
enum class New1 { Blue };
}
)";
std::string After = runClangRenameOnCode(Before, "ns::Old1", "ns::New1");
CompareSnippets(Expected, After);
}
} // anonymous namespace
} // namespace test
} // namespace clang_rename
} // namesdpace clang

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,229 @@
//===-- 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 overrided 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