[clang-tools-extra] r290421 - [change-namespace] consider namespace aliases to shorten qualified names.

Eric Liu via cfe-commits cfe-commits at lists.llvm.org
Fri Dec 23 02:47:09 PST 2016


Author: ioeric
Date: Fri Dec 23 04:47:09 2016
New Revision: 290421

URL: http://llvm.org/viewvc/llvm-project?rev=290421&view=rev
Log:
[change-namespace] consider namespace aliases to shorten qualified names.

Reviewers: hokein

Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D28052

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=290421&r1=290420&r2=290421&view=diff
==============================================================================
--- clang-tools-extra/trunk/change-namespace/ChangeNamespace.cpp (original)
+++ clang-tools-extra/trunk/change-namespace/ChangeNamespace.cpp Fri Dec 23 04:47:09 2016
@@ -306,6 +306,11 @@ void ChangeNamespaceTool::registerMatche
                                         IsVisibleInNewNs)
                          .bind("using_namespace"),
                      this);
+  // Match namespace alias declarations.
+  Finder->addMatcher(namespaceAliasDecl(isExpansionInFileMatching(FilePattern),
+                                        IsVisibleInNewNs)
+                         .bind("namespace_alias"),
+                     this);
 
   // Match old namespace blocks.
   Finder->addMatcher(
@@ -429,6 +434,10 @@ void ChangeNamespaceTool::run(
                  Result.Nodes.getNodeAs<UsingDirectiveDecl>(
                      "using_namespace")) {
     UsingNamespaceDecls.insert(UsingNamespace);
+  } else if (const auto *NamespaceAlias =
+                 Result.Nodes.getNodeAs<NamespaceAliasDecl>(
+                     "namespace_alias")) {
+    NamespaceAliasDecls.insert(NamespaceAlias);
   } else if (const auto *NsDecl =
                  Result.Nodes.getNodeAs<NamespaceDecl>("old_ns")) {
     moveOldNamespace(Result, NsDecl);
@@ -687,6 +696,38 @@ void ChangeNamespaceTool::replaceQualifi
         ReplaceName = FromDeclNameRef;
     }
   }
+  // Checks if there is any namespace alias declarations that can shorten the
+  // qualified name.
+  for (const auto *NamespaceAlias : NamespaceAliasDecls) {
+    if (!isDeclVisibleAtLocation(*Result.SourceManager, NamespaceAlias, DeclCtx,
+                                 Start))
+      continue;
+    StringRef FromDeclNameRef = FromDeclName;
+    if (FromDeclNameRef.consume_front(
+            NamespaceAlias->getNamespace()->getQualifiedNameAsString() +
+            "::")) {
+      std::string AliasName = NamespaceAlias->getNameAsString();
+      std::string AliasQualifiedName =
+          NamespaceAlias->getQualifiedNameAsString();
+      // We only consider namespace aliases define in the global namepspace or
+      // in namespaces that are directly visible from the reference, i.e.
+      // ancestor of the `OldNs`. Note that declarations in ancestor namespaces
+      // but not visible in the new namespace is filtered out by
+      // "IsVisibleInNewNs" matcher.
+      if (AliasQualifiedName != AliasName) {
+        // The alias is defined in some namespace.
+        assert(StringRef(AliasQualifiedName).endswith("::" + AliasName));
+        llvm::StringRef AliasNs =
+            StringRef(AliasQualifiedName).drop_back(AliasName.size() + 2);
+        if (!llvm::StringRef(OldNs).startswith(AliasNs))
+          continue;
+      }
+      std::string NameWithAliasNamespace =
+          (AliasName + "::" + FromDeclNameRef).str();
+      if (NameWithAliasNamespace.size() < ReplaceName.size())
+        ReplaceName = NameWithAliasNamespace;
+    }
+  }
   // Checks if there is any using shadow declarations that can shorten the
   // qualified name.
   bool Matched = false;

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=290421&r1=290420&r2=290421&view=diff
==============================================================================
--- clang-tools-extra/trunk/change-namespace/ChangeNamespace.h (original)
+++ clang-tools-extra/trunk/change-namespace/ChangeNamespace.h Fri Dec 23 04:47:09 2016
@@ -154,6 +154,9 @@ private:
   // Records all using namespace declarations, which can be used to shorten
   // namespace specifiers.
   llvm::SmallPtrSet<const UsingDirectiveDecl *, 8> UsingNamespaceDecls;
+  // Records all namespace alias declarations, which can be used to shorten
+  // namespace specifiers.
+  llvm::SmallPtrSet<const NamespaceAliasDecl *, 8> NamespaceAliasDecls;
   // TypeLocs of CXXCtorInitializer. Types of CXXCtorInitializers do not need to
   // be fixed.
   llvm::SmallVector<TypeLoc, 8> BaseCtorInitializerTypeLocs;

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=290421&r1=290420&r2=290421&view=diff
==============================================================================
--- clang-tools-extra/trunk/unittests/change-namespace/ChangeNamespaceTests.cpp (original)
+++ clang-tools-extra/trunk/unittests/change-namespace/ChangeNamespaceTests.cpp Fri Dec 23 04:47:09 2016
@@ -825,6 +825,114 @@ TEST_F(ChangeNamespaceTest, UsingNamespa
   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"




More information about the cfe-commits mailing list