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 Callbacks called before and after each source file processed by a
     78 /// FrontendAction created by the FrontedActionFactory returned by \c
     79 /// newFrontendActionFactory.
     80 class SourceFileCallbacks {
     81 public:
     82   virtual ~SourceFileCallbacks() {}
     83 
     84   /// \brief Called before a source file is processed by a FrontEndAction.
     85   /// \see clang::FrontendAction::BeginSourceFileAction
     86   virtual bool handleBeginSource(CompilerInstance &CI, StringRef Filename) {
     87     return true;
     88   }
     89 
     90   /// \brief Called after a source file is processed by a FrontendAction.
     91   /// \see clang::FrontendAction::EndSourceFileAction
     92   virtual void handleEndSource() {}
     93 };
     94 
     95 /// \brief Returns a new FrontendActionFactory for any type that provides an
     96 /// implementation of newASTConsumer().
     97 ///
     98 /// FactoryT must implement: ASTConsumer *newASTConsumer().
     99 ///
    100 /// Example:
    101 /// struct ProvidesASTConsumers {
    102 ///   clang::ASTConsumer *newASTConsumer();
    103 /// } Factory;
    104 /// FrontendActionFactory *FactoryAdapter =
    105 ///   newFrontendActionFactory(&Factory);
    106 template <typename FactoryT>
    107 inline FrontendActionFactory *newFrontendActionFactory(
    108     FactoryT *ConsumerFactory, SourceFileCallbacks *Callbacks = NULL);
    109 
    110 /// \brief Runs (and deletes) the tool on 'Code' with the -fsyntax-only flag.
    111 ///
    112 /// \param ToolAction The action to run over the code.
    113 /// \param Code C++ code.
    114 /// \param FileName The file name which 'Code' will be mapped as.
    115 ///
    116 /// \return - True if 'ToolAction' was successfully executed.
    117 bool runToolOnCode(clang::FrontendAction *ToolAction, const Twine &Code,
    118                    const Twine &FileName = "input.cc");
    119 
    120 /// \brief Runs (and deletes) the tool on 'Code' with the -fsyntax-only flag and
    121 ///        with additional other flags.
    122 ///
    123 /// \param ToolAction The action to run over the code.
    124 /// \param Code C++ code.
    125 /// \param Args Additional flags to pass on.
    126 /// \param FileName The file name which 'Code' will be mapped as.
    127 ///
    128 /// \return - True if 'ToolAction' was successfully executed.
    129 bool runToolOnCodeWithArgs(clang::FrontendAction *ToolAction, const Twine &Code,
    130                            const std::vector<std::string> &Args,
    131                            const Twine &FileName = "input.cc");
    132 
    133 /// \brief Utility to run a FrontendAction in a single clang invocation.
    134 class ToolInvocation {
    135  public:
    136   /// \brief Create a tool invocation.
    137   ///
    138   /// \param CommandLine The command line arguments to clang. Note that clang
    139   /// uses its binary name (CommandLine[0]) to locate its builtin headers.
    140   /// Callers have to ensure that they are installed in a compatible location
    141   /// (see clang driver implementation) or mapped in via mapVirtualFile.
    142   /// \param ToolAction The action to be executed. Class takes ownership.
    143   /// \param Files The FileManager used for the execution. Class does not take
    144   /// ownership.
    145   ToolInvocation(ArrayRef<std::string> CommandLine, FrontendAction *ToolAction,
    146                  FileManager *Files);
    147 
    148   /// \brief Map a virtual file to be used while running the tool.
    149   ///
    150   /// \param FilePath The path at which the content will be mapped.
    151   /// \param Content A null terminated buffer of the file's content.
    152   void mapVirtualFile(StringRef FilePath, StringRef Content);
    153 
    154   /// \brief Run the clang invocation.
    155   ///
    156   /// \returns True if there were no errors during execution.
    157   bool run();
    158 
    159  private:
    160   void addFileMappingsTo(SourceManager &SourceManager);
    161 
    162   bool runInvocation(const char *BinaryName,
    163                      clang::driver::Compilation *Compilation,
    164                      clang::CompilerInvocation *Invocation);
    165 
    166   std::vector<std::string> CommandLine;
    167   OwningPtr<FrontendAction> ToolAction;
    168   FileManager *Files;
    169   // Maps <file name> -> <file content>.
    170   llvm::StringMap<StringRef> MappedFileContents;
    171 };
    172 
    173 /// \brief Utility to run a FrontendAction over a set of files.
    174 ///
    175 /// This class is written to be usable for command line utilities.
    176 /// By default the class uses ClangSyntaxOnlyAdjuster to modify
    177 /// command line arguments before the arguments are used to run
    178 /// a frontend action. One could install an additional command line
    179 /// arguments adjuster by calling the appendArgumentsAdjuster() method.
    180 class ClangTool {
    181  public:
    182   /// \brief Constructs a clang tool to run over a list of files.
    183   ///
    184   /// \param Compilations The CompilationDatabase which contains the compile
    185   ///        command lines for the given source paths.
    186   /// \param SourcePaths The source files to run over. If a source files is
    187   ///        not found in Compilations, it is skipped.
    188   ClangTool(const CompilationDatabase &Compilations,
    189             ArrayRef<std::string> SourcePaths);
    190 
    191   virtual ~ClangTool() { clearArgumentsAdjusters(); }
    192 
    193   /// \brief Map a virtual file to be used while running the tool.
    194   ///
    195   /// \param FilePath The path at which the content will be mapped.
    196   /// \param Content A null terminated buffer of the file's content.
    197   void mapVirtualFile(StringRef FilePath, StringRef Content);
    198 
    199   /// \brief Install command line arguments adjuster.
    200   ///
    201   /// \param Adjuster Command line arguments adjuster.
    202   //
    203   /// FIXME: Function is deprecated. Use (clear/append)ArgumentsAdjuster instead.
    204   /// Remove it once all callers are gone.
    205   void setArgumentsAdjuster(ArgumentsAdjuster *Adjuster);
    206 
    207   /// \brief Append a command line arguments adjuster to the adjuster chain.
    208   ///
    209   /// \param Adjuster An argument adjuster, which will be run on the output of
    210   ///        previous argument adjusters.
    211   void appendArgumentsAdjuster(ArgumentsAdjuster *Adjuster);
    212 
    213   /// \brief Clear the command line arguments adjuster chain.
    214   void clearArgumentsAdjusters();
    215 
    216   /// Runs a frontend action over all files specified in the command line.
    217   ///
    218   /// \param ActionFactory Factory generating the frontend actions. The function
    219   /// takes ownership of this parameter. A new action is generated for every
    220   /// processed translation unit.
    221   virtual int run(FrontendActionFactory *ActionFactory);
    222 
    223   /// \brief Returns the file manager used in the tool.
    224   ///
    225   /// The file manager is shared between all translation units.
    226   FileManager &getFiles() { return Files; }
    227 
    228  private:
    229   // We store compile commands as pair (file name, compile command).
    230   std::vector< std::pair<std::string, CompileCommand> > CompileCommands;
    231 
    232   FileManager Files;
    233   // Contains a list of pairs (<file name>, <file content>).
    234   std::vector< std::pair<StringRef, StringRef> > MappedFileContents;
    235 
    236   SmallVector<ArgumentsAdjuster *, 2> ArgsAdjusters;
    237 };
    238 
    239 template <typename T>
    240 FrontendActionFactory *newFrontendActionFactory() {
    241   class SimpleFrontendActionFactory : public FrontendActionFactory {
    242   public:
    243     virtual clang::FrontendAction *create() { return new T; }
    244   };
    245 
    246   return new SimpleFrontendActionFactory;
    247 }
    248 
    249 template <typename FactoryT>
    250 inline FrontendActionFactory *newFrontendActionFactory(
    251     FactoryT *ConsumerFactory, SourceFileCallbacks *Callbacks) {
    252   class FrontendActionFactoryAdapter : public FrontendActionFactory {
    253   public:
    254     explicit FrontendActionFactoryAdapter(FactoryT *ConsumerFactory,
    255                                           SourceFileCallbacks *Callbacks)
    256       : ConsumerFactory(ConsumerFactory), Callbacks(Callbacks) {}
    257 
    258     virtual clang::FrontendAction *create() {
    259       return new ConsumerFactoryAdaptor(ConsumerFactory, Callbacks);
    260     }
    261 
    262   private:
    263     class ConsumerFactoryAdaptor : public clang::ASTFrontendAction {
    264     public:
    265       ConsumerFactoryAdaptor(FactoryT *ConsumerFactory,
    266                              SourceFileCallbacks *Callbacks)
    267         : ConsumerFactory(ConsumerFactory), Callbacks(Callbacks) {}
    268 
    269       clang::ASTConsumer *CreateASTConsumer(clang::CompilerInstance &,
    270                                             StringRef) {
    271         return ConsumerFactory->newASTConsumer();
    272       }
    273 
    274     protected:
    275       virtual bool BeginSourceFileAction(CompilerInstance &CI,
    276                                          StringRef Filename) LLVM_OVERRIDE {
    277         if (!clang::ASTFrontendAction::BeginSourceFileAction(CI, Filename))
    278           return false;
    279         if (Callbacks != NULL)
    280           return Callbacks->handleBeginSource(CI, Filename);
    281         return true;
    282       }
    283       virtual void EndSourceFileAction() LLVM_OVERRIDE {
    284         if (Callbacks != NULL)
    285           Callbacks->handleEndSource();
    286         clang::ASTFrontendAction::EndSourceFileAction();
    287       }
    288 
    289     private:
    290       FactoryT *ConsumerFactory;
    291       SourceFileCallbacks *Callbacks;
    292     };
    293     FactoryT *ConsumerFactory;
    294     SourceFileCallbacks *Callbacks;
    295   };
    296 
    297   return new FrontendActionFactoryAdapter(ConsumerFactory, Callbacks);
    298 }
    299 
    300 /// \brief Returns the absolute path of \c File, by prepending it with
    301 /// the current directory if \c File is not absolute.
    302 ///
    303 /// Otherwise returns \c File.
    304 /// If 'File' starts with "./", the returned path will not contain the "./".
    305 /// Otherwise, the returned path will contain the literal path-concatenation of
    306 /// the current directory and \c File.
    307 ///
    308 /// The difference to llvm::sys::fs::make_absolute is that we prefer
    309 /// ::getenv("PWD") if available.
    310 /// FIXME: Make this functionality available from llvm::sys::fs and delete
    311 ///        this function.
    312 ///
    313 /// \param File Either an absolute or relative path.
    314 std::string getAbsolutePath(StringRef File);
    315 
    316 } // end namespace tooling
    317 } // end namespace clang
    318 
    319 #endif // LLVM_CLANG_TOOLING_TOOLING_H
    320