//===-- ChangeNamespaceTests.cpp - Change namespace unit tests ---*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "ChangeNamespace.h" #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/Tooling.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/MemoryBuffer.h" #include "gtest/gtest.h" #include #include #include namespace clang { namespace change_namespace { namespace { class ChangeNamespaceTest : public ::testing::Test { public: std::string runChangeNamespaceOnCode(llvm::StringRef Code) { clang::RewriterTestContext Context; clang::FileID ID = Context.createInMemoryFile(FileName, Code); std::map FileToReplacements; change_namespace::ChangeNamespaceTool NamespaceTool( OldNamespace, NewNamespace, FilePattern, /*WhiteListedSymbolPatterns*/ {}, &FileToReplacements); ast_matchers::MatchFinder Finder; NamespaceTool.registerMatchers(&Finder); std::unique_ptr Factory = tooling::newFrontendActionFactory(&Finder); if (!tooling::runToolOnCodeWithArgs(Factory->create(), Code, {"-std=c++11"}, FileName)) return ""; formatAndApplyAllReplacements(FileToReplacements, Context.Rewrite); return format(Context.getRewrittenText(ID)); } 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(ChangedCode)); if (!ChangedCode) { llvm::errs() << llvm::toString(ChangedCode.takeError()); return ""; } return *ChangedCode; } protected: std::string FileName = "input.cc"; std::string OldNamespace = "na::nb"; std::string NewNamespace = "x::y"; std::string FilePattern = "input.cc"; }; TEST_F(ChangeNamespaceTest, NoMatchingNamespace) { std::string Code = "namespace na {\n" "namespace nx {\n" "class A {};\n" "} // namespace nx\n" "} // namespace na\n"; std::string Expected = "namespace na {\n" "namespace nx {\n" "class A {};\n" "} // namespace nx\n" "} // namespace na\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, SimpleMoveWithoutTypeRefs) { std::string Code = "namespace na {\n" "namespace nb {\n" "class A {};\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "\n\n" "namespace x {\n" "namespace y {\n" "class A {};\n" "} // namespace y\n" "} // namespace x\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, NewNsNestedInOldNs) { NewNamespace = "na::nb::nc"; std::string Code = "namespace na {\n" "namespace nb {\n" "class A {};\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "namespace na {\n" "namespace nb {\n" "namespace nc {\n" "class A {};\n" "} // namespace nc\n" "} // namespace nb\n" "} // namespace na\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, NewNsNestedInOldNsWithSurroundingNewLines) { NewNamespace = "na::nb::nc"; std::string Code = "namespace na {\n" "namespace nb {\n" "\n" "class A {};\n" "\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "namespace na {\n" "namespace nb {\n" "namespace nc {\n" "\n" "class A {};\n" "\n" "} // namespace nc\n" "} // namespace nb\n" "} // namespace na\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, MoveOldNsWithSurroundingNewLines) { NewNamespace = "nx::ny"; std::string Code = "namespace na {\n" "namespace nb {\n" "\n" "class A {};\n" "\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "\n\n" "namespace nx {\n" "namespace ny {\n" "\n" "class A {};\n" "\n" "} // namespace ny\n" "} // namespace nx\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, NewNsNestedInOldNsWithRefs) { NewNamespace = "na::nb::nc"; std::string Code = "namespace na {\n" "class A {};\n" "namespace nb {\n" "class B {};\n" "class C {};\n" "void f() { A a; B b; }\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "namespace na {\n" "class A {};\n" "namespace nb {\n" "namespace nc {\n" "class B {};\n" "class C {};\n" "void f() { A a; B b; }\n" "} // namespace nc\n" "} // namespace nb\n" "} // namespace na\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, SimpleMoveIntoAnotherNestedNamespace) { NewNamespace = "na::nc"; std::string Code = "namespace na {\n" "namespace nb {\n" "class A {};\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "namespace na {\n" "\n" "namespace nc {\n" "class A {};\n" "} // namespace nc\n" "} // namespace na\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, MoveIntoAnotherNestedNamespaceWithRef) { NewNamespace = "na::nc"; std::string Code = "namespace na {\n" "class A {};\n" "namespace nb {\n" "class X { A a; };\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "namespace na {\n" "class A {};\n" "\n" "namespace nc {\n" "class X { A a; };\n" "} // namespace nc\n" "} // namespace na\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, MoveIntoExistingNamespaceAndShortenRefs) { std::string Code = "namespace x {\n" "namespace z {\n" "class Z {};\n" "} // namespace z\n" "namespace y {\n" "class T {};\n" "} // namespace y\n" "} // namespace x\n" "namespace na {\n" "class A{};\n" "namespace nb {\n" "class X { A a; x::z::Z zz; x::y::T t; };\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "namespace x {\n" "namespace z {\n" "class Z {};\n" "} // namespace z\n" "namespace y {\n" "class T {};\n" "} // namespace y\n" "} // namespace x\n" "namespace na {\n" "class A {};\n\n" "} // namespace na\n" "namespace x {\n" "namespace y {\n" "class X { na::A a; z::Z zz; T t; };\n" "} // namespace y\n" "} // namespace x\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, SimpleMoveNestedNamespace) { NewNamespace = "na::x::y"; std::string Code = "namespace na {\n" "class A {};\n" "namespace nb {\n" "class B {};\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "namespace na {\n" "class A {};\n" "\n" "namespace x {\n" "namespace y {\n" "class B {};\n" "} // namespace y\n" "} // namespace x\n" "} // namespace na\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, SimpleMoveWithTypeRefs) { std::string Code = "namespace na {\n" "class C_A {};\n" "namespace nc {\n" "class C_C {};" "} // namespace nc\n" "namespace nb {\n" "class C_X {\n" "public:\n" " C_A a;\n" " nc::C_C c;\n" "};\n" "class C_Y {\n" " C_X x;\n" "};\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "namespace na {\n" "class C_A {};\n" "namespace nc {\n" "class C_C {};" "} // namespace nc\n" "\n" "} // namespace na\n" "namespace x {\n" "namespace y {\n" "class C_X {\n" "public:\n" " na::C_A a;\n" " na::nc::C_C c;\n" "};\n" "class C_Y {\n" " C_X x;\n" "};\n" "} // namespace y\n" "} // namespace x\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, TypeLocInTemplateSpecialization) { std::string Code = "namespace na {\n" "class A {};\n" "template \n" "class B {};\n" "template \n" "class Two {};\n" "namespace nc { class C {}; }\n" "} // na\n" "\n" "namespace na {\n" "namespace nb {\n" "void f() {\n" " B b;\n" " B b_c;\n" " Two two;\n" "}\n" "} // nb\n" "} // na\n"; std::string Expected = "namespace na {\n" "class A {};\n" "template \n" "class B {};\n" "template \n" "class Two {};\n" "namespace nc { class C {}; }\n" "} // na\n" "\n" "\n" "namespace x {\n" "namespace y {\n" "void f() {\n" " na::B b;\n" " na::B b_c;\n" " na::Two two;\n" "}\n" "} // namespace y\n" "} // namespace x\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, LeaveForwardDeclarationBehind) { std::string Code = "namespace na {\n" "namespace nb {\n" "class FWD;\n" "class FWD2;\n" "class A {\n" " FWD *fwd;\n" "};\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "namespace na {\n" "namespace nb {\n" "class FWD;\n" "class FWD2;\n" "} // namespace nb\n" "} // namespace na\n" "namespace x {\n" "namespace y {\n" "\n" "class A {\n" " na::nb::FWD *fwd;\n" "};\n" "} // namespace y\n" "} // namespace x\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, InsertForwardDeclsProperly) { std::string Code = "namespace na {\n" "namespace nb {\n" "\n" "class FWD;\n" "class FWD2;\n" "class A {\n" " FWD *fwd;\n" "};\n" "\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "namespace na {\n" "namespace nb {\n" "class FWD;\n" "class FWD2;\n" "} // namespace nb\n" "} // namespace na\n" "namespace x {\n" "namespace y {\n" "\n" "class A {\n" " na::nb::FWD *fwd;\n" "};\n" "\n" "} // namespace y\n" "} // namespace x\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, TemplateClassForwardDeclaration) { std::string Code = "namespace na {\n" "namespace nb {\n" "class FWD;\n" "template class FWD_TEMP;\n" "class A {\n" " FWD *fwd;\n" "};\n" "template class TEMP {};\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "namespace na {\n" "namespace nb {\n" "class FWD;\n" "template class FWD_TEMP;\n" "} // namespace nb\n" "} // namespace na\n" "namespace x {\n" "namespace y {\n" "\n" "class A {\n" " na::nb::FWD *fwd;\n" "};\n" "template class TEMP {};\n" "} // namespace y\n" "} // namespace x\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, DontMoveForwardDeclarationInClass) { std::string Code = "namespace na {\n" "namespace nb {\n" "class A {\n" " class FWD;\n" " FWD *fwd;\n" " template class FWD_TEMP;\n" "};\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "\n\n" "namespace x {\n" "namespace y {\n" "class A {\n" " class FWD;\n" " FWD *fwd;\n" " template class FWD_TEMP;\n" "};\n" "} // namespace y\n" "} // namespace x\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, MoveFunctions) { std::string Code = "namespace na {\n" "class C_A {};\n" "namespace nc {\n" "class C_C {};" "} // namespace nc\n" "namespace nb {\n" "void fwd();\n" "void f(C_A ca, nc::C_C cc) {\n" " C_A ca_1 = ca;\n" "}\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "namespace na {\n" "class C_A {};\n" "namespace nc {\n" "class C_C {};" "} // namespace nc\n" "\n" "} // namespace na\n" "namespace x {\n" "namespace y {\n" "void fwd();\n" "void f(na::C_A ca, na::nc::C_C cc) {\n" " na::C_A ca_1 = ca;\n" "}\n" "} // namespace y\n" "} // namespace x\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, FixUsingShadowDecl) { std::string Code = "class GLOB {};\n" "using BLOG = GLOB;\n" "namespace na {\n" "namespace nc {\n" "class SAME {};\n" "}\n" "namespace nd {\n" "class SAME {};\n" "}\n" "namespace nb {\n" "using nc::SAME;\n" "using YO = nd::SAME;\n" "typedef nd::SAME IDENTICAL;\n" "void f(nd::SAME Same) {}\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "class GLOB {};\n" "using BLOG = GLOB;\n" "namespace na {\n" "namespace nc {\n" "class SAME {};\n" "}\n" "namespace nd {\n" "class SAME {};\n" "}\n" "\n" "} // namespace na\n" "namespace x {\n" "namespace y {\n" "using ::na::nc::SAME;\n" "using YO = na::nd::SAME;\n" "typedef na::nd::SAME IDENTICAL;\n" "void f(na::nd::SAME Same) {}\n" "} // namespace y\n" "} // namespace x\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, DontFixUsingShadowDeclInClasses) { std::string Code = "namespace na {\n" "class A {};\n" "class Base { public: Base() {} void m() {} };\n" "namespace nb {\n" "class D : public Base {\n" "public:\n" " using AA = A; using B = Base;\n" " using Base::m; using Base::Base;\n" "};" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "namespace na {\n" "class A {};\n" "class Base { public: Base() {} void m() {} };\n" "\n" "} // namespace na\n" "namespace x {\n" "namespace y {\n" "class D : public na::Base {\n" "public:\n" " using AA = na::A; using B = na::Base;\n" " using Base::m; using Base::Base;\n" "};" "} // namespace y\n" "} // namespace x\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, TypeInNestedNameSpecifier) { std::string Code = "namespace na {\n" "class C_A {\n" "public:\n" " class Nested {\n" " public:\n" " static int NestedX;\n" " static void nestedFunc() {}\n" " };\n" "};\n" "namespace nb {\n" "class C_X {\n" " C_A na;\n" " C_A::Nested nested;\n" " void f() {\n" " C_A::Nested::nestedFunc();\n" " int X = C_A::Nested::NestedX;\n" " }\n" "};\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "namespace na {\n" "class C_A {\n" "public:\n" " class Nested {\n" " public:\n" " static int NestedX;\n" " static void nestedFunc() {}\n" " };\n" "};\n" "\n" "} // namespace na\n" "namespace x {\n" "namespace y {\n" "class C_X {\n" " na::C_A na;\n" " na::C_A::Nested nested;\n" " void f() {\n" " na::C_A::Nested::nestedFunc();\n" " int X = na::C_A::Nested::NestedX;\n" " }\n" "};\n" "} // namespace y\n" "} // namespace x\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, FixFunctionNameSpecifiers) { std::string Code = "namespace na {\n" "class A {\n" "public:\n" " static void f() {}\n" " static void g();\n" "};\n" "void A::g() {}" "void a_f() {}\n" "static void static_f() {}\n" "namespace nb {\n" "void f() { a_f(); static_f(); A::f(); }\n" "void g() { f(); A::g(); }\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "namespace na {\n" "class A {\n" "public:\n" " static void f() {}\n" " static void g();\n" "};\n" "void A::g() {}" "void a_f() {}\n" "static void static_f() {}\n" "\n" "} // namespace na\n" "namespace x {\n" "namespace y {\n" "void f() { na::a_f(); na::static_f(); na::A::f(); }\n" "void g() { f(); na::A::g(); }\n" "} // namespace y\n" "} // namespace x\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, FixOverloadedOperatorFunctionNameSpecifiers) { std::string Code = "namespace na {\n" "class A {\n" "public:\n" " int x;\n" " bool operator==(const A &RHS) const { return x == RHS.x; }\n" "};\n" "bool operator<(const A &LHS, const A &RHS) { return LHS.x == RHS.x; }\n" "namespace nb {\n" "bool f() {\n" " A x, y;\n" " auto f = operator<;\n" " return (x == y) && (x < y) && (operator<(x, y));\n" "}\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "namespace na {\n" "class A {\n" "public:\n" " int x;\n" " bool operator==(const A &RHS) const { return x == RHS.x; }\n" "};\n" "bool operator<(const A &LHS, const A &RHS) { return LHS.x == RHS.x; }\n" "\n" "} // namespace na\n" "namespace x {\n" "namespace y {\n" "bool f() {\n" " na::A x, y;\n" " auto f = na::operator<;\n" // FIXME: function calls to overloaded operators are not fixed now even if // they are referenced by qualified names. " return (x == y) && (x < y) && (operator<(x,y));\n" "}\n" "} // namespace y\n" "} // namespace x\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, FixNonCallingFunctionReferences) { std::string Code = "namespace na {\n" "class A {\n" "public:\n" " static void f() {}\n" "};\n" "void a_f() {}\n" "static void s_f() {}\n" "namespace nb {\n" "void f() {\n" " auto *ref1 = A::f;\n" " auto *ref2 = a_f;\n" " auto *ref3 = s_f;\n" "}\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "namespace na {\n" "class A {\n" "public:\n" " static void f() {}\n" "};\n" "void a_f() {}\n" "static void s_f() {}\n" "\n" "} // namespace na\n" "namespace x {\n" "namespace y {\n" "void f() {\n" " auto *ref1 = na::A::f;\n" " auto *ref2 = na::a_f;\n" " auto *ref3 = na::s_f;\n" "}\n" "} // namespace y\n" "} // namespace x\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, MoveAndFixGlobalVariables) { std::string Code = "namespace na {\n" "int GlobA;\n" "static int GlobAStatic = 0;\n" "namespace nc { int GlobC; }\n" "namespace nb {\n" "int GlobB;\n" "void f() {\n" " int a = GlobA;\n" " int b = GlobAStatic;\n" " int c = nc::GlobC;\n" "}\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "namespace na {\n" "int GlobA;\n" "static int GlobAStatic = 0;\n" "namespace nc { int GlobC; }\n" "\n" "} // namespace na\n" "namespace x {\n" "namespace y {\n" "int GlobB;\n" "void f() {\n" " int a = na::GlobA;\n" " int b = na::GlobAStatic;\n" " int c = na::nc::GlobC;\n" "}\n" "} // namespace y\n" "} // namespace x\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, DoNotFixStaticVariableOfClass) { std::string Code = "namespace na {\n" "class A {\n" "public:\n" "static int A1;\n" "static int A2;\n" "};\n" "int A::A1 = 0;\n" "namespace nb {\n" "void f() {\n" " int a = A::A1; int b = A::A2;\n" "}\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "namespace na {\n" "class A {\n" "public:\n" "static int A1;\n" "static int A2;\n" "};\n" "int A::A1 = 0;\n" "\n" "} // namespace na\n" "namespace x {\n" "namespace y {\n" "void f() {\n" " int a = na::A::A1; int b = na::A::A2;\n" "}\n" "} // namespace y\n" "} // namespace x\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, NoMisplaceAtEOF) { std::string Code = "namespace na {\n" "namespace nb {\n" "class A;\n" "class B {};\n" "}" "}"; std::string Expected = "namespace na {\n" "namespace nb {\n" "class A;\n" "}\n" "}\n" "namespace x {\n" "namespace y {\n" "\n" "class B {};\n" "} // namespace y\n" "} // namespace x\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, CommentsBeforeMovedClass) { std::string Code = "namespace na {\n" "namespace nb {\n" "\n\n" "// Wild comments.\n" "\n" "// Comments.\n" "// More comments.\n" "class B {\n" " // Private comments.\n" " int a;\n" "};\n" "}\n" "}"; std::string Expected = "\n" "\n" "namespace x {\n" "namespace y {\n" "\n\n" "// Wild comments.\n" "\n" "// Comments.\n" "// More comments.\n" "class B {\n" " // Private comments.\n" " int a;\n" "};\n" "} // namespace y\n" "} // namespace x\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, UsingShadowDeclInGlobal) { std::string Code = "namespace glob {\n" "class Glob {};\n" "void GFunc() {}\n" "}\n" "using glob::Glob;\n" "using glob::GFunc;\n" "namespace na {\n" "namespace nb {\n" "void f() { Glob g; GFunc(); }\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "namespace glob {\n" "class Glob {};\n" "void GFunc() {}\n" "}\n" "using glob::Glob;\n" "using glob::GFunc;\n" "\n" "namespace x {\n" "namespace y {\n" "void f() { Glob g; GFunc(); }\n" "} // namespace y\n" "} // namespace x\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, UsingShadowDeclsInAnonymousNamespaces) { std::string Code = "namespace util {\n" "class Util {};\n" "void func() {}\n" "}\n" "namespace na {\n" "namespace nb {\n" "namespace {\n" "using ::util::Util;\n" "using ::util::func;\n" "void f() { Util u; func(); }\n" "}\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "namespace util {\n" "class Util {};\n" "void func() {}\n" "} // namespace util\n" "\n" "namespace x {\n" "namespace y {\n" "namespace {\n" "using ::util::Util;\n" "using ::util::func;\n" "void f() { Util u; func(); }\n" "}\n" "} // namespace y\n" "} // namespace x\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, UsingNamespaceInGlobal) { std::string Code = "namespace glob {\n" "class Glob {};\n" "}\n" "using namespace glob;\n" "namespace na {\n" "namespace nb {\n" "void f() { Glob g; }\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "namespace glob {\n" "class Glob {};\n" "}\n" "using namespace glob;\n" "\n" "namespace x {\n" "namespace y {\n" "void f() { Glob g; }\n" "} // namespace y\n" "} // namespace x\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, NamespaceAliasInGlobal) { std::string Code = "namespace glob {\n" "class Glob {};\n" "}\n" "namespace glob2 { class Glob2 {}; }\n" "namespace gl = glob;\n" "namespace gl2 = glob2;\n" "namespace na {\n" "namespace nb {\n" "void f() { gl::Glob g; gl2::Glob2 g2; }\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "namespace glob {\n" "class Glob {};\n" "}\n" "namespace glob2 { class Glob2 {}; }\n" "namespace gl = glob;\n" "namespace gl2 = glob2;\n" "\n" "namespace x {\n" "namespace y {\n" "void f() { gl::Glob g; gl2::Glob2 g2; }\n" "} // namespace y\n" "} // namespace x\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, NamespaceAliasInNamespace) { std::string Code = "namespace glob {\n" "class Glob {};\n" "}\n" "namespace na {\n" "namespace nb {\n" "namespace gl = glob;\n" "void f() { gl::Glob g; }\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "namespace glob {\n" "class Glob {};\n" "}\n" "\n" "namespace x {\n" "namespace y {\n" "namespace gl = glob;\n" "void f() { gl::Glob g; }\n" "} // namespace y\n" "} // namespace x\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, NamespaceAliasInAncestorNamespace) { NewNamespace = "na::nx"; std::string Code = "namespace glob {\n" "class Glob {};\n" "}\n" "namespace other { namespace gl = glob; }\n" "namespace na {\n" "namespace ga = glob;\n" "namespace nb {\n" "void f() { ga::Glob g; }\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "namespace glob {\n" "class Glob {};\n" "}\n" "namespace other { namespace gl = glob; }\n" "namespace na {\n" "namespace ga = glob;\n" "\n" "namespace nx {\n" "void f() { ga::Glob g; }\n" "} // namespace nx\n" "} // namespace na\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, NamespaceAliasInOtherNamespace) { std::string Code = "namespace glob {\n" "class Glob {};\n" "}\n" "namespace other { namespace gl = glob; }\n" "namespace na {\n" "namespace ga = glob;\n" "namespace nb {\n" "void f() { glob::Glob g; }\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "namespace glob {\n" "class Glob {};\n" "}\n" "namespace other { namespace gl = glob; }\n" "namespace na {\n" "namespace ga = glob;\n" "\n" "} // namespace na\n" "namespace x {\n" "namespace y {\n" "void f() { glob::Glob g; }\n" "} // namespace y\n" "} // namespace x\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, UsingDeclAfterReference) { std::string Code = "namespace glob {\n" "class Glob {};\n" "}\n" "namespace na {\n" "namespace nb {\n" "void f() { glob::Glob g; }\n" "} // namespace nb\n" "} // namespace na\n" "using glob::Glob;\n" "using namespace glob;\n"; std::string Expected = "namespace glob {\n" "class Glob {};\n" "}\n" "\n" "namespace x {\n" "namespace y {\n" "void f() { glob::Glob g; }\n" "} // namespace y\n" "} // namespace x\n" "using glob::Glob;\n" "using namespace glob;\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, UsingNamespaceAfterReference) { NewNamespace = "na::nc"; std::string Code = "namespace glob {\n" "class Glob {};\n" "}\n" "namespace na {\n" "namespace nb {\n" "void f() { glob::Glob g; }\n" "} // namespace nb\n" "using namespace glob;\n" "} // namespace na\n"; std::string Expected = "namespace glob {\n" "class Glob {};\n" "}\n" "namespace na {\n" "\n" "namespace nc {\n" "void f() { glob::Glob g; }\n" "} // namespace nc\n" "using namespace glob;\n" "} // namespace na\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, UsingNamespaceAndUsingShadowInGlobal) { std::string Code = "namespace glob1 {\n" "namespace glob2 {\n" "class Glob {};\n" "}\n" "}\n" "using glob1::glob2::Glob;\n" "using namespace glob1;\n" "namespace na {\n" "namespace nb {\n" "void f() { Glob g; }\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "namespace glob1 {\n" "namespace glob2 {\n" "class Glob {};\n" "}\n" "}\n" "using glob1::glob2::Glob;\n" "using namespace glob1;\n" "\n" "namespace x {\n" "namespace y {\n" "void f() { Glob g; }\n" "} // namespace y\n" "} // namespace x\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, UsingAliasInGlobal) { std::string Code = "namespace glob {\n" "class Glob {};\n" "}\n" "using GLB = glob::Glob;\n" "using BLG = glob::Glob;\n" "namespace na {\n" "namespace nb {\n" "void f() { GLB g; BLG blg; }\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "namespace glob {\n" "class Glob {};\n" "}\n" "using GLB = glob::Glob;\n" "using BLG = glob::Glob;\n" "\n" "namespace x {\n" "namespace y {\n" "void f() { GLB g; BLG blg; }\n" "} // namespace y\n" "} // namespace x\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, UsingShadowDeclAndMovedNamespace) { std::string Code = "namespace na { class C_A {};\n }\n" "using na::C_A;\n" "namespace na {\n" "namespace nb {\n" "class C_X {\n" "public:\n" " C_A a;\n" "};\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "namespace na { class C_A {};\n }\n" "using na::C_A;\n" "\n" "namespace x {\n" "namespace y {\n" "class C_X {\n" "public:\n" " C_A a;\n" "};\n" "} // namespace y\n" "} // namespace x\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, UsingNamespaceDeclAndMovedNamespace) { std::string Code = "namespace na { class C_A {};\n }\n" "using namespace na;\n" "namespace na {\n" "namespace nb {\n" "class C_X {\n" "public:\n" " C_A ca;\n" "};\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "namespace na { class C_A {};\n }\n" "using namespace na;\n" "\n" "namespace x {\n" "namespace y {\n" "class C_X {\n" "public:\n" " C_A ca;\n" "};\n" "} // namespace y\n" "} // namespace x\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, UsingShadowDeclInFunction) { std::string Code = "namespace glob {\n" "class Glob {};\n" "}\n" "namespace na {\n" "namespace nb {\n" "void f() {\n" " using glob::Glob;\n" " Glob g;\n" "}\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "namespace glob {\n" "class Glob {};\n" "}\n" "\n" "namespace x {\n" "namespace y {\n" "void f() {\n" " using ::glob::Glob;\n" " Glob g;\n" "}\n" "} // namespace y\n" "} // namespace x\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, UsingShadowDeclInClass) { std::string Code = "namespace na { class C_A {}; }\n" "namespace na {\n" "namespace nb {\n" "void f() {\n" " using ::na::C_A;\n" " C_A ca;\n" "}\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "namespace na { class C_A {}; }\n" "\n" "namespace x {\n" "namespace y {\n" "void f() {\n" " using ::na::C_A;\n" " C_A ca;\n" "}\n" "} // namespace y\n" "} // namespace x\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, UsingDeclInMovedNamespace) { std::string Code = "namespace nx { void f(); }\n" "namespace na {\n" "using nx::f;\n" "namespace nb {\n" "void d() { f(); }\n" "} // nb\n" "} // na\n"; std::string Expected = "namespace nx { void f(); }\n" "namespace na {\n" "using nx::f;\n" "\n" "} // na\n" "namespace x {\n" "namespace y {\n" "void d() { nx::f(); }\n" "} // namespace y\n" "} // namespace x\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, UsingDeclInMovedNamespaceNotNested) { OldNamespace = "na"; std::string Code = "namespace nx { void f(); }\n" "namespace na {\n" "using ::nx::f;\n" "void d() { f(); }\n" "} // na\n"; std::string Expected = "namespace nx { void f(); }\n" "\n" "namespace x {\n" "namespace y {\n" "using ::nx::f;\n" "void d() { f(); }\n" "} // namespace y\n" "} // namespace x\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, UsingDeclInMovedNamespaceMultiNested) { OldNamespace = "a::b::c::d"; NewNamespace = "a::b::x::y"; std::string Code = "namespace nx { void f(); void g(); }\n" "namespace a {\n" "namespace b {\n" "using ::nx::f;\n" "namespace c {\n" "using ::nx::g;\n" "namespace d {\n" "void d() { f(); g(); }\n" "} // d\n" "} // c\n" "} // b\n" "} // a\n"; std::string Expected = "namespace nx { void f(); void g(); }\n" "namespace a {\n" "namespace b {\n" "using ::nx::f;\n" "namespace c {\n" "using ::nx::g;\n" "\n" "} // c\n" "namespace x {\n" "namespace y {\n" "void d() { f(); nx::g(); }\n" "} // namespace y\n" "} // namespace x\n" "} // b\n" "} // a\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, UsingShadowDeclInTheParentOfOldNamespace) { OldNamespace = "nb::nc"; NewNamespace = "nb::nd"; std::string Code = "namespace na { class A {}; }\n" "namespace nb {\n" "using na::A;\n" "namespace nc {\n" "void d() { A a; }\n" "} // nc\n" "} // nb\n"; std::string Expected = "namespace na { class A {}; }\n" "namespace nb {\n" "using na::A;\n" "\n" "namespace nd {\n" "void d() { A a; }\n" "} // namespace nd\n" "} // nb\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, UsingShadowDeclInOldNamespace) { OldNamespace = "nb"; NewNamespace = "nc"; std::string Code = "namespace na { class A {}; }\n" "namespace nb {\n" "using na::A;\n" "void d() { A a; }\n" "struct X { A a; };\n" "} // nb\n"; std::string Expected = "namespace na { class A {}; }\n" "\n" "namespace nc {\n" "using ::na::A;\n" "void d() { A a; }\n" "struct X { A a; };\n" "} // namespace nc\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, UsingShadowDeclOfTemplateClass) { OldNamespace = "nb"; NewNamespace = "nc"; std::string Code = "namespace na {\n" "template \n" "class A { T t; };\n" "} // namespace na\n" "namespace nb {\n" "using na::A;\n" "void d() { A a; }\n" "} // nb\n"; std::string Expected = "namespace na {\n" "template \n" "class A { T t; };\n" "} // namespace na\n" "\n" "namespace nc {\n" "using ::na::A;\n" "void d() { A a; }\n" "} // namespace nc\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, UsingShadowDeclOfTemplateFunction) { OldNamespace = "nb"; NewNamespace = "nc"; std::string Code = "namespace na {\n" "template \n" "void f() { T t; };\n" "} // namespace na\n" "namespace nb {\n" "using na::f;\n" "void d() { f(); }\n" "} // nb\n"; std::string Expected = "namespace na {\n" "template \n" "void f() { T t; };\n" "} // namespace na\n" "\n" "namespace nc {\n" "using ::na::f;\n" "void d() { f(); }\n" "} // namespace nc\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, UsingAliasDecl) { std::string Code = "namespace nx { namespace ny { class X {}; } }\n" "namespace na {\n" "namespace nb {\n" "using Y = nx::ny::X;\n" "void f() { Y y; }\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "namespace nx { namespace ny { class X {}; } }\n" "\n" "namespace x {\n" "namespace y {\n" "using Y = nx::ny::X;\n" "void f() { Y y; }\n" "} // namespace y\n" "} // namespace x\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, UsingAliasDeclInGlobal) { std::string Code = "namespace nx { namespace ny { class X {}; } }\n" "using Y = nx::ny::X;\n" "namespace na {\n" "namespace nb {\n" "void f() { Y y; }\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "namespace nx { namespace ny { class X {}; } }\n" "using Y = nx::ny::X;\n" "\n" "namespace x {\n" "namespace y {\n" "void f() { Y y; }\n" "} // namespace y\n" "} // namespace x\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, TypedefAliasDecl) { std::string Code = "namespace nx { namespace ny { class X {}; } }\n" "namespace na {\n" "namespace nb {\n" "typedef nx::ny::X Y;\n" "void f() { Y y; }\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "namespace nx { namespace ny { class X {}; } }\n" "\n" "namespace x {\n" "namespace y {\n" "typedef nx::ny::X Y;\n" "void f() { Y y; }\n" "} // namespace y\n" "} // namespace x\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, DerivedClassWithConstructors) { std::string Code = "namespace nx { namespace ny { class X { public: X(int i) {} }; } }\n" "namespace na {\n" "namespace nb {\n" "class A : public nx::ny::X {\n" "public:\n" " A() : X(0) {}\n" " A(int i);\n" "};\n" "A::A(int i) : X(i) {}\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "namespace nx { namespace ny { class X { public: X(int i) {} }; } }\n" "\n\n" "namespace x {\n" "namespace y {\n" "class A : public nx::ny::X {\n" "public:\n" " A() : X(0) {}\n" " A(int i);\n" "};\n" "A::A(int i) : X(i) {}\n" "} // namespace y\n" "} // namespace x\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, DerivedClassWithQualifiedConstructors) { std::string Code = "namespace nx { namespace ny { class X { public: X(int i) {} }; } }\n" "namespace na {\n" "namespace nb {\n" "class A : public nx::ny::X {\n" "public:\n" " A() : X::X(0) {}\n" " A(int i);\n" "};\n" "A::A(int i) : X::X(i) {}\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "namespace nx { namespace ny { class X { public: X(int i) {} }; } }\n" "\n\n" "namespace x {\n" "namespace y {\n" "class A : public nx::ny::X {\n" "public:\n" " A() : X::X(0) {}\n" " A(int i);\n" "};\n" "A::A(int i) : X::X(i) {}\n" "} // namespace y\n" "} // namespace x\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, DerivedClassWithConstructorsAndTypeRefs) { std::string Code = "namespace nx { namespace ny { class X { public: X(int i) {} }; } }\n" "namespace na {\n" "namespace nb {\n" "class A : public nx::ny::X {\n" "public:\n" " A() : X(0) {}\n" " A(int i);\n" "};\n" "A::A(int i) : X(i) { X x(1);}\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "namespace nx { namespace ny { class X { public: X(int i) {} }; } }\n" "\n\n" "namespace x {\n" "namespace y {\n" "class A : public nx::ny::X {\n" "public:\n" " A() : X(0) {}\n" " A(int i);\n" "};\n" "A::A(int i) : X(i) { nx::ny::X x(1);}\n" "} // namespace y\n" "} // namespace x\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, MoveToGlobalNamespace) { NewNamespace = ""; std::string Code = "namespace na {\n" "class C_A {};\n" "namespace nc {\n" "class C_C {};" "} // namespace nc\n" "namespace nb {\n" "class C_X {\n" "public:\n" " C_A a;\n" " nc::C_C c;\n" "};\n" "class C_Y {\n" " C_X x;\n" "};\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "namespace na {\n" "class C_A {};\n" "namespace nc {\n" "class C_C {};" "} // namespace nc\n" "\n" "} // namespace na\n" "class C_X {\n" "public:\n" " na::C_A a;\n" " na::nc::C_C c;\n" "};\n" "class C_Y {\n" " C_X x;\n" "};\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, KeepGlobalSpecifier) { std::string Code = "class Glob {};\n" "namespace na {\n" "class C_A {};\n" "namespace nc {\n" "class C_C {};" "} // namespace nc\n" "namespace nb {\n" "class C_X {\n" "public:\n" " ::Glob glob_1;\n" " Glob glob_2;\n" " C_A a_1;\n" " ::na::C_A a_2;\n" " nc::C_C c;\n" "};\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "class Glob {};\n" "namespace na {\n" "class C_A {};\n" "namespace nc {\n" "class C_C {};" "} // namespace nc\n" "\n" "} // namespace na\n" "namespace x {\n" "namespace y {\n" "class C_X {\n" "public:\n" " ::Glob glob_1;\n" " Glob glob_2;\n" " na::C_A a_1;\n" " ::na::C_A a_2;\n" " na::nc::C_C c;\n" "};\n" "} // namespace y\n" "} // namespace x\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, UsingAliasInTemplate) { NewNamespace = "na::nb::nc"; std::string Code = "namespace some_ns {\n" "template \n" "class G {};\n" "} // namespace some_ns\n" "namespace na {\n" "template\n" "using GG = some_ns::G;\n" "} // namespace na\n" "namespace na {\n" "namespace nb {\n" "void f() {\n" " GG g;\n" "}\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "namespace some_ns {\n" "template \n" "class G {};\n" "} // namespace some_ns\n" "namespace na {\n" "template\n" "using GG = some_ns::G;\n" "} // namespace na\n" "namespace na {\n" "namespace nb {\n" "namespace nc {\n" "void f() {\n" " GG g;\n" "}\n" "} // namespace nc\n" "} // namespace nb\n" "} // namespace na\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, TemplateUsingAliasInBaseClass) { NewNamespace = "na::nb::nc"; std::string Code = "namespace some_ns {\n" "template \n" "class G {};\n" "} // namespace some_ns\n" "namespace na {\n" "class Base {\n" "public:\n" " template\n" " using GG = some_ns::G;\n" "\n" " struct Nested {};\n" "};\n" "class Derived : public Base {};\n" "} // namespace na\n" "namespace na {\n" "namespace nb {\n" "void f() {\n" " Derived::GG g;\n" " const Derived::GG gg;\n" " const Derived::GG* gg_ptr;\n" " struct Derived::Nested nested;\n" " const struct Derived::Nested *nested_ptr;\n" "}\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "namespace some_ns {\n" "template \n" "class G {};\n" "} // namespace some_ns\n" "namespace na {\n" "class Base {\n" "public:\n" " template\n" " using GG = some_ns::G;\n" "\n" " struct Nested {};\n" "};\n" "class Derived : public Base {};\n" "} // namespace na\n" "namespace na {\n" "namespace nb {\n" "namespace nc {\n" "void f() {\n" " Derived::GG g;\n" " const Derived::GG gg;\n" " const Derived::GG* gg_ptr;\n" " struct Derived::Nested nested;\n" " const struct Derived::Nested *nested_ptr;\n" "}\n" "} // namespace nc\n" "} // namespace nb\n" "} // namespace na\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, ExistingNamespaceConflictWithNewNamespace) { OldNamespace = "nx"; NewNamespace = "ny::na::nc"; std::string Code = "namespace na {\n" "class A {};\n" "} // namespace na\n" "namespace nb {\n" "class B {};\n" "} // namespace nb\n" "namespace nx {\n" "class X {\n" " na::A a; nb::B b;\n" "};\n" "} // namespace nx\n"; std::string Expected = "namespace na {\n" "class A {};\n" "} // namespace na\n" "namespace nb {\n" "class B {};\n" "} // namespace nb\n" "\n" "namespace ny {\n" "namespace na {\n" "namespace nc {\n" "class X {\n" " ::na::A a; nb::B b;\n" "};\n" "} // namespace nc\n" "} // namespace na\n" "} // namespace ny\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, SymbolConflictWithNewNamespace) { OldNamespace = "nx"; NewNamespace = "ny::na::nc"; std::string Code = "namespace na {\n" "class A {};\n" "namespace nb {\n" "class B {};\n" "} // namespace nb\n" "} // namespace na\n" "namespace ny {\n" "class Y {};\n" "}\n" "namespace nx {\n" "class X {\n" " na::A a; na::nb::B b;\n" " ny::Y y;" "};\n" "} // namespace nx\n"; std::string Expected = "namespace na {\n" "class A {};\n" "namespace nb {\n" "class B {};\n" "} // namespace nb\n" "} // namespace na\n" "namespace ny {\n" "class Y {};\n" "}\n" "\n" "namespace ny {\n" "namespace na {\n" "namespace nc {\n" "class X {\n" " ::na::A a; ::na::nb::B b;\n" " Y y;\n" "};\n" "} // namespace nc\n" "} // namespace na\n" "} // namespace ny\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, ShortenNamespaceSpecifier) { OldNamespace = "nx"; NewNamespace = "ny::na"; std::string Code = "class G {};\n" "namespace ny {\n" "class Y {};\n" "namespace na {\n" "class A {};\n" "namespace nc { class C {}; } // namespace nc\n" "}\n // namespace na\n" "}\n // namespace ny\n" "namespace nx {\n" "class X {\n" " G g; ny::Y y; ny::na::A a; ny::na::nc::C c;\n" "};\n" "} // namespace nx\n"; std::string Expected = "class G {};\n" "namespace ny {\n" "class Y {};\n" "namespace na {\n" "class A {};\n" "namespace nc { class C {}; } // namespace nc\n" "}\n // namespace na\n" "}\n // namespace ny\n" "\n" "namespace ny {\n" "namespace na {\n" "class X {\n" " G g; Y y; A a; nc::C c;\n" "};\n" "} // namespace na\n" "} // namespace ny\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, ShortenNamespaceSpecifierInAnonymousNamespace) { OldNamespace = "nx"; NewNamespace = "ny::na"; std::string Code = "class G {};\n" "namespace ny {\n" "class Y {};\n" "namespace na {\n" "class A {};\n" "namespace nc { class C {}; } // namespace nc\n" "}\n // namespace na\n" "}\n // namespace ny\n" "namespace nx {\n" "namespace {\n" "class X {\n" " G g; ::ny::Y y; ::ny::na::A a; ::ny::na::nc::C c;\n" "};\n" "} // namespace\n" "} // namespace nx\n"; std::string Expected = "class G {};\n" "namespace ny {\n" "class Y {};\n" "namespace na {\n" "class A {};\n" "namespace nc { class C {}; } // namespace nc\n" "}\n // namespace na\n" "}\n // namespace ny\n" "\n" "namespace ny {\n" "namespace na {\n" "namespace {\n" "class X {\n" " G g; Y y; A a; nc::C c;\n" "};\n" "} // namespace\n" "} // namespace na\n" "} // namespace ny\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, SimpleMoveEnum) { std::string Code = "namespace na {\n" "namespace nb {\n" "enum class X { X1, X2 };\n" "enum Y { Y1, Y2 };\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "\n\nnamespace x {\n" "namespace y {\n" "enum class X { X1, X2 };\n" "enum Y { Y1, Y2 };\n" "} // namespace y\n" "} // namespace x\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, ReferencesToEnums) { std::string Code = "enum Glob { G1, G2 };\n" "namespace na {\n" "enum class X { X1 };\n" "enum Y { Y1, Y2 };\n" "namespace nb {\n" "void f() {\n" " Glob g1 = Glob::G1;\n" " Glob g2 = G2;\n" " X x1 = X::X1;\n" " Y y1 = Y::Y1;\n" " Y y2 = Y2;\n" "}\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "enum Glob { G1, G2 };\n" "namespace na {\n" "enum class X { X1 };\n" "enum Y { Y1, Y2 };\n" "\n" "} // namespace na\n" "namespace x {\n" "namespace y {\n" "void f() {\n" " Glob g1 = Glob::G1;\n" " Glob g2 = G2;\n" " na::X x1 = na::X::X1;\n" " na::Y y1 = na::Y::Y1;\n" " na::Y y2 = na::Y2;\n" "}\n" "} // namespace y\n" "} // namespace x\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, NoRedundantEnumUpdate) { std::string Code = "namespace ns {\n" "enum class X { X1 };\n" "enum Y { Y1, Y2 };\n" "} // namespace ns\n" "namespace na {\n" "namespace nb {\n" "void f() {\n" " ns::X x1 = ns::X::X1;\n" " ns::Y y1 = ns::Y::Y1;\n" " ns::Y y2 = ns::Y2;\n" "}\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "namespace ns {\n" "enum class X { X1 };\n" "enum Y { Y1, Y2 };\n" "} // namespace ns\n" "\n" "namespace x {\n" "namespace y {\n" "void f() {\n" " ns::X x1 = ns::X::X1;\n" " ns::Y y1 = ns::Y::Y1;\n" " ns::Y y2 = ns::Y2;\n" "}\n" "} // namespace y\n" "} // namespace x\n"; ; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, EnumsAndUsingShadows) { std::string Code = "namespace ns {\n" "enum class X { X1 };\n" "enum Y { Y1, Y2, Y3 };\n" "} // namespace ns\n" "using ns::X;\n" "using ns::Y;\n" "using ns::Y::Y2;\n" "using ns::Y::Y3;\n" "namespace na {\n" "namespace nb {\n" "void f() {\n" " X x1 = X::X1;\n" " Y y1 = Y::Y1;\n" " Y y2 = Y2;\n" " Y y3 = Y3;\n" "}\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "namespace ns {\n" "enum class X { X1 };\n" "enum Y { Y1, Y2, Y3 };\n" "} // namespace ns\n" "using ns::X;\n" "using ns::Y;\n" "using ns::Y::Y2;\n" "using ns::Y::Y3;\n" "\n" "namespace x {\n" "namespace y {\n" "void f() {\n" " X x1 = X::X1;\n" " Y y1 = Y::Y1;\n" " Y y2 = Y2;\n" " Y y3 = Y3;\n" "}\n" "} // namespace y\n" "} // namespace x\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, EnumsAndAliases) { std::string Code = "namespace ns {\n" "enum class X { X1 };\n" "enum Y { Y1, Y2, Y3 };\n" "} // namespace ns\n" "typedef ns::X TX;\n" "typedef ns::Y TY;\n" "using UX = ns::X;\n" "using UY = ns::Y;\n" "namespace na {\n" "namespace nb {\n" "void f() {\n" " ns::X x1 = ns::X::X1;\n" " TX tx1 = TX::X1;\n" " UX ux1 = UX::X1;\n" " ns::Y y1 = ns::Y::Y1;\n" " TY ty1 = TY::Y1;\n" " UY uy1 = UY::Y1;\n" "}\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "namespace ns {\n" "enum class X { X1 };\n" "enum Y { Y1, Y2, Y3 };\n" "} // namespace ns\n" "typedef ns::X TX;\n" "typedef ns::Y TY;\n" "using UX = ns::X;\n" "using UY = ns::Y;\n" "\n" "namespace x {\n" "namespace y {\n" "void f() {\n" " ns::X x1 = ns::X::X1;\n" " TX tx1 = TX::X1;\n" " UX ux1 = UX::X1;\n" " ns::Y y1 = ns::Y::Y1;\n" " TY ty1 = TY::Y1;\n" " UY uy1 = UY::Y1;\n" "}\n" "} // namespace y\n" "} // namespace x\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, EnumInClass) { std::string Code = "namespace na {\n" "struct X { enum E { E1 }; };\n" "namespace nb {\n" "void f() {\n" " X::E e = X::E1;\n" " X::E ee = X::E::E1;\n" "}\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "namespace na {\n" "struct X { enum E { E1 }; };\n" "\n" "} // namespace na\n" "namespace x {\n" "namespace y {\n" "void f() {\n" " na::X::E e = na::X::E1;\n" " na::X::E ee = na::X::E::E1;\n" "}\n" "} // namespace y\n" "} // namespace x\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, TypeAsTemplateParameter) { std::string Code = "namespace na {\n" "struct X {};\n" "namespace nb {\n" "template \n" "void TempTemp(const TT& t) {\n" " TT tmp;\n" "}\n" "template \n" "void Temp(const T& t) {\n" " T tmp = t;\n" " TempTemp(tmp);\n" " TempTemp(t);\n" "}\n" "void f() {\n" " X x;\n" " Temp(x);\n" "}\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "namespace na {\n" "struct X {};\n" "\n" "} // namespace na\n" "namespace x {\n" "namespace y {\n" "template \n" "void TempTemp(const TT& t) {\n" " TT tmp;\n" "}\n" "template \n" "void Temp(const T& t) {\n" " T tmp = t;\n" " TempTemp(tmp);\n" " TempTemp(t);\n" "}\n" "void f() {\n" " na::X x;\n" " Temp(x);\n" "}\n" "} // namespace y\n" "} // namespace x\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, DefaultMoveConstructors) { std::string Code = "namespace na {\n" "class B {\n" " public:\n" " B() = default;\n" " // Allow move only.\n" " B(B&&) = default;\n" " B& operator=(B&&) = default;\n" " B(const B&) = delete;\n" " B& operator=(const B&) = delete;\n" " private:\n" " int ref_;\n" "};\n" "} // namespace na\n" "namespace na {\n" "namespace nb {\n" "class A {\n" "public:\n" " A() = default;\n" " A(A&&) = default;\n" " A& operator=(A&&) = default;\n" "private:\n" " B b;\n" " A(const A&) = delete;\n" " A& operator=(const A&) = delete;\n" "};\n" "void f() { A a; a = A(); A aa = A(); }\n" "} // namespace nb\n" "} // namespace na\n"; std::string Expected = "namespace na {\n" "class B {\n" " public:\n" " B() = default;\n" " // Allow move only.\n" " B(B&&) = default;\n" " B& operator=(B&&) = default;\n" " B(const B&) = delete;\n" " B& operator=(const B&) = delete;\n" " private:\n" " int ref_;\n" "};\n" "} // namespace na\n" "\n" "namespace x {\n" "namespace y {\n" "class A {\n" "public:\n" " A() = default;\n" " A(A&&) = default;\n" " A& operator=(A&&) = default;\n" "private:\n" " na::B b;\n" " A(const A&) = delete;\n" " A& operator=(const A&) = delete;\n" "};\n" "void f() { A a; a = A(); A aa = A(); }\n" "} // namespace y\n" "} // namespace x\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } TEST_F(ChangeNamespaceTest, InjectedClassNameInFriendDecl) { OldNamespace = "d"; NewNamespace = "e"; std::string Code = "namespace a{\n" "template \n" "class Base {\n" " public:\n" " void f() {\n" " T t;\n" " t.priv();\n" " }\n" "};\n" "} // namespace a\n" "namespace d {\n" "class D : public a::Base {\n" " private:\n" " friend class Base;\n" " void priv() {}\n" " Base b;\n" "};\n" "\n" "void f() {\n" " D d;\n" " a:: Base b;\n" " b.f();\n" "}\n" "} // namespace d\n"; std::string Expected = "namespace a{\n" "template \n" "class Base {\n" " public:\n" " void f() {\n" " T t;\n" " t.priv();\n" " }\n" "};\n" "} // namespace a\n" "\n" "namespace e {\n" "class D : public a::Base {\n" " private:\n" " friend class Base;\n" " void priv() {}\n" " a::Base b;\n" "};\n" "\n" "void f() {\n" " D d;\n" " a::Base b;\n" " b.f();\n" "}\n" "} // namespace e\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } } // anonymous namespace } // namespace change_namespace } // namespace clang