[clang-tools-extra] r288969 - [change-namespace] always add a '::' prefix when a symbol reference needs to be fully-qualified.
Eric Liu via cfe-commits
cfe-commits at lists.llvm.org
Wed Dec 7 12:08:02 PST 2016
Author: ioeric
Date: Wed Dec 7 14:08:02 2016
New Revision: 288969
URL: http://llvm.org/viewvc/llvm-project?rev=288969&view=rev
Log:
[change-namespace] always add a '::' prefix when a symbol reference needs to be fully-qualified.
Modified:
clang-tools-extra/trunk/change-namespace/ChangeNamespace.cpp
clang-tools-extra/trunk/change-namespace/ChangeNamespace.h
clang-tools-extra/trunk/unittests/change-namespace/ChangeNamespaceTests.cpp
Modified: clang-tools-extra/trunk/change-namespace/ChangeNamespace.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/change-namespace/ChangeNamespace.cpp?rev=288969&r1=288968&r2=288969&view=diff
==============================================================================
--- clang-tools-extra/trunk/change-namespace/ChangeNamespace.cpp (original)
+++ clang-tools-extra/trunk/change-namespace/ChangeNamespace.cpp Wed Dec 7 14:08:02 2016
@@ -663,6 +663,10 @@ void ChangeNamespaceTool::replaceQualifi
// old namespace, we don't create replacement.
if (NestedName == ReplaceName)
return;
+ // If the reference need to be fully-qualified, add a leading "::" unless
+ // NewNamespace is the global namespace.
+ if (ReplaceName == FromDeclName && !NewNamespace.empty())
+ ReplaceName = "::" + ReplaceName;
auto R = createReplacement(Start, End, ReplaceName, *Result.SourceManager);
auto Err = FileToReplacements[R.getFilePath()].add(R);
if (Err)
Modified: clang-tools-extra/trunk/change-namespace/ChangeNamespace.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/change-namespace/ChangeNamespace.h?rev=288969&r1=288968&r2=288969&view=diff
==============================================================================
--- clang-tools-extra/trunk/change-namespace/ChangeNamespace.h (original)
+++ clang-tools-extra/trunk/change-namespace/ChangeNamespace.h Wed Dec 7 14:08:02 2016
@@ -24,6 +24,9 @@ namespace change_namespace {
// namespaces while references to symbols (e.g. types, functions) which are not
// defined in the changed namespace will be correctly qualified by prepending
// namespace specifiers before them.
+// This will try to add shortest namespace specifiers possible. When a symbol
+// reference needs to be fully-qualified, this adds a "::" prefix to the
+// namespace specifiers unless the new namespace is the global namespace.
// For classes, only classes that are declared/defined in the given namespace in
// speficifed files will be moved: forward declarations will remain in the old
// namespace.
@@ -38,7 +41,7 @@ namespace change_namespace {
// class FWD;
// } // a
// namespace x {
-// class A { a::FWD *fwd; }
+// class A { ::a::FWD *fwd; }
// } // x
// FIXME: support moving typedef, enums across namespaces.
class ChangeNamespaceTool : public ast_matchers::MatchFinder::MatchCallback {
Modified: clang-tools-extra/trunk/unittests/change-namespace/ChangeNamespaceTests.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/change-namespace/ChangeNamespaceTests.cpp?rev=288969&r1=288968&r2=288969&view=diff
==============================================================================
--- clang-tools-extra/trunk/unittests/change-namespace/ChangeNamespaceTests.cpp (original)
+++ clang-tools-extra/trunk/unittests/change-namespace/ChangeNamespaceTests.cpp Wed Dec 7 14:08:02 2016
@@ -174,6 +174,40 @@ TEST_F(ChangeNamespaceTest, MoveIntoAnot
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"
@@ -222,8 +256,8 @@ TEST_F(ChangeNamespaceTest, SimpleMoveWi
"namespace y {\n"
"class C_X {\n"
"public:\n"
- " na::C_A a;\n"
- " na::nc::C_C c;\n"
+ " ::na::C_A a;\n"
+ " ::na::nc::C_C c;\n"
"};\n"
"class C_Y {\n"
" C_X x;\n"
@@ -265,9 +299,9 @@ TEST_F(ChangeNamespaceTest, TypeLocInTem
"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"
+ " ::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";
@@ -294,7 +328,7 @@ TEST_F(ChangeNamespaceTest, LeaveForward
"namespace y {\n"
"\n"
"class A {\n"
- " na::nb::FWD *fwd;\n"
+ " ::na::nb::FWD *fwd;\n"
"};\n"
"} // namespace y\n"
"} // namespace x\n";
@@ -322,7 +356,7 @@ TEST_F(ChangeNamespaceTest, TemplateClas
"namespace y {\n"
"\n"
"class A {\n"
- " na::nb::FWD *fwd;\n"
+ " ::na::nb::FWD *fwd;\n"
"};\n"
"template<typename T> class TEMP {};\n"
"} // namespace y\n"
@@ -377,8 +411,8 @@ TEST_F(ChangeNamespaceTest, MoveFunction
"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"
+ "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";
@@ -417,9 +451,9 @@ TEST_F(ChangeNamespaceTest, FixUsingShad
"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"
+ "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));
@@ -445,9 +479,9 @@ TEST_F(ChangeNamespaceTest, DontFixUsing
"} // namespace na\n"
"namespace x {\n"
"namespace y {\n"
- "class D : public na::Base {\n"
+ "class D : public ::na::Base {\n"
"public:\n"
- " using AA = na::A; using B = na::Base;\n"
+ " using AA = ::na::A; using B = ::na::Base;\n"
" using Base::m; using Base::Base;\n"
"};"
"} // namespace y\n"
@@ -492,11 +526,11 @@ TEST_F(ChangeNamespaceTest, TypeInNested
"namespace x {\n"
"namespace y {\n"
"class C_X {\n"
- " na::C_A na;\n"
- " na::C_A::Nested nested;\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"
+ " ::na::C_A::Nested::nestedFunc();\n"
+ " int X = ::na::C_A::Nested::NestedX;\n"
" }\n"
"};\n"
"} // namespace y\n"
@@ -534,8 +568,8 @@ TEST_F(ChangeNamespaceTest, FixFunctionN
"} // 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"
+ "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));
@@ -551,7 +585,9 @@ TEST_F(ChangeNamespaceTest, FixNonCallin
"static void s_f() {}\n"
"namespace nb {\n"
"void f() {\n"
- "auto *ref1 = A::f; auto *ref2 = a_f; auto *ref3 = s_f;\n"
+ " auto *ref1 = A::f;\n"
+ " auto *ref2 = a_f;\n"
+ " auto *ref3 = s_f;\n"
"}\n"
"} // namespace nb\n"
"} // namespace na\n";
@@ -568,7 +604,9 @@ TEST_F(ChangeNamespaceTest, FixNonCallin
"namespace x {\n"
"namespace y {\n"
"void f() {\n"
- "auto *ref1 = na::A::f; auto *ref2 = na::a_f; auto *ref3 = na::s_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";
@@ -600,9 +638,9 @@ TEST_F(ChangeNamespaceTest, MoveAndFixGl
"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"
+ " int a = ::na::GlobA;\n"
+ " int b = ::na::GlobAStatic;\n"
+ " int c = ::na::nc::GlobC;\n"
"}\n"
"} // namespace y\n"
"} // namespace x\n";
@@ -619,7 +657,9 @@ TEST_F(ChangeNamespaceTest, DoNotFixStat
"};\n"
"int A::A1 = 0;\n"
"namespace nb {\n"
- "void f() { int a = A::A1; int b = A::A2; }"
+ "void f() {\n"
+ " int a = A::A1; int b = A::A2;\n"
+ "}\n"
"} // namespace nb\n"
"} // namespace na\n";
@@ -634,7 +674,9 @@ TEST_F(ChangeNamespaceTest, DoNotFixStat
"} // namespace na\n"
"namespace x {\n"
"namespace y {\n"
- "void f() { int a = na::A::A1; int b = na::A::A2; }"
+ "void f() {\n"
+ " int a = ::na::A::A1; int b = ::na::A::A2;\n"
+ "}\n"
"} // namespace y\n"
"} // namespace x\n";
@@ -966,7 +1008,7 @@ TEST_F(ChangeNamespaceTest, UsingDeclInM
"} // na\n"
"namespace x {\n"
"namespace y {\n"
- "void d() { nx::f(); }\n"
+ "void d() { ::nx::f(); }\n"
"} // namespace y\n"
"} // namespace x\n";
EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
@@ -1017,7 +1059,7 @@ TEST_F(ChangeNamespaceTest, UsingDeclInM
"} // c\n"
"namespace x {\n"
"namespace y {\n"
- "void d() { f(); nx::g(); }\n"
+ "void d() { f(); ::nx::g(); }\n"
"} // namespace y\n"
"} // namespace x\n"
"} // b\n"
@@ -1192,7 +1234,7 @@ TEST_F(ChangeNamespaceTest, DerivedClass
" A() : X(0) {}\n"
" A(int i);\n"
"};\n"
- "A::A(int i) : X(i) { nx::ny::X x(1);}\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));
@@ -1234,6 +1276,47 @@ TEST_F(ChangeNamespaceTest, MoveToGlobal
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));
+}
+
} // anonymous namespace
} // namespace change_namespace
} // namespace clang
More information about the cfe-commits
mailing list