ASTMatchFinder.h revision f7f295f321fd434e1e542844a71f538a56f2f8fb
1//===--- ASTMatchFinder.h - Structural query framework ----------*- 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// Provides a way to construct an ASTConsumer that runs given matchers 11// over the AST and invokes a given callback on every match. 12// 13// The general idea is to construct a matcher expression that describes a 14// subtree match on the AST. Next, a callback that is executed every time the 15// expression matches is registered, and the matcher is run over the AST of 16// some code. Matched subexpressions can be bound to string IDs and easily 17// be accessed from the registered callback. The callback can than use the 18// AST nodes that the subexpressions matched on to output information about 19// the match or construct changes that can be applied to the code. 20// 21// Example: 22// class HandleMatch : public MatchFinder::MatchCallback { 23// public: 24// virtual void Run(const MatchFinder::MatchResult &Result) { 25// const CXXRecordDecl *Class = 26// Result.Nodes.GetDeclAs<CXXRecordDecl>("id"); 27// ... 28// } 29// }; 30// 31// int main(int argc, char **argv) { 32// ClangTool Tool(argc, argv); 33// MatchFinder finder; 34// finder.AddMatcher(Id("id", record(hasName("::a_namespace::AClass"))), 35// new HandleMatch); 36// return Tool.Run(newFrontendActionFactory(&finder)); 37// } 38// 39//===----------------------------------------------------------------------===// 40 41#ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCH_FINDER_H 42#define LLVM_CLANG_AST_MATCHERS_AST_MATCH_FINDER_H 43 44#include "clang/ASTMatchers/ASTMatchers.h" 45 46namespace clang { 47 48namespace ast_matchers { 49 50/// \brief A class to allow finding matches over the Clang AST. 51/// 52/// After creation, you can add multiple matchers to the MatchFinder via 53/// calls to addMatcher(...). 54/// 55/// Once all matchers are added, newASTConsumer() returns an ASTConsumer 56/// that will trigger the callbacks specified via addMatcher(...) when a match 57/// is found. 58/// 59/// The order of matches is guaranteed to be equivalent to doing a pre-order 60/// traversal on the AST, and applying the matchers in the order in which they 61/// were added to the MatchFinder. 62/// 63/// See ASTMatchers.h for more information about how to create matchers. 64/// 65/// Not intended to be subclassed. 66class MatchFinder { 67public: 68 /// \brief Contains all information for a given match. 69 /// 70 /// Every time a match is found, the MatchFinder will invoke the registered 71 /// MatchCallback with a MatchResult containing information about the match. 72 struct MatchResult { 73 MatchResult(const BoundNodes &Nodes, clang::ASTContext *Context); 74 75 /// \brief Contains the nodes bound on the current match. 76 /// 77 /// This allows user code to easily extract matched AST nodes. 78 const BoundNodes Nodes; 79 80 /// \brief Utilities for interpreting the matched AST structures. 81 /// @{ 82 clang::ASTContext * const Context; 83 clang::SourceManager * const SourceManager; 84 /// @} 85 }; 86 87 /// \brief Called when the Match registered for it was successfully found 88 /// in the AST. 89 class MatchCallback { 90 public: 91 virtual ~MatchCallback(); 92 93 /// \brief Called on every match by the \c MatchFinder. 94 virtual void run(const MatchResult &Result) = 0; 95 96 /// \brief Called at the start of each translation unit. 97 /// 98 /// Optionally override to do per translation unit tasks. 99 virtual void onStartOfTranslationUnit() {} 100 }; 101 102 /// \brief Called when parsing is finished. Intended for testing only. 103 class ParsingDoneTestCallback { 104 public: 105 virtual ~ParsingDoneTestCallback(); 106 virtual void run() = 0; 107 }; 108 109 MatchFinder(); 110 ~MatchFinder(); 111 112 /// \brief Adds a matcher to execute when running over the AST. 113 /// 114 /// Calls 'Action' with the BoundNodes on every match. 115 /// Adding more than one 'NodeMatch' allows finding different matches in a 116 /// single pass over the AST. 117 /// 118 /// Does not take ownership of 'Action'. 119 /// @{ 120 void addMatcher(const DeclarationMatcher &NodeMatch, 121 MatchCallback *Action); 122 void addMatcher(const TypeMatcher &NodeMatch, 123 MatchCallback *Action); 124 void addMatcher(const StatementMatcher &NodeMatch, 125 MatchCallback *Action); 126 void addMatcher(const NestedNameSpecifierMatcher &NodeMatch, 127 MatchCallback *Action); 128 void addMatcher(const NestedNameSpecifierLocMatcher &NodeMatch, 129 MatchCallback *Action); 130 void addMatcher(const TypeLocMatcher &NodeMatch, 131 MatchCallback *Action); 132 /// @} 133 134 /// \brief Adds a matcher to execute when running over the AST. 135 /// 136 /// This is similar to \c addMatcher(), but it uses the dynamic interface. It 137 /// is more flexible, but the lost type information enables a caller to pass 138 /// a matcher that cannot match anything. 139 /// 140 /// \returns \c true if the matcher is a valid top-level matcher, \c false 141 /// otherwise. 142 bool addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch, 143 MatchCallback *Action); 144 145 /// \brief Creates a clang ASTConsumer that finds all matches. 146 clang::ASTConsumer *newASTConsumer(); 147 148 /// \brief Calls the registered callbacks on all matches on the given \p Node. 149 /// 150 /// Note that there can be multiple matches on a single node, for 151 /// example when using decl(forEachDescendant(stmt())). 152 /// 153 /// @{ 154 template <typename T> void match(const T &Node, ASTContext &Context) { 155 match(clang::ast_type_traits::DynTypedNode::create(Node), Context); 156 } 157 void match(const clang::ast_type_traits::DynTypedNode &Node, 158 ASTContext &Context); 159 /// @} 160 161 /// \brief Registers a callback to notify the end of parsing. 162 /// 163 /// The provided closure is called after parsing is done, before the AST is 164 /// traversed. Useful for benchmarking. 165 /// Each call to FindAll(...) will call the closure once. 166 void registerTestCallbackAfterParsing(ParsingDoneTestCallback *ParsingDone); 167 168private: 169 /// \brief For each \c DynTypedMatcher a \c MatchCallback that will be called 170 /// when it matches. 171 std::vector<std::pair<const internal::DynTypedMatcher*, MatchCallback*> > 172 MatcherCallbackPairs; 173 174 /// \brief Called when parsing is done. 175 ParsingDoneTestCallback *ParsingDone; 176}; 177 178/// \brief Returns the results of matching \p Matcher on \p Node. 179/// 180/// Collects the \c BoundNodes of all callback invocations when matching 181/// \p Matcher on \p Node and returns the collected results. 182/// 183/// Multiple results occur when using matchers like \c forEachDescendant, 184/// which generate a result for each sub-match. 185/// 186/// \see selectFirst 187/// @{ 188template <typename MatcherT, typename NodeT> 189SmallVector<BoundNodes, 1> 190match(MatcherT Matcher, const NodeT &Node, ASTContext &Context); 191 192template <typename MatcherT> 193SmallVector<BoundNodes, 1> 194match(MatcherT Matcher, const ast_type_traits::DynTypedNode &Node, 195 ASTContext &Context); 196/// @} 197 198/// \brief Returns the first result of type \c NodeT bound to \p BoundTo. 199/// 200/// Returns \c NULL if there is no match, or if the matching node cannot be 201/// casted to \c NodeT. 202/// 203/// This is useful in combanation with \c match(): 204/// \code 205/// Decl *D = selectFirst<Decl>("id", match(Matcher.bind("id"), 206/// Node, Context)); 207/// \endcode 208template <typename NodeT> 209NodeT * 210selectFirst(StringRef BoundTo, const SmallVectorImpl<BoundNodes> &Results) { 211 for (SmallVectorImpl<BoundNodes>::const_iterator I = Results.begin(), 212 E = Results.end(); 213 I != E; ++I) { 214 if (NodeT *Node = I->getNodeAs<NodeT>(BoundTo)) 215 return Node; 216 } 217 return NULL; 218} 219 220namespace internal { 221class CollectMatchesCallback : public MatchFinder::MatchCallback { 222public: 223 virtual void run(const MatchFinder::MatchResult &Result) { 224 Nodes.push_back(Result.Nodes); 225 } 226 SmallVector<BoundNodes, 1> Nodes; 227}; 228} 229 230template <typename MatcherT> 231SmallVector<BoundNodes, 1> 232match(MatcherT Matcher, const ast_type_traits::DynTypedNode &Node, 233 ASTContext &Context) { 234 internal::CollectMatchesCallback Callback; 235 MatchFinder Finder; 236 Finder.addMatcher(Matcher, &Callback); 237 Finder.match(Node, Context); 238 return Callback.Nodes; 239} 240 241template <typename MatcherT, typename NodeT> 242SmallVector<BoundNodes, 1> 243match(MatcherT Matcher, const NodeT &Node, ASTContext &Context) { 244 return match(Matcher, ast_type_traits::DynTypedNode::create(Node), Context); 245} 246 247} // end namespace ast_matchers 248} // end namespace clang 249 250#endif // LLVM_CLANG_AST_MATCHERS_AST_MATCH_FINDER_H 251