[ASTMatchers] Extend hasParameter and hasAnyParameter matches to handle Objective-C methods

Differential Revision: https://reviews.llvm.org/D44707

llvm-svn: 328746
This commit is contained in:
George Karpenkov 2018-03-29 00:51:11 +00:00
parent b3f471a4bd
commit 9d1d0c4c57
5 changed files with 104 additions and 20 deletions

View File

@ -5298,7 +5298,7 @@ matches 'int x = 0' in
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('hasAnyParameter0')"><a name="hasAnyParameter0Anchor">hasAnyParameter</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ParmVarDecl.html">ParmVarDecl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasAnyParameter0"><pre>Matches any parameter of a function declaration.
<tr><td colspan="4" class="doc" id="hasAnyParameter0"><pre>Matches any parameter of a function or ObjC method declaration.
Does not match the 'this' parameter of a method.
@ -5308,6 +5308,13 @@ cxxMethodDecl(hasAnyParameter(hasName("y")))
matches f(int x, int y, int z) {}
with hasAnyParameter(...)
matching int y
For ObjectiveC, given
@interface I - (void) f:(int) y; @end
the matcher objcMethodDecl(hasAnyParameter(hasName("y")))
matches the declaration of method f with hasParameter
matching y.
</pre></td></tr>
@ -5347,7 +5354,8 @@ with compoundStmt()
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('hasParameter0')"><a name="hasParameter0Anchor">hasParameter</a></td><td>unsigned N, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ParmVarDecl.html">ParmVarDecl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasParameter0"><pre>Matches the n'th parameter of a function declaration.
<tr><td colspan="4" class="doc" id="hasParameter0"><pre>Matches the n'th parameter of a function or an ObjC method
declaration.
Given
class X { void f(int x) {} };
@ -5355,6 +5363,13 @@ cxxMethodDecl(hasParameter(0, hasType(varDecl())))
matches f(int x) {}
with hasParameter(...)
matching int x
For ObjectiveC, given
@interface I - (void) f:(int) y; @end
the matcher objcMethodDecl(hasParameter(0, hasName("y")))
matches the declaration of method f with hasParameter
matching y.
</pre></td></tr>
@ -5713,6 +5728,47 @@ matches the [webView ...] message invocation.
</pre></td></tr>
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMethodDecl.html">ObjCMethodDecl</a>&gt;</td><td class="name" onclick="toggle('hasAnyParameter1')"><a name="hasAnyParameter1Anchor">hasAnyParameter</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ParmVarDecl.html">ParmVarDecl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasAnyParameter1"><pre>Matches any parameter of a function or ObjC method declaration.
Does not match the 'this' parameter of a method.
Given
class X { void f(int x, int y, int z) {} };
cxxMethodDecl(hasAnyParameter(hasName("y")))
matches f(int x, int y, int z) {}
with hasAnyParameter(...)
matching int y
For ObjectiveC, given
@interface I - (void) f:(int) y; @end
the matcher objcMethodDecl(hasAnyParameter(hasName("y")))
matches the declaration of method f with hasParameter
matching y.
</pre></td></tr>
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMethodDecl.html">ObjCMethodDecl</a>&gt;</td><td class="name" onclick="toggle('hasParameter1')"><a name="hasParameter1Anchor">hasParameter</a></td><td>unsigned N, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ParmVarDecl.html">ParmVarDecl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasParameter1"><pre>Matches the n'th parameter of a function or an ObjC method
declaration.
Given
class X { void f(int x) {} };
cxxMethodDecl(hasParameter(0, hasType(varDecl())))
matches f(int x) {}
with hasParameter(...)
matching int x
For ObjectiveC, given
@interface I - (void) f:(int) y; @end
the matcher objcMethodDecl(hasParameter(0, hasName("y")))
matches the declaration of method f with hasParameter
matching y.
</pre></td></tr>
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1OpaqueValueExpr.html">OpaqueValueExpr</a>&gt;</td><td class="name" onclick="toggle('hasSourceExpression1')"><a name="hasSourceExpression1Anchor">hasSourceExpression</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasSourceExpression1"><pre>Matches if the cast's source expression
or opaque value's source expression matches the given matcher.

View File

