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    /// \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
176private:
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/// @{
196template <typename MatcherT, typename NodeT>
197SmallVector<BoundNodes, 1>
198match(MatcherT Matcher, const NodeT &Node, ASTContext &Context);
199
200template <typename MatcherT>
201SmallVector<BoundNodes, 1>
202match(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
216template <typename NodeT>
217NodeT *
218selectFirst(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 nullptr;
226}
227
228namespace internal {
229class CollectMatchesCallback : public MatchFinder::MatchCallback {
230public:
231  void run(const MatchFinder::MatchResult &Result) override {
232    Nodes.push_back(Result.Nodes);
233  }
234  SmallVector<BoundNodes, 1> Nodes;
235};
236}
237
238template <typename MatcherT>
239SmallVector<BoundNodes, 1>
240match(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
249template <typename MatcherT, typename NodeT>
250SmallVector<BoundNodes, 1>
251match(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