diff options
-rw-r--r-- | docs/LibASTMatchersReference.html | 34 | ||||
-rw-r--r-- | include/clang/ASTMatchers/ASTMatchers.h | 23 | ||||
-rw-r--r-- | unittests/ASTMatchers/ASTMatchersTest.cpp | 28 |
3 files changed, 85 insertions, 0 deletions
diff --git a/docs/LibASTMatchersReference.html b/docs/LibASTMatchersReference.html index 163743cdc9..672c12d9b9 100644 --- a/docs/LibASTMatchersReference.html +++ b/docs/LibASTMatchersReference.html @@ -1675,6 +1675,40 @@ match expressions.</p> <tr style="text-align:left"><th>Return type</th><th>Name</th><th>Parameters</th></tr> <!-- START_TRAVERSAL_MATCHERS --> +<tr><td>Matcher<*></td><td class="name" onclick="toggle('eachOf0')"><a name="eachOf0Anchor">eachOf</a></td><td>Matcher<*> P1, Matcher<*> P2</td></tr> +<tr><td colspan="4" class="doc" id="eachOf0"><pre>Matches if any of the given matchers matches. + +Unlike anyOf, eachOf will generate a match result for each +matching submatcher. + +For example, in: + class A { int a; int b; }; +The matcher: + recordDecl(eachOf(has(fieldDecl(hasName("a")).bind("v")), + has(fieldDecl(hasName("b")).bind("v")))) +will generate two results binding "v", the first of which binds +the field declaration of a, the second the field declaration of +b. + +Usable as: Any Matcher +</pre></td></tr> + + +<tr><td>Matcher<*></td><td class="name" onclick="toggle('findAll0')"><a name="findAll0Anchor">findAll</a></td><td>Matcher<T> Matcher</td></tr> +<tr><td colspan="4" class="doc" id="findAll0"><pre>Matches if the node or any descendant matches. + +Generates results for each match. + +For example, in: + class A { class B {}; class C {}; }; +The matcher: + recordDecl(hasName("::A"), findAll(recordDecl(isDefinition()).bind("m"))) +will generate results for A, B and C. + +Usable as: Any Matcher +</pre></td></tr> + + <tr><td>Matcher<*></td><td class="name" onclick="toggle('forEach0')"><a name="forEach0Anchor">forEach</a></td><td>Matcher<ChildT> ChildMatcher</td></tr> <tr><td colspan="4" class="doc" id="forEach0"><pre>Matches AST nodes that have child AST nodes that match the provided matcher. diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h index bd26d09b8b..933ef6b27e 100644 --- a/include/clang/ASTMatchers/ASTMatchers.h +++ b/include/clang/ASTMatchers/ASTMatchers.h @@ -1450,6 +1450,29 @@ forEachDescendant( DescendantT>(DescendantMatcher); } +/// \brief Matches if the node or any descendant matches. +/// +/// Generates results for each match. +/// +/// For example, in: +/// \code +/// class A { class B {}; class C {}; }; +/// \endcode +/// The matcher: +/// \code +/// recordDecl(hasName("::A"), findAll(recordDecl(isDefinition()).bind("m"))) +/// \endcode +/// will generate results for \c A, \c B and \c C. +/// +/// Usable as: Any Matcher +template <typename T> +internal::PolymorphicMatcherWithParam2< + internal::EachOfMatcher, internal::Matcher<T>, + internal::ArgumentAdaptingMatcher<internal::ForEachDescendantMatcher, T> > +findAll(const internal::Matcher<T> &Matcher) { + return eachOf(Matcher, forEachDescendant(Matcher)); +} + /// \brief Matches AST nodes that have a parent that matches the provided /// matcher. /// diff --git a/unittests/ASTMatchers/ASTMatchersTest.cpp b/unittests/ASTMatchers/ASTMatchersTest.cpp index dc8b15fde1..8668b4970e 100644 --- a/unittests/ASTMatchers/ASTMatchersTest.cpp +++ b/unittests/ASTMatchers/ASTMatchersTest.cpp @@ -2854,6 +2854,34 @@ TEST(ForEachDescendant, BindsCorrectNodes) { new VerifyIdIsBoundTo<FunctionDecl>("decl", 1))); } +TEST(FindAll, BindsNodeOnMatch) { + EXPECT_TRUE(matchAndVerifyResultTrue( + "class A {};", + recordDecl(hasName("::A"), findAll(recordDecl(hasName("::A")).bind("v"))), + new VerifyIdIsBoundTo<CXXRecordDecl>("v", 1))); +} + +TEST(FindAll, BindsDescendantNodeOnMatch) { + EXPECT_TRUE(matchAndVerifyResultTrue( + "class A { int a; int b; };", + recordDecl(hasName("::A"), findAll(fieldDecl().bind("v"))), + new VerifyIdIsBoundTo<FieldDecl>("v", 2))); +} + +TEST(FindAll, BindsNodeAndDescendantNodesOnOneMatch) { + EXPECT_TRUE(matchAndVerifyResultTrue( + "class A { int a; int b; };", + recordDecl(hasName("::A"), + findAll(decl(anyOf(recordDecl(hasName("::A")).bind("v"), + fieldDecl().bind("v"))))), + new VerifyIdIsBoundTo<Decl>("v", 3))); + + EXPECT_TRUE(matchAndVerifyResultTrue( + "class A { class B {}; class C {}; };", + recordDecl(hasName("::A"), findAll(recordDecl(isDefinition()).bind("v"))), + new VerifyIdIsBoundTo<CXXRecordDecl>("v", 3))); +} + TEST(EachOf, TriggersForEachMatch) { EXPECT_TRUE(matchAndVerifyResultTrue( "class A { int a; int b; };", |