clang API Documentation

ASTMatchFinder.h
Go to the documentation of this file.
00001 //===--- ASTMatchFinder.h - Structural query framework ----------*- C++ -*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 //  Provides a way to construct an ASTConsumer that runs given matchers
00011 //  over the AST and invokes a given callback on every match.
00012 //
00013 //  The general idea is to construct a matcher expression that describes a
00014 //  subtree match on the AST. Next, a callback that is executed every time the
00015 //  expression matches is registered, and the matcher is run over the AST of
00016 //  some code. Matched subexpressions can be bound to string IDs and easily
00017 //  be accessed from the registered callback. The callback can than use the
00018 //  AST nodes that the subexpressions matched on to output information about
00019 //  the match or construct changes that can be applied to the code.
00020 //
00021 //  Example:
00022 //  class HandleMatch : public MatchFinder::MatchCallback {
00023 //  public:
00024 //    virtual void Run(const MatchFinder::MatchResult &Result) {
00025 //      const CXXRecordDecl *Class =
00026 //          Result.Nodes.GetDeclAs<CXXRecordDecl>("id");
00027 //      ...
00028 //    }
00029 //  };
00030 //
00031 //  int main(int argc, char **argv) {
00032 //    ClangTool Tool(argc, argv);
00033 //    MatchFinder finder;
00034 //    finder.AddMatcher(Id("id", record(hasName("::a_namespace::AClass"))),
00035 //                      new HandleMatch);
00036 //    return Tool.Run(newFrontendActionFactory(&finder));
00037 //  }
00038 //
00039 //===----------------------------------------------------------------------===//
00040 
00041 #ifndef LLVM_CLANG_ASTMATCHERS_ASTMATCHFINDER_H
00042 #define LLVM_CLANG_ASTMATCHERS_ASTMATCHFINDER_H
00043 
00044 #include "clang/ASTMatchers/ASTMatchers.h"
00045 #include "llvm/ADT/StringMap.h"
00046 #include "llvm/Support/Timer.h"
00047 
00048 namespace clang {
00049 
00050 namespace ast_matchers {
00051 
00052 /// \brief A class to allow finding matches over the Clang AST.
00053 ///
00054 /// After creation, you can add multiple matchers to the MatchFinder via
00055 /// calls to addMatcher(...).
00056 ///
00057 /// Once all matchers are added, newASTConsumer() returns an ASTConsumer
00058 /// that will trigger the callbacks specified via addMatcher(...) when a match
00059 /// is found.
00060 ///
00061 /// The order of matches is guaranteed to be equivalent to doing a pre-order
00062 /// traversal on the AST, and applying the matchers in the order in which they
00063 /// were added to the MatchFinder.
00064 ///
00065 /// See ASTMatchers.h for more information about how to create matchers.
00066 ///
00067 /// Not intended to be subclassed.
00068 class MatchFinder {
00069 public:
00070   /// \brief Contains all information for a given match.
00071   ///
00072   /// Every time a match is found, the MatchFinder will invoke the registered
00073   /// MatchCallback with a MatchResult containing information about the match.
00074   struct MatchResult {
00075     MatchResult(const BoundNodes &Nodes, clang::ASTContext *Context);
00076 
00077     /// \brief Contains the nodes bound on the current match.
00078     ///
00079     /// This allows user code to easily extract matched AST nodes.
00080     const BoundNodes Nodes;
00081 
00082     /// \brief Utilities for interpreting the matched AST structures.
00083     /// @{
00084     clang::ASTContext * const Context;
00085     clang::SourceManager * const SourceManager;
00086     /// @}
00087   };
00088 
00089   /// \brief Called when the Match registered for it was successfully found
00090   /// in the AST.
00091   class MatchCallback {
00092   public:
00093     virtual ~MatchCallback();
00094 
00095     /// \brief Called on every match by the \c MatchFinder.
00096     virtual void run(const MatchResult &Result) = 0;
00097 
00098     /// \brief Called at the start of each translation unit.
00099     ///
00100     /// Optionally override to do per translation unit tasks.
00101     virtual void onStartOfTranslationUnit() {}
00102 
00103     /// \brief Called at the end of each translation unit.
00104     ///
00105     /// Optionally override to do per translation unit tasks.
00106     virtual void onEndOfTranslationUnit() {}
00107 
00108     /// \brief An id used to group the matchers.
00109     ///
00110     /// This id is used, for example, for the profiling output.
00111     /// It defaults to "<unknown>".
00112     virtual StringRef getID() const;
00113   };
00114 
00115   /// \brief Called when parsing is finished. Intended for testing only.
00116   class ParsingDoneTestCallback {
00117   public:
00118     virtual ~ParsingDoneTestCallback();
00119     virtual void run() = 0;
00120   };
00121 
00122   struct MatchFinderOptions {
00123     struct Profiling {
00124       Profiling(llvm::StringMap<llvm::TimeRecord> &Records)
00125           : Records(Records) {}
00126 
00127       /// \brief Per bucket timing information.
00128       llvm::StringMap<llvm::TimeRecord> &Records;
00129     };
00130 
00131     /// \brief Enables per-check timers.
00132     ///
00133     /// It prints a report after match.
00134     llvm::Optional<Profiling> CheckProfiling;
00135   };
00136 
00137   MatchFinder(MatchFinderOptions Options = MatchFinderOptions());
00138   ~MatchFinder();
00139 
00140   /// \brief Adds a matcher to execute when running over the AST.
00141   ///
00142   /// Calls 'Action' with the BoundNodes on every match.
00143   /// Adding more than one 'NodeMatch' allows finding different matches in a
00144   /// single pass over the AST.
00145   ///
00146   /// Does not take ownership of 'Action'.
00147   /// @{
00148   void addMatcher(const DeclarationMatcher &NodeMatch,
00149                   MatchCallback *Action);
00150   void addMatcher(const TypeMatcher &NodeMatch,
00151                   MatchCallback *Action);
00152   void addMatcher(const StatementMatcher &NodeMatch,
00153                   MatchCallback *Action);
00154   void addMatcher(const NestedNameSpecifierMatcher &NodeMatch,
00155                   MatchCallback *Action);
00156   void addMatcher(const NestedNameSpecifierLocMatcher &NodeMatch,
00157                   MatchCallback *Action);
00158   void addMatcher(const TypeLocMatcher &NodeMatch,
00159                   MatchCallback *Action);
00160   /// @}
00161 
00162   /// \brief Adds a matcher to execute when running over the AST.
00163   ///
00164   /// This is similar to \c addMatcher(), but it uses the dynamic interface. It
00165   /// is more flexible, but the lost type information enables a caller to pass
00166   /// a matcher that cannot match anything.
00167   ///
00168   /// \returns \c true if the matcher is a valid top-level matcher, \c false
00169   ///   otherwise.
00170   bool addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch,
00171                          MatchCallback *Action);
00172 
00173   /// \brief Creates a clang ASTConsumer that finds all matches.
00174   std::unique_ptr<clang::ASTConsumer> newASTConsumer();
00175 
00176   /// \brief Calls the registered callbacks on all matches on the given \p Node.
00177   ///
00178   /// Note that there can be multiple matches on a single node, for
00179   /// example when using decl(forEachDescendant(stmt())).
00180   ///
00181   /// @{
00182   template <typename T> void match(const T &Node, ASTContext &Context) {
00183     match(clang::ast_type_traits::DynTypedNode::create(Node), Context);
00184   }
00185   void match(const clang::ast_type_traits::DynTypedNode &Node,
00186              ASTContext &Context);
00187   /// @}
00188 
00189   /// \brief Finds all matches in the given AST.
00190   void matchAST(ASTContext &Context);
00191 
00192   /// \brief Registers a callback to notify the end of parsing.
00193   ///
00194   /// The provided closure is called after parsing is done, before the AST is
00195   /// traversed. Useful for benchmarking.
00196   /// Each call to FindAll(...) will call the closure once.
00197   void registerTestCallbackAfterParsing(ParsingDoneTestCallback *ParsingDone);
00198 
00199   /// \brief For each \c Matcher<> a \c MatchCallback that will be called
00200   /// when it matches.
00201   struct MatchersByType {
00202     std::vector<std::pair<DeclarationMatcher, MatchCallback *>> Decl;
00203     std::vector<std::pair<TypeMatcher, MatchCallback *>> Type;
00204     std::vector<std::pair<StatementMatcher, MatchCallback *>> Stmt;
00205     std::vector<std::pair<NestedNameSpecifierMatcher, MatchCallback *>>
00206         NestedNameSpecifier;
00207     std::vector<std::pair<NestedNameSpecifierLocMatcher, MatchCallback *>>
00208         NestedNameSpecifierLoc;
00209     std::vector<std::pair<TypeLocMatcher, MatchCallback *>> TypeLoc;
00210     /// \brief All the callbacks in one container to simplify iteration.
00211     std::vector<MatchCallback *> AllCallbacks;
00212   };
00213 
00214 private:
00215   MatchersByType Matchers;
00216 
00217   MatchFinderOptions Options;
00218 
00219   /// \brief Called when parsing is done.
00220   ParsingDoneTestCallback *ParsingDone;
00221 };
00222 
00223 /// \brief Returns the results of matching \p Matcher on \p Node.
00224 ///
00225 /// Collects the \c BoundNodes of all callback invocations when matching
00226 /// \p Matcher on \p Node and returns the collected results.
00227 ///
00228 /// Multiple results occur when using matchers like \c forEachDescendant,
00229 /// which generate a result for each sub-match.
00230 ///
00231 /// \see selectFirst
00232 /// @{
00233 template <typename MatcherT, typename NodeT>
00234 SmallVector<BoundNodes, 1>
00235 match(MatcherT Matcher, const NodeT &Node, ASTContext &Context);
00236 
00237 template <typename MatcherT>
00238 SmallVector<BoundNodes, 1>
00239 match(MatcherT Matcher, const ast_type_traits::DynTypedNode &Node,
00240       ASTContext &Context);
00241 /// @}
00242 
00243 /// \brief Returns the first result of type \c NodeT bound to \p BoundTo.
00244 ///
00245 /// Returns \c NULL if there is no match, or if the matching node cannot be
00246 /// casted to \c NodeT.
00247 ///
00248 /// This is useful in combanation with \c match():
00249 /// \code
00250 ///   const Decl *D = selectFirst<Decl>("id", match(Matcher.bind("id"),
00251 ///                                                 Node, Context));
00252 /// \endcode
00253 template <typename NodeT>
00254 const NodeT *
00255 selectFirst(StringRef BoundTo, const SmallVectorImpl<BoundNodes> &Results) {
00256   for (const BoundNodes &N : Results) {
00257     if (const NodeT *Node = N.getNodeAs<NodeT>(BoundTo))
00258       return Node;
00259   }
00260   return nullptr;
00261 }
00262 
00263 namespace internal {
00264 class CollectMatchesCallback : public MatchFinder::MatchCallback {
00265 public:
00266   void run(const MatchFinder::MatchResult &Result) override {
00267     Nodes.push_back(Result.Nodes);
00268   }
00269   SmallVector<BoundNodes, 1> Nodes;
00270 };
00271 }
00272 
00273 template <typename MatcherT>
00274 SmallVector<BoundNodes, 1>
00275 match(MatcherT Matcher, const ast_type_traits::DynTypedNode &Node,
00276       ASTContext &Context) {
00277   internal::CollectMatchesCallback Callback;
00278   MatchFinder Finder;
00279   Finder.addMatcher(Matcher, &Callback);
00280   Finder.match(Node, Context);
00281   return std::move(Callback.Nodes);
00282 }
00283 
00284 template <typename MatcherT, typename NodeT>
00285 SmallVector<BoundNodes, 1>
00286 match(MatcherT Matcher, const NodeT &Node, ASTContext &Context) {
00287   return match(Matcher, ast_type_traits::DynTypedNode::create(Node), Context);
00288 }
00289 
00290 } // end namespace ast_matchers
00291 } // end namespace clang
00292 
00293 #endif