omtcyfz updated this revision to Diff 70397.
omtcyfz marked 11 inline comments as done.
omtcyfz added a comment.
Addressing a round of comments.
https://reviews.llvm.org/D24192
Files:
CMakeLists.txt
clang-refactor/CMakeLists.txt
clang-refactor/driver/CMakeLists.txt
clang-refactor/driver/Driver.cpp
clang-refactor/driver/ModuleManager.cpp
clang-refactor/driver/ModuleManager.h
clang-refactor/modules/CMakeLists.txt
clang-refactor/modules/core/RefactoringModule.h
Index: clang-refactor/modules/core/RefactoringModule.h
===================================================================
--- /dev/null
+++ clang-refactor/modules/core/RefactoringModule.h
@@ -0,0 +1,169 @@
+//===--- RefactoringModule.h - clang-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_CLANG_REFACTOR_REFACTORING_MODULE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_REFACTOR_REFACTORING_MODULE_H
+
+#include "clang/Tooling/CommonOptionsParser.h"
+#include "clang/Tooling/Refactoring.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Signals.h"
+
+#include <string>
+
+namespace clang {
+namespace refactor {
+
+class RefactoringModule {
+public:
+ RefactoringModule(const std::string &ModuleName,
+ const std::string &ModuleMetaDescription)
+ : ModuleName(ModuleName), ModuleMetaDescription(ModuleMetaDescription) {}
+
+ // Refactoring consists of 3.5 stages:
+ //
+ // 0. Check arguments for validity.
+ //
+ // 1. Extract infromation needed for the refactoring upon tool invocation.
+ //
+ // 2. Handle translation unit and identify whether the refactoring can be
+ // applied. If it can, store the replacements. Panic otherwise.
+ //
+ // 3. Merge duplicate replacements, panic if there are conflicting ones.
+ // Process translation unit and apply refactoring.
+ //
+ // Few examples of how each of these stages would look like for future
+ // modules "rename" and "inline".
+ //
+ // Rename
+ // ======
+ //
+ // 0. Check arguments for validity.
+ //
+ // 1. Rename operates with USRs, so the first stage would be finding the
+ // symbol, which will be renamed and storing its USR.
+ //
+ // 2. Check whether renaming will introduce any name conflicts. If it won't
+ // find each occurance of the symbol in translation unit using USR and store
+ // replacements.
+ //
+ // 3. Apply replacements or output diagnostics. Handle duplicates and panic if
+ // there are conflicts.
+ //
+ // Inline
+ // ======
+ //
+ // 0. Check arguments for validity.
+ //
+ // 1. Find function, identify what the possible issues might be.
+ //
+ // 2. Check whether inlining will introduce any issues, e.g. there is a
+ // pointer passed somewhere to the inlined function and after inlining it the
+ // code will no longer compile. If it won't find function calls, add needed
+ // temprorary variables and replace the call with function body.
+ //
+ // 3. Apply replacements. Handle duplicates and panic if there are conflicts.
+ //
+ // Summary
+ // =======
+ //
+ // As one can easily see, step 1 should be performed upon module invocation
+ // and it needs to process translation unit, from which the passed <source0>
+ // comes from.
+ //
+ // With appropriate facilities step 2 can be parallelized to process multiple
+ // translation units of the project independently. If none of them have any
+ // issues with applying this refactoring replacements are stored and queued
+ // for later.
+ //
+ // Step 3 can be parallelized even more easily. It basically consists of text
+ // replacements.
+ //
+ int run(int argc, const char **argv) {
+ // Register options.
+ llvm::cl::OptionCategory RefactoringModuleOptions(ModuleName.c_str(),
+ ModuleMetaDescription.c_str());
+ registerCustomOptions(RefactoringModuleOptions);
+ registerCustomOptions(RefactoringModuleOptions);
+ // Parse options and get compilations.
+ llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
+ tooling::CommonOptionsParser OptionsParser(argc, argv,
+ RefactoringModuleOptions);
+ tooling::RefactoringTool Tool(OptionsParser.getCompilations(),
+ OptionsParser.getSourcePathList());
+
+ // Actual routine.
+ checkArguments();
+ extractRefactoringInformation();
+ handleTranslationUnit();
+ applyReplacementsOrOutputDiagnostics();
+ return 0;
+ }
+
+ // Routine for regiestering common modules options.
+ void registerCommonOptions(llvm::cl::OptionCategory &Category) {
+ }
+
+ // A way for each tool to provide additional options. Overriding this one is
+ // optional.
+ virtual void registerCustomOptions(llvm::cl::OptionCategory &Category) {}
+
+ // Step 0.
+ // Just checking arguments.
+ //
+ // Panic: if they are not valid.
+ virtual int checkArguments() = 0;
+
+ // Step 1.
+ //
+ // Process translation <source0> and figure out what should be done.
+ //
+ // Panic: if refactoring can not be applied. E.g. unsupported cases like
+ // renaming macros etc.
+ virtual int extractRefactoringInformation() = 0;
+
+ // Step 2.
+ //
+ // Find places where refactoring should be applied and store replacements for
+ // the future.
+ //
+ // Panic: if there are any issues with applying refactorings to the
+ // translation unit.
+ virtual int handleTranslationUnit() = 0;
+
+ // Step 3.
+ //
+ // Handle duplicates.
+ //
+ // Panic: if there are conflicting replacements.
+ virtual int applyReplacementsOrOutputDiagnostics() = 0;
+
+ virtual ~RefactoringModule() = default;
+
+ StringRef getModuleName() { return ModuleName; }
+
+ StringRef getModuleMetaDescription() { return ModuleMetaDescription; }
+
+private:
+ // ModuleName is the lowercase submodule name, which will be passed to
+ // clang-refactor to invoke the submodule tool.
+ const std::string ModuleName;
+
+ // ModuleMetaDescription will appear as the module description upon calling
+ // $ clang-refactor --help
+ const std::string ModuleMetaDescription;
+};
+
+} // end namespace refactor
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_REFACTOR_REFACTORING_MODULE_H
Index: clang-refactor/modules/CMakeLists.txt
===================================================================
--- /dev/null
+++ clang-refactor/modules/CMakeLists.txt
@@ -0,0 +1 @@
+include_directories(core)
Index: clang-refactor/driver/ModuleManager.h
===================================================================
--- /dev/null
+++ clang-refactor/driver/ModuleManager.h
@@ -0,0 +1,40 @@
+//===--- ModuleManager.h - clang-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_CLANG_REFACTOR_MODULE_MANAGER_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_REFACTOR_MODULE_MANAGER_H
+
+#include "llvm/ADT/StringRef.h"
+
+#include <string>
+#include <vector>
+#include <unordered_map>
+
+#include "core/RefactoringModule.h"
+
+using namespace llvm;
+
+namespace clang {
+namespace refactor {
+
+class ModuleManager {
+public:
+ void AddModule(StringRef Command, std::unique_ptr<RefactoringModule> Module);
+
+ int Dispatch(StringRef Command, int argc, const char **argv);
+
+private:
+ std::vector<std::unique_ptr<RefactoringModule>> RegisteredModules;
+ std::unordered_map<std::string, unsigned> CommandToModuleID;
+};
+
+} // end namespace refactor
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_REFACTOR_MODULE_MANAGER_H
Index: clang-refactor/driver/ModuleManager.cpp
===================================================================
--- /dev/null
+++ clang-refactor/driver/ModuleManager.cpp
@@ -0,0 +1,29 @@
+//===--- ModuleManager.cpp - clang-refactor ---------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ModuleManager.h"
+
+namespace clang {
+namespace refactor {
+
+void ModuleManager::AddModule(StringRef Command,
+ std::unique_ptr<RefactoringModule> Module) {
+ RegisteredModules.push_back(std::move(Module));
+ CommandToModuleID[Command] = RegisteredModules.size() - 1;
+}
+
+int ModuleManager::Dispatch(StringRef Command, int argc, const char **argv) {
+ if (CommandToModuleID.find(Command) != CommandToModuleID.end()) {
+ return RegisteredModules[CommandToModuleID[Command]]->run(argc, argv);
+ }
+ return 1;
+}
+
+} // end namespace refactor
+} // end namespace clang
Index: clang-refactor/driver/Driver.cpp
===================================================================
--- /dev/null
+++ clang-refactor/driver/Driver.cpp
@@ -0,0 +1,55 @@
+//===--- Driver.cpp - clang-refactor ----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file This file implements a clang-refactor tool.
+///
+////===----------------------------------------------------------------------===//
+
+#include "clang/Tooling/CommonOptionsParser.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include "ModuleManager.h"
+
+namespace clang {
+namespace refactor {
+
+const char HelpHead[] = "USAGE: clang-refactor [subcommand] [options] "
+ "<source0> [... <sourceN>]\n"
+ "\n"
+ "Subcommands:\n";
+
+static int printHelpMessage() {
+ llvm::outs() << HelpHead;
+ return 1;
+}
+
+int clangRefactorMain(int argc, const char **argv) {
+ ModuleManager Manager;
+ std::string Command = "";
+ if (argc > 1) {
+ llvm::StringRef FirstArgument(argv[1]);
+ if (FirstArgument == "-h" || FirstArgument == "-help" ||
+ FirstArgument == "--help")
+ return printHelpMessage();
+ Command = argv[1];
+ std::string Invocation = std::string(argv[0]) + " " + argv[1];
+ argv[1] = Invocation.c_str();
+ Manager.Dispatch(Command, argc - 1, argv + 1);
+ } else {
+ return printHelpMessage();
+ }
+ return 0;
+}
+
+} // end namespace refactor
+} // end namespace clang
+
+int main(int argc, const char **argv) {
+ return clang::refactor::clangRefactorMain(argc, argv);
+}
Index: clang-refactor/driver/CMakeLists.txt
===================================================================
--- /dev/null
+++ clang-refactor/driver/CMakeLists.txt
@@ -0,0 +1,17 @@
+set(LLVM_LINK_COMPONENTS
+ Support
+ )
+
+add_clang_executable(clang-refactor
+ Driver.cpp
+
+ ModuleManager.cpp
+ )
+
+target_link_libraries(clang-refactor
+ clangAST
+ clangASTMatchers
+ clangBasic
+ clangFrontend
+ clangTooling
+ )
Index: clang-refactor/CMakeLists.txt
===================================================================
--- /dev/null
+++ clang-refactor/CMakeLists.txt
@@ -0,0 +1,4 @@
+include_directories(modules)
+
+add_subdirectory(driver)
+add_subdirectory(modules)
Index: CMakeLists.txt
===================================================================
--- CMakeLists.txt
+++ CMakeLists.txt
@@ -1,5 +1,6 @@
add_subdirectory(clang-apply-replacements)
add_subdirectory(clang-rename)
+add_subdirectory(clang-refactor)
add_subdirectory(clang-reorder-fields)
add_subdirectory(modularize)
if(CLANG_ENABLE_STATIC_ANALYZER)
@@ -23,4 +24,3 @@
if( CLANG_TOOLS_EXTRA_INCLUDE_DOCS )
add_subdirectory(docs)
endif()
-
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits