RegistryTest.cpp revision 99e0df4ab60c5fa4afd2bf63b896fd4f88792127
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 VariantMatcher constructMatcher(StringRef MatcherName, 40 Diagnostics *Error = NULL) { 41 Diagnostics DummyError; 42 if (!Error) Error = &DummyError; 43 const VariantMatcher Out = 44 Registry::constructMatcher(MatcherName, SourceRange(), Args(), Error); 45 EXPECT_EQ("", DummyError.toStringFull()); 46 return Out; 47 } 48 49 VariantMatcher constructMatcher(StringRef MatcherName, 50 const VariantValue &Arg1, 51 Diagnostics *Error = NULL) { 52 Diagnostics DummyError; 53 if (!Error) Error = &DummyError; 54 const VariantMatcher Out = Registry::constructMatcher( 55 MatcherName, SourceRange(), Args(Arg1), Error); 56 EXPECT_EQ("", DummyError.toStringFull()); 57 return Out; 58 } 59 60 VariantMatcher constructMatcher(StringRef MatcherName, 61 const VariantValue &Arg1, 62 const VariantValue &Arg2, 63 Diagnostics *Error = NULL) { 64 Diagnostics DummyError; 65 if (!Error) Error = &DummyError; 66 const VariantMatcher Out = Registry::constructMatcher( 67 MatcherName, SourceRange(), Args(Arg1, Arg2), Error); 68 EXPECT_EQ("", DummyError.toStringFull()); 69 return Out; 70 } 71}; 72 73TEST_F(RegistryTest, CanConstructNoArgs) { 74 Matcher<Stmt> IsArrowValue = constructMatcher( 75 "memberExpr", constructMatcher("isArrow")).getTypedMatcher<Stmt>(); 76 Matcher<Stmt> BoolValue = 77 constructMatcher("boolLiteral").getTypedMatcher<Stmt>(); 78 79 const std::string ClassSnippet = "struct Foo { int x; };\n" 80 "Foo *foo = new Foo;\n" 81 "int i = foo->x;\n"; 82 const std::string BoolSnippet = "bool Foo = true;\n"; 83 84 EXPECT_TRUE(matches(ClassSnippet, IsArrowValue)); 85 EXPECT_TRUE(matches(BoolSnippet, BoolValue)); 86 EXPECT_FALSE(matches(ClassSnippet, BoolValue)); 87 EXPECT_FALSE(matches(BoolSnippet, IsArrowValue)); 88} 89 90TEST_F(RegistryTest, ConstructWithSimpleArgs) { 91 Matcher<Decl> Value = constructMatcher( 92 "namedDecl", constructMatcher("hasName", std::string("X"))) 93 .getTypedMatcher<Decl>(); 94 EXPECT_TRUE(matches("class X {};", Value)); 95 EXPECT_FALSE(matches("int x;", Value)); 96 97 Value = functionDecl(constructMatcher("parameterCountIs", 2) 98 .getTypedMatcher<FunctionDecl>()); 99 EXPECT_TRUE(matches("void foo(int,int);", Value)); 100 EXPECT_FALSE(matches("void foo(int);", Value)); 101} 102 103TEST_F(RegistryTest, ConstructWithMatcherArgs) { 104 Matcher<Decl> HasInitializerSimple = constructMatcher( 105 "varDecl", constructMatcher("hasInitializer", constructMatcher("stmt"))) 106 .getTypedMatcher<Decl>(); 107 Matcher<Decl> HasInitializerComplex = constructMatcher( 108 "varDecl", 109 constructMatcher("hasInitializer", constructMatcher("callExpr"))) 110 .getTypedMatcher<Decl>(); 111 112 std::string code = "int i;"; 113 EXPECT_FALSE(matches(code, HasInitializerSimple)); 114 EXPECT_FALSE(matches(code, HasInitializerComplex)); 115 116 code = "int i = 1;"; 117 EXPECT_TRUE(matches(code, HasInitializerSimple)); 118 EXPECT_FALSE(matches(code, HasInitializerComplex)); 119 120 code = "int y(); int i = y();"; 121 EXPECT_TRUE(matches(code, HasInitializerSimple)); 122 EXPECT_TRUE(matches(code, HasInitializerComplex)); 123 124 Matcher<Decl> HasParameter = 125 functionDecl(constructMatcher( 126 "hasParameter", 1, constructMatcher("hasName", std::string("x"))) 127 .getTypedMatcher<FunctionDecl>()); 128 EXPECT_TRUE(matches("void f(int a, int x);", HasParameter)); 129 EXPECT_FALSE(matches("void f(int x, int a);", HasParameter)); 130} 131 132TEST_F(RegistryTest, OverloadedMatchers) { 133 Matcher<Stmt> CallExpr0 = constructMatcher( 134 "callExpr", 135 constructMatcher("callee", constructMatcher("memberExpr", 136 constructMatcher("isArrow")))) 137 .getTypedMatcher<Stmt>(); 138 139 Matcher<Stmt> CallExpr1 = constructMatcher( 140 "callExpr", 141 constructMatcher( 142 "callee", 143 constructMatcher("methodDecl", 144 constructMatcher("hasName", std::string("x"))))) 145 .getTypedMatcher<Stmt>(); 146 147 std::string Code = "class Y { public: void x(); }; void z() { Y y; y.x(); }"; 148 EXPECT_FALSE(matches(Code, CallExpr0)); 149 EXPECT_TRUE(matches(Code, CallExpr1)); 150 151 Code = "class Z { public: void z() { this->z(); } };"; 152 EXPECT_TRUE(matches(Code, CallExpr0)); 153 EXPECT_FALSE(matches(Code, CallExpr1)); 154} 155 156TEST_F(RegistryTest, PolymorphicMatchers) { 157 const VariantMatcher IsDefinition = constructMatcher("isDefinition"); 158 Matcher<Decl> Var = 159 constructMatcher("varDecl", IsDefinition).getTypedMatcher<Decl>(); 160 Matcher<Decl> Class = 161 constructMatcher("recordDecl", IsDefinition).getTypedMatcher<Decl>(); 162 Matcher<Decl> Func = 163 constructMatcher("functionDecl", IsDefinition).getTypedMatcher<Decl>(); 164 EXPECT_TRUE(matches("int a;", Var)); 165 EXPECT_FALSE(matches("extern int a;", Var)); 166 EXPECT_TRUE(matches("class A {};", Class)); 167 EXPECT_FALSE(matches("class A;", Class)); 168 EXPECT_TRUE(matches("void f(){};", Func)); 169 EXPECT_FALSE(matches("void f();", Func)); 170 171 Matcher<Decl> Anything = constructMatcher("anything").getTypedMatcher<Decl>(); 172 Matcher<Decl> RecordDecl = 173 constructMatcher("recordDecl", VariantMatcher::SingleMatcher(Anything)) 174 .getTypedMatcher<Decl>(); 175 176 EXPECT_TRUE(matches("int a;", Anything)); 177 EXPECT_TRUE(matches("class A {};", Anything)); 178 EXPECT_TRUE(matches("void f(){};", Anything)); 179 // FIXME: A couple of tests have been suppressed. 180 // I know it'd be bad with _MSC_VER here, though. 181#if !defined(_MSC_VER) 182 EXPECT_FALSE(matches("int a;", RecordDecl)); 183#endif 184 EXPECT_TRUE(matches("class A {};", RecordDecl)); 185#if !defined(_MSC_VER) 186 EXPECT_FALSE(matches("void f(){};", RecordDecl)); 187#endif 188} 189 190TEST_F(RegistryTest, TemplateArgument) { 191 Matcher<Decl> HasTemplateArgument = constructMatcher( 192 "classTemplateSpecializationDecl", 193 constructMatcher( 194 "hasAnyTemplateArgument", 195 constructMatcher("refersToType", 196 constructMatcher("asString", std::string("int"))))) 197 .getTypedMatcher<Decl>(); 198 EXPECT_TRUE(matches("template<typename T> class A {}; A<int> a;", 199 HasTemplateArgument)); 200 EXPECT_FALSE(matches("template<typename T> class A {}; A<char> a;", 201 HasTemplateArgument)); 202} 203 204TEST_F(RegistryTest, TypeTraversal) { 205 Matcher<Type> M = constructMatcher( 206 "pointerType", 207 constructMatcher("pointee", constructMatcher("isConstQualified"), 208 constructMatcher("isInteger"))).getTypedMatcher<Type>(); 209 EXPECT_FALSE(matches("int *a;", M)); 210 EXPECT_TRUE(matches("int const *b;", M)); 211 212 M = constructMatcher( 213 "arrayType", 214 constructMatcher("hasElementType", constructMatcher("builtinType"))) 215 .getTypedMatcher<Type>(); 216 EXPECT_FALSE(matches("struct A{}; A a[7];;", M)); 217 EXPECT_TRUE(matches("int b[7];", M)); 218} 219 220TEST_F(RegistryTest, CXXCtorInitializer) { 221 Matcher<Decl> CtorDecl = constructMatcher( 222 "constructorDecl", 223 constructMatcher( 224 "hasAnyConstructorInitializer", 225 constructMatcher("forField", 226 constructMatcher("hasName", std::string("foo"))))) 227 .getTypedMatcher<Decl>(); 228 EXPECT_TRUE(matches("struct Foo { Foo() : foo(1) {} int foo; };", CtorDecl)); 229 EXPECT_FALSE(matches("struct Foo { Foo() {} int foo; };", CtorDecl)); 230 EXPECT_FALSE(matches("struct Foo { Foo() : bar(1) {} int bar; };", CtorDecl)); 231} 232 233TEST_F(RegistryTest, Adaptative) { 234 Matcher<Decl> D = constructMatcher( 235 "recordDecl", 236 constructMatcher( 237 "has", 238 constructMatcher("recordDecl", 239 constructMatcher("hasName", std::string("X"))))) 240 .getTypedMatcher<Decl>(); 241 EXPECT_TRUE(matches("class X {};", D)); 242 EXPECT_TRUE(matches("class Y { class X {}; };", D)); 243 EXPECT_FALSE(matches("class Y { class Z {}; };", D)); 244 245 Matcher<Stmt> S = constructMatcher( 246 "forStmt", 247 constructMatcher( 248 "hasDescendant", 249 constructMatcher("varDecl", 250 constructMatcher("hasName", std::string("X"))))) 251 .getTypedMatcher<Stmt>(); 252 EXPECT_TRUE(matches("void foo() { for(int X;;); }", S)); 253 EXPECT_TRUE(matches("void foo() { for(;;) { int X; } }", S)); 254 EXPECT_FALSE(matches("void foo() { for(;;); }", S)); 255 EXPECT_FALSE(matches("void foo() { if (int X = 0){} }", S)); 256 257 S = constructMatcher( 258 "compoundStmt", constructMatcher("hasParent", constructMatcher("ifStmt"))) 259 .getTypedMatcher<Stmt>(); 260 EXPECT_TRUE(matches("void foo() { if (true) { int x = 42; } }", S)); 261 EXPECT_FALSE(matches("void foo() { if (true) return; }", S)); 262} 263 264TEST_F(RegistryTest, Errors) { 265 // Incorrect argument count. 266 OwningPtr<Diagnostics> Error(new Diagnostics()); 267 EXPECT_TRUE(constructMatcher("hasInitializer", Error.get()).isNull()); 268 EXPECT_EQ("Incorrect argument count. (Expected = 1) != (Actual = 0)", 269 Error->toString()); 270 Error.reset(new Diagnostics()); 271 EXPECT_TRUE(constructMatcher("isArrow", std::string(), Error.get()).isNull()); 272 EXPECT_EQ("Incorrect argument count. (Expected = 0) != (Actual = 1)", 273 Error->toString()); 274 275 // Bad argument type 276 Error.reset(new Diagnostics()); 277 EXPECT_TRUE(constructMatcher("ofClass", std::string(), Error.get()).isNull()); 278 EXPECT_EQ("Incorrect type for arg 1. (Expected = Matcher<CXXRecordDecl>) != " 279 "(Actual = String)", 280 Error->toString()); 281 Error.reset(new Diagnostics()); 282 EXPECT_TRUE(constructMatcher("recordDecl", constructMatcher("recordDecl"), 283 constructMatcher("parameterCountIs", 3), 284 Error.get()).isNull()); 285 EXPECT_EQ("Incorrect type for arg 2. (Expected = Matcher<CXXRecordDecl>) != " 286 "(Actual = Matcher<FunctionDecl>)", 287 Error->toString()); 288} 289 290} // end anonymous namespace 291} // end namespace dynamic 292} // end namespace ast_matchers 293} // end namespace clang 294