Index: change-namespace/ChangeNamespace.h =================================================================== --- change-namespace/ChangeNamespace.h +++ change-namespace/ChangeNamespace.h @@ -142,9 +142,6 @@ // Records all using declarations, which can be used to shorten namespace // specifiers. llvm::SmallPtrSet UsingDecls; - // Records all type alias declarations, which can be used to shorten namespace - // specifiers. - llvm::SmallPtrSet TypeAliasDecls; // Records all using namespace declarations, which can be used to shorten // namespace specifiers. llvm::SmallPtrSet UsingNamespaceDecls; Index: change-namespace/ChangeNamespace.cpp =================================================================== --- change-namespace/ChangeNamespace.cpp +++ change-namespace/ChangeNamespace.cpp @@ -287,11 +287,6 @@ usingDecl(isExpansionInFileMatching(FilePattern), IsVisibleInNewNs) .bind("using"), this); - // Match using declarations. - Finder->addMatcher( - typeAliasDecl(isExpansionInFileMatching(FilePattern), IsVisibleInNewNs) - .bind("type_alias"), - this); // Match using namespace declarations. Finder->addMatcher(usingDirectiveDecl(isExpansionInFileMatching(FilePattern), IsVisibleInNewNs) @@ -379,9 +374,6 @@ const ast_matchers::MatchFinder::MatchResult &Result) { if (const auto *Using = Result.Nodes.getNodeAs("using")) { UsingDecls.insert(Using); - } else if (const auto *AliasDecl = - Result.Nodes.getNodeAs("type_alias")) { - TypeAliasDecls.insert(AliasDecl); } else if (const auto *UsingNamespace = Result.Nodes.getNodeAs( "using_namespace")) { @@ -629,8 +621,27 @@ const auto *FromDecl = Result.Nodes.getNodeAs("from_decl"); // `hasDeclaration` gives underlying declaration, but if the type is // a typedef type, we need to use the typedef type instead. - if (auto *Typedef = Type.getType()->getAs()) + if (auto *Typedef = Type.getType()->getAs()) { FromDecl = Typedef->getDecl(); + auto IsInMovedNs = [&](const NamedDecl *D) { + if (!llvm::StringRef(D->getQualifiedNameAsString()) + .startswith(OldNamespace + "::")) + return false; + auto ExpansionLoc = + Result.SourceManager->getExpansionLoc(D->getLocStart()); + if (ExpansionLoc.isInvalid()) + return false; + llvm::StringRef Filename = + Result.SourceManager->getFilename(ExpansionLoc); + llvm::Regex RE(FilePattern); + return RE.match(Filename); + }; + // Don't fix the \p Type if it refers to a type alias decl in the moved + // namespace since the alias decl will be moved along with the type + // reference. + if (IsInMovedNs(FromDecl)) + return; + } const Decl *DeclCtx = Result.Nodes.getNodeAs("dc"); assert(DeclCtx && "Empty decl context."); Index: unittests/change-namespace/ChangeNamespaceTests.cpp =================================================================== --- unittests/change-namespace/ChangeNamespaceTests.cpp +++ unittests/change-namespace/ChangeNamespaceTests.cpp @@ -962,127 +962,48 @@ EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } -/* -TEST_F(ChangeNamespaceTest, ClassWithConstructors) { - std::string Code = "namespace na {\n" - "namespace nb {\n" - "class A {" - "public:\n" - " A() {}\n" - " A(int i);\n" - "};\n" - "A::A(int i) {}\n" - "} // namespace nb\n" - "} // namespace na\n"; - std::string Expected = "\n\n" - "namespace x {\n" - "namespace y {\n" - "class A {" - "public:\n" - " A() {}\n" - " A(int i);\n" - "};\n" - "A::A(int i) {}\n" - "} // namespace y\n" - "} // namespace x\n"; - EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); -} - -TEST_F(ChangeNamespaceTest, DerivedClassWithConstructors) { +TEST_F(ChangeNamespaceTest, UsingAliasDeclInGlobal) { std::string Code = - "namespace nx { namespace ny { class X { public: X(int i) {} }; } }\n" + "namespace nx { namespace ny { class X {}; } }\n" + "using Y = nx::ny::X;\n" "namespace na {\n" "namespace nb {\n" - "class A : public nx::ny::X {" - "public:\n" - " A() : nx::ny::X::X(0) {}\n" - " A(int i);\n" - "};\n" - "A::A(int i) : nx::ny::X::X(i) {}\n" + "void f() { Y y; }\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 {" - "public:\n" - " A() : nx::ny::X::X(0) {}\n" - " A(int i);\n" - "};\n" - "A::A(int i) : nx::ny::X::X(i) {}\n" - "} // namespace y\n" - "} // namespace x\n"; - EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); -} -TEST_F(ChangeNamespaceTest, DerivedClassWithConstructorsAndUsingDecl) { - std::string Code = - "namespace nx { class XYZ { public: XYZ(int i) {} }; }\n" - "namespace na {\n" - "namespace nb {\n" - "using nx::XYZ;\n" - "class A : public XYZ {" - "public:\n" - " A() : XYZ::XYZ(0) {}\n" - " A(int i);\n" - "};\n" - "A::A(int i) : XYZ::XYZ(i) {}\n" - "} // namespace nb\n" - "} // namespace na\n"; - std::string Expected = - "namespace nx { class XYZ { public: XYZ(int i) {} }; }\n" - "\n\n" - "namespace x {\n" - "namespace y {\n" - "using ::nx::XYZ;\n" - "class A : public XYZ {" - "public:\n" - " A() : XYZ::XYZ(0) {}\n" - " A(int i);\n" - "};\n" - "A::A(int i) : XYZ::XYZ(i) {}\n" - "} // namespace y\n" - "} // namespace x\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, ConstructorsAndUsingDeclInAnonymous) { + +TEST_F(ChangeNamespaceTest, TypedefAliasDecl) { std::string Code = - "namespace nx { class XYZ { public: XYZ(int i) {} }; }\n" + "namespace nx { namespace ny { class X {}; } }\n" "namespace na {\n" "namespace nb {\n" - "using nx::XYZ;\n" - "namespace {\n" - "class A : public XYZ {" - "public:\n" - " A() : XYZ::XYZ(0) {}\n" - " A(int i);\n" - "};\n" - "A::A(int i) : XYZ::XYZ(i) {}\n" - "} // namespace\n" + "typedef nx::ny::X Y;\n" + "void f() { Y y; }\n" "} // namespace nb\n" "} // namespace na\n"; - std::string Expected = - "namespace nx { class XYZ { public: XYZ(int i) {} }; }\n" - "\n\n" - "namespace x {\n" - "namespace y {\n" - "using ::nx::XYZ;\n" - "namespace {\n" - "class A : public XYZ {" - "public:\n" - " A() : XYZ::XYZ(0) {}\n" - " A(int i);\n" - "};\n" - "A::A(int i) : XYZ::XYZ(i) {}\n" - "} // namespace\n" - "} // namespace y\n" - "} // namespace x\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)); } -*/ } // anonymous namespace } // namespace change_namespace