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) @@ -24,4 +25,3 @@ if( CLANG_TOOLS_EXTRA_INCLUDE_DOCS ) add_subdirectory(docs) endif() - 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: clang-refactor/driver/CMakeLists.txt =================================================================== --- /dev/null +++ clang-refactor/driver/CMakeLists.txt @@ -0,0 +1,19 @@ +set(LLVM_LINK_COMPONENTS + Support + ) + +add_clang_executable(clang-refactor + Driver.cpp + + ModuleManager.cpp + ) + +target_link_libraries(clang-refactor + clangAST + clangASTMatchers + clangBasic + clangFrontend + clangTooling + + clangRefactorModuleCore + ) Index: clang-refactor/driver/Driver.cpp =================================================================== --- /dev/null +++ clang-refactor/driver/Driver.cpp @@ -0,0 +1,48 @@ +//===--- 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 { + +static int printHelpMessage(ModuleManager &Manager) { + llvm::outs() << Manager.getTopLevelHelp(); + return 1; +} + +int clangRefactorMain(int argc, const char **argv) { + ModuleManager Manager; + if (argc > 1) { + llvm::StringRef FirstArgument(argv[1]); + if (FirstArgument == "-h" || FirstArgument == "-help" || + FirstArgument == "--help") + return printHelpMessage(Manager); + const std::string Command = argv[1]; + argv[1] = (llvm::Twine(argv[0]) + " " + llvm::Twine(argv[1])).str().c_str(); + Manager.Dispatch(Command, argc - 1, argv + 1); + } else { + return printHelpMessage(Manager); + } + 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/ModuleManager.h =================================================================== --- /dev/null +++ clang-refactor/driver/ModuleManager.h @@ -0,0 +1,46 @@ +//===--- 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 "core/RefactoringModule.h" + +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/StringRef.h" + +#include +#include +#include + +namespace clang { +namespace refactor { + +class ModuleManager { +public: + void AddModule(StringRef Command, std::unique_ptr Module); + + int Dispatch(StringRef Command, int argc, const char **argv); + + std::string getTopLevelHelp(); + +private: + std::vector> RegisteredModules; + std::unordered_map CommandToModuleID; + + const std::string HelpHead = "USAGE: clang-refactor [subcommand] [options] " + " [... ]\n" + "\n" + "Subcommands:\n"; +}; + +} // 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,38 @@ +//===--- 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 Module) { + RegisteredModules.push_back(std::move(Module)); + CommandToModuleID[Command] = RegisteredModules.size() - 1; +} + +int ModuleManager::Dispatch(StringRef Command, int argc, const char **argv) { + auto it = CommandToModuleID.find(Command); + if (it != CommandToModuleID.end()) { + return RegisteredModules[it->second]->run(argc, argv); + } + return 1; +} + +std::string ModuleManager::getTopLevelHelp() { + std::string Result = HelpHead; + for (const auto &Module : RegisteredModules) { + Result += std::string(Module->getModuleName()); + } + return Result; +} + +} // end namespace refactor +} // end namespace clang Index: clang-refactor/modules/CMakeLists.txt =================================================================== --- /dev/null +++ clang-refactor/modules/CMakeLists.txt @@ -0,0 +1,3 @@ +include_directories(core) + +add_subdirectory(core) Index: clang-refactor/modules/core/CMakeLists.txt =================================================================== --- /dev/null +++ clang-refactor/modules/core/CMakeLists.txt @@ -0,0 +1,12 @@ +add_clang_library(clangRefactorModuleCore + RefactoringModule.cpp + + LINK_LIBS + clangAST + clangASTMatchers + clangBasic + clangFrontend + clangLex + clangTooling + clangToolingCore + ) Index: clang-refactor/modules/core/RefactoringModule.h =================================================================== --- /dev/null +++ clang-refactor/modules/core/RefactoringModule.h @@ -0,0 +1,142 @@ +//===--- 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/CompilationDatabase.h" +#include "clang/Tooling/Refactoring.h" +#include "clang/Tooling/Tooling.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/ErrorOr.h" +#include "llvm/Support/MemoryBuffer.h" +#include "clang/Basic/Diagnostic.h" +#include "llvm/Support/Signals.h" +#include + +namespace clang { +namespace refactor { + +class RefactoringModule { +public: + RefactoringModule(const std::string &ModuleName, + const std::string &ModuleMetaDescription) + : ModuleName(ModuleName), ModuleMetaDescription(ModuleMetaDescription) {} + + //===--------------------------------------------------------------------===// + // Refactoring cosists of 3 stages. + // + //===--------------------------------------------------------------------===// + // + // Stage I: Plan execution. + // + // In this stage the submodule parses arguments, determines whether the + // refactoring invokation is correct and stores information neeeded to perform + // that refactoring in each affected translation unit. + // + // Input: Command line (?) arguments. + // + // Ouput: List of affected translation units, in which the refactoring would + // happen, and submodule-specific information needed for the execution. + // + // Has access to: AST belongs to, cross-reference index. + // + //===--------------------------------------------------------------------===// + // + // Stage II: Running on a single translation unit. + // + // Input: submodule-specific information needed for the execution from + // Stage I. + // + // Output: list of replacements and diagnostics. + // + // Has access to: AST of given translation unit. + // + //===--------------------------------------------------------------------===// + // + // Stage III: Apply replacements and output diagnostics. + // + // This step is not submodule-specific. Therefore, it should be delegated to + // the common interface. + // + // Input: Replacements and diagnostics from stage II. + // + // Output: Applied replacements and issued diagnostics. + // + //===--------------------------------------------------------------------===// + + int run(int argc, const char **argv); + + // Routine for registering common refactoring options. + // + // Common options reused by multiple tools like "-offset", "verbose" etc + // should go here. + 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) = 0; + + //===--------------------------------------------------------------------===// + // Stage I: Plan execution. + + // This processes given translation unit of and retrieves + // information needed for the refactoring. + // + // Input: ASTContext of translation unit belongs to. + // + // Output: Serialized refactoring-specific information; + virtual std::string getExecutionInformation() = 0; + + // Return translation units affected by certain refactoring. As a temporary + // solution it can return all translation units, regardless of them being + // affected by refactoring. + // + // Input: Serialized refactroing-specific information. + // + // Output: List of translation units. + virtual std::vector getAffectedTUs(tooling::CompilationDatabase, + std::string RefactoringInfo); + //===--------------------------------------------------------------------===// + + //===--------------------------------------------------------------------===// + // Stage II: Running on a single translation unit. + virtual llvm::ErrorOr< + std::pair>> + handleTranslationUnit() = 0; + //===--------------------------------------------------------------------===// + + //===--------------------------------------------------------------------===// + // Stage III: Apply replacements and output diagnostics. + llvm::Error + applyReplacementsAndOutputDiagnostics(tooling::Replacements Replacements, + std::vector Diags); + //===--------------------------------------------------------------------===// + + StringRef getModuleName(); + StringRef getModuleMetaDescription(); + + virtual ~RefactoringModule() = default; + +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/core/RefactoringModule.cpp =================================================================== --- /dev/null +++ clang-refactor/modules/core/RefactoringModule.cpp @@ -0,0 +1,47 @@ +//===--- RefactoringModule.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 "RefactoringModule.h" + +namespace clang { +namespace refactor { + +int RefactoringModule::run(int argc, const char **argv) { + return 0; +} + +void RefactoringModule::registerCommonOptions( + llvm::cl::OptionCategory &Category) {} + +std::vector +RefactoringModule::getAffectedTUs(tooling::CompilationDatabase DB, + std::string RefactoringInfo) { + std::vector TranslationUnits; + // FIXME: Don't return all files; return one file per translation unit. + TranslationUnits = DB.getAllFiles(); + return TranslationUnits; +} + +StringRef RefactoringModule::getModuleName() { return ModuleName; } + +StringRef RefactoringModule::getModuleMetaDescription() { + return ModuleMetaDescription; +} + +llvm::Error RefactoringModule::applyReplacementsAndOutputDiagnostics( + tooling::Replacements Replacements, + std::vector Diags) { + llvm::Error Err; + // TODO: Issue diagnostics. + // TODO: Apply replacements. + return Err; +} + +} // end namespace refactor +} // end namespace clang