Author: benhamilton Date: Mon Apr 22 10:54:11 2019 New Revision: 358904 URL: http://llvm.org/viewvc/llvm-project?rev=358904&view=rev Log: [ASTMatchers] Introduce Objective-C matchers `isClassMessage`, `isClassMethod`, and `isInstanceMethod`
Summary: isClassMessage is an equivalent to isInstanceMessage for ObjCMessageExpr, but matches message expressions to classes. isClassMethod and isInstanceMethod check whether a method declaration (or definition) is for a class method or instance method (respectively). Contributed by @mywman! Reviewers: benhamilton, klimek, mwyman Reviewed By: benhamilton, mwyman Subscribers: cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D60920 Modified: cfe/trunk/docs/LibASTMatchersReference.html cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp cfe/trunk/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp Modified: cfe/trunk/docs/LibASTMatchersReference.html URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/LibASTMatchersReference.html?rev=358904&r1=358903&r2=358904&view=diff ============================================================================== --- cfe/trunk/docs/LibASTMatchersReference.html (original) +++ cfe/trunk/docs/LibASTMatchersReference.html Mon Apr 22 10:54:11 2019 @@ -3567,11 +3567,24 @@ represent an error condition in the tree </pre></td></tr> +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>></td><td class="name" onclick="toggle('isClassMessage0')"><a name="isClassMessage0Anchor">isClassMessage</a></td><td></td></tr> +<tr><td colspan="4" class="doc" id="isClassMessage0"><pre>Returns true when the Objective-C message is sent to a class. + +Example +matcher = objcMessageExpr(isClassMessage()) +matches + [NSString stringWithFormat:@"format"]; +but not + NSString *x = @"hello"; + [x containsString:@"h"]; +</pre></td></tr> + + <tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>></td><td class="name" onclick="toggle('isInstanceMessage0')"><a name="isInstanceMessage0Anchor">isInstanceMessage</a></td><td></td></tr> <tr><td colspan="4" class="doc" id="isInstanceMessage0"><pre>Returns true when the Objective-C message is sent to an instance. Example -matcher = objcMessagaeExpr(isInstanceMessage()) +matcher = objcMessageExpr(isInstanceMessage()) matches NSString *x = @"hello"; [x containsString:@"h"]; @@ -3580,6 +3593,30 @@ but not </pre></td></tr> +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCMethodDecl.html">ObjCMethodDecl</a>></td><td class="name" onclick="toggle('isClassMethod0')"><a name="isClassMethod0Anchor">isClassMethod</a></td><td></td></tr> +<tr><td colspan="4" class="doc" id="isClassMethod0"><pre>Returns true when the Objective-C method declaration is a class method. + +Example +matcher = objcMethodDecl(isClassMethod()) +matches + @interface I + (void)foo; @end +but not + @interface I - (void)bar; @end +</pre></td></tr> + + +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCMethodDecl.html">ObjCMethodDecl</a>></td><td class="name" onclick="toggle('isInstanceMessage0')"><a name="isInstanceMessage0Anchor">isInstanceMethod</a></td><td></td></tr> +<tr><td colspan="4" class="doc" id="isInstanceMethod0"><pre>Returns true when the Objective-C method declaration is an instance method. + +Example +matcher = objcMethodDecl(isInstanceMethod()) +matches + @interface I - (void)bar; @end +but not + @interface I + (void)foo; @end +</pre></td></tr> + + <tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>></td><td class="name" onclick="toggle('matchesSelector0')"><a name="matchesSelector0Anchor">matchesSelector</a></td><td>std::string RegExp</td></tr> <tr><td colspan="4" class="doc" id="matchesSelector0"><pre>Matches ObjC selectors whose name contains a substring matched by the given RegExp. Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h?rev=358904&r1=358903&r2=358904&view=diff ============================================================================== --- cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h (original) +++ cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h Mon Apr 22 10:54:11 2019 @@ -2938,10 +2938,59 @@ AST_MATCHER_P(ObjCMessageExpr, hasReceiv return InnerMatcher.matches(TypeDecl, Finder, Builder); } +/// Returns true when the Objective-C method declaration is a class method. +/// +/// Example +/// matcher = objcMethodDecl(isClassMethod()) +/// matches +/// \code +/// @interface I + (void)foo; @end +/// \endcode +/// but not +/// \code +/// @interface I - (void)bar; @end +/// \endcode +AST_MATCHER(ObjCMethodDecl, isClassMethod) { + return Node.isClassMethod(); +} + +/// Returns true when the Objective-C method declaration is an instance method. +/// +/// Example +/// matcher = objcMethodDecl(isInstanceMethod()) +/// matches +/// \code +/// @interface I - (void)bar; @end +/// \endcode +/// but not +/// \code +/// @interface I + (void)foo; @end +/// \endcode +AST_MATCHER(ObjCMethodDecl, isInstanceMethod) { + return Node.isInstanceMethod(); +} + +/// Returns true when the Objective-C message is sent to a class. +/// +/// Example +/// matcher = objcMessageExpr(isClassMessage()) +/// matches +/// \code +/// [NSString stringWithFormat:@"format"]; +/// \endcode +/// but not +/// \code +/// NSString *x = @"hello"; +/// [x containsString:@"h"]; +/// \endcode +AST_MATCHER(ObjCMessageExpr, isClassMessage) { + return Node.isClassMessage(); +} + /// Returns true when the Objective-C message is sent to an instance. /// /// Example -/// matcher = objcMessagaeExpr(isInstanceMessage()) +/// matcher = objcMessageExpr(isInstanceMessage()) /// matches /// \code /// NSString *x = @"hello"; Modified: cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp?rev=358904&r1=358903&r2=358904&view=diff ============================================================================== --- cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp (original) +++ cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp Mon Apr 22 10:54:11 2019 @@ -344,6 +344,8 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(isBitField); REGISTER_MATCHER(isCatchAll); REGISTER_MATCHER(isClass); + REGISTER_MATCHER(isClassMessage); + REGISTER_MATCHER(isClassMethod); REGISTER_MATCHER(isConst); REGISTER_MATCHER(isConstQualified); REGISTER_MATCHER(isConstexpr); @@ -367,6 +369,7 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(isInTemplateInstantiation); REGISTER_MATCHER(isInline); REGISTER_MATCHER(isInstanceMessage); + REGISTER_MATCHER(isInstanceMethod); REGISTER_MATCHER(isInstantiated); REGISTER_MATCHER(isInstantiationDependent); REGISTER_MATCHER(isInteger); Modified: cfe/trunk/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp?rev=358904&r1=358903&r2=358904&view=diff ============================================================================== --- cfe/trunk/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp (original) +++ cfe/trunk/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp Mon Apr 22 10:54:11 2019 @@ -454,6 +454,20 @@ TEST(Matcher, HasReceiver) { objcMessageExpr(hasReceiver(declRefExpr(to(varDecl(hasName("x")))))))); } +TEST(Matcher, isClassMessage) { + EXPECT_TRUE(matchesObjC( + "@interface NSString +(NSString *) stringWithFormat; @end " + "void f() { [NSString stringWithFormat]; }", + objcMessageExpr(isClassMessage()))); + + EXPECT_FALSE(matchesObjC( + "@interface NSString @end " + "void f(NSString *x) {" + "[x containsString];" + "}", + objcMessageExpr(isClassMessage()))); +} + TEST(Matcher, isInstanceMessage) { EXPECT_TRUE(matchesObjC( "@interface NSString @end " @@ -469,6 +483,46 @@ TEST(Matcher, isInstanceMessage) { } +TEST(Matcher, isClassMethod) { + EXPECT_TRUE(matchesObjC( + "@interface Bar + (void)bar; @end", + objcMethodDecl(isClassMethod()))); + + EXPECT_TRUE(matchesObjC( + "@interface Bar @end" + "@implementation Bar + (void)bar {} @end", + objcMethodDecl(isClassMethod()))); + + EXPECT_FALSE(matchesObjC( + "@interface Foo - (void)foo; @end", + objcMethodDecl(isClassMethod()))); + + EXPECT_FALSE(matchesObjC( + "@interface Foo @end " + "@implementation Foo - (void)foo {} @end", + objcMethodDecl(isClassMethod()))); +} + +TEST(Matcher, isInstanceMethod) { + EXPECT_TRUE(matchesObjC( + "@interface Foo - (void)foo; @end", + objcMethodDecl(isInstanceMethod()))); + + EXPECT_TRUE(matchesObjC( + "@interface Foo @end " + "@implementation Foo - (void)foo {} @end", + objcMethodDecl(isInstanceMethod()))); + + EXPECT_FALSE(matchesObjC( + "@interface Bar + (void)bar; @end", + objcMethodDecl(isInstanceMethod()))); + + EXPECT_FALSE(matchesObjC( + "@interface Bar @end" + "@implementation Bar + (void)bar {} @end", + objcMethodDecl(isInstanceMethod()))); +} + TEST(MatcherCXXMemberCallExpr, On) { auto Snippet1 = R"cc( struct Y { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits