]> granicus.if.org Git - clang/commitdiff
[ASTMatchers] Introduce Objective-C matchers `isClassMessage`, `isClassMethod`, and...
authorBen Hamilton <benhamilton@google.com>
Mon, 22 Apr 2019 17:54:11 +0000 (17:54 +0000)
committerBen Hamilton <benhamilton@google.com>
Mon, 22 Apr 2019 17:54:11 +0000 (17:54 +0000)
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

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@358904 91177308-0d34-0410-b5e6-96231b3b80d8

docs/LibASTMatchersReference.html
include/clang/ASTMatchers/ASTMatchers.h
lib/ASTMatchers/Dynamic/Registry.cpp
unittests/ASTMatchers/ASTMatchersTraversalTest.cpp

index 3f8e4178d6bfeee756d92598a49ef4dfa8e11801..f0e965568da06a3a56a0e1a3102285085eb3ca95 100644 (file)
@@ -3567,11 +3567,24 @@ represent an error condition in the tree!
 </pre></td></tr>
 
 
+<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>&gt;</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&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>&gt;</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&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCMethodDecl.html">ObjCMethodDecl</a>&gt;</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&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCMethodDecl.html">ObjCMethodDecl</a>&gt;</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&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>&gt;</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.
index c5ec9f48a05a3b8f858daf3550787477371c2896..661dcbc76705bf421c8f163abdc5d616332a1518 100644 (file)
@@ -2938,10 +2938,59 @@ AST_MATCHER_P(ObjCMessageExpr, hasReceiverType, internal::Matcher<QualType>,
   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";
index b7e0a25757e8b130fa96a228be1dd8a7928a25b5..37f1a0077a05bfeaf37b42a754776353c1a983d5 100644 (file)
@@ -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);
index bdd476091afd7e78ca4c690064949a0ee7e675d8..dafc8c52e9a822abe29347bdd1966f3bee22e893 100644 (file)
@@ -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 {