From 9df3ac1f564b0b8367290edceba71a225b7f7f99 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Thu, 13 Oct 2016 08:48:42 +0000 Subject: [PATCH] Recommit r283538 "[clang-move] Support moving multiple classes in one run." llvm-svn: 284109 --- clang-tools-extra/clang-move/ClangMove.cpp | 22 +++++++-- clang-tools-extra/clang-move/ClangMove.h | 5 +- .../clang-move/tool/ClangMoveMain.cpp | 8 +-- .../test/clang-move/Inputs/multiple_class_test.cpp | 27 ++++++++++ .../test/clang-move/Inputs/multiple_class_test.h | 30 ++++++++++++ clang-tools-extra/test/clang-move/move-class.cpp | 4 +- .../test/clang-move/move-multiple-classes.cpp | 57 ++++++++++++++++++++++ .../unittests/clang-move/ClangMoveTests.cpp | 8 +-- 8 files changed, 145 insertions(+), 16 deletions(-) create mode 100644 clang-tools-extra/test/clang-move/Inputs/multiple_class_test.cpp create mode 100644 clang-tools-extra/test/clang-move/Inputs/multiple_class_test.h create mode 100644 clang-tools-extra/test/clang-move/move-multiple-classes.cpp diff --git a/clang-tools-extra/clang-move/ClangMove.cpp b/clang-tools-extra/clang-move/ClangMove.cpp index fe19fa0..c429a18 100644 --- a/clang-tools-extra/clang-move/ClangMove.cpp +++ b/clang-tools-extra/clang-move/ClangMove.cpp @@ -297,31 +297,43 @@ ClangMoveTool::ClangMoveTool( : Spec(MoveSpec), FileToReplacements(FileToReplacements), OriginalRunningDirectory(OriginalRunningDirectory), FallbackStyle(FallbackStyle) { - Spec.Name = llvm::StringRef(Spec.Name).ltrim(':'); if (!Spec.NewHeader.empty()) CCIncludes.push_back("#include \"" + Spec.NewHeader + "\"\n"); } void ClangMoveTool::registerMatchers(ast_matchers::MatchFinder *Finder) { - std::string FullyQualifiedName = "::" + Spec.Name; + SmallVector ClassNames; + llvm::StringRef(Spec.Names).split(ClassNames, ','); + Optional> InMovedClassNames; + for (StringRef ClassName : ClassNames) { + llvm::StringRef GlobalClassName = ClassName.trim().ltrim(':'); + const auto HasName = hasName(("::" + GlobalClassName).str()); + InMovedClassNames = + InMovedClassNames ? anyOf(*InMovedClassNames, HasName) : HasName; + } + if (!InMovedClassNames) { + llvm::errs() << "No classes being moved.\n"; + return; + } + auto InOldHeader = isExpansionInFile( MakeAbsolutePath(OriginalRunningDirectory, Spec.OldHeader)); auto InOldCC = isExpansionInFile( MakeAbsolutePath(OriginalRunningDirectory, Spec.OldCC)); auto InOldFiles = anyOf(InOldHeader, InOldCC); auto InMovedClass = - hasDeclContext(cxxRecordDecl(hasName(FullyQualifiedName))); + hasDeclContext(cxxRecordDecl(*InMovedClassNames)); // Match moved class declarations. auto MovedClass = cxxRecordDecl( - InOldFiles, hasName(FullyQualifiedName), isDefinition(), + InOldFiles, *InMovedClassNames, isDefinition(), hasDeclContext(anyOf(namespaceDecl(), translationUnitDecl()))); Finder->addMatcher(MovedClass.bind("moved_class"), this); // Match moved class methods (static methods included) which are defined // outside moved class declaration. Finder->addMatcher(cxxMethodDecl(InOldFiles, - ofClass(hasName(FullyQualifiedName)), + ofClass(*InMovedClassNames), isDefinition()) .bind("class_method"), this); diff --git a/clang-tools-extra/clang-move/ClangMove.h b/clang-tools-extra/clang-move/ClangMove.h index 0cacae8..28885e2 100644 --- a/clang-tools-extra/clang-move/ClangMove.h +++ b/clang-tools-extra/clang-move/ClangMove.h @@ -37,8 +37,9 @@ public: }; struct MoveDefinitionSpec { - // A fully qualified name, e.g. "X", "a::X". - std::string Name; + // A comma-separated list of fully qualified names, e.g. "Foo", + // "a::Foo, b::Foo". + std::string Names; // The file path of old header, can be relative path and absolute path. std::string OldHeader; // The file path of old cc, can be relative path and absolute path. diff --git a/clang-tools-extra/clang-move/tool/ClangMoveMain.cpp b/clang-tools-extra/clang-move/tool/ClangMoveMain.cpp index 09f5805..91677d7 100644 --- a/clang-tools-extra/clang-move/tool/ClangMoveMain.cpp +++ b/clang-tools-extra/clang-move/tool/ClangMoveMain.cpp @@ -37,8 +37,10 @@ std::error_code CreateNewFile(const llvm::Twine &path) { cl::OptionCategory ClangMoveCategory("clang-move options"); -cl::opt Name("name", cl::desc("The name of class being moved."), - cl::cat(ClangMoveCategory)); +cl::opt + Names("names", cl::desc("A comma-separated list of the names of classes " + "being moved, e.g. \"Foo\", \"a::Foo, b::Foo\"."), + cl::cat(ClangMoveCategory)); cl::opt OldHeader("old_header", @@ -86,7 +88,7 @@ int main(int argc, const char **argv) { tooling::RefactoringTool Tool(OptionsParser.getCompilations(), OptionsParser.getSourcePathList()); move::ClangMoveTool::MoveDefinitionSpec Spec; - Spec.Name = Name; + Spec.Names = Names; Spec.OldHeader = OldHeader; Spec.NewHeader = NewHeader; Spec.OldCC = OldCC; diff --git a/clang-tools-extra/test/clang-move/Inputs/multiple_class_test.cpp b/clang-tools-extra/test/clang-move/Inputs/multiple_class_test.cpp new file mode 100644 index 0000000..302475b --- /dev/null +++ b/clang-tools-extra/test/clang-move/Inputs/multiple_class_test.cpp @@ -0,0 +1,27 @@ +#include "multiple_class_test.h" + +namespace a { +int Move1::f() { + return 0; +} +} // namespace a + +namespace b { +int Move2::f() { + return 0; +} +} // namespace b + +namespace c { +int Move3::f() { + return 0; +} + +int Move4::f() { + return 0; +} + +int NoMove::f() { + return 0; +} +} // namespace c diff --git a/clang-tools-extra/test/clang-move/Inputs/multiple_class_test.h b/clang-tools-extra/test/clang-move/Inputs/multiple_class_test.h new file mode 100644 index 0000000..cedb8d5 --- /dev/null +++ b/clang-tools-extra/test/clang-move/Inputs/multiple_class_test.h @@ -0,0 +1,30 @@ +namespace a { +class Move1 { +public: + int f(); +}; +} // namespace a + +namespace b { +class Move2 { +public: + int f(); +}; +} // namespace b + +namespace c { +class Move3 { +public: + int f(); +}; + +class Move4 { +public: + int f(); +}; + +class NoMove { +public: + int f(); +}; +} // namespace c diff --git a/clang-tools-extra/test/clang-move/move-class.cpp b/clang-tools-extra/test/clang-move/move-class.cpp index 93d8c4e..56aad1b 100644 --- a/clang-tools-extra/test/clang-move/move-class.cpp +++ b/clang-tools-extra/test/clang-move/move-class.cpp @@ -6,7 +6,7 @@ // RUN: cp %S/Inputs/test.cpp %T/clang-move/src // RUN: touch %T/clang-move/include/test2.h // RUN: cd %T/clang-move/build -// RUN: clang-move -name="a::Foo" -new_cc=%T/clang-move/new_test.cpp -new_header=%T/clang-move/new_test.h -old_cc=../src/test.cpp -old_header=../include/test.h %T/clang-move/src/test.cpp +// RUN: clang-move -names="a::Foo" -new_cc=%T/clang-move/new_test.cpp -new_header=%T/clang-move/new_test.h -old_cc=../src/test.cpp -old_header=../include/test.h %T/clang-move/src/test.cpp // RUN: FileCheck -input-file=%T/clang-move/new_test.cpp -check-prefix=CHECK-NEW-TEST-CPP %s // RUN: FileCheck -input-file=%T/clang-move/new_test.h -check-prefix=CHECK-NEW-TEST-H %s // RUN: FileCheck -input-file=%T/clang-move/src/test.cpp -check-prefix=CHECK-OLD-TEST-CPP %s @@ -15,7 +15,7 @@ // RUN: cp %S/Inputs/test.h %T/clang-move/include // RUN: cp %S/Inputs/test.cpp %T/clang-move/src // RUN: cd %T/clang-move/build -// RUN: clang-move -name="a::Foo" -new_cc=%T/clang-move/new_test.cpp -new_header=%T/clang-move/new_test.h -old_cc=%T/clang-move/src/test.cpp -old_header=%T/clang-move/include/test.h %T/clang-move/src/test.cpp +// RUN: clang-move -names="a::Foo" -new_cc=%T/clang-move/new_test.cpp -new_header=%T/clang-move/new_test.h -old_cc=%T/clang-move/src/test.cpp -old_header=%T/clang-move/include/test.h %T/clang-move/src/test.cpp // RUN: FileCheck -input-file=%T/clang-move/new_test.cpp -check-prefix=CHECK-NEW-TEST-CPP %s // RUN: FileCheck -input-file=%T/clang-move/new_test.h -check-prefix=CHECK-NEW-TEST-H %s // RUN: FileCheck -input-file=%T/clang-move/src/test.cpp -check-prefix=CHECK-OLD-TEST-CPP %s diff --git a/clang-tools-extra/test/clang-move/move-multiple-classes.cpp b/clang-tools-extra/test/clang-move/move-multiple-classes.cpp new file mode 100644 index 0000000..4e8cf4b --- /dev/null +++ b/clang-tools-extra/test/clang-move/move-multiple-classes.cpp @@ -0,0 +1,57 @@ +// RUN: mkdir -p %T/move-multiple-classes +// RUN: cp %S/Inputs/multiple_class_test* %T/move-multiple-classes/ +// RUN: cd %T/move-multiple-classes +// RUN: clang-move -names="a::Move1, b::Move2,c::Move3,c::Move4" -new_cc=%T/move-multiple-classes/new_multiple_class_test.cpp -new_header=%T/move-multiple-classes/new_multiple_class_test.h -old_cc=%T/move-multiple-classes/multiple_class_test.cpp -old_header=../move-multiple-classes/multiple_class_test.h %T/move-multiple-classes/multiple_class_test.cpp -- +// RUN: FileCheck -input-file=%T/move-multiple-classes/new_multiple_class_test.cpp -check-prefix=CHECK-NEW-TEST-CPP %s +// RUN: FileCheck -input-file=%T/move-multiple-classes/new_multiple_class_test.h -check-prefix=CHECK-NEW-TEST-H %s +// RUN: FileCheck -input-file=%T/move-multiple-classes/multiple_class_test.cpp -check-prefix=CHECK-OLD-TEST-CPP %s +// RUN: FileCheck -input-file=%T/move-multiple-classes/multiple_class_test.h -check-prefix=CHECK-OLD-TEST-H %s +// +// CHECK-OLD-TEST-H: namespace c { +// CHECK-OLD-TEST-H: class NoMove { +// CHECK-OLD-TEST-H: public: +// CHECK-OLD-TEST-H: int f(); +// CHECK-OLD-TEST-H: }; +// CHECK-OLD-TEST-H: } // namespace c + +// CHECK-OLD-TEST-CPP: #include "{{.*}}multiple_class_test.h" +// CHECK-OLD-TEST-CPP: namespace c { +// CHECK-OLD-TEST-CPP: int NoMove::f() { +// CHECK-OLD-TEST-CPP: return 0; +// CHECK-OLD-TEST-CPP: } +// CHECK-OLD-TEST-CPP: } // namespace c + +// CHECK-NEW-TEST-H: namespace a { +// CHECK-NEW-TEST-H: class Move1 { +// CHECK-NEW-TEST-H: public: +// CHECK-NEW-TEST-H: int f(); +// CHECK-NEW-TEST-H: }; +// CHECK-NEW-TEST-H: } // namespace a +// CHECK-NEW-TEST-H: namespace b { +// CHECK-NEW-TEST-H: class Move2 { +// CHECK-NEW-TEST-H: public: +// CHECK-NEW-TEST-H: int f(); +// CHECK-NEW-TEST-H: }; +// CHECK-NEW-TEST-H: } // namespace b +// CHECK-NEW-TEST-H: namespace c { +// CHECK-NEW-TEST-H: class Move3 { +// CHECK-NEW-TEST-H: public: +// CHECK-NEW-TEST-H: int f(); +// CHECK-NEW-TEST-H: }; +// CHECK-NEW-TEST-H: class Move4 { +// CHECK-NEW-TEST-H: public: +// CHECK-NEW-TEST-H: int f(); +// CHECK-NEW-TEST-H: }; +// CHECK-NEW-TEST-H: } // namespace c + +// CHECK-NEW-TEST-CPP: #include "{{.*}}new_multiple_class_test.h" +// CHECK-NEW-TEST-CPP: namespace a { +// CHECK-NEW-TEST-CPP: int Move1::f() { return 0; } +// CHECK-NEW-TEST-CPP: } // namespace a +// CHECK-NEW-TEST-CPP: namespace b { +// CHECK-NEW-TEST-CPP: int Move2::f() { return 0; } +// CHECK-NEW-TEST-CPP: } // namespace b +// CHECK-NEW-TEST-CPP: namespace c { +// CHECK-NEW-TEST-CPP: int Move3::f() { return 0; } +// CHECK-NEW-TEST-CPP: int Move4::f() { return 0; } +// CHECK-NEW-TEST-CPP: } // namespace c diff --git a/clang-tools-extra/unittests/clang-move/ClangMoveTests.cpp b/clang-tools-extra/unittests/clang-move/ClangMoveTests.cpp index 0ac4a65..f4845cd 100644 --- a/clang-tools-extra/unittests/clang-move/ClangMoveTests.cpp +++ b/clang-tools-extra/unittests/clang-move/ClangMoveTests.cpp @@ -210,7 +210,7 @@ runClangMoveOnCode(const move::ClangMoveTool::MoveDefinitionSpec &Spec) { TEST(ClangMove, MoveHeaderAndCC) { move::ClangMoveTool::MoveDefinitionSpec Spec; - Spec.Name = "a::b::Foo"; + Spec.Names = "a::b::Foo"; Spec.OldHeader = "foo.h"; Spec.OldCC = "foo.cc"; Spec.NewHeader = "new_foo.h"; @@ -225,7 +225,7 @@ TEST(ClangMove, MoveHeaderAndCC) { TEST(ClangMove, MoveHeaderOnly) { move::ClangMoveTool::MoveDefinitionSpec Spec; - Spec.Name = "a::b::Foo"; + Spec.Names = "a::b::Foo"; Spec.OldHeader = "foo.h"; Spec.NewHeader = "new_foo.h"; auto Results = runClangMoveOnCode(Spec); @@ -236,7 +236,7 @@ TEST(ClangMove, MoveHeaderOnly) { TEST(ClangMove, MoveCCOnly) { move::ClangMoveTool::MoveDefinitionSpec Spec; - Spec.Name = "a::b::Foo"; + Spec.Names = "a::b::Foo"; Spec.OldCC = "foo.cc"; Spec.NewCC = "new_foo.cc"; std::string ExpectedHeader = "#include \"foo.h\"\n\n"; @@ -248,7 +248,7 @@ TEST(ClangMove, MoveCCOnly) { TEST(ClangMove, MoveNonExistClass) { move::ClangMoveTool::MoveDefinitionSpec Spec; - Spec.Name = "NonExistFoo"; + Spec.Names = "NonExistFoo"; Spec.OldHeader = "foo.h"; Spec.OldCC = "foo.cc"; Spec.NewHeader = "new_foo.h"; -- 2.7.4