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 "../ASTMatchersTest.h" 11 #include "clang/ASTMatchers/Dynamic/Registry.h" 12 #include "gtest/gtest.h" 13 #include <vector> 14 15 namespace clang { 16 namespace ast_matchers { 17 namespace dynamic { 18 namespace { 19 20 using ast_matchers::internal::Matcher; 21 22 class RegistryTest : public ::testing::Test { 23 public: 24 std::vector<ParserValue> Args() { return std::vector<ParserValue>(); } 25 std::vector<ParserValue> Args(const VariantValue &Arg1) { 26 std::vector<ParserValue> Out(1); 27 Out[0].Value = Arg1; 28 return Out; 29 } 30 std::vector<ParserValue> Args(const VariantValue &Arg1, 31 const VariantValue &Arg2) { 32 std::vector<ParserValue> Out(2); 33 Out[0].Value = Arg1; 34 Out[1].Value = Arg2; 35 return Out; 36 } 37 38 llvm::Optional<MatcherCtor> lookupMatcherCtor(StringRef MatcherName, 39 Diagnostics *Error = 0) { 40 Diagnostics DummyError; 41 if (!Error) Error = &DummyError; 42 llvm::Optional<MatcherCtor> Ctor = 43 Registry::lookupMatcherCtor(MatcherName, SourceRange(), Error); 44 EXPECT_EQ("", DummyError.toStringFull()); 45 return Ctor; 46 } 47 48 VariantMatcher constructMatcher(StringRef MatcherName, 49 Diagnostics *Error = NULL) { 50 Diagnostics DummyError; 51 if (!Error) Error = &DummyError; 52 llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName, Error); 53 VariantMatcher Out; 54 if (Ctor) 55 Out = Registry::constructMatcher(*Ctor, SourceRange(), Args(), Error); 56 EXPECT_EQ("", DummyError.toStringFull()); 57 return Out; 58 } 59 60 VariantMatcher constructMatcher(StringRef MatcherName, 61 const VariantValue &Arg1, 62 Diagnostics *Error = NULL) { 63 Diagnostics DummyError; 64 if (!Error) Error = &DummyError; 65 llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName, Error); 66 VariantMatcher Out; 67 if (Ctor) 68 Out = Registry::constructMatcher(*Ctor, SourceRange(), Args(Arg1), Error); 69 EXPECT_EQ("", DummyError.toStringFull()) << MatcherName; 70 return Out; 71 } 72 73 VariantMatcher constructMatcher(StringRef MatcherName, 74 const VariantValue &Arg1, 75 const VariantValue &Arg2, 76 Diagnostics *Error = NULL) { 77 Diagnostics DummyError; 78 if (!Error) Error = &DummyError; 79 llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName, Error); 80 VariantMatcher Out; 81 if (Ctor) 82 Out = Registry::constructMatcher(*Ctor, SourceRange(), Args(Arg1, Arg2), 83 Error); 84 EXPECT_EQ("", DummyError.toStringFull()); 85 return Out; 86 } 87 88 typedef std::vector<MatcherCompletion> CompVector; 89 90 CompVector getCompletions() { 91 return Registry::getCompletions( 92 llvm::ArrayRef<std::pair<MatcherCtor, unsigned> >()); 93 } 94 95 CompVector getCompletions(StringRef MatcherName1, unsigned ArgNo1) { 96 std::vector<std::pair<MatcherCtor, unsigned> > Context; 97 llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName1); 98 if (!Ctor) 99 return CompVector(); 100 Context.push_back(std::make_pair(*Ctor, ArgNo1)); 101 return Registry::getCompletions(Context); 102 } 103 104 CompVector getCompletions(StringRef MatcherName1, unsigned ArgNo1, 105 StringRef MatcherName2, unsigned ArgNo2) { 106 std::vector<std::pair<MatcherCtor, unsigned> > Context; 107 llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName1); 108 if (!Ctor) 109 return CompVector(); 110 Context.push_back(std::make_pair(*Ctor, ArgNo1)); 111 Ctor = lookupMatcherCtor(MatcherName2); 112 if (!Ctor) 113 return CompVector(); 114 Context.push_back(std::make_pair(*Ctor, ArgNo2)); 115 return Registry::getCompletions(Context); 116 } 117 118 bool hasCompletion(const CompVector &Comps, StringRef TypedText, 119 StringRef MatcherDecl = StringRef(), unsigned *Index = 0) { 120 for (CompVector::const_iterator I = Comps.begin(), E = Comps.end(); I != E; 121 ++I) { 122 if (I->TypedText == TypedText && 123 (MatcherDecl.empty() || I->MatcherDecl == MatcherDecl)) { 124 if (Index) 125 *Index = I - Comps.begin(); 126 return true; 127 } 128 } 129 return false; 130 } 131 }; 132 133 TEST_F(RegistryTest, CanConstructNoArgs) { 134 Matcher<Stmt> IsArrowValue = constructMatcher( 135 "memberExpr", constructMatcher("isArrow")).getTypedMatcher<Stmt>(); 136 Matcher<Stmt> BoolValue = 137 constructMatcher("boolLiteral").getTypedMatcher<Stmt>(); 138 139 const std::string ClassSnippet = "struct Foo { int x; };\n" 140 "Foo *foo = new Foo;\n" 141 "int i = foo->x;\n"; 142 const std::string BoolSnippet = "bool Foo = true;\n"; 143 144 EXPECT_TRUE(matches(ClassSnippet, IsArrowValue)); 145 EXPECT_TRUE(matches(BoolSnippet, BoolValue)); 146 EXPECT_FALSE(matches(ClassSnippet, BoolValue)); 147 EXPECT_FALSE(matches(BoolSnippet, IsArrowValue)); 148 } 149 150 TEST_F(RegistryTest, ConstructWithSimpleArgs) { 151 Matcher<Decl> Value = constructMatcher( 152 "namedDecl", constructMatcher("hasName", std::string("X"))) 153 .getTypedMatcher<Decl>(); 154 EXPECT_TRUE(matches("class X {};", Value)); 155 EXPECT_FALSE(matches("int x;", Value)); 156 157 Value = functionDecl(constructMatcher("parameterCountIs", 2) 158 .getTypedMatcher<FunctionDecl>()); 159 EXPECT_TRUE(matches("void foo(int,int);", Value)); 160 EXPECT_FALSE(matches("void foo(int);", Value)); 161 } 162 163 TEST_F(RegistryTest, ConstructWithMatcherArgs) { 164 Matcher<Decl> HasInitializerSimple = constructMatcher( 165 "varDecl", constructMatcher("hasInitializer", constructMatcher("stmt"))) 166 .getTypedMatcher<Decl>(); 167 Matcher<Decl> HasInitializerComplex = constructMatcher( 168 "varDecl", 169 constructMatcher("hasInitializer", constructMatcher("callExpr"))) 170 .getTypedMatcher<Decl>(); 171 172 std::string code = "int i;"; 173 EXPECT_FALSE(matches(code, HasInitializerSimple)); 174 EXPECT_FALSE(matches(code, HasInitializerComplex)); 175 176 code = "int i = 1;"; 177 EXPECT_TRUE(matches(code, HasInitializerSimple)); 178 EXPECT_FALSE(matches(code, HasInitializerComplex)); 179 180 code = "int y(); int i = y();"; 181 EXPECT_TRUE(matches(code, HasInitializerSimple)); 182 EXPECT_TRUE(matches(code, HasInitializerComplex)); 183 184 Matcher<Decl> HasParameter = 185 functionDecl(constructMatcher( 186 "hasParameter", 1, constructMatcher("hasName", std::string("x"))) 187 .getTypedMatcher<FunctionDecl>()); 188 EXPECT_TRUE(matches("void f(int a, int x);", HasParameter)); 189 EXPECT_FALSE(matches("void f(int x, int a);", HasParameter)); 190 } 191 192 TEST_F(RegistryTest, OverloadedMatchers) { 193 Matcher<Stmt> CallExpr0 = constructMatcher( 194 "callExpr", 195 constructMatcher("callee", constructMatcher("memberExpr", 196 constructMatcher("isArrow")))) 197 .getTypedMatcher<Stmt>(); 198 199 Matcher<Stmt> CallExpr1 = constructMatcher( 200 "callExpr", 201 constructMatcher( 202 "callee", 203 constructMatcher("methodDecl", 204 constructMatcher("hasName", std::string("x"))))) 205 .getTypedMatcher<Stmt>(); 206 207 std::string Code = "class Y { public: void x(); }; void z() { Y y; y.x(); }"; 208 EXPECT_FALSE(matches(Code, CallExpr0)); 209 EXPECT_TRUE(matches(Code, CallExpr1)); 210 211 Code = "class Z { public: void z() { this->z(); } };"; 212 EXPECT_TRUE(matches(Code, CallExpr0)); 213 EXPECT_FALSE(matches(Code, CallExpr1)); 214 215 Matcher<Decl> DeclDecl = declaratorDecl(hasTypeLoc( 216 constructMatcher( 217 "loc", constructMatcher("asString", std::string("const double *"))) 218 .getTypedMatcher<TypeLoc>())); 219 220 Matcher<NestedNameSpecifierLoc> NNSL = 221 constructMatcher( 222 "loc", VariantMatcher::SingleMatcher(nestedNameSpecifier( 223 specifiesType(hasDeclaration(recordDecl(hasName("A"))))))) 224 .getTypedMatcher<NestedNameSpecifierLoc>(); 225 226 Code = "const double * x = 0;"; 227 EXPECT_TRUE(matches(Code, DeclDecl)); 228 EXPECT_FALSE(matches(Code, NNSL)); 229 230 Code = "struct A { struct B {}; }; A::B a_b;"; 231 EXPECT_FALSE(matches(Code, DeclDecl)); 232 EXPECT_TRUE(matches(Code, NNSL)); 233 } 234 235 TEST_F(RegistryTest, PolymorphicMatchers) { 236 const VariantMatcher IsDefinition = constructMatcher("isDefinition"); 237 Matcher<Decl> Var = 238 constructMatcher("varDecl", IsDefinition).getTypedMatcher<Decl>(); 239 Matcher<Decl> Class = 240 constructMatcher("recordDecl", IsDefinition).getTypedMatcher<Decl>(); 241 Matcher<Decl> Func = 242 constructMatcher("functionDecl", IsDefinition).getTypedMatcher<Decl>(); 243 EXPECT_TRUE(matches("int a;", Var)); 244 EXPECT_FALSE(matches("extern int a;", Var)); 245 EXPECT_TRUE(matches("class A {};", Class)); 246 EXPECT_FALSE(matches("class A;", Class)); 247 EXPECT_TRUE(matches("void f(){};", Func)); 248 EXPECT_FALSE(matches("void f();", Func)); 249 250 Matcher<Decl> Anything = constructMatcher("anything").getTypedMatcher<Decl>(); 251 Matcher<Decl> RecordDecl = constructMatcher( 252 "recordDecl", constructMatcher("hasName", std::string("Foo")), 253 VariantMatcher::SingleMatcher(Anything)).getTypedMatcher<Decl>(); 254 255 EXPECT_TRUE(matches("int Foo;", Anything)); 256 EXPECT_TRUE(matches("class Foo {};", Anything)); 257 EXPECT_TRUE(matches("void Foo(){};", Anything)); 258 EXPECT_FALSE(matches("int Foo;", RecordDecl)); 259 EXPECT_TRUE(matches("class Foo {};", RecordDecl)); 260 EXPECT_FALSE(matches("void Foo(){};", RecordDecl)); 261 262 Matcher<Stmt> ConstructExpr = constructMatcher( 263 "constructExpr", 264 constructMatcher( 265 "hasDeclaration", 266 constructMatcher( 267 "methodDecl", 268 constructMatcher( 269 "ofClass", constructMatcher("hasName", std::string("Foo")))))) 270 .getTypedMatcher<Stmt>(); 271 EXPECT_FALSE(matches("class Foo { public: Foo(); };", ConstructExpr)); 272 EXPECT_TRUE( 273 matches("class Foo { public: Foo(); }; Foo foo = Foo();", ConstructExpr)); 274 } 275 276 TEST_F(RegistryTest, TemplateArgument) { 277 Matcher<Decl> HasTemplateArgument = constructMatcher( 278 "classTemplateSpecializationDecl", 279 constructMatcher( 280 "hasAnyTemplateArgument", 281 constructMatcher("refersToType", 282 constructMatcher("asString", std::string("int"))))) 283 .getTypedMatcher<Decl>(); 284 EXPECT_TRUE(matches("template<typename T> class A {}; A<int> a;", 285 HasTemplateArgument)); 286 EXPECT_FALSE(matches("template<typename T> class A {}; A<char> a;", 287 HasTemplateArgument)); 288 } 289 290 TEST_F(RegistryTest, TypeTraversal) { 291 Matcher<Type> M = constructMatcher( 292 "pointerType", 293 constructMatcher("pointee", constructMatcher("isConstQualified"), 294 constructMatcher("isInteger"))).getTypedMatcher<Type>(); 295 EXPECT_FALSE(matches("int *a;", M)); 296 EXPECT_TRUE(matches("int const *b;", M)); 297 298 M = constructMatcher( 299 "arrayType", 300 constructMatcher("hasElementType", constructMatcher("builtinType"))) 301 .getTypedMatcher<Type>(); 302 EXPECT_FALSE(matches("struct A{}; A a[7];;", M)); 303 EXPECT_TRUE(matches("int b[7];", M)); 304 } 305 306 TEST_F(RegistryTest, CXXCtorInitializer) { 307 Matcher<Decl> CtorDecl = constructMatcher( 308 "constructorDecl", 309 constructMatcher( 310 "hasAnyConstructorInitializer", 311 constructMatcher("forField", 312 constructMatcher("hasName", std::string("foo"))))) 313 .getTypedMatcher<Decl>(); 314 EXPECT_TRUE(matches("struct Foo { Foo() : foo(1) {} int foo; };", CtorDecl)); 315 EXPECT_FALSE(matches("struct Foo { Foo() {} int foo; };", CtorDecl)); 316 EXPECT_FALSE(matches("struct Foo { Foo() : bar(1) {} int bar; };", CtorDecl)); 317 } 318 319 TEST_F(RegistryTest, Adaptative) { 320 Matcher<Decl> D = constructMatcher( 321 "recordDecl", 322 constructMatcher( 323 "has", 324 constructMatcher("recordDecl", 325 constructMatcher("hasName", std::string("X"))))) 326 .getTypedMatcher<Decl>(); 327 EXPECT_TRUE(matches("class X {};", D)); 328 EXPECT_TRUE(matches("class Y { class X {}; };", D)); 329 EXPECT_FALSE(matches("class Y { class Z {}; };", D)); 330 331 Matcher<Stmt> S = constructMatcher( 332 "forStmt", 333 constructMatcher( 334 "hasDescendant", 335 constructMatcher("varDecl", 336 constructMatcher("hasName", std::string("X"))))) 337 .getTypedMatcher<Stmt>(); 338 EXPECT_TRUE(matches("void foo() { for(int X;;); }", S)); 339 EXPECT_TRUE(matches("void foo() { for(;;) { int X; } }", S)); 340 EXPECT_FALSE(matches("void foo() { for(;;); }", S)); 341 EXPECT_FALSE(matches("void foo() { if (int X = 0){} }", S)); 342 343 S = constructMatcher( 344 "compoundStmt", constructMatcher("hasParent", constructMatcher("ifStmt"))) 345 .getTypedMatcher<Stmt>(); 346 EXPECT_TRUE(matches("void foo() { if (true) { int x = 42; } }", S)); 347 EXPECT_FALSE(matches("void foo() { if (true) return; }", S)); 348 } 349 350 TEST_F(RegistryTest, VariadicOp) { 351 Matcher<Decl> D = constructMatcher( 352 "anyOf", 353 constructMatcher("recordDecl", 354 constructMatcher("hasName", std::string("Foo"))), 355 constructMatcher("namedDecl", 356 constructMatcher("hasName", std::string("foo")))) 357 .getTypedMatcher<Decl>(); 358 359 EXPECT_TRUE(matches("void foo(){}", D)); 360 EXPECT_TRUE(matches("struct Foo{};", D)); 361 EXPECT_FALSE(matches("int i = 0;", D)); 362 363 D = constructMatcher( 364 "allOf", constructMatcher("recordDecl"), 365 constructMatcher( 366 "namedDecl", 367 constructMatcher("anyOf", 368 constructMatcher("hasName", std::string("Foo")), 369 constructMatcher("hasName", std::string("Bar"))))) 370 .getTypedMatcher<Decl>(); 371 372 EXPECT_FALSE(matches("void foo(){}", D)); 373 EXPECT_TRUE(matches("struct Foo{};", D)); 374 EXPECT_FALSE(matches("int i = 0;", D)); 375 EXPECT_TRUE(matches("class Bar{};", D)); 376 EXPECT_FALSE(matches("class OtherBar{};", D)); 377 378 D = recordDecl( 379 has(fieldDecl(hasName("Foo"))), 380 constructMatcher( 381 "unless", 382 constructMatcher("namedDecl", 383 constructMatcher("hasName", std::string("Bar")))) 384 .getTypedMatcher<Decl>()); 385 386 EXPECT_FALSE(matches("class Bar{ int Foo; };", D)); 387 EXPECT_TRUE(matches("class OtherBar{ int Foo; };", D)); 388 } 389 390 TEST_F(RegistryTest, Errors) { 391 // Incorrect argument count. 392 std::unique_ptr<Diagnostics> Error(new Diagnostics()); 393 EXPECT_TRUE(constructMatcher("hasInitializer", Error.get()).isNull()); 394 EXPECT_EQ("Incorrect argument count. (Expected = 1) != (Actual = 0)", 395 Error->toString()); 396 Error.reset(new Diagnostics()); 397 EXPECT_TRUE(constructMatcher("isArrow", std::string(), Error.get()).isNull()); 398 EXPECT_EQ("Incorrect argument count. (Expected = 0) != (Actual = 1)", 399 Error->toString()); 400 Error.reset(new Diagnostics()); 401 EXPECT_TRUE(constructMatcher("anyOf", Error.get()).isNull()); 402 EXPECT_EQ("Incorrect argument count. (Expected = (2, )) != (Actual = 0)", 403 Error->toString()); 404 Error.reset(new Diagnostics()); 405 EXPECT_TRUE(constructMatcher("unless", std::string(), std::string(), 406 Error.get()).isNull()); 407 EXPECT_EQ("Incorrect argument count. (Expected = (1, 1)) != (Actual = 2)", 408 Error->toString()); 409 410 // Bad argument type 411 Error.reset(new Diagnostics()); 412 EXPECT_TRUE(constructMatcher("ofClass", std::string(), Error.get()).isNull()); 413 EXPECT_EQ("Incorrect type for arg 1. (Expected = Matcher<CXXRecordDecl>) != " 414 "(Actual = String)", 415 Error->toString()); 416 Error.reset(new Diagnostics()); 417 EXPECT_TRUE(constructMatcher("recordDecl", constructMatcher("recordDecl"), 418 constructMatcher("parameterCountIs", 3), 419 Error.get()).isNull()); 420 EXPECT_EQ("Incorrect type for arg 2. (Expected = Matcher<CXXRecordDecl>) != " 421 "(Actual = Matcher<FunctionDecl>)", 422 Error->toString()); 423 424 // Bad argument type with variadic. 425 Error.reset(new Diagnostics()); 426 EXPECT_TRUE(constructMatcher("anyOf", std::string(), std::string(), 427 Error.get()).isNull()); 428 EXPECT_EQ( 429 "Incorrect type for arg 1. (Expected = Matcher<>) != (Actual = String)", 430 Error->toString()); 431 Error.reset(new Diagnostics()); 432 EXPECT_TRUE(constructMatcher( 433 "recordDecl", 434 constructMatcher("allOf", 435 constructMatcher("isDerivedFrom", std::string("FOO")), 436 constructMatcher("isArrow")), 437 Error.get()).isNull()); 438 EXPECT_EQ("Incorrect type for arg 1. " 439 "(Expected = Matcher<CXXRecordDecl>) != " 440 "(Actual = Matcher<CXXRecordDecl>&Matcher<MemberExpr>)", 441 Error->toString()); 442 } 443 444 TEST_F(RegistryTest, Completion) { 445 CompVector Comps = getCompletions(); 446 EXPECT_TRUE(hasCompletion( 447 Comps, "hasParent(", "Matcher<Decl|Stmt> hasParent(Matcher<Decl|Stmt>)")); 448 EXPECT_TRUE(hasCompletion(Comps, "whileStmt(", 449 "Matcher<Stmt> whileStmt(Matcher<WhileStmt>...)")); 450 451 CompVector WhileComps = getCompletions("whileStmt", 0); 452 453 unsigned HasBodyIndex, HasParentIndex, AllOfIndex; 454 EXPECT_TRUE(hasCompletion(WhileComps, "hasBody(", 455 "Matcher<WhileStmt> hasBody(Matcher<Stmt>)", 456 &HasBodyIndex)); 457 EXPECT_TRUE(hasCompletion(WhileComps, "hasParent(", 458 "Matcher<Stmt> hasParent(Matcher<Decl|Stmt>)", 459 &HasParentIndex)); 460 EXPECT_TRUE(hasCompletion(WhileComps, "allOf(", 461 "Matcher<T> allOf(Matcher<T>...)", &AllOfIndex)); 462 EXPECT_GT(HasParentIndex, HasBodyIndex); 463 EXPECT_GT(AllOfIndex, HasParentIndex); 464 465 EXPECT_FALSE(hasCompletion(WhileComps, "whileStmt(")); 466 EXPECT_FALSE(hasCompletion(WhileComps, "ifStmt(")); 467 468 CompVector AllOfWhileComps = 469 getCompletions("allOf", 0, "whileStmt", 0); 470 ASSERT_EQ(AllOfWhileComps.size(), WhileComps.size()); 471 EXPECT_TRUE(std::equal(WhileComps.begin(), WhileComps.end(), 472 AllOfWhileComps.begin())); 473 474 CompVector DeclWhileComps = 475 getCompletions("decl", 0, "whileStmt", 0); 476 EXPECT_EQ(0u, DeclWhileComps.size()); 477 478 CompVector NamedDeclComps = getCompletions("namedDecl", 0); 479 EXPECT_TRUE( 480 hasCompletion(NamedDeclComps, "isPublic()", "Matcher<Decl> isPublic()")); 481 EXPECT_TRUE(hasCompletion(NamedDeclComps, "hasName(\"", 482 "Matcher<NamedDecl> hasName(string)")); 483 } 484 485 } // end anonymous namespace 486 } // end namespace dynamic 487 } // end namespace ast_matchers 488 } // end namespace clang 489