Home | History | Annotate | Download | only in Tooling
      1 //===--- Tooling.h - Framework for standalone Clang tools -------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 //  This file implements functions to run clang tools standalone instead
     11 //  of running them as a plugin.
     12 //
     13 //  A ClangTool is initialized with a CompilationDatabase and a set of files
     14 //  to run over. The tool will then run a user-specified FrontendAction over
     15 //  all TUs in which the given files are compiled.
     16 //
     17 //  It is also possible to run a FrontendAction over a snippet of code by
     18 //  calling runToolOnCode, which is useful for unit testing.
     19 //
     20 //  Applications that need more fine grained control over how to run
     21 //  multiple FrontendActions over code can use ToolInvocation.
     22 //
     23 //  Example tools:
     24 //  - running clang -fsyntax-only over source code from an editor to get
     25 //    fast syntax checks
     26 //  - running match/replace tools over C++ code
     27 //
     28 //===----------------------------------------------------------------------===//
     29 
     30 #ifndef LLVM_CLANG_TOOLING_TOOLING_H
     31 #define LLVM_CLANG_TOOLING_TOOLING_H
     32 
     33 #include "clang/Basic/FileManager.h"
     34 #include "clang/Basic/LLVM.h"
     35 #include "clang/Driver/Util.h"
     36 #include "clang/Frontend/FrontendAction.h"
     37 #include "clang/Tooling/ArgumentsAdjusters.h"
     38 #include "clang/Tooling/CompilationDatabase.h"
     39 #include "llvm/ADT/StringMap.h"
     40 #include "llvm/ADT/Twine.h"
     41 #include <string>
     42 #include <vector>
     43 
     44 namespace clang {
     45 
     46 namespace driver {
     47 class Compilation;
     48 } // end namespace driver
     49 
     50 class CompilerInvocation;
     51 class SourceManager;
     52 class FrontendAction;
     53 
     54 namespace tooling {
     55 
     56 /// \brief Interface to generate clang::FrontendActions.
     57 class FrontendActionFactory {
     58 public:
     59   virtual ~FrontendActionFactory();
     60 
     61   /// \brief Returns a new clang::FrontendAction.
     62   ///
     63   /// The caller takes ownership of the returned action.
     64   virtual clang::FrontendAction *create() = 0;
     65 };
     66 
     67 /// \brief Returns a new FrontendActionFactory for a given type.
     68 ///
     69 /// T must extend clang::FrontendAction.
     70 ///
     71 /// Example:
     72 /// FrontendActionFactory *Factory =
     73 ///   newFrontendActionFactory<clang::SyntaxOnlyAction>();
     74 template <typename T>
     75 FrontendActionFactory *newFrontendActionFactory();
     76 
     77 /// \brief Called at the end of each source file when used with
     78 /// \c newFrontendActionFactory.
     79 class EndOfSourceFileCallback {
     80 public:
     81   virtual ~EndOfSourceFileCallback() {}
     82   virtual void run() = 0;
     83 };
     84 
     85 /// \brief Returns a new FrontendActionFactory for any type that provides an
     86 /// implementation of newASTConsumer().
     87 ///
     88 /// FactoryT must implement: ASTConsumer *newASTConsumer().
     89 ///
     90 /// Example:
     91 /// struct ProvidesASTConsumers {
     92 ///   clang::ASTConsumer *newASTConsumer();
     93 /// } Factory;
     94 /// FrontendActionFactory *FactoryAdapter =
     95 ///   newFrontendActionFactory(&Factory);
     96 template <typename FactoryT>
     97 inline FrontendActionFactory *newFrontendActionFactory(
     98     FactoryT *ConsumerFactory, EndOfSourceFileCallback *EndCallback = NULL);
     99 
    100 /// \brief Runs (and deletes) the tool on 'Code' with the -fsyntax-only flag.
    101 ///
    102 /// \param ToolAction The action to run over the code.
    103 /// \param Code C++ code.
    104 /// \param FileName The file name which 'Code' will be mapped as.
    105 ///
    106 /// \return - True if 'ToolAction' was successfully executed.
    107 bool runToolOnCode(clang::FrontendAction *ToolAction, const Twine &Code,
    108                    const Twine &FileName = "input.cc");
    109 
    110 /// \brief Runs (and deletes) the tool on 'Code' with the -fsyntax-only flag and
    111 ///        with additional other flags.
    112 ///
    113 /// \param ToolAction The action to run over the code.
    114 /// \param Code C++ code.
    115 /// \param Args Additional flags to pass on.
    116 /// \param FileName The file name which 'Code' will be mapped as.
    117 ///
    118 /// \return - True if 'ToolAction' was successfully executed.
    119 bool runToolOnCodeWithArgs(clang::FrontendAction *ToolAction, const Twine &Code,
    120                            const std::vector<std::string> &Args,
    121                            const Twine &FileName = "input.cc");
    122 
    123 /// \brief Utility to run a FrontendAction in a single clang invocation.
    124 class ToolInvocation {
    125  public:
    126   /// \brief Create a tool invocation.
    127   ///
    128   /// \param CommandLine The command line arguments to clang. Note that clang
    129   /// uses its binary name (CommandLine[0]) to locate its builtin headers.
    130   /// Callers have to ensure that they are installed in a compatible location
    131   /// (see clang driver implementation) or mapped in via mapVirtualFile.
    132   /// \param ToolAction The action to be executed. Class takes ownership.
    133   /// \param Files The FileManager used for the execution. Class does not take
    134   /// ownership.
    135   ToolInvocation(ArrayRef<std::string> CommandLine, FrontendAction *ToolAction,
    136                  FileManager *Files);
    137 
    138   /// \brief Map a virtual file to be used while running the tool.
    139   ///
    140   /// \param FilePath The path at which the content will be mapped.
    141   /// \param Content A null terminated buffer of the file's content.
    142   void mapVirtualFile(StringRef FilePath, StringRef Content);
    143 
    144   /// \brief Run the clang invocation.
    145   ///
    146   /// \returns True if there were no errors during execution.
    147   bool run();
    148 
    149  private:
    150   void addFileMappingsTo(SourceManager &SourceManager);
    151 
    152   bool runInvocation(const char *BinaryName,
    153                      clang::driver::Compilation *Compilation,
    154                      clang::CompilerInvocation *Invocation);
    155 
    156   std::vector<std::string> CommandLine;
    157   OwningPtr<FrontendAction> ToolAction;
    158   FileManager *Files;
    159   // Maps <file name> -> <file content>.
    160   llvm::StringMap<StringRef> MappedFileContents;
    161 };
    162 
    163 /// \brief Utility to run a FrontendAction over a set of files.
    164 ///
    165 /// This class is written to be usable for command line utilities.
    166 /// By default the class uses ClangSyntaxOnlyAdjuster to modify
    167 /// command line arguments before the arguments are used to run
    168 /// a frontend action. One could install another command line
    169 /// arguments adjuster by call setArgumentsAdjuster() method.
    170 class ClangTool {
    171  public:
    172   /// \brief Constructs a clang tool to run over a list of files.
    173   ///
    174   /// \param Compilations The CompilationDatabase which contains the compile
    175   ///        command lines for the given source paths.
    176   /// \param SourcePaths The source files to run over. If a source files is
    177   ///        not found in Compilations, it is skipped.
    178   ClangTool(const CompilationDatabase &Compilations,
    179             ArrayRef<std::string> SourcePaths);
    180 
    181   virtual ~ClangTool() {}
    182 
    183   /// \brief Map a virtual file to be used while running the tool.
    184   ///
    185   /// \param FilePath The path at which the content will be mapped.
    186   /// \param Content A null terminated buffer of the file's content.
    187   void mapVirtualFile(StringRef FilePath, StringRef Content);
    188 
    189   /// \brief Install command line arguments adjuster.
    190   ///
    191   /// \param Adjuster Command line arguments adjuster.
    192   void setArgumentsAdjuster(ArgumentsAdjuster *Adjuster);
    193 
    194   /// Runs a frontend action over all files specified in the command line.
    195   ///
    196   /// \param ActionFactory Factory generating the frontend actions. The function
    197   /// takes ownership of this parameter. A new action is generated for every
    198   /// processed translation unit.
    199   virtual int run(FrontendActionFactory *ActionFactory);
    200 
    201   /// \brief Returns the file manager used in the tool.
    202   ///
    203   /// The file manager is shared between all translation units.
    204   FileManager &getFiles() { return Files; }
    205 
    206  private:
    207   // We store compile commands as pair (file name, compile command).
    208   std::vector< std::pair<std::string, CompileCommand> > CompileCommands;
    209 
    210   FileManager Files;
    211   // Contains a list of pairs (<file name>, <file content>).
    212   std::vector< std::pair<StringRef, StringRef> > MappedFileContents;
    213 
    214   OwningPtr<ArgumentsAdjuster> ArgsAdjuster;
    215 };
    216 
    217 template <typename T>
    218 FrontendActionFactory *newFrontendActionFactory() {
    219   class SimpleFrontendActionFactory : public FrontendActionFactory {
    220   public:
    221     virtual clang::FrontendAction *create() { return new T; }
    222   };
    223 
    224   return new SimpleFrontendActionFactory;
    225 }
    226 
    227 template <typename FactoryT>
    228 inline FrontendActionFactory *newFrontendActionFactory(
    229     FactoryT *ConsumerFactory, EndOfSourceFileCallback *EndCallback) {
    230   class FrontendActionFactoryAdapter : public FrontendActionFactory {
    231   public:
    232     explicit FrontendActionFactoryAdapter(FactoryT *ConsumerFactory,
    233                                           EndOfSourceFileCallback *EndCallback)
    234       : ConsumerFactory(ConsumerFactory), EndCallback(EndCallback) {}
    235 
    236     virtual clang::FrontendAction *create() {
    237       return new ConsumerFactoryAdaptor(ConsumerFactory, EndCallback);
    238     }
    239 
    240   private:
    241     class ConsumerFactoryAdaptor : public clang::ASTFrontendAction {
    242     public:
    243       ConsumerFactoryAdaptor(FactoryT *ConsumerFactory,
    244                              EndOfSourceFileCallback *EndCallback)
    245         : ConsumerFactory(ConsumerFactory), EndCallback(EndCallback) {}
    246 
    247       clang::ASTConsumer *CreateASTConsumer(clang::CompilerInstance &,
    248                                             StringRef) {
    249         return ConsumerFactory->newASTConsumer();
    250       }
    251 
    252     protected:
    253       virtual void EndSourceFileAction() {
    254         if (EndCallback != NULL)
    255           EndCallback->run();
    256         clang::ASTFrontendAction::EndSourceFileAction();
    257       }
    258 
    259     private:
    260       FactoryT *ConsumerFactory;
    261       EndOfSourceFileCallback *EndCallback;
    262     };
    263     FactoryT *ConsumerFactory;
    264     EndOfSourceFileCallback *EndCallback;
    265   };
    266 
    267   return new FrontendActionFactoryAdapter(ConsumerFactory, EndCallback);
    268 }
    269 
    270 /// \brief Returns the absolute path of \c File, by prepending it with
    271 /// the current directory if \c File is not absolute.
    272 ///
    273 /// Otherwise returns \c File.
    274 /// If 'File' starts with "./", the returned path will not contain the "./".
    275 /// Otherwise, the returned path will contain the literal path-concatenation of
    276 /// the current directory and \c File.
    277 ///
    278 /// The difference to llvm::sys::fs::make_absolute is that we prefer
    279 /// ::getenv("PWD") if available.
    280 /// FIXME: Make this functionality available from llvm::sys::fs and delete
    281 ///        this function.
    282 ///
    283 /// \param File Either an absolute or relative path.
    284 std::string getAbsolutePath(StringRef File);
    285 
    286 } // end namespace tooling
    287 } // end namespace clang
    288 
    289 #endif // LLVM_CLANG_TOOLING_TOOLING_H
    290