diff options
author | Jordan Rupprecht <rupprecht@google.com> | 2019-05-14 21:58:59 +0000 |
---|---|---|
committer | Jordan Rupprecht <rupprecht@google.com> | 2019-05-14 21:58:59 +0000 |
commit | 46054fed6aeeabea27b9ba4a3ef81ab5ff9b9645 (patch) | |
tree | d12279f80b5729d0324f066002c838baa736fbd2 /unittests/clang-change-namespace/ChangeNamespaceTests.cpp | |
parent | 5026a9a16d10a2edf09be54c7225f49b5789c69e (diff) | |
parent | 0eb1ac6d1df856f065717226ef34d00679a211fe (diff) |
Creating branches/google/stable and tags/google/stable/2019-05-14 from r360103upstream/stable
git-svn-id: https://llvm.org/svn/llvm-project/clang-tools-extra/branches/google/stable@360714 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'unittests/clang-change-namespace/ChangeNamespaceTests.cpp')
-rw-r--r-- | unittests/clang-change-namespace/ChangeNamespaceTests.cpp | 2281 |
1 files changed, 2281 insertions, 0 deletions
diff --git a/unittests/clang-change-namespace/ChangeNamespaceTests.cpp b/unittests/clang-change-namespace/ChangeNamespaceTests.cpp new file mode 100644 index 00000000..d66fede2 --- /dev/null +++ b/unittests/clang-change-namespace/ChangeNamespaceTests.cpp @@ -0,0 +1,2281 @@ +//===-- ChangeNamespaceTests.cpp - Change namespace unit tests ---*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#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/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 "llvm/Support/VirtualFileSystem.h" +#include "gtest/gtest.h" +#include <memory> +#include <string> +#include <vector> + +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<std::string, tooling::Replacements> FileToReplacements; + change_namespace::ChangeNamespaceTool NamespaceTool( + OldNamespace, NewNamespace, FilePattern, + /*WhiteListedSymbolPatterns*/ {}, &FileToReplacements); + ast_matchers::MatchFinder Finder; + NamespaceTool.registerMatchers(&Finder); + std::unique_ptr<tooling::FrontendActionFactory> 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<bool>(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 <typename T>\n" + "class B {};\n" + "template <typename T1, typename T2>\n" + "class Two {};\n" + "namespace nc { class C {}; }\n" + "} // na\n" + "\n" + "namespace na {\n" + "namespace nb {\n" + "void f() {\n" + " B<A> b;\n" + " B<nc::C> b_c;\n" + " Two<A, nc::C> two;\n" + "}\n" + "} // nb\n" + "} // na\n"; + std::string Expected = "namespace na {\n" + "class A {};\n" + "template <typename T>\n" + "class B {};\n" + "template <typename T1, typename T2>\n" + "class Two {};\n" + "namespace nc { class C {}; }\n" + "} // na\n" + "\n" + "\n" + "namespace x {\n" + "namespace y {\n" + "void f() {\n" + " na::B<na::A> b;\n" + " na::B<na::nc::C> b_c;\n" + " na::Two<na::A, na::nc::C> 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<typename T> class FWD_TEMP;\n" + "class A {\n" + " FWD *fwd;\n" + "};\n" + "template<typename T> class TEMP {};\n" + "} // namespace nb\n" + "} // namespace na\n"; + std::string Expected = "namespace na {\n" + "namespace nb {\n" + "class FWD;\n" + "template<typename T> 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<typename T> 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<typename T> 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<typename T> 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 <typename T>\n" + "class A { T t; };\n" + "} // namespace na\n" + "namespace nb {\n" + "using na::A;\n" + "void d() { A<int> a; }\n" + "} // nb\n"; + + std::string Expected = "namespace na {\n" + "template <typename T>\n" + "class A { T t; };\n" + "} // namespace na\n" + "\n" + "namespace nc {\n" + "using ::na::A;\n" + "void d() { A<int> 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 <typename T>\n" + "void f() { T t; };\n" + "} // namespace na\n" + "namespace nb {\n" + "using na::f;\n" + "void d() { f<int>(); }\n" + "} // nb\n"; + + std::string Expected = "namespace na {\n" + "template <typename T>\n" + "void f() { T t; };\n" + "} // namespace na\n" + "\n" + "namespace nc {\n" + "using ::na::f;\n" + "void d() { f<int>(); }\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 <typename T, typename S>\n" + "class G {};\n" + "} // namespace some_ns\n" + "namespace na {\n" + "template<typename P>\n" + "using GG = some_ns::G<int, P>;\n" + "} // namespace na\n" + "namespace na {\n" + "namespace nb {\n" + "void f() {\n" + " GG<float> g;\n" + "}\n" + "} // namespace nb\n" + "} // namespace na\n"; + std::string Expected = "namespace some_ns {\n" + "template <typename T, typename S>\n" + "class G {};\n" + "} // namespace some_ns\n" + "namespace na {\n" + "template<typename P>\n" + "using GG = some_ns::G<int, P>;\n" + "} // namespace na\n" + "namespace na {\n" + "namespace nb {\n" + "namespace nc {\n" + "void f() {\n" + " GG<float> 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 <typename T, typename S>\n" + "class G {};\n" + "} // namespace some_ns\n" + "namespace na {\n" + "class Base {\n" + "public:\n" + " template<typename P>\n" + " using GG = some_ns::G<int, P>;\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<float> g;\n" + " const Derived::GG<int> gg;\n" + " const Derived::GG<int>* 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 <typename T, typename S>\n" + "class G {};\n" + "} // namespace some_ns\n" + "namespace na {\n" + "class Base {\n" + "public:\n" + " template<typename P>\n" + " using GG = some_ns::G<int, P>;\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<float> g;\n" + " const Derived::GG<int> gg;\n" + " const Derived::GG<int>* 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 <typename TT>\n" + "void TempTemp(const TT& t) {\n" + " TT tmp;\n" + "}\n" + "template <typename T>\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 <typename TT>\n" + "void TempTemp(const TT& t) {\n" + " TT tmp;\n" + "}\n" + "template <typename T>\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 <typename T>\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<D> {\n" + " private:\n" + " friend class Base<D>;\n" + " void priv() {}\n" + " Base b;\n" + "};\n" + "\n" + "void f() {\n" + " D d;\n" + " a:: Base<D> b;\n" + " b.f();\n" + "}\n" + "} // namespace d\n"; + std::string Expected = "namespace a{\n" + "template <typename T>\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<D> {\n" + " private:\n" + " friend class Base<D>;\n" + " void priv() {}\n" + " a::Base b;\n" + "};\n" + "\n" + "void f() {\n" + " D d;\n" + " a::Base<D> b;\n" + " b.f();\n" + "}\n" + "} // namespace e\n"; + EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); +} + +TEST_F(ChangeNamespaceTest, FullyQualifyConflictNamespace) { + std::string Code = + "namespace x { namespace util { class Some {}; } }\n" + "namespace x { namespace y {namespace base { class Base {}; } } }\n" + "namespace util { class Status {}; }\n" + "namespace base { class Base {}; }\n" + "namespace na {\n" + "namespace nb {\n" + "void f() {\n" + " util::Status s1; x::util::Some s2;\n" + " base::Base b1; x::y::base::Base b2;\n" + "}\n" + "} // namespace nb\n" + "} // namespace na\n"; + + std::string Expected = + "namespace x { namespace util { class Some {}; } }\n" + "namespace x { namespace y {namespace base { class Base {}; } } }\n" + "namespace util { class Status {}; }\n" + "namespace base { class Base {}; }\n" + "\n" + "namespace x {\n" + "namespace y {\n" + "void f() {\n" + " ::util::Status s1; util::Some s2;\n" + " ::base::Base b1; base::Base b2;\n" + "}\n" + "} // namespace y\n" + "} // namespace x\n"; + + EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); +} + +} // anonymous namespace +} // namespace change_namespace +} // namespace clang |