RegistryTest.cpp revision 3f84bb341bfb1312842b09db71d76bc3898ba247
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 MatcherList constructMatcher(StringRef MatcherName, 40 Diagnostics *Error = NULL) { 41 Diagnostics DummyError; 42 if (!Error) Error = &DummyError; 43 const MatcherList Out = 44 Registry::constructMatcher(MatcherName, SourceRange(), Args(), Error); 45 EXPECT_EQ("", DummyError.ToStringFull()); 46 return Out; 47 } 48 49 MatcherList constructMatcher(StringRef MatcherName, const VariantValue &Arg1, 50 Diagnostics *Error = NULL) { 51 Diagnostics DummyError; 52 if (!Error) Error = &DummyError; 53 const MatcherList Out = Registry::constructMatcher( 54 MatcherName, SourceRange(), Args(Arg1), Error); 55 EXPECT_EQ("", DummyError.ToStringFull()); 56 return Out; 57 } 58 59 MatcherList constructMatcher(StringRef MatcherName, const VariantValue &Arg1, 60 const VariantValue &Arg2, 61 Diagnostics *Error = NULL) { 62 Diagnostics DummyError; 63 if (!Error) Error = &DummyError; 64 const MatcherList Out = Registry::constructMatcher( 65 MatcherName, SourceRange(), Args(Arg1, Arg2), Error); 66 EXPECT_EQ("", DummyError.ToStringFull()); 67 return Out; 68 } 69}; 70 71TEST_F(RegistryTest, CanConstructNoArgs) { 72 Matcher<Stmt> IsArrowValue = constructMatcher( 73 "memberExpr", constructMatcher("isArrow")).getTypedMatcher<Stmt>(); 74 Matcher<Stmt> BoolValue = 75 constructMatcher("boolLiteral").getTypedMatcher<Stmt>(); 76 77 const std::string ClassSnippet = "struct Foo { int x; };\n" 78 "Foo *foo = new Foo;\n" 79 "int i = foo->x;\n"; 80 const std::string BoolSnippet = "bool Foo = true;\n"; 81 82 EXPECT_TRUE(matches(ClassSnippet, IsArrowValue)); 83 EXPECT_TRUE(matches(BoolSnippet, BoolValue)); 84 EXPECT_FALSE(matches(ClassSnippet, BoolValue)); 85 EXPECT_FALSE(matches(BoolSnippet, IsArrowValue)); 86} 87 88TEST_F(RegistryTest, ConstructWithSimpleArgs) { 89 Matcher<Decl> Value = constructMatcher( 90 "namedDecl", constructMatcher("hasName", std::string("X"))) 91 .getTypedMatcher<Decl>(); 92 EXPECT_TRUE(matches("class X {};", Value)); 93 EXPECT_FALSE(matches("int x;", Value)); 94 95 Value = functionDecl(constructMatcher("parameterCountIs", 2) 96 .getTypedMatcher<FunctionDecl>()); 97 EXPECT_TRUE(matches("void foo(int,int);", Value)); 98 EXPECT_FALSE(matches("void foo(int);", Value)); 99} 100 101TEST_F(RegistryTest, ConstructWithMatcherArgs) { 102 Matcher<Decl> HasInitializerSimple = 103 constructMatcher("varDecl", constructMatcher("hasInitializer", stmt())) 104 .getTypedMatcher<Decl>(); 105 Matcher<Decl> HasInitializerComplex = constructMatcher( 106 "varDecl", constructMatcher("hasInitializer", callExpr())) 107 .getTypedMatcher<Decl>(); 108 109 std::string code = "int i;"; 110 EXPECT_FALSE(matches(code, HasInitializerSimple)); 111 EXPECT_FALSE(matches(code, HasInitializerComplex)); 112 113 code = "int i = 1;"; 114 EXPECT_TRUE(matches(code, HasInitializerSimple)); 115 EXPECT_FALSE(matches(code, HasInitializerComplex)); 116 117 code = "int y(); int i = y();"; 118 EXPECT_TRUE(matches(code, HasInitializerSimple)); 119 EXPECT_TRUE(matches(code, HasInitializerComplex)); 120 121 Matcher<Decl> HasParameter = functionDecl(constructMatcher( 122 "hasParameter", 1, hasName("x")).getTypedMatcher<FunctionDecl>()); 123 EXPECT_TRUE(matches("void f(int a, int x);", HasParameter)); 124 EXPECT_FALSE(matches("void f(int x, int a);", HasParameter)); 125} 126 127TEST_F(RegistryTest, PolymorphicMatchers) { 128 const MatcherList IsDefinition = constructMatcher("isDefinition"); 129 Matcher<Decl> Var = 130 constructMatcher("varDecl", IsDefinition).getTypedMatcher<Decl>(); 131 Matcher<Decl> Class = 132 constructMatcher("recordDecl", IsDefinition).getTypedMatcher<Decl>(); 133 Matcher<Decl> Func = 134 constructMatcher("functionDecl", IsDefinition).getTypedMatcher<Decl>(); 135 EXPECT_TRUE(matches("int a;", Var)); 136 EXPECT_FALSE(matches("extern int a;", Var)); 137 EXPECT_TRUE(matches("class A {};", Class)); 138 EXPECT_FALSE(matches("class A;", Class)); 139 EXPECT_TRUE(matches("void f(){};", Func)); 140 EXPECT_FALSE(matches("void f();", Func)); 141 142 Matcher<Decl> Anything = constructMatcher("anything").getTypedMatcher<Decl>(); 143 Matcher<Decl> RecordDecl = 144 constructMatcher("recordDecl", Anything).getTypedMatcher<Decl>(); 145 146 EXPECT_TRUE(matches("int a;", Anything)); 147 EXPECT_TRUE(matches("class A {};", Anything)); 148 EXPECT_TRUE(matches("void f(){};", Anything)); 149 // FIXME: A couple of tests have been suppressed. 150 // I know it'd be bad with _MSC_VER here, though. 151#if !defined(_MSC_VER) 152 EXPECT_FALSE(matches("int a;", RecordDecl)); 153#endif 154 EXPECT_TRUE(matches("class A {};", RecordDecl)); 155#if !defined(_MSC_VER) 156 EXPECT_FALSE(matches("void f(){};", RecordDecl)); 157#endif 158} 159 160TEST_F(RegistryTest, TypeTraversal) { 161 Matcher<Type> M = constructMatcher( 162 "pointerType", 163 constructMatcher("pointee", constructMatcher("isConstQualified"), 164 constructMatcher("isInteger"))).getTypedMatcher<Type>(); 165 EXPECT_FALSE(matches("int *a;", M)); 166 EXPECT_TRUE(matches("int const *b;", M)); 167 168 M = constructMatcher( 169 "arrayType", 170 constructMatcher("hasElementType", constructMatcher("builtinType"))) 171 .getTypedMatcher<Type>(); 172 EXPECT_FALSE(matches("struct A{}; A a[7];;", M)); 173 EXPECT_TRUE(matches("int b[7];", M)); 174} 175 176TEST_F(RegistryTest, Errors) { 177 // Incorrect argument count. 178 OwningPtr<Diagnostics> Error(new Diagnostics()); 179 EXPECT_TRUE(constructMatcher("hasInitializer", Error.get()).empty()); 180 EXPECT_EQ("Incorrect argument count. (Expected = 1) != (Actual = 0)", 181 Error->ToString()); 182 Error.reset(new Diagnostics()); 183 EXPECT_TRUE(constructMatcher("isArrow", std::string(), Error.get()).empty()); 184 EXPECT_EQ("Incorrect argument count. (Expected = 0) != (Actual = 1)", 185 Error->ToString()); 186 187 // Bad argument type 188 Error.reset(new Diagnostics()); 189 EXPECT_TRUE(constructMatcher("ofClass", std::string(), Error.get()).empty()); 190 EXPECT_EQ("Incorrect type for arg 1. (Expected = Matcher<CXXRecordDecl>) != " 191 "(Actual = String)", 192 Error->ToString()); 193 Error.reset(new Diagnostics()); 194 EXPECT_TRUE(constructMatcher("recordDecl", recordDecl(), parameterCountIs(3), 195 Error.get()).empty()); 196 EXPECT_EQ("Incorrect type for arg 2. (Expected = Matcher<CXXRecordDecl>) != " 197 "(Actual = Matcher<FunctionDecl>)", 198 Error->ToString()); 199} 200 201} // end anonymous namespace 202} // end namespace dynamic 203} // end namespace ast_matchers 204} // end namespace clang 205