]> granicus.if.org Git - clang/blobdiff - include/clang/ASTMatchers/ASTMatchFinder.h
Header guard canonicalization, clang part.
[clang] / include / clang / ASTMatchers / ASTMatchFinder.h
index ba8e0a7ecccaf583fd97e158dd9e2d2ed6b7010a..75525ad1d62eccb1b8780ed9951bed05958fa16a 100644 (file)
@@ -38,8 +38,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCH_FINDER_H
-#define LLVM_CLANG_AST_MATCHERS_AST_MATCH_FINDER_H
+#ifndef LLVM_CLANG_ASTMATCHERS_ASTMATCHFINDER_H
+#define LLVM_CLANG_ASTMATCHERS_ASTMATCHFINDER_H
 
 #include "clang/ASTMatchers/ASTMatchers.h"
 
@@ -56,6 +56,10 @@ namespace ast_matchers {
 /// that will trigger the callbacks specified via addMatcher(...) when a match
 /// is found.
 ///
+/// The order of matches is guaranteed to be equivalent to doing a pre-order
+/// traversal on the AST, and applying the matchers in the order in which they
+/// were added to the MatchFinder.
+///
 /// See ASTMatchers.h for more information about how to create matchers.
 ///
 /// Not intended to be subclassed.
@@ -85,7 +89,19 @@ public:
   class MatchCallback {
   public:
     virtual ~MatchCallback();
+
+    /// \brief Called on every match by the \c MatchFinder.
     virtual void run(const MatchResult &Result) = 0;
+
+    /// \brief Called at the start of each translation unit.
+    ///
+    /// Optionally override to do per translation unit tasks.
+    virtual void onStartOfTranslationUnit() {}
+
+    /// \brief Called at the end of each translation unit.
+    ///
+    /// Optionally override to do per translation unit tasks.
+    virtual void onEndOfTranslationUnit() {}
   };
 
   /// \brief Called when parsing is finished. Intended for testing only.
@@ -120,16 +136,36 @@ public:
                   MatchCallback *Action);
   /// @}
 
+  /// \brief Adds a matcher to execute when running over the AST.
+  ///
+  /// This is similar to \c addMatcher(), but it uses the dynamic interface. It
+  /// is more flexible, but the lost type information enables a caller to pass
+  /// a matcher that cannot match anything.
+  ///
+  /// \returns \c true if the matcher is a valid top-level matcher, \c false
+  ///   otherwise.
+  bool addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch,
+                         MatchCallback *Action);
+
   /// \brief Creates a clang ASTConsumer that finds all matches.
-  clang::ASTConsumer *newASTConsumer();
+  std::unique_ptr<clang::ASTConsumer> newASTConsumer();
 
-  /// \brief Finds all matches on the given \c Node.
+  /// \brief Calls the registered callbacks on all matches on the given \p Node.
+  ///
+  /// Note that there can be multiple matches on a single node, for
+  /// example when using decl(forEachDescendant(stmt())).
   ///
   /// @{
-  void findAll(const Decl &Node, ASTContext &Context);
-  void findAll(const Stmt &Node, ASTContext &Context);
+  template <typename T> void match(const T &Node, ASTContext &Context) {
+    match(clang::ast_type_traits::DynTypedNode::create(Node), Context);
+  }
+  void match(const clang::ast_type_traits::DynTypedNode &Node,
+             ASTContext &Context);
   /// @}
 
+  /// \brief Finds all matches in the given AST.
+  void matchAST(ASTContext &Context);
+
   /// \brief Registers a callback to notify the end of parsing.
   ///
   /// The provided closure is called after parsing is done, before the AST is
@@ -140,14 +176,81 @@ public:
 private:
   /// \brief For each \c DynTypedMatcher a \c MatchCallback that will be called
   /// when it matches.
-  std::vector<std::pair<const internal::DynTypedMatcher*, MatchCallback*> >
+  std::vector<std::pair<internal::DynTypedMatcher, MatchCallback *> >
     MatcherCallbackPairs;
 
   /// \brief Called when parsing is done.
   ParsingDoneTestCallback *ParsingDone;
 };
 
+/// \brief Returns the results of matching \p Matcher on \p Node.
+///
+/// Collects the \c BoundNodes of all callback invocations when matching
+/// \p Matcher on \p Node and returns the collected results.
+///
+/// Multiple results occur when using matchers like \c forEachDescendant,
+/// which generate a result for each sub-match.
+///
+/// \see selectFirst
+/// @{
+template <typename MatcherT, typename NodeT>
+SmallVector<BoundNodes, 1>
+match(MatcherT Matcher, const NodeT &Node, ASTContext &Context);
+
+template <typename MatcherT>
+SmallVector<BoundNodes, 1>
+match(MatcherT Matcher, const ast_type_traits::DynTypedNode &Node,
+      ASTContext &Context);
+/// @}
+
+/// \brief Returns the first result of type \c NodeT bound to \p BoundTo.
+///
+/// Returns \c NULL if there is no match, or if the matching node cannot be
+/// casted to \c NodeT.
+///
+/// This is useful in combanation with \c match():
+/// \code
+///   const Decl *D = selectFirst<Decl>("id", match(Matcher.bind("id"),
+///                                                 Node, Context));
+/// \endcode
+template <typename NodeT>
+const NodeT *
+selectFirst(StringRef BoundTo, const SmallVectorImpl<BoundNodes> &Results) {
+  for (const BoundNodes &N : Results) {
+    if (const NodeT *Node = N.getNodeAs<NodeT>(BoundTo))
+      return Node;
+  }
+  return nullptr;
+}
+
+namespace internal {
+class CollectMatchesCallback : public MatchFinder::MatchCallback {
+public:
+  void run(const MatchFinder::MatchResult &Result) override {
+    Nodes.push_back(Result.Nodes);
+  }
+  SmallVector<BoundNodes, 1> Nodes;
+};
+}
+
+template <typename MatcherT>
+SmallVector<BoundNodes, 1>
+match(MatcherT Matcher, const ast_type_traits::DynTypedNode &Node,
+      ASTContext &Context) {
+  internal::CollectMatchesCallback Callback;
+  MatchFinder Finder;
+  Finder.addMatcher(Matcher, &Callback);
+  Finder.match(Node, Context);
+  return Callback.Nodes;
+}
+
+template <typename MatcherT, typename NodeT>
+SmallVector<BoundNodes, 1>
+match(MatcherT Matcher, const NodeT &Node, ASTContext &Context) {
+  return match(Matcher, ast_type_traits::DynTypedNode::create(Node), Context);
+}
+
 } // end namespace ast_matchers
 } // end namespace clang
 
-#endif // LLVM_CLANG_AST_MATCHERS_AST_MATCH_FINDER_H
+#endif