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 46 namespace clang { 47 48 namespace 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. 66 class MatchFinder { 67 public: 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 /// \brief Called at the end of each translation unit. 102 /// 103 /// Optionally override to do per translation unit tasks. 104 virtual void onEndOfTranslationUnit() {} 105 }; 106 107 /// \brief Called when parsing is finished. Intended for testing only. 108 class ParsingDoneTestCallback { 109 public: 110 virtual ~ParsingDoneTestCallback(); 111 virtual void run() = 0; 112 }; 113 114 MatchFinder(); 115 ~MatchFinder(); 116 117 /// \brief Adds a matcher to execute when running over the AST. 118 /// 119 /// Calls 'Action' with the BoundNodes on every match. 120 /// Adding more than one 'NodeMatch' allows finding different matches in a 121 /// single pass over the AST. 122 /// 123 /// Does not take ownership of 'Action'. 124 /// @{ 125 void addMatcher(const DeclarationMatcher &NodeMatch, 126 MatchCallback *Action); 127 void addMatcher(const TypeMatcher &NodeMatch, 128 MatchCallback *Action); 129 void addMatcher(const StatementMatcher &NodeMatch, 130 MatchCallback *Action); 131 void addMatcher(const NestedNameSpecifierMatcher &NodeMatch, 132 MatchCallback *Action); 133 void addMatcher(const NestedNameSpecifierLocMatcher &NodeMatch, 134 MatchCallback *Action); 135 void addMatcher(const TypeLocMatcher &NodeMatch, 136 MatchCallback *Action); 137 /// @} 138 139 /// \brief Adds a matcher to execute when running over the AST. 140 /// 141 /// This is similar to \c addMatcher(), but it uses the dynamic interface. It 142 /// is more flexible, but the lost type information enables a caller to pass 143 /// a matcher that cannot match anything. 144 /// 145 /// \returns \c true if the matcher is a valid top-level matcher, \c false 146 /// otherwise. 147 bool addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch, 148 MatchCallback *Action); 149 150 /// \brief Creates a clang ASTConsumer that finds all matches. 151 clang::ASTConsumer *newASTConsumer(); 152 153 /// \brief Calls the registered callbacks on all matches on the given \p Node. 154 /// 155 /// Note that there can be multiple matches on a single node, for 156 /// example when using decl(forEachDescendant(stmt())). 157 /// 158 /// @{ 159 template <typename T> void match(const T &Node, ASTContext &Context) { 160 match(clang::ast_type_traits::DynTypedNode::create(Node), Context); 161 } 162 void match(const clang::ast_type_traits::DynTypedNode &Node, 163 ASTContext &Context); 164 /// @} 165 166 /// \brief Finds all matches in the given AST. 167 void matchAST(ASTContext &Context); 168 169 /// \brief Registers a callback to notify the end of parsing. 170 /// 171 /// The provided closure is called after parsing is done, before the AST is 172 /// traversed. Useful for benchmarking. 173 /// Each call to FindAll(...) will call the closure once. 174 void registerTestCallbackAfterParsing(ParsingDoneTestCallback *ParsingDone); 175 176 private: 177 /// \brief For each \c DynTypedMatcher a \c MatchCallback that will be called 178 /// when it matches. 179 std::vector<std::pair<internal::DynTypedMatcher, MatchCallback *> > 180 MatcherCallbackPairs; 181 182 /// \brief Called when parsing is done. 183 ParsingDoneTestCallback *ParsingDone; 184 }; 185 186 /// \brief Returns the results of matching \p Matcher on \p Node. 187 /// 188 /// Collects the \c BoundNodes of all callback invocations when matching 189 /// \p Matcher on \p Node and returns the collected results. 190 /// 191 /// Multiple results occur when using matchers like \c forEachDescendant, 192 /// which generate a result for each sub-match. 193 /// 194 /// \see selectFirst 195 /// @{ 196 template <typename MatcherT, typename NodeT> 197 SmallVector<BoundNodes, 1> 198 match(MatcherT Matcher, const NodeT &Node, ASTContext &Context); 199 200 template <typename MatcherT> 201 SmallVector<BoundNodes, 1> 202 match(MatcherT Matcher, const ast_type_traits::DynTypedNode &Node, 203 ASTContext &Context); 204 /// @} 205 206 /// \brief Returns the first result of type \c NodeT bound to \p BoundTo. 207 /// 208 /// Returns \c NULL if there is no match, or if the matching node cannot be 209 /// casted to \c NodeT. 210 /// 211 /// This is useful in combanation with \c match(): 212 /// \code 213 /// Decl *D = selectFirst<Decl>("id", match(Matcher.bind("id"), 214 /// Node, Context)); 215 /// \endcode 216 template <typename NodeT> 217 NodeT * 218 selectFirst(StringRef BoundTo, const SmallVectorImpl<BoundNodes> &Results) { 219 for (SmallVectorImpl<BoundNodes>::const_iterator I = Results.begin(), 220 E = Results.end(); 221 I != E; ++I) { 222 if (NodeT *Node = I->getNodeAs<NodeT>(BoundTo)) 223 return Node; 224 } 225 return NULL; 226 } 227 228 namespace internal { 229 class CollectMatchesCallback : public MatchFinder::MatchCallback { 230 public: 231 virtual void run(const MatchFinder::MatchResult &Result) { 232 Nodes.push_back(Result.Nodes); 233 } 234 SmallVector<BoundNodes, 1> Nodes; 235 }; 236 } 237 238 template <typename MatcherT> 239 SmallVector<BoundNodes, 1> 240 match(MatcherT Matcher, const ast_type_traits::DynTypedNode &Node, 241 ASTContext &Context) { 242 internal::CollectMatchesCallback Callback; 243 MatchFinder Finder; 244 Finder.addMatcher(Matcher, &Callback); 245 Finder.match(Node, Context); 246 return Callback.Nodes; 247 } 248 249 template <typename MatcherT, typename NodeT> 250 SmallVector<BoundNodes, 1> 251 match(MatcherT Matcher, const NodeT &Node, ASTContext &Context) { 252 return match(Matcher, ast_type_traits::DynTypedNode::create(Node), Context); 253 } 254 255 } // end namespace ast_matchers 256 } // end namespace clang 257 258 #endif // LLVM_CLANG_AST_MATCHERS_AST_MATCH_FINDER_H 259