RegistryTest.cpp revision e05481991929c83ea8de8e66dee9e59bd31bfb3d
1//===- unittest/ASTMatchers/Dynamic/RegistryTest.cpp - Registry unit tests -===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===-----------------------------------------------------------------------===// 9 10#include <vector> 11 12#include "../ASTMatchersTest.h" 13#include "clang/ASTMatchers/Dynamic/Registry.h" 14#include "gtest/gtest.h" 15 16namespace clang { 17namespace ast_matchers { 18namespace dynamic { 19namespace { 20 21using ast_matchers::internal::Matcher; 22 23class RegistryTest : public ::testing::Test { 24public: 25 std::vector<ParserValue> Args() { return std::vector<ParserValue>(); } 26 std::vector<ParserValue> Args(const VariantValue &Arg1) { 27 std::vector<ParserValue> Out(1); 28 Out[0].Value = Arg1; 29 return Out; 30 } 31 std::vector<ParserValue> Args(const VariantValue &Arg1, 32 const VariantValue &Arg2) { 33 std::vector<ParserValue> Out(2); 34 Out[0].Value = Arg1; 35 Out[1].Value = Arg2; 36 return Out; 37 } 38 39 template <class T> 40 Matcher<T> constructMatcher(StringRef MatcherName, Diagnostics *Error) { 41 return Registry::constructMatcher(MatcherName, SourceRange(), Args(), Error) 42 .getTypedMatcher<T>(); 43 } 44 45 template <class T> 46 Matcher<T> constructMatcher(StringRef MatcherName, const VariantValue &Arg1, 47 Diagnostics *Error) { 48 return Registry::constructMatcher(MatcherName, SourceRange(), Args(Arg1), 49 Error).getTypedMatcher<T>(); 50 } 51 52 template <class T> 53 Matcher<T> constructMatcher(StringRef MatcherName, const VariantValue &Arg1, 54 const VariantValue &Arg2, Diagnostics *Error) { 55 return Registry::constructMatcher(MatcherName, SourceRange(), 56 Args(Arg1, Arg2), Error) 57 .getTypedMatcher<T>(); 58 } 59}; 60 61TEST_F(RegistryTest, CanConstructNoArgs) { 62 Matcher<Stmt> IsArrowValue = constructMatcher<Stmt>( 63 "memberExpr", constructMatcher<MemberExpr>("isArrow", NULL), NULL); 64 Matcher<Stmt> BoolValue = constructMatcher<Stmt>("boolLiteral", NULL); 65 66 const std::string ClassSnippet = "struct Foo { int x; };\n" 67 "Foo *foo = new Foo;\n" 68 "int i = foo->x;\n"; 69 const std::string BoolSnippet = "bool Foo = true;\n"; 70 71 EXPECT_TRUE(matches(ClassSnippet, IsArrowValue)); 72 EXPECT_TRUE(matches(BoolSnippet, BoolValue)); 73 EXPECT_FALSE(matches(ClassSnippet, BoolValue)); 74 EXPECT_FALSE(matches(BoolSnippet, IsArrowValue)); 75} 76 77TEST_F(RegistryTest, ConstructWithSimpleArgs) { 78 Matcher<Decl> Value = constructMatcher<Decl>( 79 "namedDecl", 80 constructMatcher<NamedDecl>("hasName", std::string("X"), NULL), NULL); 81 EXPECT_TRUE(matches("class X {};", Value)); 82 EXPECT_FALSE(matches("int x;", Value)); 83 84 Value = 85 functionDecl(constructMatcher<FunctionDecl>("parameterCountIs", 2, NULL)); 86 EXPECT_TRUE(matches("void foo(int,int);", Value)); 87 EXPECT_FALSE(matches("void foo(int);", Value)); 88} 89 90TEST_F(RegistryTest, ConstructWithMatcherArgs) { 91 Matcher<Decl> HasInitializerSimple = constructMatcher<Decl>( 92 "varDecl", constructMatcher<VarDecl>("hasInitializer", stmt(), NULL), 93 NULL); 94 Matcher<Decl> HasInitializerComplex = constructMatcher<Decl>( 95 "varDecl", constructMatcher<VarDecl>("hasInitializer", callExpr(), NULL), 96 NULL); 97 98 std::string code = "int i;"; 99 EXPECT_FALSE(matches(code, HasInitializerSimple)); 100 EXPECT_FALSE(matches(code, HasInitializerComplex)); 101 102 code = "int i = 1;"; 103 EXPECT_TRUE(matches(code, HasInitializerSimple)); 104 EXPECT_FALSE(matches(code, HasInitializerComplex)); 105 106 code = "int y(); int i = y();"; 107 EXPECT_TRUE(matches(code, HasInitializerSimple)); 108 EXPECT_TRUE(matches(code, HasInitializerComplex)); 109 110 Matcher<Decl> HasParameter = functionDecl( 111 constructMatcher<FunctionDecl>("hasParameter", 1, hasName("x"), NULL)); 112 EXPECT_TRUE(matches("void f(int a, int x);", HasParameter)); 113 EXPECT_FALSE(matches("void f(int x, int a);", HasParameter)); 114} 115 116TEST_F(RegistryTest, PolymorphicMatchers) { 117 const MatcherList IsDefinition = 118 Registry::constructMatcher("isDefinition", SourceRange(), Args(), NULL); 119 Matcher<Decl> Var = constructMatcher<Decl>("varDecl", IsDefinition, NULL); 120 Matcher<Decl> Class = 121 constructMatcher<Decl>("recordDecl", IsDefinition, NULL); 122 Matcher<Decl> Func = 123 constructMatcher<Decl>("functionDecl", IsDefinition, NULL); 124 EXPECT_TRUE(matches("int a;", Var)); 125 EXPECT_FALSE(matches("extern int a;", Var)); 126 EXPECT_TRUE(matches("class A {};", Class)); 127 EXPECT_FALSE(matches("class A;", Class)); 128 EXPECT_TRUE(matches("void f(){};", Func)); 129 EXPECT_FALSE(matches("void f();", Func)); 130 131 Matcher<Decl> Anything = constructMatcher<Decl>("anything", NULL); 132 Matcher<Decl> RecordDecl = 133 constructMatcher<Decl>("recordDecl", Anything, NULL); 134 135 EXPECT_TRUE(matches("int a;", Anything)); 136 EXPECT_TRUE(matches("class A {};", Anything)); 137 EXPECT_TRUE(matches("void f(){};", Anything)); 138 // FIXME: A couple of tests have been suppressed. 139 // I know it'd be bad with _MSC_VER here, though. 140#if !defined(_MSC_VER) 141 EXPECT_FALSE(matches("int a;", RecordDecl)); 142#endif 143 EXPECT_TRUE(matches("class A {};", RecordDecl)); 144#if !defined(_MSC_VER) 145 EXPECT_FALSE(matches("void f(){};", RecordDecl)); 146#endif 147} 148 149TEST_F(RegistryTest, Errors) { 150 // Incorrect argument count. 151 OwningPtr<Diagnostics> Error(new Diagnostics()); 152 EXPECT_TRUE(Registry::constructMatcher("hasInitializer", SourceRange(), 153 Args(), Error.get()).empty()); 154 EXPECT_EQ("Incorrect argument count. (Expected = 1) != (Actual = 0)", 155 Error->ToString()); 156 Error.reset(new Diagnostics()); 157 EXPECT_TRUE(Registry::constructMatcher( 158 "isArrow", SourceRange(), Args(std::string()), Error.get()).empty()); 159 EXPECT_EQ("Incorrect argument count. (Expected = 0) != (Actual = 1)", 160 Error->ToString()); 161 162 // Bad argument type 163 Error.reset(new Diagnostics()); 164 EXPECT_TRUE(Registry::constructMatcher( 165 "ofClass", SourceRange(), Args(std::string()), Error.get()).empty()); 166 EXPECT_EQ("Incorrect type for arg 1. (Expected = Matcher<CXXRecordDecl>) != " 167 "(Actual = String)", 168 Error->ToString()); 169 Error.reset(new Diagnostics()); 170 EXPECT_TRUE(Registry::constructMatcher( 171 "recordDecl", SourceRange(), Args(recordDecl(), parameterCountIs(3)), 172 Error.get()).empty()); 173 EXPECT_EQ("Incorrect type for arg 2. (Expected = Matcher<CXXRecordDecl>) != " 174 "(Actual = Matcher<FunctionDecl>)", 175 Error->ToString()); 176} 177 178} // end anonymous namespace 179} // end namespace dynamic 180} // end namespace ast_matchers 181} // end namespace clang 182