r328747 - [ASTMatchers] Introduce a matcher for matching any given Objective-C selector
George Karpenkov via cfe-commits
cfe-commits at lists.llvm.org
Wed Mar 28 17:51:12 PDT 2018
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;
More information about the cfe-commits
mailing list