Author: george.karpenkov Date: Wed Mar 28 17:51:12 2018 New Revision: 328747
URL: http://llvm.org/viewvc/llvm-project?rev=328747&view=rev Log: [ASTMatchers] Introduce a matcher for matching any given Objective-C selector Incudes a tiny related refactoring. Differential Revision: https://reviews.llvm.org/D44858 Modified: cfe/trunk/docs/LibASTMatchersReference.html cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h cfe/trunk/lib/ASTMatchers/ASTMatchersInternal.cpp cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp cfe/trunk/unittests/ASTMatchers/ASTMatchersNodeTest.cpp cfe/trunk/unittests/ASTMatchers/Dynamic/ParserTest.cpp Modified: cfe/trunk/docs/LibASTMatchersReference.html URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/LibASTMatchersReference.html?rev=328747&r1=328746&r2=328747&view=diff ============================================================================== --- cfe/trunk/docs/LibASTMatchersReference.html (original) +++ cfe/trunk/docs/LibASTMatchersReference.html Wed Mar 28 17:51:12 2018 @@ -3958,6 +3958,17 @@ This matcher is only provided as a perfo </pre></td></tr> +<tr><td>Matcher<internal::Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>>></td><td class="name" onclick="toggle('hasAnySelector0')"><a name="hasAnySelector0Anchor">hasAnySelector</a></td><td>StringRef, ..., StringRef</td></tr> +<tr><td colspan="4" class="doc" id="hasAnySelector0"><pre>Matches when at least one of the supplied string equals to the +Selector.getAsString() + + matcher = objCMessageExpr(hasSelector("methodA:", "methodB:")); + matches both of the expressions below: + [myObj methodA:argA]; + [myObj methodB:argB]; +</pre></td></tr> + + <tr><td>Matcher<internal::Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>>></td><td class="name" onclick="toggle('isInTemplateInstantiation0')"><a name="isInTemplateInstantiation0Anchor">isInTemplateInstantiation</a></td><td></td></tr> <tr><td colspan="4" class="doc" id="isInTemplateInstantiation0"><pre>Matches statements inside of a template instantiation. Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h?rev=328747&r1=328746&r2=328747&view=diff ============================================================================== --- cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h (original) +++ cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h Wed Mar 28 17:51:12 2018 @@ -2313,9 +2313,7 @@ inline internal::Matcher<Stmt> sizeOfExp /// namespace a { namespace b { class X; } } /// \endcode inline internal::Matcher<NamedDecl> hasName(const std::string &Name) { - std::vector<std::string> Names; - Names.push_back(Name); - return internal::Matcher<NamedDecl>(new internal::HasNameMatcher(Names)); + return internal::Matcher<NamedDecl>(new internal::HasNameMatcher({Name})); } /// \brief Matches NamedDecl nodes that have any of the specified names. @@ -2711,7 +2709,7 @@ AST_MATCHER_P(ObjCMessageExpr, hasReceiv const QualType TypeDecl = Node.getReceiverType(); return InnerMatcher.matches(TypeDecl, Finder, Builder); } - + /// \brief Matches when BaseName == Selector.getAsString() /// /// matcher = objCMessageExpr(hasSelector("loadHTMLString:baseURL:")); @@ -2725,7 +2723,21 @@ AST_MATCHER_P(ObjCMessageExpr, hasSelect return BaseName.compare(Sel.getAsString()) == 0; } - + +/// \brief Matches when at least one of the supplied string equals to the +/// Selector.getAsString() +/// +/// matcher = objCMessageExpr(hasSelector("methodA:", "methodB:")); +/// matches both of the expressions below: +/// \code +/// [myObj methodA:argA]; +/// [myObj methodB:argB]; +/// \endcode +extern const internal::VariadicFunction<internal::Matcher<ObjCMessageExpr>, + StringRef, + internal::hasAnySelectorFunc> + hasAnySelector; + /// \brief Matches ObjC selectors whose name contains /// a substring matched by the given RegExp. /// matcher = objCMessageExpr(matchesSelector("loadHTMLString\:baseURL?")); Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h?rev=328747&r1=328746&r2=328747&view=diff ============================================================================== --- cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h (original) +++ cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h Wed Mar 28 17:51:12 2018 @@ -731,6 +731,11 @@ class HasNameMatcher : public SingleNode /// HasNameMatcher. Matcher<NamedDecl> hasAnyNameFunc(ArrayRef<const StringRef *> NameRefs); +/// \brief Trampoline function to use VariadicFunction<> to construct a +/// hasAnySelector matcher. +Matcher<ObjCMessageExpr> hasAnySelectorFunc( + ArrayRef<const StringRef *> NameRefs); + /// \brief Matches declarations for QualType and CallExpr. /// /// Type argument DeclMatcherT is required by PolymorphicMatcherWithParam1 but Modified: cfe/trunk/lib/ASTMatchers/ASTMatchersInternal.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/ASTMatchersInternal.cpp?rev=328747&r1=328746&r2=328747&view=diff ============================================================================== --- cfe/trunk/lib/ASTMatchers/ASTMatchersInternal.cpp (original) +++ cfe/trunk/lib/ASTMatchers/ASTMatchersInternal.cpp Wed Mar 28 17:51:12 2018 @@ -315,12 +315,31 @@ bool AnyOfVariadicOperator(const ast_typ return false; } -Matcher<NamedDecl> hasAnyNameFunc(ArrayRef<const StringRef *> NameRefs) { +inline static +std::vector<std::string> vectorFromRefs(ArrayRef<const StringRef *> NameRefs) { std::vector<std::string> Names; for (auto *Name : NameRefs) Names.emplace_back(*Name); - return internal::Matcher<NamedDecl>( - new internal::HasNameMatcher(std::move(Names))); + return Names; +} + +Matcher<NamedDecl> hasAnyNameFunc(ArrayRef<const StringRef *> NameRefs) { + std::vector<std::string> Names = vectorFromRefs(NameRefs); + return internal::Matcher<NamedDecl>(new internal::HasNameMatcher(Names)); +} + +AST_MATCHER_P(ObjCMessageExpr, hasAnySelectorMatcher, std::vector<std::string>, + Matches) { + std::string SelString = Node.getSelector().getAsString(); + for (const std::string &S : Matches) + if (S == SelString) + return true; + return false; +} + +Matcher<ObjCMessageExpr> hasAnySelectorFunc( + ArrayRef<const StringRef *> NameRefs) { + return hasAnySelectorMatcher(vectorFromRefs(NameRefs)); } HasNameMatcher::HasNameMatcher(std::vector<std::string> N) @@ -393,7 +412,8 @@ public: /// Return true if there are still any patterns left. bool consumeNameSuffix(StringRef NodeName, bool CanSkip) { for (size_t I = 0; I < Patterns.size();) { - if (internal::consumeNameSuffix(Patterns[I].P, NodeName) || + if (::clang::ast_matchers::internal::consumeNameSuffix(Patterns[I].P, + NodeName) || CanSkip) { ++I; } else { Modified: cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp?rev=328747&r1=328746&r2=328747&view=diff ============================================================================== --- cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp (original) +++ cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp Wed Mar 28 17:51:12 2018 @@ -286,6 +286,7 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(hasReturnValue); REGISTER_MATCHER(hasRHS); REGISTER_MATCHER(hasSelector); + REGISTER_MATCHER(hasAnySelector); REGISTER_MATCHER(hasSingleDecl); REGISTER_MATCHER(hasSize); REGISTER_MATCHER(hasSizeExpr); Modified: cfe/trunk/unittests/ASTMatchers/ASTMatchersNodeTest.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/ASTMatchersNodeTest.cpp?rev=328747&r1=328746&r2=328747&view=diff ============================================================================== --- cfe/trunk/unittests/ASTMatchers/ASTMatchersNodeTest.cpp (original) +++ cfe/trunk/unittests/ASTMatchers/ASTMatchersNodeTest.cpp Wed Mar 28 17:51:12 2018 @@ -1565,11 +1565,22 @@ TEST(ObjCMessageExprMatcher, SimpleExprs EXPECT_TRUE(matchesObjC( Objc1String, objcMessageExpr(anything()))); + EXPECT_TRUE(matchesObjC(Objc1String, + objcMessageExpr(hasAnySelector({ + "contents", "meth:"})) + + )); EXPECT_TRUE(matchesObjC( Objc1String, objcMessageExpr(hasSelector("contents")))); EXPECT_TRUE(matchesObjC( Objc1String, + objcMessageExpr(hasAnySelector("contents", "contentsA")))); + EXPECT_FALSE(matchesObjC( + Objc1String, + objcMessageExpr(hasAnySelector("contentsB", "contentsC")))); + EXPECT_TRUE(matchesObjC( + Objc1String, objcMessageExpr(matchesSelector("cont*")))); EXPECT_FALSE(matchesObjC( Objc1String, Modified: cfe/trunk/unittests/ASTMatchers/Dynamic/ParserTest.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/Dynamic/ParserTest.cpp?rev=328747&r1=328746&r2=328747&view=diff ============================================================================== --- cfe/trunk/unittests/ASTMatchers/Dynamic/ParserTest.cpp (original) +++ cfe/trunk/unittests/ASTMatchers/Dynamic/ParserTest.cpp Wed Mar 28 17:51:12 2018 @@ -236,6 +236,17 @@ TEST(ParserTest, FullParserTest) { Error.toStringFull()); } +TEST(ParserTest, VariadicMatchTest) { + Diagnostics Error; + llvm::Optional<DynTypedMatcher> OM(Parser::parseMatcherExpression( + "stmt(objcMessageExpr(hasAnySelector(\"methodA\", \"methodB:\")))", + &Error)); + EXPECT_EQ("", Error.toStringFull()); + auto M = OM->unconditionalConvertTo<Stmt>(); + EXPECT_TRUE(matchesObjC("@interface I @end " + "void foo(I* i) { [i methodA]; }", M)); +} + std::string ParseWithError(StringRef Code) { Diagnostics Error; VariantValue Value; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits