diff options
author | Manuel Klimek <klimek@google.com> | 2013-02-06 10:33:21 +0000 |
---|---|---|
committer | Manuel Klimek <klimek@google.com> | 2013-02-06 10:33:21 +0000 |
commit | cf87bffc346244f0ed8eae7fffb52a0f03cd0413 (patch) | |
tree | a4330235837fae6bb6880f23fcafb99655fb55e2 /unittests/ASTMatchers/ASTMatchersTest.cpp | |
parent | 4e778091b0ff42895644ca8bef30f1a91ba6b32b (diff) |
Adds a convenience function selectFirst to simplify matching.
A very common use case is to search for the first occurrence of
a certain node that is a descendant of another node. In that
case, selectFirst significantly simplifies the code at the client side.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@174499 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'unittests/ASTMatchers/ASTMatchersTest.cpp')
-rw-r--r-- | unittests/ASTMatchers/ASTMatchersTest.cpp | 28 |
1 files changed, 16 insertions, 12 deletions
diff --git a/unittests/ASTMatchers/ASTMatchersTest.cpp b/unittests/ASTMatchers/ASTMatchersTest.cpp index 8668b4970e..60a79e86de 100644 --- a/unittests/ASTMatchers/ASTMatchersTest.cpp +++ b/unittests/ASTMatchers/ASTMatchersTest.cpp @@ -3493,53 +3493,57 @@ TEST(NNSLoc, NestedNameSpecifierLocsAsDescendants) { template <typename T> class VerifyMatchOnNode : public BoundNodesCallback { public: - VerifyMatchOnNode(StringRef Id, const internal::Matcher<T> &InnerMatcher) - : Id(Id), InnerMatcher(InnerMatcher) { + VerifyMatchOnNode(StringRef Id, const internal::Matcher<T> &InnerMatcher, + StringRef InnerId) + : Id(Id), InnerMatcher(InnerMatcher), InnerId(InnerId) { } virtual bool run(const BoundNodes *Nodes) { return false; } virtual bool run(const BoundNodes *Nodes, ASTContext *Context) { const T *Node = Nodes->getNodeAs<T>(Id); - SmallVector<BoundNodes, 1> Result = match(InnerMatcher, *Node, *Context); - return !Result.empty(); + return selectFirst<const T>(InnerId, + match(InnerMatcher, *Node, *Context)) != NULL; } private: std::string Id; internal::Matcher<T> InnerMatcher; + std::string InnerId; }; TEST(MatchFinder, CanMatchDeclarationsRecursively) { EXPECT_TRUE(matchAndVerifyResultTrue( "class X { class Y {}; };", recordDecl(hasName("::X")).bind("X"), new VerifyMatchOnNode<clang::Decl>( - "X", decl(hasDescendant(recordDecl(hasName("X::Y"))))))); + "X", decl(hasDescendant(recordDecl(hasName("X::Y")).bind("Y"))), + "Y"))); EXPECT_TRUE(matchAndVerifyResultFalse( "class X { class Y {}; };", recordDecl(hasName("::X")).bind("X"), new VerifyMatchOnNode<clang::Decl>( - "X", decl(hasDescendant(recordDecl(hasName("X::Z"))))))); + "X", decl(hasDescendant(recordDecl(hasName("X::Z")).bind("Z"))), + "Z"))); } TEST(MatchFinder, CanMatchStatementsRecursively) { EXPECT_TRUE(matchAndVerifyResultTrue( "void f() { if (1) { for (;;) { } } }", ifStmt().bind("if"), - new VerifyMatchOnNode<clang::Stmt>("if", - stmt(hasDescendant(forStmt()))))); + new VerifyMatchOnNode<clang::Stmt>( + "if", stmt(hasDescendant(forStmt().bind("for"))), "for"))); EXPECT_TRUE(matchAndVerifyResultFalse( "void f() { if (1) { for (;;) { } } }", ifStmt().bind("if"), - new VerifyMatchOnNode<clang::Stmt>("if", - stmt(hasDescendant(declStmt()))))); + new VerifyMatchOnNode<clang::Stmt>( + "if", stmt(hasDescendant(declStmt().bind("decl"))), "decl"))); } TEST(MatchFinder, CanMatchSingleNodesRecursively) { EXPECT_TRUE(matchAndVerifyResultTrue( "class X { class Y {}; };", recordDecl(hasName("::X")).bind("X"), new VerifyMatchOnNode<clang::Decl>( - "X", recordDecl(has(recordDecl(hasName("X::Y"))))))); + "X", recordDecl(has(recordDecl(hasName("X::Y")).bind("Y"))), "Y"))); EXPECT_TRUE(matchAndVerifyResultFalse( "class X { class Y {}; };", recordDecl(hasName("::X")).bind("X"), new VerifyMatchOnNode<clang::Decl>( - "X", recordDecl(has(recordDecl(hasName("X::Z"))))))); + "X", recordDecl(has(recordDecl(hasName("X::Z")).bind("Z"))), "Z"))); } class VerifyStartOfTranslationUnit : public MatchFinder::MatchCallback { |