summaryrefslogtreecommitdiffstats
path: root/unittests/clang-change-namespace/ChangeNamespaceTests.cpp
diff options
context:
space:
mode:
authorJordan Rupprecht <rupprecht@google.com>2019-05-14 21:58:59 +0000
committerJordan Rupprecht <rupprecht@google.com>2019-05-14 21:58:59 +0000
commit46054fed6aeeabea27b9ba4a3ef81ab5ff9b9645 (patch)
treed12279f80b5729d0324f066002c838baa736fbd2 /unittests/clang-change-namespace/ChangeNamespaceTests.cpp
parent5026a9a16d10a2edf09be54c7225f49b5789c69e (diff)
parent0eb1ac6d1df856f065717226ef34d00679a211fe (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.cpp2281
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