forked from OSchip/llvm-project
Add AST matchers for ObjCProtocolDecl, ObjCCategoryDecl, ObjCMethodDecl, ObjCIvarDecl, and ObjCPropertyDecl.
Patch by Dave Lee. llvm-svn: 297882
This commit is contained in:
parent
43e3f97797
commit
9fd6ee6a78
|
@ -337,6 +337,15 @@ nonTypeTemplateParmDecl()
|
||||||
</pre></td></tr>
|
</pre></td></tr>
|
||||||
|
|
||||||
|
|
||||||
|
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('objcCategoryDecl0')"><a name="objcCategoryDecl0Anchor">objcCategoryDecl</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCCategoryDecl.html">ObjCCategoryDecl</a>>...</td></tr>
|
||||||
|
<tr><td colspan="4" class="doc" id="objcCategoryDecl0"><pre>Matches Objective-C category declarations.
|
||||||
|
|
||||||
|
Example matches Foo (Additions)
|
||||||
|
@interface Foo (Additions)
|
||||||
|
@end
|
||||||
|
</pre></td></tr>
|
||||||
|
|
||||||
|
|
||||||
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('objcInterfaceDecl0')"><a name="objcInterfaceDecl0Anchor">objcInterfaceDecl</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCInterfaceDecl.html">ObjCInterfaceDecl</a>>...</td></tr>
|
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('objcInterfaceDecl0')"><a name="objcInterfaceDecl0Anchor">objcInterfaceDecl</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCInterfaceDecl.html">ObjCInterfaceDecl</a>>...</td></tr>
|
||||||
<tr><td colspan="4" class="doc" id="objcInterfaceDecl0"><pre>Matches Objective-C interface declarations.
|
<tr><td colspan="4" class="doc" id="objcInterfaceDecl0"><pre>Matches Objective-C interface declarations.
|
||||||
|
|
||||||
|
@ -346,6 +355,50 @@ Example matches Foo
|
||||||
</pre></td></tr>
|
</pre></td></tr>
|
||||||
|
|
||||||
|
|
||||||
|
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('objcIvarDecl0')"><a name="objcIvarDecl0Anchor">objcIvarDecl</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCIvarDecl.html">ObjCIvarDecl</a>>...</td></tr>
|
||||||
|
<tr><td colspan="4" class="doc" id="objcIvarDecl0"><pre>Matches Objective-C instance variable declarations.
|
||||||
|
|
||||||
|
Example matches _enabled
|
||||||
|
@implementation Foo {
|
||||||
|
BOOL _enabled;
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
</pre></td></tr>
|
||||||
|
|
||||||
|
|
||||||
|
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('objcMethodDecl0')"><a name="objcMethodDecl0Anchor">objcMethodDecl</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMethodDecl.html">ObjCMethodDecl</a>>...</td></tr>
|
||||||
|
<tr><td colspan="4" class="doc" id="objcMethodDecl0"><pre>Matches Objective-C method declarations.
|
||||||
|
|
||||||
|
Example matches both declaration and definition of -[Foo method]
|
||||||
|
@interface Foo
|
||||||
|
- (void)method;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation Foo
|
||||||
|
- (void)method {}
|
||||||
|
@end
|
||||||
|
</pre></td></tr>
|
||||||
|
|
||||||
|
|
||||||
|
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('objcPropertyDecl0')"><a name="objcPropertyDecl0Anchor">objcPropertyDecl</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCPropertyDecl.html">ObjCPropertyDecl</a>>...</td></tr>
|
||||||
|
<tr><td colspan="4" class="doc" id="objcPropertyDecl0"><pre>Matches Objective-C property declarations.
|
||||||
|
|
||||||
|
Example matches enabled
|
||||||
|
@interface Foo
|
||||||
|
@property BOOL enabled;
|
||||||
|
@end
|
||||||
|
</pre></td></tr>
|
||||||
|
|
||||||
|
|
||||||
|
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('objcProtocolDecl0')"><a name="objcProtocolDecl0Anchor">objcProtocolDecl</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCProtocolDecl.html">ObjCProtocolDecl</a>>...</td></tr>
|
||||||
|
<tr><td colspan="4" class="doc" id="objcProtocolDecl0"><pre>Matches Objective-C protocol declarations.
|
||||||
|
|
||||||
|
Example matches FooDelegate
|
||||||
|
@protocol FooDelegate
|
||||||
|
@end
|
||||||
|
</pre></td></tr>
|
||||||
|
|
||||||
|
|
||||||
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('parmVarDecl0')"><a name="parmVarDecl0Anchor">parmVarDecl</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ParmVarDecl.html">ParmVarDecl</a>>...</td></tr>
|
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('parmVarDecl0')"><a name="parmVarDecl0Anchor">parmVarDecl</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ParmVarDecl.html">ParmVarDecl</a>>...</td></tr>
|
||||||
<tr><td colspan="4" class="doc" id="parmVarDecl0"><pre>Matches parameter variable declarations.
|
<tr><td colspan="4" class="doc" id="parmVarDecl0"><pre>Matches parameter variable declarations.
|
||||||
|
|
||||||
|
|
|
@ -1118,6 +1118,69 @@ const internal::VariadicDynCastAllOfMatcher<
|
||||||
Decl,
|
Decl,
|
||||||
ObjCInterfaceDecl> objcInterfaceDecl;
|
ObjCInterfaceDecl> objcInterfaceDecl;
|
||||||
|
|
||||||
|
/// \brief Matches Objective-C protocol declarations.
|
||||||
|
///
|
||||||
|
/// Example matches FooDelegate
|
||||||
|
/// \code
|
||||||
|
/// @protocol FooDelegate
|
||||||
|
/// @end
|
||||||
|
/// \endcode
|
||||||
|
const internal::VariadicDynCastAllOfMatcher<
|
||||||
|
Decl,
|
||||||
|
ObjCProtocolDecl> objcProtocolDecl;
|
||||||
|
|
||||||
|
/// \brief Matches Objective-C category declarations.
|
||||||
|
///
|
||||||
|
/// Example matches Foo (Additions)
|
||||||
|
/// \code
|
||||||
|
/// @interface Foo (Additions)
|
||||||
|
/// @end
|
||||||
|
/// \endcode
|
||||||
|
const internal::VariadicDynCastAllOfMatcher<
|
||||||
|
Decl,
|
||||||
|
ObjCCategoryDecl> objcCategoryDecl;
|
||||||
|
|
||||||
|
/// \brief Matches Objective-C method declarations.
|
||||||
|
///
|
||||||
|
/// Example matches both declaration and definition of -[Foo method]
|
||||||
|
/// \code
|
||||||
|
/// @interface Foo
|
||||||
|
/// - (void)method;
|
||||||
|
/// @end
|
||||||
|
///
|
||||||
|
/// @implementation Foo
|
||||||
|
/// - (void)method {}
|
||||||
|
/// @end
|
||||||
|
/// \endcode
|
||||||
|
const internal::VariadicDynCastAllOfMatcher<
|
||||||
|
Decl,
|
||||||
|
ObjCMethodDecl> objcMethodDecl;
|
||||||
|
|
||||||
|
/// \brief Matches Objective-C instance variable declarations.
|
||||||
|
///
|
||||||
|
/// Example matches _enabled
|
||||||
|
/// \code
|
||||||
|
/// @implementation Foo {
|
||||||
|
/// BOOL _enabled;
|
||||||
|
/// }
|
||||||
|
/// @end
|
||||||
|
/// \endcode
|
||||||
|
const internal::VariadicDynCastAllOfMatcher<
|
||||||
|
Decl,
|
||||||
|
ObjCIvarDecl> objcIvarDecl;
|
||||||
|
|
||||||
|
/// \brief Matches Objective-C property declarations.
|
||||||
|
///
|
||||||
|
/// Example matches enabled
|
||||||
|
/// \code
|
||||||
|
/// @interface Foo
|
||||||
|
/// @property BOOL enabled;
|
||||||
|
/// @end
|
||||||
|
/// \endcode
|
||||||
|
const internal::VariadicDynCastAllOfMatcher<
|
||||||
|
Decl,
|
||||||
|
ObjCPropertyDecl> objcPropertyDecl;
|
||||||
|
|
||||||
/// \brief Matches expressions that introduce cleanups to be run at the end
|
/// \brief Matches expressions that introduce cleanups to be run at the end
|
||||||
/// of the sub-expression's evaluation.
|
/// of the sub-expression's evaluation.
|
||||||
///
|
///
|
||||||
|
|
|
@ -359,9 +359,14 @@ RegistryMaps::RegistryMaps() {
|
||||||
REGISTER_MATCHER(nullStmt);
|
REGISTER_MATCHER(nullStmt);
|
||||||
REGISTER_MATCHER(numSelectorArgs);
|
REGISTER_MATCHER(numSelectorArgs);
|
||||||
REGISTER_MATCHER(ofClass);
|
REGISTER_MATCHER(ofClass);
|
||||||
|
REGISTER_MATCHER(objcCategoryDecl);
|
||||||
REGISTER_MATCHER(objcInterfaceDecl);
|
REGISTER_MATCHER(objcInterfaceDecl);
|
||||||
|
REGISTER_MATCHER(objcIvarDecl);
|
||||||
REGISTER_MATCHER(objcMessageExpr);
|
REGISTER_MATCHER(objcMessageExpr);
|
||||||
|
REGISTER_MATCHER(objcMethodDecl);
|
||||||
REGISTER_MATCHER(objcObjectPointerType);
|
REGISTER_MATCHER(objcObjectPointerType);
|
||||||
|
REGISTER_MATCHER(objcPropertyDecl);
|
||||||
|
REGISTER_MATCHER(objcProtocolDecl);
|
||||||
REGISTER_MATCHER(on);
|
REGISTER_MATCHER(on);
|
||||||
REGISTER_MATCHER(onImplicitObjectArgument);
|
REGISTER_MATCHER(onImplicitObjectArgument);
|
||||||
REGISTER_MATCHER(opaqueValueExpr);
|
REGISTER_MATCHER(opaqueValueExpr);
|
||||||
|
|
|
@ -1500,9 +1500,10 @@ TEST(ObjCMessageExprMatcher, SimpleExprs) {
|
||||||
|
|
||||||
std::string Objc1String =
|
std::string Objc1String =
|
||||||
"@interface Str "
|
"@interface Str "
|
||||||
" - (Str *)uppercaseString:(Str *)str;"
|
" - (Str *)uppercaseString;"
|
||||||
"@end "
|
"@end "
|
||||||
"@interface foo "
|
"@interface foo "
|
||||||
|
"- (void)contents;"
|
||||||
"- (void)meth:(Str *)text;"
|
"- (void)meth:(Str *)text;"
|
||||||
"@end "
|
"@end "
|
||||||
" "
|
" "
|
||||||
|
@ -1540,5 +1541,45 @@ TEST(ObjCMessageExprMatcher, SimpleExprs) {
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(ObjCDeclMacher, CoreDecls) {
|
||||||
|
std::string ObjCString =
|
||||||
|
"@protocol Proto "
|
||||||
|
"- (void)protoDidThing; "
|
||||||
|
"@end "
|
||||||
|
"@interface Thing "
|
||||||
|
"@property int enabled; "
|
||||||
|
"@end "
|
||||||
|
"@interface Thing (ABC) "
|
||||||
|
"- (void)abc_doThing; "
|
||||||
|
"@end "
|
||||||
|
"@implementation Thing "
|
||||||
|
"{ id _ivar; } "
|
||||||
|
"- (void)anything {} "
|
||||||
|
"@end "
|
||||||
|
;
|
||||||
|
|
||||||
|
EXPECT_TRUE(matchesObjC(
|
||||||
|
ObjCString,
|
||||||
|
objcProtocolDecl(hasName("Proto"))));
|
||||||
|
EXPECT_TRUE(matchesObjC(
|
||||||
|
ObjCString,
|
||||||
|
objcCategoryDecl(hasName("ABC"))));
|
||||||
|
EXPECT_TRUE(matchesObjC(
|
||||||
|
ObjCString,
|
||||||
|
objcMethodDecl(hasName("protoDidThing"))));
|
||||||
|
EXPECT_TRUE(matchesObjC(
|
||||||
|
ObjCString,
|
||||||
|
objcMethodDecl(hasName("abc_doThing"))));
|
||||||
|
EXPECT_TRUE(matchesObjC(
|
||||||
|
ObjCString,
|
||||||
|
objcMethodDecl(hasName("anything"))));
|
||||||
|
EXPECT_TRUE(matchesObjC(
|
||||||
|
ObjCString,
|
||||||
|
objcIvarDecl(hasName("_ivar"))));
|
||||||
|
EXPECT_TRUE(matchesObjC(
|
||||||
|
ObjCString,
|
||||||
|
objcPropertyDecl(hasName("enabled"))));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ast_matchers
|
} // namespace ast_matchers
|
||||||
} // namespace clang
|
} // namespace clang
|
||||||
|
|
|
@ -61,7 +61,7 @@ private:
|
||||||
template <typename T>
|
template <typename T>
|
||||||
testing::AssertionResult matchesConditionally(
|
testing::AssertionResult matchesConditionally(
|
||||||
const std::string &Code, const T &AMatcher, bool ExpectMatch,
|
const std::string &Code, const T &AMatcher, bool ExpectMatch,
|
||||||
llvm::StringRef CompileArg,
|
llvm::ArrayRef<llvm::StringRef> CompileArgs,
|
||||||
const FileContentMappings &VirtualMappedFiles = FileContentMappings(),
|
const FileContentMappings &VirtualMappedFiles = FileContentMappings(),
|
||||||
const std::string &Filename = "input.cc") {
|
const std::string &Filename = "input.cc") {
|
||||||
bool Found = false, DynamicFound = false;
|
bool Found = false, DynamicFound = false;
|
||||||
|
@ -81,8 +81,9 @@ testing::AssertionResult matchesConditionally(
|
||||||
// FIXME: This is a hack to work around the fact that there's no way to do the
|
// FIXME: This is a hack to work around the fact that there's no way to do the
|
||||||
// equivalent of runToolOnCodeWithArgs without instantiating a full Driver.
|
// equivalent of runToolOnCodeWithArgs without instantiating a full Driver.
|
||||||
// We should consider having a function, at least for tests, that invokes cc1.
|
// We should consider having a function, at least for tests, that invokes cc1.
|
||||||
std::vector<std::string> Args = {CompileArg, "-frtti", "-fexceptions",
|
std::vector<std::string> Args(CompileArgs.begin(), CompileArgs.end());
|
||||||
"-target", "i386-unknown-unknown"};
|
Args.insert(Args.end(), {"-frtti", "-fexceptions",
|
||||||
|
"-target", "i386-unknown-unknown"});
|
||||||
if (!runToolOnCodeWithArgs(
|
if (!runToolOnCodeWithArgs(
|
||||||
Factory->create(), Code, Args, Filename, "clang-tool",
|
Factory->create(), Code, Args, Filename, "clang-tool",
|
||||||
std::make_shared<PCHContainerOperations>(), VirtualMappedFiles)) {
|
std::make_shared<PCHContainerOperations>(), VirtualMappedFiles)) {
|
||||||
|
@ -104,6 +105,17 @@ testing::AssertionResult matchesConditionally(
|
||||||
return testing::AssertionSuccess();
|
return testing::AssertionSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
testing::AssertionResult matchesConditionally(
|
||||||
|
const std::string &Code, const T &AMatcher, bool ExpectMatch,
|
||||||
|
llvm::StringRef CompileArg,
|
||||||
|
const FileContentMappings &VirtualMappedFiles = FileContentMappings(),
|
||||||
|
const std::string &Filename = "input.cc") {
|
||||||
|
return matchesConditionally(Code, AMatcher, ExpectMatch,
|
||||||
|
llvm::makeArrayRef(CompileArg),
|
||||||
|
VirtualMappedFiles, Filename);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
testing::AssertionResult matches(const std::string &Code, const T &AMatcher) {
|
testing::AssertionResult matches(const std::string &Code, const T &AMatcher) {
|
||||||
return matchesConditionally(Code, AMatcher, true, "-std=c++11");
|
return matchesConditionally(Code, AMatcher, true, "-std=c++11");
|
||||||
|
@ -116,11 +128,12 @@ testing::AssertionResult notMatches(const std::string &Code,
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
testing::AssertionResult matchesObjC(const std::string &Code,
|
testing::AssertionResult matchesObjC(const std::string &Code, const T &AMatcher,
|
||||||
const T &AMatcher) {
|
bool ExpectMatch = true) {
|
||||||
return matchesConditionally(
|
return matchesConditionally(Code, AMatcher, ExpectMatch,
|
||||||
Code, AMatcher, true,
|
{"-fobjc-nonfragile-abi", "-Wno-objc-root-class",
|
||||||
"", FileContentMappings(), "input.m");
|
"-Wno-incomplete-implementation"},
|
||||||
|
FileContentMappings(), "input.m");
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
@ -145,10 +158,8 @@ testing::AssertionResult notMatchesC(const std::string &Code,
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
testing::AssertionResult notMatchesObjC(const std::string &Code,
|
testing::AssertionResult notMatchesObjC(const std::string &Code,
|
||||||
const T &AMatcher) {
|
const T &AMatcher) {
|
||||||
return matchesConditionally(
|
return matchesObjC(Code, AMatcher, false);
|
||||||
Code, AMatcher, false,
|
|
||||||
"", FileContentMappings(), "input.m");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue