[PATCH] D49840: [AST] Add MatchFinder::matchSubtree
Gabor Marton via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Fri Jul 27 01:39:49 PDT 2018
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
More information about the cfe-commits
mailing list