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_ASTMATCHERS_ASTMATCHFINDER_H
42 #define LLVM_CLANG_ASTMATCHERS_ASTMATCHFINDER_H
43 
44 #include "clang/ASTMatchers/ASTMatchers.h"
45 #include "llvm/ADT/StringMap.h"
46 #include "llvm/Support/Timer.h"
47 
48 namespace clang {
49 
50 namespace ast_matchers {
51 
52 /// \brief A class to allow finding matches over the Clang AST.
53 ///
54 /// After creation, you can add multiple matchers to the MatchFinder via
55 /// calls to addMatcher(...).
56 ///
57 /// Once all matchers are added, newASTConsumer() returns an ASTConsumer
58 /// that will trigger the callbacks specified via addMatcher(...) when a match
59 /// is found.
60 ///
61 /// The order of matches is guaranteed to be equivalent to doing a pre-order
62 /// traversal on the AST, and applying the matchers in the order in which they
63 /// were added to the MatchFinder.
64 ///
65 /// See ASTMatchers.h for more information about how to create matchers.
66 ///
67 /// Not intended to be subclassed.
68 class MatchFinder {
69 public:
70   /// \brief Contains all information for a given match.
71   ///
72   /// Every time a match is found, the MatchFinder will invoke the registered
73   /// MatchCallback with a MatchResult containing information about the match.
74   struct MatchResult {
75     MatchResult(const BoundNodes &Nodes, clang::ASTContext *Context);
76 
77     /// \brief Contains the nodes bound on the current match.
78     ///
79     /// This allows user code to easily extract matched AST nodes.
80     const BoundNodes Nodes;
81 
82     /// \brief Utilities for interpreting the matched AST structures.
83     /// @{
84     clang::ASTContext * const Context;
85     clang::SourceManager * const SourceManager;
86     /// @}
87   };
88 
89   /// \brief Called when the Match registered for it was successfully found
90   /// in the AST.
91   class MatchCallback {
92   public:
93     virtual ~MatchCallback();
94 
95     /// \brief Called on every match by the \c MatchFinder.
96     virtual void run(const MatchResult &Result) = 0;
97 
98     /// \brief Called at the start of each translation unit.
99     ///
100     /// Optionally override to do per translation unit tasks.
onStartOfTranslationUnit()101     virtual void onStartOfTranslationUnit() {}
102 
103     /// \brief Called at the end of each translation unit.
104     ///
105     /// Optionally override to do per translation unit tasks.
onEndOfTranslationUnit()106     virtual void onEndOfTranslationUnit() {}
107 
108     /// \brief An id used to group the matchers.
109     ///
110     /// This id is used, for example, for the profiling output.
111     /// It defaults to "<unknown>".
112     virtual StringRef getID() const;
113   };
114 
115   /// \brief Called when parsing is finished. Intended for testing only.
116   class ParsingDoneTestCallback {
117   public:
118     virtual ~ParsingDoneTestCallback();
119     virtual void run() = 0;
120   };
121 
122   struct MatchFinderOptions {
123     struct Profiling {
ProfilingMatchFinderOptions::Profiling124       Profiling(llvm::StringMap<llvm::TimeRecord> &Records)
125           : Records(Records) {}
126 
127       /// \brief Per bucket timing information.
128       llvm::StringMap<llvm::TimeRecord> &Records;
129     };
130 
131     /// \brief Enables per-check timers.
132     ///
133     /// It prints a report after match.
134     llvm::Optional<Profiling> CheckProfiling;
135   };
136 
137   MatchFinder(MatchFinderOptions Options = MatchFinderOptions());
138   ~MatchFinder();
139 
140   /// \brief Adds a matcher to execute when running over the AST.
141   ///
142   /// Calls 'Action' with the BoundNodes on every match.
143   /// Adding more than one 'NodeMatch' allows finding different matches in a
144   /// single pass over the AST.
145   ///
146   /// Does not take ownership of 'Action'.
147   /// @{
148   void addMatcher(const DeclarationMatcher &NodeMatch,
149                   MatchCallback *Action);
150   void addMatcher(const TypeMatcher &NodeMatch,
151                   MatchCallback *Action);
152   void addMatcher(const StatementMatcher &NodeMatch,
153                   MatchCallback *Action);
154   void addMatcher(const NestedNameSpecifierMatcher &NodeMatch,
155                   MatchCallback *Action);
156   void addMatcher(const NestedNameSpecifierLocMatcher &NodeMatch,
157                   MatchCallback *Action);
158   void addMatcher(const TypeLocMatcher &NodeMatch,
159                   MatchCallback *Action);
160   /// @}
161 
162   /// \brief Adds a matcher to execute when running over the AST.
163   ///
164   /// This is similar to \c addMatcher(), but it uses the dynamic interface. It
165   /// is more flexible, but the lost type information enables a caller to pass
166   /// a matcher that cannot match anything.
167   ///
168   /// \returns \c true if the matcher is a valid top-level matcher, \c false
169   ///   otherwise.
170   bool addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch,
171                          MatchCallback *Action);
172 
173   /// \brief Creates a clang ASTConsumer that finds all matches.
174   std::unique_ptr<clang::ASTConsumer> newASTConsumer();
175 
176   /// \brief Calls the registered callbacks on all matches on the given \p Node.
177   ///
178   /// Note that there can be multiple matches on a single node, for
179   /// example when using decl(forEachDescendant(stmt())).
180   ///
181   /// @{
match(const T & Node,ASTContext & Context)182   template <typename T> void match(const T &Node, ASTContext &Context) {
183     match(clang::ast_type_traits::DynTypedNode::create(Node), Context);
184   }
185   void match(const clang::ast_type_traits::DynTypedNode &Node,
186              ASTContext &Context);
187   /// @}
188 
189   /// \brief Finds all matches in the given AST.
190   void matchAST(ASTContext &Context);
191 
192   /// \brief Registers a callback to notify the end of parsing.
193   ///
194   /// The provided closure is called after parsing is done, before the AST is
195   /// traversed. Useful for benchmarking.
196   /// Each call to FindAll(...) will call the closure once.
197   void registerTestCallbackAfterParsing(ParsingDoneTestCallback *ParsingDone);
198 
199   /// \brief For each \c Matcher<> a \c MatchCallback that will be called
200   /// when it matches.
201   struct MatchersByType {
202     std::vector<std::pair<internal::DynTypedMatcher, MatchCallback *>>
203         DeclOrStmt;
204     std::vector<std::pair<TypeMatcher, MatchCallback *>> Type;
205     std::vector<std::pair<NestedNameSpecifierMatcher, MatchCallback *>>
206         NestedNameSpecifier;
207     std::vector<std::pair<NestedNameSpecifierLocMatcher, MatchCallback *>>
208         NestedNameSpecifierLoc;
209     std::vector<std::pair<TypeLocMatcher, MatchCallback *>> TypeLoc;
210     /// \brief All the callbacks in one container to simplify iteration.
211     std::vector<MatchCallback *> AllCallbacks;
212   };
213 
214 private:
215   MatchersByType Matchers;
216 
217   MatchFinderOptions Options;
218 
219   /// \brief Called when parsing is done.
220   ParsingDoneTestCallback *ParsingDone;
221 };
222 
223 /// \brief Returns the results of matching \p Matcher on \p Node.
224 ///
225 /// Collects the \c BoundNodes of all callback invocations when matching
226 /// \p Matcher on \p Node and returns the collected results.
227 ///
228 /// Multiple results occur when using matchers like \c forEachDescendant,
229 /// which generate a result for each sub-match.
230 ///
231 /// \see selectFirst
232 /// @{
233 template <typename MatcherT, typename NodeT>
234 SmallVector<BoundNodes, 1>
235 match(MatcherT Matcher, const NodeT &Node, ASTContext &Context);
236 
237 template <typename MatcherT>
238 SmallVector<BoundNodes, 1>
239 match(MatcherT Matcher, const ast_type_traits::DynTypedNode &Node,
240       ASTContext &Context);
241 /// @}
242 
243 /// \brief Returns the first result of type \c NodeT bound to \p BoundTo.
244 ///
245 /// Returns \c NULL if there is no match, or if the matching node cannot be
246 /// casted to \c NodeT.
247 ///
248 /// This is useful in combanation with \c match():
249 /// \code
250 ///   const Decl *D = selectFirst<Decl>("id", match(Matcher.bind("id"),
251 ///                                                 Node, Context));
252 /// \endcode
253 template <typename NodeT>
254 const NodeT *
selectFirst(StringRef BoundTo,const SmallVectorImpl<BoundNodes> & Results)255 selectFirst(StringRef BoundTo, const SmallVectorImpl<BoundNodes> &Results) {
256   for (const BoundNodes &N : Results) {
257     if (const NodeT *Node = N.getNodeAs<NodeT>(BoundTo))
258       return Node;
259   }
260   return nullptr;
261 }
262 
263 namespace internal {
264 class CollectMatchesCallback : public MatchFinder::MatchCallback {
265 public:
run(const MatchFinder::MatchResult & Result)266   void run(const MatchFinder::MatchResult &Result) override {
267     Nodes.push_back(Result.Nodes);
268   }
269   SmallVector<BoundNodes, 1> Nodes;
270 };
271 }
272 
273 template <typename MatcherT>
274 SmallVector<BoundNodes, 1>
match(MatcherT Matcher,const ast_type_traits::DynTypedNode & Node,ASTContext & Context)275 match(MatcherT Matcher, const ast_type_traits::DynTypedNode &Node,
276       ASTContext &Context) {
277   internal::CollectMatchesCallback Callback;
278   MatchFinder Finder;
279   Finder.addMatcher(Matcher, &Callback);
280   Finder.match(Node, Context);
281   return std::move(Callback.Nodes);
282 }
283 
284 template <typename MatcherT, typename NodeT>
285 SmallVector<BoundNodes, 1>
match(MatcherT Matcher,const NodeT & Node,ASTContext & Context)286 match(MatcherT Matcher, const NodeT &Node, ASTContext &Context) {
287   return match(Matcher, ast_type_traits::DynTypedNode::create(Node), Context);
288 }
289 
290 } // end namespace ast_matchers
291 } // end namespace clang
292 
293 #endif
294