//===---- tools/extra/ToolTemplate.cpp - Template for refactoring tool ----===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file implements an empty refactoring tool using the clang tooling. // The goal is to lower the "barrier to entry" for writing refactoring tools. // // Usage: // tool-template ... // // Where is a CMake build directory in which a file named // compile_commands.json exists (enable -DCMAKE_EXPORT_COMPILE_COMMANDS in // CMake to get this output). // // ... specify the paths of files in the CMake source tree. This path // is looked up in the compile command database. If the path of a file is // absolute, it needs to point into CMake's source tree. If the path is // relative, the current working directory needs to be in the CMake source // tree and the file must be in a subdirectory of the current working // directory. "./" prefixes in the relative files will be automatically // removed, but the rest of a relative path must be a suffix of a path in // the compile command line database. // // For example, to use tool-template on all files in a subtree of the // source tree, use: // // /path/in/subtree $ find . -name '*.cpp'| // xargs tool-template /path/to/build // //===----------------------------------------------------------------------===// #include "clang/ASTMatchers/ASTMatchers.h" #include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/Basic/SourceManager.h" #include "clang/Frontend/FrontendActions.h" #include "clang/Lex/Lexer.h" #include "clang/Tooling/CompilationDatabase.h" #include "clang/Tooling/Refactoring.h" #include "clang/Tooling/Tooling.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Signals.h" using namespace clang; using namespace clang::ast_matchers; using namespace clang::tooling; using namespace llvm; namespace { class ToolTemplateCallback : public MatchFinder::MatchCallback { public: ToolTemplateCallback(Replacements *Replace) : Replace(Replace) {} virtual void run(const MatchFinder::MatchResult &Result) { // TODO: This routine will get called for each thing that the matchers find. // At this point, you can examine the match, and do whatever you want, // including replacing the matched text with other text (void) Replace; // This to prevent an "unused member variable" warning; } private: Replacements *Replace; }; } // end anonymous namespace // Set up the command line options cl::opt BuildPath( cl::Positional, cl::desc("")); cl::list SourcePaths( cl::Positional, cl::desc(" [... ]"), cl::OneOrMore); int main(int argc, const char **argv) { llvm::sys::PrintStackTraceOnErrorSignal(); std::unique_ptr Compilations( FixedCompilationDatabase::loadFromCommandLine(argc, argv)); cl::ParseCommandLineOptions(argc, argv); if (!Compilations) { // Couldn't find a compilation DB from the command line std::string ErrorMessage; Compilations.reset( !BuildPath.empty() ? CompilationDatabase::autoDetectFromDirectory(BuildPath, ErrorMessage) : CompilationDatabase::autoDetectFromSource(SourcePaths[0], ErrorMessage) ); // Still no compilation DB? - bail. if (!Compilations) llvm::report_fatal_error(ErrorMessage); } RefactoringTool Tool(*Compilations, SourcePaths); ast_matchers::MatchFinder Finder; ToolTemplateCallback Callback(&Tool.getReplacements()); // TODO: Put your matchers here. // Use Finder.addMatcher(...) to define the patterns in the AST that you // want to match against. You are not limited to just one matcher! return Tool.run(newFrontendActionFactory(&Finder).get()); }