@ -3466,7 +3466,8 @@ AST_MATCHER(CXXConstructExpr, requiresZeroInitialization) {
return Node.requiresZeroInitialization();
}
/// \brief Matches the n'th parameter of a function declaration.
/// \brief Matches the n'th parameter of a function or an ObjC method
/// declaration.
///
/// Given
/// \code
@ -3476,12 +3477,22 @@ AST_MATCHER(CXXConstructExpr, requiresZeroInitialization) {
/// matches f(int x) {}
/// with hasParameter(...)
/// matching int x
AST_MATCHER_P2(FunctionDecl, hasParameter,
unsigned, N, internal::Matcher<ParmVarDecl>,
InnerMatcher) {
return (N < Node.getNumParams() &&
InnerMatcher.matches(
*Node.getParamDecl(N), Finder, Builder));
///
/// For ObjectiveC, given
/// \code
/// @interface I - (void) f:(int) y; @end
/// \endcode
//
/// the matcher objcMethodDecl(hasParameter(0, hasName("y")))
/// matches the declaration of method f with hasParameter
/// matching y.
AST_POLYMORPHIC_MATCHER_P2(hasParameter,
AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl,
ObjCMethodDecl),
unsigned, N, internal::Matcher<ParmVarDecl>,
InnerMatcher) {
return (N < Node.parameters().size()
&& InnerMatcher.matches(*Node.parameters()[N], Finder, Builder));
}
/// \brief Matches all arguments and their respective ParmVarDecl.
@ -3538,7 +3549,7 @@ AST_POLYMORPHIC_MATCHER_P2(forEachArgumentWithParam,
return Matched;
}
/// \brief Matches any parameter of a function declaration.
/// \brief Matches any parameter of a function or ObjC method declaration.
///
/// Does not match the 'this' parameter of a method.
///
@ -3550,8 +3561,20 @@ AST_POLYMORPHIC_MATCHER_P2(forEachArgumentWithParam,
/// matches f(int x, int y, int z) {}
/// with hasAnyParameter(...)
/// matching int y
AST_MATCHER_P(FunctionDecl, hasAnyParameter,
internal::Matcher<ParmVarDecl>, InnerMatcher) {
///
/// For ObjectiveC, given
/// \code
/// @interface I - (void) f:(int) y; @end
/// \endcode
//
/// the matcher objcMethodDecl(hasAnyParameter(hasName("y")))
/// matches the declaration of method f with hasParameter
/// matching y.
AST_POLYMORPHIC_MATCHER_P(hasAnyParameter,
AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl,
ObjCMethodDecl),
internal::Matcher<ParmVarDecl>,
InnerMatcher) {
return matchesFirstInPointerRange(InnerMatcher, Node.param_begin(),
Node.param_end(), Finder, Builder);
}

View File

@ -87,7 +87,7 @@ public:
static std::unique_ptr<WorkList> makeUnexploredFirstPriorityQueue();
};
} // end GR namespace
} // end ento namespace
} // end clang namespace

View File

@ -539,6 +539,8 @@ TEST(HasParameter, CallsInnerMatcher) {
cxxMethodDecl(hasParameter(0, varDecl()))));
EXPECT_TRUE(notMatches("class X { void x(int) {} };",
cxxMethodDecl(hasParameter(0, hasName("x")))));
EXPECT_TRUE(matchesObjC("@interface I -(void)f:(int) x; @end",
objcMethodDecl(hasParameter(0, hasName("x")))));
}
TEST(HasParameter, DoesNotMatchIfIndexOutOfBounds) {
@ -568,6 +570,8 @@ TEST(HasAnyParameter, MatchesIndependentlyOfPosition) {
EXPECT_TRUE(matches(
"class Y {}; class X { void x(Y y, X x) {} };",
cxxMethodDecl(hasAnyParameter(hasType(recordDecl(hasName("X")))))));
EXPECT_TRUE(matchesObjC("@interface I -(void)f:(int) x; @end",
objcMethodDecl(hasAnyParameter(hasName("x")))));
}
TEST(Returns, MatchesReturnTypes) {

View File

@ -186,8 +186,8 @@ using ast_matchers::internal::Matcher;
Parser::NamedValueMap getTestNamedValues() {
Parser::NamedValueMap Values;
Values["nameX"] = llvm::StringRef("x");
Values["hasParamA"] =
VariantMatcher::SingleMatcher(hasParameter(0, hasName("a")));
Values["hasParamA"] = VariantMatcher::SingleMatcher(
functionDecl(hasParameter(0, hasName("a"))));
return Values;
}
@ -329,16 +329,17 @@ TEST(ParserTest, CompletionNamedValues) {
EXPECT_LT(0u, Comps.size());
// Can complete names and registry together.
Code = "cxxMethodDecl(hasP";
Code = "functionDecl(hasP";
Comps = Parser::completeExpression(Code, Code.size(), nullptr, &NamedValues);
ASSERT_EQ(3u, Comps.size());
EXPECT_EQ("aramA", Comps[0].TypedText);
EXPECT_EQ("Matcher<FunctionDecl> hasParamA", Comps[0].MatcherDecl);
EXPECT_EQ("arameter(", Comps[1].TypedText);
EXPECT_EQ("arameter(", Comps[0].TypedText);
EXPECT_EQ(
"Matcher<FunctionDecl> hasParameter(unsigned, Matcher<ParmVarDecl>)",
Comps[1].MatcherDecl);
Comps[0].MatcherDecl);
EXPECT_EQ("aramA", Comps[1].TypedText);
EXPECT_EQ("Matcher<Decl> hasParamA", Comps[1].MatcherDecl);
EXPECT_EQ("arent(", Comps[2].TypedText);
EXPECT_EQ(