ioeric updated this revision to Diff 71116.
ioeric marked 13 inline comments as done.
ioeric added a comment.
Herald added a subscriber: mgorny.
- Addressed review comments.
- Separate getAffectedFiles into its own interface.
https://reviews.llvm.org/D24380
Files:
CMakeLists.txt
migrate-tool/AffectedFilesFinder.h
migrate-tool/BuildManager.h
migrate-tool/CMakeLists.txt
migrate-tool/HeaderGenerator.cpp
migrate-tool/HeaderGenerator.h
migrate-tool/MigrateTool.cpp
migrate-tool/MigrateTool.h
migrate-tool/RefactoringManager.h
unittests/CMakeLists.txt
unittests/migrate-tool/CMakeLists.txt
unittests/migrate-tool/HeaderBuildTest.cpp
Index: unittests/migrate-tool/HeaderBuildTest.cpp
===================================================================
--- /dev/null
+++ unittests/migrate-tool/HeaderBuildTest.cpp
@@ -0,0 +1,100 @@
+//===-- HeaderGeneratorTest.cpp - HeaderGenerator unit tests ----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "HeaderGenerator.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace migrate_tool {
+
+TEST(HeaderGenerator, Empty) {
+ HeaderGenerator Hdr("a.h");
+ std::string Expected = "#ifndef A_H\n"
+ "#define A_H\n"
+ "\n"
+ "#endif // A_H";
+ EXPECT_EQ(Expected, Hdr.generateContent());
+}
+
+TEST(HeaderGenerator, SingleAlias) {
+ HeaderGenerator Hdr("a/b/c.h");
+ Hdr.addAlias("na::nb::C", "x::y::Z");
+ std::string Expected = "#ifndef A_B_C_H\n"
+ "#define A_B_C_H\n"
+ "namespace na {\n"
+ "namespace nb {\n"
+ "using C = ::x::y::Z;\n"
+ "} // namespace nb\n"
+ "} // namespace na\n"
+ "#endif // A_B_C_H";
+ EXPECT_EQ(Expected, Hdr.generateContent());
+}
+
+TEST(HeaderGenerator, SingleAliasWithIncludes) {
+ HeaderGenerator Hdr("a/b/c.h");
+ Hdr.addInclude("x/y/z.h");
+ Hdr.addInclude("x/y/zz.h");
+ Hdr.addAlias("na::nb::C", "x::y::Z");
+ std::string Expected = "#ifndef A_B_C_H\n"
+ "#define A_B_C_H\n"
+ "#include \"x/y/z.h\"\n"
+ "#include \"x/y/zz.h\"\n"
+ "namespace na {\n"
+ "namespace nb {\n"
+ "using C = ::x::y::Z;\n"
+ "} // namespace nb\n"
+ "} // namespace na\n"
+ "#endif // A_B_C_H";
+ EXPECT_EQ(Expected, Hdr.generateContent());
+}
+
+TEST(HeaderGenerator, MultipleAliasInOneNamespace) {
+ HeaderGenerator Hdr("a/b/c.h");
+ Hdr.addAlias("na::nb::C", "x::y::Z");
+ Hdr.addAlias("na::nb::D", "x::y::D");
+ Hdr.addAlias("na::nb::Q", "x::y::Q");
+ std::string Expected = "#ifndef A_B_C_H\n"
+ "#define A_B_C_H\n"
+ "namespace na {\n"
+ "namespace nb {\n"
+ "using C = ::x::y::Z;\n"
+ "using D = ::x::y::D;\n"
+ "using Q = ::x::y::Q;\n"
+ "} // namespace nb\n"
+ "} // namespace na\n"
+ "#endif // A_B_C_H";
+ EXPECT_EQ(Expected, Hdr.generateContent());
+}
+
+TEST(HeaderGenerator, AliasesInMultipleNamespace) {
+ HeaderGenerator Hdr("a/b/c.h");
+ Hdr.addAlias("nb::Q", "x::Q");
+ Hdr.addAlias("na::nb::C", "x::y::Z");
+ Hdr.addAlias("na::nc::D", "x::y::D");
+ Hdr.addAlias("na::nb::Q", "x::y::Q");
+ std::string Expected = "#ifndef A_B_C_H\n"
+ "#define A_B_C_H\n"
+ "namespace nb {\n"
+ "using Q = ::x::Q;\n"
+ "} // namespace nb\n"
+ "namespace na {\n"
+ "namespace nb {\n"
+ "using C = ::x::y::Z;\n"
+ "using Q = ::x::y::Q;\n"
+ "} // namespace nb\n"
+ "namespace nc {\n"
+ "using D = ::x::y::D;\n"
+ "} // namespace nc\n"
+ "} // namespace na\n"
+ "#endif // A_B_C_H";
+ EXPECT_EQ(Expected, Hdr.generateContent());
+}
+
+} // namespace migrate_tool
+} // namespace clang
Index: unittests/migrate-tool/CMakeLists.txt
===================================================================
--- /dev/null
+++ unittests/migrate-tool/CMakeLists.txt
@@ -0,0 +1,25 @@
+set(LLVM_LINK_COMPONENTS
+ support
+ )
+
+get_filename_component(MIGRATE_TOOL_SOURCE_DIR
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../migrate-tool REALPATH)
+include_directories(
+ ${MIGRATE_TOOL_SOURCE_DIR}
+ )
+
+# We'd like to clang/unittests/Tooling/RewriterTestContext.h in the test.
+include_directories(${CLANG_SOURCE_DIR})
+
+add_extra_unittest(MigrateToolTests
+ HeaderBuildTest.cpp
+ )
+
+target_link_libraries(MigrateToolTests
+ migrateTool
+ clangBasic
+ clangFormat
+ clangRewrite
+ clangTooling
+ clangToolingCore
+ )
Index: unittests/CMakeLists.txt
===================================================================
--- unittests/CMakeLists.txt
+++ unittests/CMakeLists.txt
@@ -10,3 +10,4 @@
add_subdirectory(clang-query)
add_subdirectory(clang-tidy)
add_subdirectory(include-fixer)
+add_subdirectory(migrate-tool)
Index: migrate-tool/RefactoringManager.h
===================================================================
--- /dev/null
+++ migrate-tool/RefactoringManager.h
@@ -0,0 +1,54 @@
+//===-- RefactoringManager.h - Perform refactoring on files. ------*- C++ -*-=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_MIGRATE_TOOL_REFACTORINGMANAGER_H
+#define LLVM_CLANG_TOOLS_EXTRA_MIGRATE_TOOL_REFACTORINGMANAGER_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Error.h"
+#include <set>
+
+namespace clang {
+namespace migrate_tool {
+
+// This defines interfaces for a codebase-dependent `RefactoringManager` that
+// performs some refactoring operations.
+class RefactoringManager {
+public:
+ // Adds #include directives in \p Includes to each file in \p Files.
+ virtual llvm::Error
+ addIncludesToFiles(const std::set<llvm::StringRef> &Includes,
+ llvm::ArrayRef<std::string> Files) = 0;
+
+ // Applies all rename rules in \p Renames on all \p Files.
+ // Rename rules are a set of <Old Name, New Name> pair.
+ virtual llvm::Error renameSymbolsInFiles(
+ llvm::ArrayRef<std::pair<llvm::StringRef, llvm::StringRef>> Renames,
+ llvm::ArrayRef<std::string> Files) = 0;
+
+ // Changes namespace \p OldNamespace to \p NewNamespace in \p Files and
+ // the corresponding files in translation units that match the given \p
+ // FilePattern.
+ virtual llvm::Error changeNamespaceInFiles(
+ llvm::StringRef OldNamespace, llvm::StringRef NewNamespace,
+ llvm::StringRef FilePattern, llvm::ArrayRef<llvm::StringRef> Files) = 0;
+
+ // Moves definitions of \p Symbols from \p OldHeader and the corresponding
+ // source file to \p NewHeader and the new source file.
+ virtual llvm::Error
+ moveSymbolsAcrossFiles(llvm::ArrayRef<llvm::StringRef> Symbols,
+ llvm::StringRef OldHeader,
+ llvm::StringRef NewHeader) = 0;
+};
+
+} // namespace migrate_tool
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_MIGRATE_TOOL_REFACTORINGMANAGER_H
Index: migrate-tool/MigrateTool.h
===================================================================
--- /dev/null
+++ migrate-tool/MigrateTool.h
@@ -0,0 +1,100 @@
+//===-- MigrateTool.h - Migrate class, function etc. ------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_MIGRATE_TOOL_MIGRATETOOL_H
+#define LLVM_CLANG_TOOLS_EXTRA_MIGRATE_TOOL_MIGRATETOOL_H
+
+#include "AffectedFilesFinder.h"
+#include "BuildManager.h"
+#include "RefactoringManager.h"
+#include "llvm/Support/Error.h"
+
+namespace clang {
+namespace migrate_tool {
+
+// This tool automates the entire process of migrating a C++ symbol (class,
+// function, enum etc.) including renaming a symbol and/or moving a symbol
+// across namespace and/or files. Besides moving the symbol definition, it also
+// takes care of users of the symbol (i.e. update all references of old symbol
+// to new symbol) as well as build rules.
+// The migration path is divided into 3 phases:
+// 1. Preparation phase.
+// Create an alias from the old symbol name to to new symbol name. If the
+// symbol is to be moved acrossed files, a new temporary header containing
+// type alias is created.
+// 2. Renaming phase.
+// Update all affected projects (i.e. users of the old symbol) to use the
+// new symbol name via the alias above.
+// 3. Migration phase.
+// Actual migration happens at this phase after all affected projects are
+// updated.
+// Move the symbol definition to the new file if the symbol is to be moved
+// to a different file.
+// Rename the symbol (i.e. the definition) if the symbol is to be renamed.
+// Change the namespace in which the symbol is defined if the symbol is to
+// be moved to a different namespace.
+// With this migration path, we can divide the three phases into three separate
+// patches. For large scale changes where many projects are affected, the
+// renaming phase can be splitted into multiple smaller patches to make the
+// both refactoring and review process easier.
+class MigrateTool {
+public:
+ class MigrateSpec {
+ public:
+ enum class MigrateType {
+ Class,
+ Unknown,
+ };
+
+ llvm::StringRef getOldHeader() const { return OldHeader; }
+ llvm::StringRef getNewHeader() const { return NewHeader; }
+ llvm::StringRef getOldName() const { return OldName; }
+ llvm::StringRef getNewName() const { return NewName; }
+
+ private:
+ std::string OldHeader;
+ std::string NewHeader;
+ std::string OldName;
+ std::string NewName;
+ };
+
+ // FIXME: support handling multiple `MigrateSpec`s in one run.
+ MigrateTool(const MigrateSpec &Spec, BuildManager *BuildMgr,
+ RefactoringManager *Refactor, AffectedFilesFinder *Finder);
+
+ llvm::Error run();
+
+private:
+ // Preparation phase. See comment for the class above.
+ llvm::Error prepare();
+
+ // Renaming phase. See comment for the class above.
+ llvm::Error rename();
+
+ // Migration phase. See comment for the class above.
+ llvm::Error migrate();
+
+ // Create a new file with the given `Content`.
+ llvm::Error createFile(llvm::StringRef FilePath, llvm::StringRef Content);
+
+ MigrateSpec Spec;
+ // A codebase-dependent `BuildManager` that takes care of build rules during
+ // the migration.
+ BuildManager *BuildMgr;
+ // A codebase-dependent `RefactoringManager` that performs some refactoring
+ // operations.
+ RefactoringManager *RefactorMgr;
+ // Finds files that are affected by refactoring actions.
+ AffectedFilesFinder *Finder;
+};
+
+} // namespace migrate_tool
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_MIGRATE_TOOL_MIGRATETOOL_H
Index: migrate-tool/MigrateTool.cpp
===================================================================
--- /dev/null
+++ migrate-tool/MigrateTool.cpp
@@ -0,0 +1,134 @@
+//===-- MigrateTool.cpp - Migrate class, function etc. ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MigrateTool.h"
+#include "HeaderGenerator.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Process.h"
+#include <fstream>
+#include <set>
+
+namespace clang {
+namespace migrate_tool {
+
+MigrateTool::MigrateTool(const MigrateSpec &Spec, BuildManager *BuildMgr,
+ RefactoringManager *Refactor,
+ AffectedFilesFinder *Finder)
+ : Spec(Spec), BuildMgr(BuildMgr), RefactorMgr(Refactor), Finder(Finder) {}
+
+llvm::Error MigrateTool::createFile(llvm::StringRef FilePath,
+ llvm::StringRef Content) {
+ std::error_code EC;
+ llvm::raw_fd_ostream File(FilePath.str(), EC,
+ llvm::sys::fs::OpenFlags::F_None);
+ if (EC)
+ return llvm::errorCodeToError(EC);
+ File << Content.str();
+ File.close();
+ return llvm::Error::success();
+}
+
+llvm::Error MigrateTool::prepare() {
+ llvm::outs() << "Preparation phase.\n";
+ HeaderGenerator NewHeader(Spec.getNewHeader());
+ if (Spec.getNewHeader() == Spec.getOldHeader()) {
+ // FIXME: rename class within the same file. No need for new header. Just
+ // insert the alias in the old header.
+ return llvm::make_error<llvm::StringError>(
+ "Inplace renaming is not supported yet.",
+ llvm::inconvertibleErrorCode());
+ }
+ // Construct a new header for the symbol alias.
+ NewHeader.addInclude(Spec.getOldHeader());
+ if (Spec.getNewName() != Spec.getOldName())
+ NewHeader.addAlias(Spec.getNewName(), Spec.getOldName());
+
+ // Create new header and build target.
+ std::string Code = NewHeader.generateContent();
+ if (auto Err = createFile(NewHeader.getName(), Code))
+ return Err;
+ BuildMgr->addLibrary({NewHeader.getName()});
+
+ return llvm::Error::success();
+}
+
+llvm::Error MigrateTool::rename() {
+ llvm::outs() << "Rename phase.\n";
+ // Get all files that are affected by the migration, i.e. users of the symbol.
+ auto Files = Finder->getAffectedFiles(Spec.getOldName());
+ if (!Files)
+ return Files.takeError();
+ llvm::SmallVector<std::pair<llvm::StringRef, llvm::StringRef>, 4> Renames;
+ std::set<llvm::StringRef> NewIncludes;
+ if (Spec.getOldName() != Spec.getNewName())
+ Renames.emplace_back(Spec.getOldName(), Spec.getNewName());
+ if (Spec.getOldHeader() != Spec.getNewHeader())
+ NewIncludes.insert(Spec.getNewHeader());
+ if (auto Err = RefactorMgr->renameSymbolsInFiles(Renames, *Files))
+ return Err;
+ if (auto Err = RefactorMgr->addIncludesToFiles(NewIncludes, *Files))
+ return Err;
+ // Add dependency to affected target.
+ std::string NewTarget = BuildMgr->getBuildTargetForFile(Spec.getNewHeader());
+ for (llvm::StringRef File : *Files)
+ BuildMgr->addDependency(BuildMgr->getBuildTargetForFile(File), NewTarget);
+ return llvm::Error::success();
+}
+
+static inline llvm::StringRef
+extractNamespaceFromQualifiedName(llvm::StringRef QualifiedName) {
+ return QualifiedName.rsplit(':').second;
+}
+
+llvm::Error MigrateTool::migrate() {
+ llvm::outs() << "Migrate phase.\n";
+ // Move symbol definitions, rename symbol definitions, change
+ // surroudning namespaces, and update build rules if necessary.
+ llvm::SmallVector<std::pair<llvm::StringRef, llvm::StringRef>, 4> Renames;
+ if (Spec.getOldName() != Spec.getNewName())
+ Renames.emplace_back(Spec.getOldName(), Spec.getNewName());
+ llvm::SmallVector<llvm::StringRef, 4> MovedSymbols;
+ MovedSymbols.push_back(Spec.getOldName());
+ // FIXME: consider source files. Need to determine whether source files send
+ // with ".cpp" or ".cc" etc.
+ // FIXME: copy dependencies from old target to new target.
+ if (auto Err = RefactorMgr->moveSymbolsAcrossFiles(
+ MovedSymbols, Spec.getOldHeader(), Spec.getNewHeader()))
+ return Err;
+ if (auto Err =
+ RefactorMgr->renameSymbolsInFiles(Renames, {Spec.getNewHeader()}))
+ return Err;
+
+ llvm::StringRef OldNamespace =
+ extractNamespaceFromQualifiedName(Spec.getOldName());
+ llvm::StringRef NewNamespace =
+ extractNamespaceFromQualifiedName(Spec.getNewName());
+
+ llvm::SmallVector<llvm::StringRef, 4> Files;
+ Files.push_back(Spec.getNewHeader());
+ if (auto Err = RefactorMgr->changeNamespaceInFiles(
+ OldNamespace, NewNamespace, Spec.getNewHeader(), Files))
+ return Err;
+
+ return llvm::Error::success();
+}
+
+llvm::Error MigrateTool::run() {
+ if (auto Err = prepare())
+ return Err;
+ if (auto Err = rename())
+ return Err;
+ if (auto Err = migrate())
+ return Err;
+ return llvm::Error::success();
+}
+
+} // namespace migrate_tool
+} // namespace clang
Index: migrate-tool/HeaderGenerator.h
===================================================================
--- /dev/null
+++ migrate-tool/HeaderGenerator.h
@@ -0,0 +1,58 @@
+//===-- HeaderGenerator.h - Generate new headers. ----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_MIGRATE_TOOL_HEADERGENERATOR_H
+#define LLVM_CLANG_TOOLS_EXTRA_MIGRATE_TOOL_HEADERGENERATOR_H
+
+#include "llvm/ADT/StringRef.h"
+#include <vector>
+
+namespace clang {
+namespace migrate_tool {
+
+// This constructs a C++ header containing type aliases.
+class HeaderGenerator {
+public:
+ HeaderGenerator(llvm::StringRef HeaderName);
+
+ // Returns the name of the header.
+ llvm::StringRef getName() const { return HeaderName; }
+
+ /// \brief Adds an `using` shadow declaration from \p TypeName to \p NewName.
+ /// Both names should be fully-qualified.
+ /// For example, if \p NewName is `a::b::New` and TypeName is `x::y::Old`.
+ /// Then, the following code will be added into the header:
+ /// \code
+ /// namespace a {
+ /// namespace b {
+ /// using New = ::x::y::Old;
+ /// } // namespace b
+ /// } // namespace a
+ /// \endcode
+ void addAlias(llvm::StringRef NewName, llvm::StringRef TypeName);
+
+ // Adds an #include into the header.
+ void addInclude(llvm::StringRef IncludeHeader);
+
+ // Generates the header content containing given aliases and #include's.
+ // FIXME: consider code style.
+ std::string generateContent() const;
+
+private:
+ std::string HeaderName;
+ std::string HeaderGuard;
+ // Old symbol name, New symbol name pairs.
+ std::vector<std::pair<std::string, std::string>> Aliases;
+ std::vector<std::string> Includes;
+};
+
+} // namespace migrate_tool
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_MIGRATE_TOOL_HEADERGENERATOR_H
Index: migrate-tool/HeaderGenerator.cpp
===================================================================
--- /dev/null
+++ migrate-tool/HeaderGenerator.cpp
@@ -0,0 +1,112 @@
+//===-- HeaderGenerator.cpp - Generate new headers. -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "HeaderGenerator.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <sstream>
+
+namespace clang {
+namespace migrate_tool {
+
+namespace {
+
+class Namespace {
+public:
+ Namespace(llvm::StringRef Name, bool IsTopLevel = false)
+ : Name(Name), IsTopLevel(IsTopLevel) {
+ assert(!(!Name.empty() && IsTopLevel) &&
+ "A namespace must be either a top-level namespace with no name or "
+ "not a top-level namespace with name.");
+ }
+
+ void addAlias(llvm::StringRef NewName, llvm::StringRef TypeName) {
+ std::string OS;
+ llvm::raw_string_ostream SS(OS);
+ SS << "using " << NewName.str() << " = ::" << TypeName.str() << ";";
+ SS.flush();
+ CodeBlocks.push_back(OS);
+ }
+
+ Namespace *addNestedNamespace(llvm::StringRef Name) {
+ auto Pair = NestedNamespaces.try_emplace(Name, Name);
+ return &Pair.first->getValue();
+ }
+
+ std::string GenerateNamespaceCodeBlock() const {
+ std::vector<std::string> Lines;
+ if (!IsTopLevel)
+ Lines.push_back("namespace " + Name + " {");
+ // Add code blocks.
+ Lines.insert(Lines.end(), CodeBlocks.begin(), CodeBlocks.end());
+ // Add nested namespaces.
+ // If there are multiple nested namespaces, add newlines around each
+ // namespace.
+ for (const auto &Entry : NestedNamespaces)
+ Lines.push_back(Entry.second.GenerateNamespaceCodeBlock());
+ if (!IsTopLevel)
+ Lines.push_back("} // namespace " + Name);
+ return llvm::join(Lines.begin(), Lines.end(), "\n");
+ }
+
+private:
+ std::string Name;
+ bool IsTopLevel;
+ std::vector<std::string> CodeBlocks;
+ llvm::StringMap<Namespace> NestedNamespaces;
+};
+
+} // namespace
+
+HeaderGenerator::HeaderGenerator(llvm::StringRef HeaderName)
+ : HeaderName(HeaderName), HeaderGuard(HeaderName) {
+ // FIXME: use clang-tidy to generate the header guard.
+ std::replace(HeaderGuard.begin(), HeaderGuard.end(), '/', '_');
+ std::replace(HeaderGuard.begin(), HeaderGuard.end(), '.', '_');
+ HeaderGuard = llvm::StringRef(HeaderGuard).upper();
+}
+
+void HeaderGenerator::addAlias(llvm::StringRef NewName, llvm::StringRef TypeName) {
+ Aliases.emplace_back(NewName, TypeName);
+}
+
+void HeaderGenerator::addInclude(llvm::StringRef IncludeHeader) {
+ Includes.push_back(IncludeHeader);
+}
+
+// FIXME: format generated code.
+std::string HeaderGenerator::generateContent() const {
+ std::vector<std::string> Lines;
+ Lines.push_back("#ifndef " + HeaderGuard);
+ Lines.push_back("#define " + HeaderGuard);
+ for (const auto &Include : Includes)
+ Lines.push_back("#include \"" + Include + "\"");
+
+ Namespace TopNs("", /*IsTopLevel=*/true);
+ // Generate namespces containing aliases.
+ for (const auto &Entry : Aliases) {
+ llvm::StringRef NewName = Entry.first;
+ llvm::SmallVector<llvm::StringRef, 4> NewNameSplitted;
+ NewName.split(NewNameSplitted, "::");
+ auto *CurNs = &TopNs;
+ for (auto I = NewNameSplitted.begin(), E = NewNameSplitted.end() - 1;
+ I != E; ++I)
+ CurNs = CurNs->addNestedNamespace(*I);
+ CurNs->addAlias(NewNameSplitted.back(), Entry.second);
+ }
+
+ Lines.push_back(TopNs.GenerateNamespaceCodeBlock());
+ Lines.push_back("#endif // " + HeaderGuard);
+ return llvm::join(Lines.begin(), Lines.end(), "\n");
+}
+
+} // namespace migrate_tool
+} // namespace clang
Index: migrate-tool/CMakeLists.txt
===================================================================
--- /dev/null
+++ migrate-tool/CMakeLists.txt
@@ -0,0 +1,15 @@
+set(LLVM_LINK_COMPONENTS
+ support
+ )
+
+add_clang_library(migrateTool
+ HeaderGenerator.cpp
+ MigrateTool.cpp
+
+ LINK_LIBS
+ clangAST
+ clangBasic
+ clangFormat
+ clangTooling
+ clangToolingCore
+ )
Index: migrate-tool/BuildManager.h
===================================================================
--- /dev/null
+++ migrate-tool/BuildManager.h
@@ -0,0 +1,39 @@
+//===-- BuildManager.h - Manages build targets ------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_MIGRATE_TOOL_BUILDMANAGER_H
+#define LLVM_CLANG_TOOLS_EXTRA_MIGRATE_TOOL_BUILDMANAGER_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace clang {
+namespace migrate_tool {
+
+// This defines interfaces for a codebase-dependent build manager.
+class BuildManager {
+public:
+ // Adds a new library build target with \p Sources as source files. The name
+ // of the new library will be \p Name if it is provided; otherwise, the name
+ // will be auto-generated.
+ virtual bool addLibrary(llvm::ArrayRef<std::string> Sources,
+ llvm::StringRef Name = llvm::StringRef()) = 0;
+
+ // Adds a new dependency to the build target.
+ virtual bool addDependency(llvm::StringRef BuildTarget,
+ llvm::StringRef Dependency) = 0;
+
+ // Returns the name of the build target containing \p File.
+ virtual std::string getBuildTargetForFile(llvm::StringRef File) = 0;
+};
+
+} // namespace migrate_tool
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_MIGRATE_TOOL_BUILDMANAGER_H
Index: migrate-tool/AffectedFilesFinder.h
===================================================================
--- /dev/null
+++ migrate-tool/AffectedFilesFinder.h
@@ -0,0 +1,33 @@
+//===-- AffectedFilesFinder.h - Finds files affected by a refactor.-*- C++ -*=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_MIGRATE_TOOL_AFFECTEDFILESINGFINDER_H
+#define LLVM_CLANG_TOOLS_EXTRA_MIGRATE_TOOL_AFFECTEDFILESINGFINDER_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Error.h"
+#include <vector>
+
+namespace clang {
+namespace migrate_tool {
+
+// This defines interface for finding files that are affected by a refactoring
+// action, e.g. renaming a symbol.
+class AffectedFilesFinder {
+public:
+ // Get all files that need to be updated when a symbol is renamed and/or
+ // moved.
+ virtual llvm::Expected<std::vector<std::string>>
+ getAffectedFiles(llvm::StringRef Symbol) = 0;
+};
+
+} // namespace migrate_tool
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_MIGRATE_TOOL_AFFECTEDFILESINGFINDER_H
Index: CMakeLists.txt
===================================================================
--- CMakeLists.txt
+++ CMakeLists.txt
@@ -1,6 +1,7 @@
add_subdirectory(clang-apply-replacements)
add_subdirectory(clang-rename)
add_subdirectory(clang-reorder-fields)
+add_subdirectory(migrate-tool)
add_subdirectory(modularize)
if(CLANG_ENABLE_STATIC_ANALYZER)
add_subdirectory(clang-tidy)
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits