diff options
author | Manuel Klimek <klimek@google.com> | 2012-07-06 05:48:52 +0000 |
---|---|---|
committer | Manuel Klimek <klimek@google.com> | 2012-07-06 05:48:52 +0000 |
commit | 4da216637fa1ad4bdfd31bc265edb57ca35c2c12 (patch) | |
tree | 08b93fbc99de82a43b0bb4dba96dbfbf96abac45 /include/clang/ASTMatchers/ASTMatchFinder.h | |
parent | ea7eb071166c69e11bfda4f1d89d5c2b6bbcdca3 (diff) |
Adds the AST Matcher library, which provides a in-C++ DSL to express
matches on interesting parts of the AST, and callback mechanisms to
act on them.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@159805 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include/clang/ASTMatchers/ASTMatchFinder.h')
-rw-r--r-- | include/clang/ASTMatchers/ASTMatchFinder.h | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/include/clang/ASTMatchers/ASTMatchFinder.h b/include/clang/ASTMatchers/ASTMatchFinder.h new file mode 100644 index 0000000000..dd237eece3 --- /dev/null +++ b/include/clang/ASTMatchers/ASTMatchFinder.h @@ -0,0 +1,141 @@ +//===--- ASTMatchFinder.h - Structural query framework ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Provides a way to construct an ASTConsumer that runs given matchers +// over the AST and invokes a given callback on every match. +// +// The general idea is to construct a matcher expression that describes a +// subtree match on the AST. Next, a callback that is executed every time the +// expression matches is registered, and the matcher is run over the AST of +// some code. Matched subexpressions can be bound to string IDs and easily +// be accessed from the registered callback. The callback can than use the +// AST nodes that the subexpressions matched on to output information about +// the match or construct changes that can be applied to the code. +// +// Example: +// class HandleMatch : public MatchFinder::MatchCallback { +// public: +// virtual void Run(const MatchFinder::MatchResult &Result) { +// const CXXRecordDecl *Class = +// Result.Nodes.GetDeclAs<CXXRecordDecl>("id"); +// ... +// } +// }; +// +// int main(int argc, char **argv) { +// ClangTool Tool(argc, argv); +// MatchFinder finder; +// finder.AddMatcher(Id("id", record(hasName("::a_namespace::AClass"))), +// new HandleMatch); +// return Tool.Run(newFrontendActionFactory(&finder)); +// } +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCH_FINDER_H +#define LLVM_CLANG_AST_MATCHERS_AST_MATCH_FINDER_H + +#include "clang/ASTMatchers/ASTMatchers.h" + +namespace clang { + +namespace ast_matchers { + +/// \brief A class to allow finding matches over the Clang AST. +/// +/// After creation, you can add multiple matchers to the MatchFinder via +/// calls to addMatcher(...). +/// +/// Once all matchers are added, newASTConsumer() returns an ASTConsumer +/// that will trigger the callbacks specified via addMatcher(...) when a match +/// is found. +/// +/// See ASTMatchers.h for more information about how to create matchers. +/// +/// Not intended to be subclassed. +class MatchFinder { +public: + /// \brief Contains all information for a given match. + /// + /// Every time a match is found, the MatchFinder will invoke the registered + /// MatchCallback with a MatchResult containing information about the match. + struct MatchResult { + MatchResult(const BoundNodes &Nodes, clang::ASTContext *Context); + + /// \brief Contains the nodes bound on the current match. + /// + /// This allows user code to easily extract matched AST nodes. + const BoundNodes Nodes; + + /// \brief Utilities for interpreting the matched AST structures. + /// @{ + clang::ASTContext * const Context; + clang::SourceManager * const SourceManager; + /// @} + }; + + /// \brief Called when the Match registered for it was successfully found + /// in the AST. + class MatchCallback { + public: + virtual ~MatchCallback(); + virtual void run(const MatchResult &Result) = 0; + }; + + /// \brief Called when parsing is finished. Intended for testing only. + class ParsingDoneTestCallback { + public: + virtual ~ParsingDoneTestCallback(); + virtual void run() = 0; + }; + + MatchFinder(); + ~MatchFinder(); + + /// \brief Adds a matcher to execute when running over the AST. + /// + /// Calls 'Action' with the BoundNodes on every match. + /// Adding more than one 'NodeMatch' allows finding different matches in a + /// single pass over the AST. + /// + /// Does not take ownership of 'Action'. + /// @{ + void addMatcher(const DeclarationMatcher &NodeMatch, + MatchCallback *Action); + void addMatcher(const TypeMatcher &NodeMatch, + MatchCallback *Action); + void addMatcher(const StatementMatcher &NodeMatch, + MatchCallback *Action); + /// @} + + /// \brief Creates a clang ASTConsumer that finds all matches. + clang::ASTConsumer *newASTConsumer(); + + /// \brief Registers a callback to notify the end of parsing. + /// + /// The provided closure is called after parsing is done, before the AST is + /// traversed. Useful for benchmarking. + /// Each call to FindAll(...) will call the closure once. + void registerTestCallbackAfterParsing(ParsingDoneTestCallback *ParsingDone); + +private: + /// \brief The MatchCallback*'s will be called every time the + /// UntypedBaseMatcher matches on the AST. + std::vector< std::pair< + const internal::UntypedBaseMatcher*, + MatchCallback*> > Triggers; + + /// \brief Called when parsing is done. + ParsingDoneTestCallback *ParsingDone; +}; + +} // end namespace ast_matchers +} // end namespace clang + +#endif // LLVM_CLANG_AST_MATCHERS_AST_MATCH_FINDER_H |