r174315 - Add an eachOf matcher.
Daniel Jasper
djasper at google.com
Mon Feb 4 11:19:25 PST 2013
On Mon, Feb 4, 2013 at 10:42 AM, Manuel Klimek <klimek at google.com> wrote:
> Author: klimek
> Date: Mon Feb 4 03:42:38 2013
> New Revision: 174315
>
> URL: http://llvm.org/viewvc/llvm-project?rev=174315&view=rev
> Log:
> Add an eachOf matcher.
>
> eachOf gives closure on the forEach and forEachDescendant matchers.
> Before, it was impossible to implement a findAll matcher, as matching
> the node or any of its descendants was not expressible (since anyOf
> only triggers the first match).
>
> Modified:
> cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h
> cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h
> cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp
>
> Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h?rev=174315&r1=174314&r2=174315&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h (original)
> +++ cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h Mon Feb 4 03:42:38
> 2013
> @@ -1095,6 +1095,32 @@ const internal::VariadicDynCastAllOfMatc
> /// \brief Matches \c TypeLocs in the clang AST.
> const internal::VariadicDynCastAllOfMatcher<TypeLoc, TypeLoc> typeLoc;
>
> +/// \brief Matches if any of the given matchers matches.
> +///
> +/// Unlike \c anyOf, \c eachOf will generate a match result for each
> +/// matching submatcher.
> +///
> +/// For example, in:
> +/// \code
> +/// class A { int a; int b; };
> +/// \endcode
> +/// The matcher:
> +/// \code
> +/// recordDecl(eachOf(has(fieldDecl(hasName("a")).bind("v")),
> +/// has(fieldDecl(hasName("b")).bind("v"))))
> +/// \endcode
> +/// will generate two results binding "v", the first of which binds
> +/// the field declaration of \c a, the second the field declaration of
> +/// \c b.
> +///
> +/// Usable as: Any Matcher
> +template <typename M1, typename M2>
> +internal::PolymorphicMatcherWithParam2<internal::EachOfMatcher, M1, M2>
> +eachOf(const M1 &P1, const M2 &P2) {
> + return internal::PolymorphicMatcherWithParam2<internal::EachOfMatcher,
> M1,
> + M2>(P1, P2);
> +}
> +
>
Should we add more overloads (similar to anyOf and allOf)?
> /// \brief Various overloads for the anyOf matcher.
> /// @{
>
>
> Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h?rev=174315&r1=174314&r2=174315&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h (original)
> +++ cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h Mon Feb 4
> 03:42:38 2013
> @@ -832,21 +832,56 @@ private:
> /// used. They will always be instantiated with types convertible to
> /// Matcher<T>.
> template <typename T, typename MatcherT1, typename MatcherT2>
> +class EachOfMatcher : public MatcherInterface<T> {
> +public:
> + EachOfMatcher(const Matcher<T> &InnerMatcher1,
> + const Matcher<T> &InnerMatcher2)
> + : InnerMatcher1(InnerMatcher1), InnerMatcher2(InnerMatcher2) {
> + }
> +
> + virtual bool matches(const T &Node, ASTMatchFinder *Finder,
> + BoundNodesTreeBuilder *Builder) const {
> + BoundNodesTreeBuilder Builder1;
>
Could you directly use \p Builder for one of these? (I think we do that at
some other place(s) and thus it would be slightly more consistent.
> + bool Matched1 = InnerMatcher1.matches(Node, Finder, &Builder1);
> + if (Matched1)
> + Builder->addMatch(Builder1.build());
> +
> + BoundNodesTreeBuilder Builder2;
> + bool Matched2 = InnerMatcher2.matches(Node, Finder, &Builder2);
> + if (Matched2)
> + Builder->addMatch(Builder2.build());
> +
> + return Matched1 || Matched2;
> + }
> +
> +private:
> + const Matcher<T> InnerMatcher1;
> + const Matcher<T> InnerMatcher2;
> +};
> +
> +/// \brief Matches nodes of type T for which at least one of the two
> provided
> +/// matchers matches.
> +///
> +/// Type arguments MatcherT1 and MatcherT2 are
> +/// required by PolymorphicMatcherWithParam2 but not actually
> +/// used. They will always be instantiated with types convertible to
> +/// Matcher<T>.
> +template <typename T, typename MatcherT1, typename MatcherT2>
> class AnyOfMatcher : public MatcherInterface<T> {
> public:
> AnyOfMatcher(const Matcher<T> &InnerMatcher1, const Matcher<T>
> &InnerMatcher2)
> - : InnerMatcher1(InnerMatcher1), InnertMatcher2(InnerMatcher2) {}
> + : InnerMatcher1(InnerMatcher1), InnerMatcher2(InnerMatcher2) {}
>
> virtual bool matches(const T &Node,
> ASTMatchFinder *Finder,
> BoundNodesTreeBuilder *Builder) const {
> return InnerMatcher1.matches(Node, Finder, Builder) ||
> - InnertMatcher2.matches(Node, Finder, Builder);
> + InnerMatcher2.matches(Node, Finder, Builder);
> }
>
> private:
> const Matcher<T> InnerMatcher1;
> - const Matcher<T> InnertMatcher2;
> + const Matcher<T> InnerMatcher2;
> };
>
> /// \brief Creates a Matcher<T> that matches if all inner matchers match.
>
> Modified: cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp?rev=174315&r1=174314&r2=174315&view=diff
>
> ==============================================================================
> --- cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp (original)
> +++ cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp Mon Feb 4
> 03:42:38 2013
> @@ -2854,6 +2854,30 @@ TEST(ForEachDescendant, BindsCorrectNode
> new VerifyIdIsBoundTo<FunctionDecl>("decl", 1)));
> }
>
> +TEST(EachOf, TriggersForEachMatch) {
> + EXPECT_TRUE(matchAndVerifyResultTrue(
> + "class A { int a; int b; };",
> + recordDecl(eachOf(has(fieldDecl(hasName("a")).bind("v")),
> + has(fieldDecl(hasName("b")).bind("v")))),
> + new VerifyIdIsBoundTo<FieldDecl>("v", 2)));
> +}
>
Probably not important at all, but it might be nice to show that you also
get two results if you bind the outer recordDecl()..
> +
> +TEST(EachOf, BehavesLikeAnyOfUnlessBothMatch) {
> + EXPECT_TRUE(matchAndVerifyResultTrue(
> + "class A { int a; int c; };",
> + recordDecl(eachOf(has(fieldDecl(hasName("a")).bind("v")),
> + has(fieldDecl(hasName("b")).bind("v")))),
> + new VerifyIdIsBoundTo<FieldDecl>("v", 1)));
> + EXPECT_TRUE(matchAndVerifyResultTrue(
> + "class A { int c; int b; };",
> + recordDecl(eachOf(has(fieldDecl(hasName("a")).bind("v")),
> + has(fieldDecl(hasName("b")).bind("v")))),
> + new VerifyIdIsBoundTo<FieldDecl>("v", 1)));
> + EXPECT_TRUE(notMatches(
> + "class A { int c; int d; };",
> + recordDecl(eachOf(has(fieldDecl(hasName("a")).bind("v")),
> + has(fieldDecl(hasName("b")).bind("v"))))));
> +}
>
> TEST(IsTemplateInstantiation, MatchesImplicitClassTemplateInstantiation) {
> // Make sure that we can both match the class by name (::X) and by the
> type
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130204/e8763163/attachment.html>
More information about the cfe-commits
mailing list