]> granicus.if.org Git - clang/blob - include/clang/ASTMatchers/ASTMatchFinder.h
Revert "Refactor DynTypedMatcher into a value type class, just like Matcher<T>."
[clang] / include / clang / ASTMatchers / ASTMatchFinder.h
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 Creates a clang ASTConsumer that finds all matches.
140   clang::ASTConsumer *newASTConsumer();
141
142   /// \brief Calls the registered callbacks on all matches on the given \p Node.
143   ///
144   /// Note that there can be multiple matches on a single node, for
145   /// example when using decl(forEachDescendant(stmt())).
146   ///
147   /// @{
148   template <typename T> void match(const T &Node, ASTContext &Context) {
149     match(clang::ast_type_traits::DynTypedNode::create(Node), Context);
150   }
151   void match(const clang::ast_type_traits::DynTypedNode &Node,
152              ASTContext &Context);
153   /// @}
154
155   /// \brief Registers a callback to notify the end of parsing.
156   ///
157   /// The provided closure is called after parsing is done, before the AST is
158   /// traversed. Useful for benchmarking.
159   /// Each call to FindAll(...) will call the closure once.
160   void registerTestCallbackAfterParsing(ParsingDoneTestCallback *ParsingDone);
161
162 private:
163   /// \brief For each \c DynTypedMatcher a \c MatchCallback that will be called
164   /// when it matches.
165   std::vector<std::pair<const internal::DynTypedMatcher*, MatchCallback*> >
166     MatcherCallbackPairs;
167
168   /// \brief Called when parsing is done.
169   ParsingDoneTestCallback *ParsingDone;
170 };
171
172 /// \brief Returns the results of matching \p Matcher on \p Node.
173 ///
174 /// Collects the \c BoundNodes of all callback invocations when matching
175 /// \p Matcher on \p Node and returns the collected results.
176 ///
177 /// Multiple results occur when using matchers like \c forEachDescendant,
178 /// which generate a result for each sub-match.
179 ///
180 /// \see selectFirst
181 /// @{
182 template <typename MatcherT, typename NodeT>
183 SmallVector<BoundNodes, 1>
184 match(MatcherT Matcher, const NodeT &Node, ASTContext &Context);
185
186 template <typename MatcherT>
187 SmallVector<BoundNodes, 1>
188 match(MatcherT Matcher, const ast_type_traits::DynTypedNode &Node,
189       ASTContext &Context);
190 /// @}
191
192 /// \brief Returns the first result of type \c NodeT bound to \p BoundTo.
193 ///
194 /// Returns \c NULL if there is no match, or if the matching node cannot be
195 /// casted to \c NodeT.
196 ///
197 /// This is useful in combanation with \c match():
198 /// \code
199 ///   Decl *D = selectFirst<Decl>("id", match(Matcher.bind("id"),
200 ///                                           Node, Context));
201 /// \endcode
202 template <typename NodeT>
203 NodeT *
204 selectFirst(StringRef BoundTo, const SmallVectorImpl<BoundNodes> &Results) {
205   for (SmallVectorImpl<BoundNodes>::const_iterator I = Results.begin(),
206                                                    E = Results.end();
207        I != E; ++I) {
208     if (NodeT *Node = I->getNodeAs<NodeT>(BoundTo))
209       return Node;
210   }
211   return NULL;
212 }
213
214 namespace internal {
215 class CollectMatchesCallback : public MatchFinder::MatchCallback {
216 public:
217   virtual void run(const MatchFinder::MatchResult &Result) {
218     Nodes.push_back(Result.Nodes);
219   }
220   SmallVector<BoundNodes, 1> Nodes;
221 };
222 }
223
224 template <typename MatcherT>
225 SmallVector<BoundNodes, 1>
226 match(MatcherT Matcher, const ast_type_traits::DynTypedNode &Node,
227       ASTContext &Context) {
228   internal::CollectMatchesCallback Callback;
229   MatchFinder Finder;
230   Finder.addMatcher(Matcher, &Callback);
231   Finder.match(Node, Context);
232   return Callback.Nodes;
233 }
234
235 template <typename MatcherT, typename NodeT>
236 SmallVector<BoundNodes, 1>
237 match(MatcherT Matcher, const NodeT &Node, ASTContext &Context) {
238   return match(Matcher, ast_type_traits::DynTypedNode::create(Node), Context);
239 }
240
241 } // end namespace ast_matchers
242 } // end namespace clang
243
244 #endif // LLVM_CLANG_AST_MATCHERS_AST_MATCH_FINDER_H