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 16 namespace clang { 17 namespace ast_matchers { 18 namespace dynamic { 19 namespace { 20 21 using ast_matchers::internal::Matcher; 22 23 class RegistryTest : public ::testing::Test { 24 public: 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 OwningPtr<DynTypedMatcher> Out( 42 Registry::constructMatcher(MatcherName, SourceRange(), Args(), Error)); 43 return Matcher<T>::constructFrom(*Out); 44 } 45 46 template <class T> 47 Matcher<T> constructMatcher(StringRef MatcherName, const VariantValue &Arg1, 48 Diagnostics *Error) { 49 OwningPtr<DynTypedMatcher> Out(Registry::constructMatcher( 50 MatcherName, SourceRange(), Args(Arg1), Error)); 51 return Matcher<T>::constructFrom(*Out); 52 } 53 54 template <class T> 55 Matcher<T> constructMatcher(StringRef MatcherName, const VariantValue &Arg1, 56 const VariantValue &Arg2, Diagnostics *Error) { 57 OwningPtr<DynTypedMatcher> Out(Registry::constructMatcher( 58 MatcherName, SourceRange(), Args(Arg1, Arg2), Error)); 59 return Matcher<T>::constructFrom(*Out); 60 } 61 }; 62 63 TEST_F(RegistryTest, CanConstructNoArgs) { 64 Matcher<Stmt> IsArrowValue = constructMatcher<Stmt>( 65 "memberExpr", constructMatcher<MemberExpr>("isArrow", NULL), NULL); 66 Matcher<Stmt> BoolValue = constructMatcher<Stmt>("boolLiteral", NULL); 67 68 const std::string ClassSnippet = "struct Foo { int x; };\n" 69 "Foo *foo = new Foo;\n" 70 "int i = foo->x;\n"; 71 const std::string BoolSnippet = "bool Foo = true;\n"; 72 73 EXPECT_TRUE(matches(ClassSnippet, IsArrowValue)); 74 EXPECT_TRUE(matches(BoolSnippet, BoolValue)); 75 EXPECT_FALSE(matches(ClassSnippet, BoolValue)); 76 EXPECT_FALSE(matches(BoolSnippet, IsArrowValue)); 77 } 78 79 TEST_F(RegistryTest, ConstructWithSimpleArgs) { 80 Matcher<Decl> Value = constructMatcher<Decl>( 81 "namedDecl", 82 constructMatcher<NamedDecl>("hasName", std::string("X"), NULL), NULL); 83 EXPECT_TRUE(matches("class X {};", Value)); 84 EXPECT_FALSE(matches("int x;", Value)); 85 86 Value = 87 functionDecl(constructMatcher<FunctionDecl>("parameterCountIs", 2, NULL)); 88 EXPECT_TRUE(matches("void foo(int,int);", Value)); 89 EXPECT_FALSE(matches("void foo(int);", Value)); 90 } 91 92 TEST_F(RegistryTest, ConstructWithMatcherArgs) { 93 Matcher<Decl> HasInitializerSimple = constructMatcher<Decl>( 94 "varDecl", constructMatcher<VarDecl>("hasInitializer", stmt(), NULL), 95 NULL); 96 Matcher<Decl> HasInitializerComplex = constructMatcher<Decl>( 97 "varDecl", constructMatcher<VarDecl>("hasInitializer", callExpr(), NULL), 98 NULL); 99 100 std::string code = "int i;"; 101 EXPECT_FALSE(matches(code, HasInitializerSimple)); 102 EXPECT_FALSE(matches(code, HasInitializerComplex)); 103 104 code = "int i = 1;"; 105 EXPECT_TRUE(matches(code, HasInitializerSimple)); 106 EXPECT_FALSE(matches(code, HasInitializerComplex)); 107 108 code = "int y(); int i = y();"; 109 EXPECT_TRUE(matches(code, HasInitializerSimple)); 110 EXPECT_TRUE(matches(code, HasInitializerComplex)); 111 112 Matcher<Decl> HasParameter = functionDecl( 113 constructMatcher<FunctionDecl>("hasParameter", 1, hasName("x"), NULL)); 114 EXPECT_TRUE(matches("void f(int a, int x);", HasParameter)); 115 EXPECT_FALSE(matches("void f(int x, int a);", HasParameter)); 116 } 117 118 TEST_F(RegistryTest, Errors) { 119 // Incorrect argument count. 120 OwningPtr<Diagnostics> Error(new Diagnostics()); 121 EXPECT_TRUE(NULL == 122 Registry::constructMatcher("hasInitializer", SourceRange(), 123 Args(), Error.get())); 124 EXPECT_EQ("Incorrect argument count. (Expected = 1) != (Actual = 0)", 125 Error->ToString()); 126 Error.reset(new Diagnostics()); 127 EXPECT_TRUE(NULL == 128 Registry::constructMatcher("isArrow", SourceRange(), 129 Args(std::string()), Error.get())); 130 EXPECT_EQ("Incorrect argument count. (Expected = 0) != (Actual = 1)", 131 Error->ToString()); 132 133 // Bad argument type 134 Error.reset(new Diagnostics()); 135 EXPECT_TRUE(NULL == 136 Registry::constructMatcher("ofClass", SourceRange(), 137 Args(std::string()), Error.get())); 138 EXPECT_EQ("Incorrect type for arg 1. (Expected = Matcher<CXXRecordDecl>) != " 139 "(Actual = String)", 140 Error->ToString()); 141 Error.reset(new Diagnostics()); 142 EXPECT_TRUE(NULL == 143 Registry::constructMatcher( 144 "recordDecl", SourceRange(), 145 Args(recordDecl(), parameterCountIs(3)), Error.get())); 146 EXPECT_EQ("Incorrect type for arg 2. (Expected = Matcher<CXXRecordDecl>) != " 147 "(Actual = Matcher<FunctionDecl>)", 148 Error->ToString()); 149 } 150 151 } // end anonymous namespace 152 } // end namespace dynamic 153 } // end namespace ast_matchers 154 } // end namespace clang 155