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.
onStartOfTranslationUnit()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.
onEndOfTranslationUnit()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 /// @{
match(const T & Node,ASTContext & Context)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 *
selectFirst(StringRef BoundTo,const SmallVectorImpl<BoundNodes> & Results)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 nullptr;
226 }
227
228 namespace internal {
229 class CollectMatchesCallback : public MatchFinder::MatchCallback {
230 public:
run(const MatchFinder::MatchResult & Result)231 void run(const MatchFinder::MatchResult &Result) override {
232 Nodes.push_back(Result.Nodes);
233 }
234 SmallVector<BoundNodes, 1> Nodes;
235 };
236 }
237
238 template <typename MatcherT>
239 SmallVector<BoundNodes, 1>
match(MatcherT Matcher,const ast_type_traits::DynTypedNode & Node,ASTContext & Context)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>
match(MatcherT Matcher,const NodeT & Node,ASTContext & Context)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