[PATCH] D49840: [AST] Add MatchFinder::matchSubtree

Manuel Klimek via cfe-commits cfe-commits at lists.llvm.org
Fri Jul 27 01:45:31 PDT 2018


On Fri, Jul 27, 2018 at 10:39 AM Gabor Marton via Phabricator <
reviews at reviews.llvm.org> wrote:

> 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.
>

Finder.match also has an overload that takes the node. Can you wrap
"Pattern" above in the anyOf(hasDescendant(...), ...) and match on the node
instead of the full AST?


>
>
> Repository:
>   rC Clang
>
> https://reviews.llvm.org/D49840
>
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20180727/3246a389/attachment-0001.html>


More information about the cfe-commits mailing list