- //===--- ASTMatchFinder.h - Structural query framework ----------*- C++ -*-===// 
- // 
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 
- // See https://llvm.org/LICENSE.txt for license information. 
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 
- // 
- //===----------------------------------------------------------------------===// 
- // 
- //  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_ASTMATCHERS_ASTMATCHFINDER_H 
- #define LLVM_CLANG_ASTMATCHERS_ASTMATCHFINDER_H 
-   
- #include "clang/ASTMatchers/ASTMatchers.h" 
- #include "llvm/ADT/SmallPtrSet.h" 
- #include "llvm/ADT/StringMap.h" 
- #include "llvm/Support/Timer.h" 
- #include <optional> 
-   
- namespace clang { 
-   
- namespace ast_matchers { 
-   
- /// 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. 
- /// 
- /// 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. 
- class MatchFinder { 
- public: 
-   /// 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); 
-   
-     /// Contains the nodes bound on the current match. 
-     /// 
-     /// This allows user code to easily extract matched AST nodes. 
-     const BoundNodes Nodes; 
-   
-     /// Utilities for interpreting the matched AST structures. 
-     /// @{ 
-     clang::ASTContext * const Context; 
-     clang::SourceManager * const SourceManager; 
-     /// @} 
-   }; 
-   
-   /// Called when the Match registered for it was successfully found 
-   /// in the AST. 
-   class MatchCallback { 
-   public: 
-     virtual ~MatchCallback(); 
-   
-     /// Called on every match by the \c MatchFinder. 
-     virtual void run(const MatchResult &Result) = 0; 
-   
-     /// Called at the start of each translation unit. 
-     /// 
-     /// Optionally override to do per translation unit tasks. 
-     virtual void onStartOfTranslationUnit() {} 
-   
-     /// Called at the end of each translation unit. 
-     /// 
-     /// Optionally override to do per translation unit tasks. 
-     virtual void onEndOfTranslationUnit() {} 
-   
-     /// An id used to group the matchers. 
-     /// 
-     /// This id is used, for example, for the profiling output. 
-     /// It defaults to "<unknown>". 
-     virtual StringRef getID() const; 
-   
-     /// TraversalKind to use while matching and processing 
-     /// the result nodes. This API is temporary to facilitate 
-     /// third parties porting existing code to the default 
-     /// behavior of clang-tidy. 
-     virtual std::optional<TraversalKind> getCheckTraversalKind() const; 
-   }; 
-   
-   /// Called when parsing is finished. Intended for testing only. 
-   class ParsingDoneTestCallback { 
-   public: 
-     virtual ~ParsingDoneTestCallback(); 
-     virtual void run() = 0; 
-   }; 
-   
-   struct MatchFinderOptions { 
-     struct Profiling { 
-       Profiling(llvm::StringMap<llvm::TimeRecord> &Records) 
-           : Records(Records) {} 
-   
-       /// Per bucket timing information. 
-       llvm::StringMap<llvm::TimeRecord> &Records; 
-     }; 
-   
-     /// Enables per-check timers. 
-     /// 
-     /// It prints a report after match. 
-     std::optional<Profiling> CheckProfiling; 
-   }; 
-   
-   MatchFinder(MatchFinderOptions Options = MatchFinderOptions()); 
-   ~MatchFinder(); 
-   
-   /// 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); 
-   void addMatcher(const NestedNameSpecifierMatcher &NodeMatch, 
-                   MatchCallback *Action); 
-   void addMatcher(const NestedNameSpecifierLocMatcher &NodeMatch, 
-                   MatchCallback *Action); 
-   void addMatcher(const TypeLocMatcher &NodeMatch, 
-                   MatchCallback *Action); 
-   void addMatcher(const CXXCtorInitializerMatcher &NodeMatch, 
-                   MatchCallback *Action); 
-   void addMatcher(const TemplateArgumentLocMatcher &NodeMatch, 
-                   MatchCallback *Action); 
-   void addMatcher(const AttrMatcher &NodeMatch, MatchCallback *Action); 
-   /// @} 
-   
-   /// 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); 
-   
-   /// Creates a clang ASTConsumer that finds all matches. 
-   std::unique_ptr<clang::ASTConsumer> newASTConsumer(); 
-   
-   /// 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())). 
-   /// 
-   /// @{ 
-   template <typename T> void match(const T &Node, ASTContext &Context) { 
-     match(clang::DynTypedNode::create(Node), Context); 
-   } 
-   void match(const clang::DynTypedNode &Node, ASTContext &Context); 
-   /// @} 
-   
-   /// Finds all matches in the given AST. 
-   void matchAST(ASTContext &Context); 
-   
-   /// 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); 
-   
-   /// For each \c Matcher<> a \c MatchCallback that will be called 
-   /// when it matches. 
-   struct MatchersByType { 
-     std::vector<std::pair<internal::DynTypedMatcher, MatchCallback *>> 
-         DeclOrStmt; 
-     std::vector<std::pair<TypeMatcher, MatchCallback *>> Type; 
-     std::vector<std::pair<NestedNameSpecifierMatcher, MatchCallback *>> 
-         NestedNameSpecifier; 
-     std::vector<std::pair<NestedNameSpecifierLocMatcher, MatchCallback *>> 
-         NestedNameSpecifierLoc; 
-     std::vector<std::pair<TypeLocMatcher, MatchCallback *>> TypeLoc; 
-     std::vector<std::pair<CXXCtorInitializerMatcher, MatchCallback *>> CtorInit; 
-     std::vector<std::pair<TemplateArgumentLocMatcher, MatchCallback *>> 
-         TemplateArgumentLoc; 
-     std::vector<std::pair<AttrMatcher, MatchCallback *>> Attr; 
-     /// All the callbacks in one container to simplify iteration. 
-     llvm::SmallPtrSet<MatchCallback *, 16> AllCallbacks; 
-   }; 
-   
- private: 
-   MatchersByType Matchers; 
-   
-   MatchFinderOptions Options; 
-   
-   /// Called when parsing is done. 
-   ParsingDoneTestCallback *ParsingDone; 
- }; 
-   
- /// 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. 
- /// 
- /// If you want to find all matches on the sub-tree rooted at \c Node (rather 
- /// than only the matches on \c Node itself), surround the \c Matcher with a 
- /// \c findAll(). 
- /// 
- /// \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 DynTypedNode &Node, 
-                                  ASTContext &Context); 
- /// @} 
-   
- /// Returns the results of matching \p Matcher on the translation unit of 
- /// \p Context and collects the \c BoundNodes of all callback invocations. 
- template <typename MatcherT> 
- SmallVector<BoundNodes, 1> match(MatcherT Matcher, ASTContext &Context); 
-   
- /// 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); 
-   } 
-   
-   std::optional<TraversalKind> getCheckTraversalKind() const override { 
-     return std::nullopt; 
-   } 
-   
-   SmallVector<BoundNodes, 1> Nodes; 
- }; 
- } 
-   
- template <typename MatcherT> 
- SmallVector<BoundNodes, 1> match(MatcherT Matcher, const DynTypedNode &Node, 
-                                  ASTContext &Context) { 
-   internal::CollectMatchesCallback Callback; 
-   MatchFinder Finder; 
-   Finder.addMatcher(Matcher, &Callback); 
-   Finder.match(Node, Context); 
-   return std::move(Callback.Nodes); 
- } 
-   
- template <typename MatcherT, typename NodeT> 
- SmallVector<BoundNodes, 1> 
- match(MatcherT Matcher, const NodeT &Node, ASTContext &Context) { 
-   return match(Matcher, DynTypedNode::create(Node), Context); 
- } 
-   
- template <typename MatcherT> 
- SmallVector<BoundNodes, 1> 
- match(MatcherT Matcher, ASTContext &Context) { 
-   internal::CollectMatchesCallback Callback; 
-   MatchFinder Finder; 
-   Finder.addMatcher(Matcher, &Callback); 
-   Finder.matchAST(Context); 
-   return std::move(Callback.Nodes); 
- } 
-   
- inline SmallVector<BoundNodes, 1> 
- matchDynamic(internal::DynTypedMatcher Matcher, const DynTypedNode &Node, 
-              ASTContext &Context) { 
-   internal::CollectMatchesCallback Callback; 
-   MatchFinder Finder; 
-   Finder.addDynamicMatcher(Matcher, &Callback); 
-   Finder.match(Node, Context); 
-   return std::move(Callback.Nodes); 
- } 
-   
- template <typename NodeT> 
- SmallVector<BoundNodes, 1> matchDynamic(internal::DynTypedMatcher Matcher, 
-                                         const NodeT &Node, 
-                                         ASTContext &Context) { 
-   return matchDynamic(Matcher, DynTypedNode::create(Node), Context); 
- } 
-   
- inline SmallVector<BoundNodes, 1> 
- matchDynamic(internal::DynTypedMatcher Matcher, ASTContext &Context) { 
-   internal::CollectMatchesCallback Callback; 
-   MatchFinder Finder; 
-   Finder.addDynamicMatcher(Matcher, &Callback); 
-   Finder.matchAST(Context); 
-   return std::move(Callback.Nodes); 
- } 
-   
- } // end namespace ast_matchers 
- } // end namespace clang 
-   
- #endif 
-