martong added a comment.

> MatchFinder::match allows you to match a node. Wrapping your matcher code 
> with:
>  auto m = <my cool matcher>;
>  ast_matchers::match(anyOf(m, hashDescendant(m)), node, context);

Okay, I understand and accept that.
However, I consider that a different level of abstraction. 
`ast_matchers::match` uses `internal::CollectMatchesCallback` in its 
implementation. If I already have my own custom MatchCallback implemented then 
there is no way to achieve the desired behavior.

For example, in `ASTImporter` tests we use the following customized callback 
class:

  enum class DeclMatcherKind { First, Last };
  
  // Matcher class to retrieve the first/last matched node under a given AST.
  template <typename NodeType, DeclMatcherKind MatcherKind>
  class DeclMatcher : public MatchFinder::MatchCallback {
    NodeType *Node = nullptr;
    void run(const MatchFinder::MatchResult &Result) override {
      if ((MatcherKind == DeclMatcherKind::First && Node == nullptr) ||
          MatcherKind == DeclMatcherKind::Last) {
        Node = const_cast<NodeType *>(Result.Nodes.getNodeAs<NodeType>(""));
      }
    }
  public:
    // Returns the first/last matched node under the tree rooted in `D`.
    template <typename MatcherType>
    NodeType *match(const Decl *D, const MatcherType &AMatcher) {
      MatchFinder Finder;
      Finder.addMatcher(AMatcher.bind(""), this);
      Finder.matchAST(D->getASTContext());
      assert(Node);
      return Node;
    }
  };
  template <typename NodeType>
  using LastDeclMatcher = DeclMatcher<NodeType, DeclMatcherKind::Last>;
  template <typename NodeType>
  using FirstDeclMatcher = DeclMatcher<NodeType, DeclMatcherKind::First>;

And this is how we use it in the tests:

  Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX);
  auto Pattern = functionDecl(hasName("f"));
  auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
  auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);

At this point we would like to extend this `DeclMatcher` to be able to match a 
subtree, and be able to start the traverse from a specific `Decl`, something 
like this :

  auto *DV = FirsDeclMatcher<VarDecl>().match(D2, SomeOtherPattern);

Currently, I don't see how we could do this extension without the proposed 
`matchSubtree`. 
(Perhaps, we could refactor our `DeclMatcher` to not use a customized 
MatchCallback, rather use `ast_matchers::match`, but that sounds like a bad 
workaround to me.)

Hope this makes the the goal of this patch cleaner.


Repository:
  rC Clang

https://reviews.llvm.org/D49840



_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to