1 //===- unittest/ASTMatchers/Dynamic/RegistryTest.cpp - Registry unit tests -===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===-----------------------------------------------------------------------===// 8 9 #include "../ASTMatchersTest.h" 10 #include "clang/ASTMatchers/Dynamic/Registry.h" 11 #include "gtest/gtest.h" 12 #include <vector> 13 14 namespace clang { 15 namespace ast_matchers { 16 namespace dynamic { 17 namespace { 18 19 using ast_matchers::internal::Matcher; 20 21 class RegistryTest : public ::testing::Test { 22 public: 23 std::vector<ParserValue> Args() { return std::vector<ParserValue>(); } 24 std::vector<ParserValue> Args(const VariantValue &Arg1) { 25 std::vector<ParserValue> Out(1); 26 Out[0].Value = Arg1; 27 return Out; 28 } 29 std::vector<ParserValue> Args(const VariantValue &Arg1, 30 const VariantValue &Arg2) { 31 std::vector<ParserValue> Out(2); 32 Out[0].Value = Arg1; 33 Out[1].Value = Arg2; 34 return Out; 35 } 36 37 llvm::Optional<MatcherCtor> lookupMatcherCtor(StringRef MatcherName) { 38 return Registry::lookupMatcherCtor(MatcherName); 39 } 40 41 VariantMatcher constructMatcher(StringRef MatcherName, 42 Diagnostics *Error = nullptr) { 43 Diagnostics DummyError; 44 if (!Error) Error = &DummyError; 45 llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName); 46 VariantMatcher Out; 47 if (Ctor) 48 Out = Registry::constructMatcher(*Ctor, SourceRange(), Args(), Error); 49 EXPECT_EQ("", DummyError.toStringFull()); 50 return Out; 51 } 52 53 VariantMatcher constructMatcher(StringRef MatcherName, 54 const VariantValue &Arg1, 55 Diagnostics *Error = nullptr) { 56 Diagnostics DummyError; 57 if (!Error) Error = &DummyError; 58 llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName); 59 VariantMatcher Out; 60 if (Ctor) 61 Out = Registry::constructMatcher(*Ctor, SourceRange(), Args(Arg1), Error); 62 EXPECT_EQ("", DummyError.toStringFull()) << MatcherName; 63 return Out; 64 } 65 66 VariantMatcher constructMatcher(StringRef MatcherName, 67 const VariantValue &Arg1, 68 const VariantValue &Arg2, 69 Diagnostics *Error = nullptr) { 70 Diagnostics DummyError; 71 if (!Error) Error = &DummyError; 72 llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName); 73 VariantMatcher Out; 74 if (Ctor) 75 Out = Registry::constructMatcher(*Ctor, SourceRange(), Args(Arg1, Arg2), 76 Error); 77 EXPECT_EQ("", DummyError.toStringFull()); 78 return Out; 79 } 80 81 typedef std::vector<MatcherCompletion> CompVector; 82 83 CompVector getCompletions() { 84 std::vector<std::pair<MatcherCtor, unsigned> > Context; 85 return Registry::getMatcherCompletions( 86 Registry::getAcceptedCompletionTypes(Context)); 87 } 88 89 CompVector getCompletions(StringRef MatcherName1, unsigned ArgNo1) { 90 std::vector<std::pair<MatcherCtor, unsigned> > Context; 91 llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName1); 92 if (!Ctor) 93 return CompVector(); 94 Context.push_back(std::make_pair(*Ctor, ArgNo1)); 95 return Registry::getMatcherCompletions( 96 Registry::getAcceptedCompletionTypes(Context)); 97 } 98 99 CompVector getCompletions(StringRef MatcherName1, unsigned ArgNo1, 100 StringRef MatcherName2, unsigned ArgNo2) { 101 std::vector<std::pair<MatcherCtor, unsigned> > Context; 102 llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName1); 103 if (!Ctor) 104 return CompVector(); 105 Context.push_back(std::make_pair(*Ctor, ArgNo1)); 106 Ctor = lookupMatcherCtor(MatcherName2); 107 if (!Ctor) 108 return CompVector(); 109 Context.push_back(std::make_pair(*Ctor, ArgNo2)); 110 return Registry::getMatcherCompletions( 111 Registry::getAcceptedCompletionTypes(Context)); 112 } 113 114 bool hasCompletion(const CompVector &Comps, StringRef TypedText, 115 StringRef MatcherDecl = StringRef()) { 116 for (CompVector::const_iterator I = Comps.begin(), E = Comps.end(); I != E; 117 ++I) { 118 if (I->TypedText == TypedText && 119 (MatcherDecl.empty() || I->MatcherDecl == MatcherDecl)) { 120 return true; 121 } 122 } 123 return false; 124 } 125 }; 126 127 TEST_F(RegistryTest, CanConstructNoArgs) { 128 Matcher<Stmt> IsArrowValue = constructMatcher( 129 "memberExpr", constructMatcher("isArrow")).getTypedMatcher<Stmt>(); 130 Matcher<Stmt> BoolValue = 131 constructMatcher("cxxBoolLiteral").getTypedMatcher<Stmt>(); 132 133 const std::string ClassSnippet = "struct Foo { int x; };\n" 134 "Foo *foo = new Foo;\n" 135 "int i = foo->x;\n"; 136 const std::string BoolSnippet = "bool Foo = true;\n"; 137 138 EXPECT_TRUE(matches(ClassSnippet, IsArrowValue)); 139 EXPECT_TRUE(matches(BoolSnippet, BoolValue)); 140 EXPECT_FALSE(matches(ClassSnippet, BoolValue)); 141 EXPECT_FALSE(matches(BoolSnippet, IsArrowValue)); 142 } 143 144 TEST_F(RegistryTest, ConstructWithSimpleArgs) { 145 Matcher<Decl> Value = constructMatcher( 146 "namedDecl", constructMatcher("hasName", StringRef("X"))) 147 .getTypedMatcher<Decl>(); 148 EXPECT_TRUE(matches("class X {};", Value)); 149 EXPECT_FALSE(matches("int x;", Value)); 150 151 Value = functionDecl(constructMatcher("parameterCountIs", 2) 152 .getTypedMatcher<FunctionDecl>()); 153 EXPECT_TRUE(matches("void foo(int,int);", Value)); 154 EXPECT_FALSE(matches("void foo(int);", Value)); 155 } 156 157 TEST_F(RegistryTest, ConstructWithMatcherArgs) { 158 Matcher<Decl> HasInitializerSimple = constructMatcher( 159 "varDecl", constructMatcher("hasInitializer", constructMatcher("stmt"))) 160 .getTypedMatcher<Decl>(); 161 Matcher<Decl> HasInitializerComplex = constructMatcher( 162 "varDecl", 163 constructMatcher("hasInitializer", constructMatcher("callExpr"))) 164 .getTypedMatcher<Decl>(); 165 166 std::string code = "int i;"; 167 EXPECT_FALSE(matches(code, HasInitializerSimple)); 168 EXPECT_FALSE(matches(code, HasInitializerComplex)); 169 170 code = "int i = 1;"; 171 EXPECT_TRUE(matches(code, HasInitializerSimple)); 172 EXPECT_FALSE(matches(code, HasInitializerComplex)); 173 174 code = "int y(); int i = y();"; 175 EXPECT_TRUE(matches(code, HasInitializerSimple)); 176 EXPECT_TRUE(matches(code, HasInitializerComplex)); 177 178 Matcher<Decl> HasParameter = 179 functionDecl(constructMatcher( 180 "hasParameter", 1, constructMatcher("hasName", StringRef("x"))) 181 .getTypedMatcher<FunctionDecl>()); 182 EXPECT_TRUE(matches("void f(int a, int x);", HasParameter)); 183 EXPECT_FALSE(matches("void f(int x, int a);", HasParameter)); 184 } 185 186 TEST_F(RegistryTest, OverloadedMatchers) { 187 Matcher<Stmt> CallExpr0 = constructMatcher( 188 "callExpr", 189 constructMatcher("callee", constructMatcher("memberExpr", 190 constructMatcher("isArrow")))) 191 .getTypedMatcher<Stmt>(); 192 193 Matcher<Stmt> CallExpr1 = constructMatcher( 194 "callExpr", 195 constructMatcher( 196 "callee", 197 constructMatcher("cxxMethodDecl", 198 constructMatcher("hasName", StringRef("x"))))) 199 .getTypedMatcher<Stmt>(); 200 201 std::string Code = "class Y { public: void x(); }; void z() { Y y; y.x(); }"; 202 EXPECT_FALSE(matches(Code, CallExpr0)); 203 EXPECT_TRUE(matches(Code, CallExpr1)); 204 205 Code = "class Z { public: void z() { this->z(); } };"; 206 EXPECT_TRUE(matches(Code, CallExpr0)); 207 EXPECT_FALSE(matches(Code, CallExpr1)); 208 209 Matcher<Decl> DeclDecl = declaratorDecl(hasTypeLoc( 210 constructMatcher( 211 "loc", constructMatcher("asString", StringRef("const double *"))) 212 .getTypedMatcher<TypeLoc>())); 213 214 Matcher<NestedNameSpecifierLoc> NNSL = 215 constructMatcher( 216 "loc", VariantMatcher::SingleMatcher(nestedNameSpecifier( 217 specifiesType(hasDeclaration(recordDecl(hasName("A"))))))) 218 .getTypedMatcher<NestedNameSpecifierLoc>(); 219 220 Code = "const double * x = 0;"; 221 EXPECT_TRUE(matches(Code, DeclDecl)); 222 EXPECT_FALSE(matches(Code, NNSL)); 223 224 Code = "struct A { struct B {}; }; A::B a_b;"; 225 EXPECT_FALSE(matches(Code, DeclDecl)); 226 EXPECT_TRUE(matches(Code, NNSL)); 227 } 228 229 TEST_F(RegistryTest, PolymorphicMatchers) { 230 const VariantMatcher IsDefinition = constructMatcher("isDefinition"); 231 Matcher<Decl> Var = 232 constructMatcher("varDecl", IsDefinition).getTypedMatcher<Decl>(); 233 Matcher<Decl> Class = 234 constructMatcher("recordDecl", IsDefinition).getTypedMatcher<Decl>(); 235 Matcher<Decl> Func = 236 constructMatcher("functionDecl", IsDefinition).getTypedMatcher<Decl>(); 237 EXPECT_TRUE(matches("int a;", Var)); 238 EXPECT_FALSE(matches("extern int a;", Var)); 239 EXPECT_TRUE(matches("class A {};", Class)); 240 EXPECT_FALSE(matches("class A;", Class)); 241 EXPECT_TRUE(matches("void f(){};", Func)); 242 EXPECT_FALSE(matches("void f();", Func)); 243 244 Matcher<Decl> Anything = constructMatcher("anything").getTypedMatcher<Decl>(); 245 Matcher<Decl> RecordDecl = constructMatcher( 246 "recordDecl", constructMatcher("hasName", StringRef("Foo")), 247 VariantMatcher::SingleMatcher(Anything)).getTypedMatcher<Decl>(); 248 249 EXPECT_TRUE(matches("int Foo;", Anything)); 250 EXPECT_TRUE(matches("class Foo {};", Anything)); 251 EXPECT_TRUE(matches("void Foo(){};", Anything)); 252 EXPECT_FALSE(matches("int Foo;", RecordDecl)); 253 EXPECT_TRUE(matches("class Foo {};", RecordDecl)); 254 EXPECT_FALSE(matches("void Foo(){};", RecordDecl)); 255 256 Matcher<Stmt> ConstructExpr = constructMatcher( 257 "cxxConstructExpr", 258 constructMatcher( 259 "hasDeclaration", 260 constructMatcher( 261 "cxxMethodDecl", 262 constructMatcher( 263 "ofClass", constructMatcher("hasName", StringRef("Foo")))))) 264 .getTypedMatcher<Stmt>(); 265 EXPECT_FALSE(matches("class Foo { public: Foo(); };", ConstructExpr)); 266 EXPECT_TRUE( 267 matches("class Foo { public: Foo(); }; Foo foo = Foo();", ConstructExpr)); 268 } 269 270 TEST_F(RegistryTest, TemplateArgument) { 271 Matcher<Decl> HasTemplateArgument = constructMatcher( 272 "classTemplateSpecializationDecl", 273 constructMatcher( 274 "hasAnyTemplateArgument", 275 constructMatcher("refersToType", 276 constructMatcher("asString", StringRef("int"))))) 277 .getTypedMatcher<Decl>(); 278 EXPECT_TRUE(matches("template<typename T> class A {}; A<int> a;", 279 HasTemplateArgument)); 280 EXPECT_FALSE(matches("template<typename T> class A {}; A<char> a;", 281 HasTemplateArgument)); 282 } 283 284 TEST_F(RegistryTest, TypeTraversal) { 285 Matcher<Type> M = constructMatcher( 286 "pointerType", 287 constructMatcher("pointee", constructMatcher("isConstQualified"), 288 constructMatcher("isInteger"))).getTypedMatcher<Type>(); 289 EXPECT_FALSE(matches("int *a;", M)); 290 EXPECT_TRUE(matches("int const *b;", M)); 291 292 M = constructMatcher( 293 "arrayType", 294 constructMatcher("hasElementType", constructMatcher("builtinType"))) 295 .getTypedMatcher<Type>(); 296 EXPECT_FALSE(matches("struct A{}; A a[7];;", M)); 297 EXPECT_TRUE(matches("int b[7];", M)); 298 } 299 300 TEST_F(RegistryTest, CXXBaseSpecifier) { 301 // TODO: rewrite with top-level cxxBaseSpecifier matcher when available 302 DeclarationMatcher ClassHasAnyDirectBase = 303 constructMatcher("cxxRecordDecl", 304 constructMatcher("hasDirectBase", 305 constructMatcher("cxxBaseSpecifier"))) 306 .getTypedMatcher<Decl>(); 307 EXPECT_TRUE(matches("class X {}; class Y : X {};", ClassHasAnyDirectBase)); 308 EXPECT_TRUE(notMatches("class X {};", ClassHasAnyDirectBase)); 309 } 310 311 TEST_F(RegistryTest, CXXCtorInitializer) { 312 Matcher<Decl> CtorDecl = constructMatcher( 313 "cxxConstructorDecl", 314 constructMatcher( 315 "hasAnyConstructorInitializer", 316 constructMatcher("forField", 317 constructMatcher("hasName", StringRef("foo"))))) 318 .getTypedMatcher<Decl>(); 319 EXPECT_TRUE(matches("struct Foo { Foo() : foo(1) {} int foo; };", CtorDecl)); 320 EXPECT_FALSE(matches("struct Foo { Foo() {} int foo; };", CtorDecl)); 321 EXPECT_FALSE(matches("struct Foo { Foo() : bar(1) {} int bar; };", CtorDecl)); 322 } 323 324 TEST_F(RegistryTest, Adaptative) { 325 Matcher<Decl> D = constructMatcher( 326 "recordDecl", 327 constructMatcher( 328 "has", 329 constructMatcher("recordDecl", 330 constructMatcher("hasName", StringRef("X"))))) 331 .getTypedMatcher<Decl>(); 332 EXPECT_TRUE(matches("class X {};", D)); 333 EXPECT_TRUE(matches("class Y { class X {}; };", D)); 334 EXPECT_FALSE(matches("class Y { class Z {}; };", D)); 335 336 Matcher<Stmt> S = constructMatcher( 337 "forStmt", 338 constructMatcher( 339 "hasDescendant", 340 constructMatcher("varDecl", 341 constructMatcher("hasName", StringRef("X"))))) 342 .getTypedMatcher<Stmt>(); 343 EXPECT_TRUE(matches("void foo() { for(int X;;); }", S)); 344 EXPECT_TRUE(matches("void foo() { for(;;) { int X; } }", S)); 345 EXPECT_FALSE(matches("void foo() { for(;;); }", S)); 346 EXPECT_FALSE(matches("void foo() { if (int X = 0){} }", S)); 347 348 S = constructMatcher( 349 "compoundStmt", constructMatcher("hasParent", constructMatcher("ifStmt"))) 350 .getTypedMatcher<Stmt>(); 351 EXPECT_TRUE(matches("void foo() { if (true) { int x = 42; } }", S)); 352 EXPECT_FALSE(matches("void foo() { if (true) return; }", S)); 353 } 354 355 TEST_F(RegistryTest, VariadicOp) { 356 Matcher<Decl> D = constructMatcher( 357 "anyOf", 358 constructMatcher("recordDecl", 359 constructMatcher("hasName", StringRef("Foo"))), 360 constructMatcher("functionDecl", 361 constructMatcher("hasName", StringRef("foo")))) 362 .getTypedMatcher<Decl>(); 363 364 EXPECT_TRUE(matches("void foo(){}", D)); 365 EXPECT_TRUE(matches("struct Foo{};", D)); 366 EXPECT_FALSE(matches("int i = 0;", D)); 367 368 D = constructMatcher( 369 "allOf", constructMatcher("recordDecl"), 370 constructMatcher( 371 "namedDecl", 372 constructMatcher("anyOf", 373 constructMatcher("hasName", StringRef("Foo")), 374 constructMatcher("hasName", StringRef("Bar"))))) 375 .getTypedMatcher<Decl>(); 376 377 EXPECT_FALSE(matches("void foo(){}", D)); 378 EXPECT_TRUE(matches("struct Foo{};", D)); 379 EXPECT_FALSE(matches("int i = 0;", D)); 380 EXPECT_TRUE(matches("class Bar{};", D)); 381 EXPECT_FALSE(matches("class OtherBar{};", D)); 382 383 D = recordDecl( 384 has(fieldDecl(hasName("Foo"))), 385 constructMatcher( 386 "unless", 387 constructMatcher("namedDecl", 388 constructMatcher("hasName", StringRef("Bar")))) 389 .getTypedMatcher<Decl>()); 390 391 EXPECT_FALSE(matches("class Bar{ int Foo; };", D)); 392 EXPECT_TRUE(matches("class OtherBar{ int Foo; };", D)); 393 394 D = constructMatcher( 395 "namedDecl", constructMatcher("hasName", StringRef("Foo")), 396 constructMatcher("unless", constructMatcher("recordDecl"))) 397 .getTypedMatcher<Decl>(); 398 EXPECT_TRUE(matches("void Foo(){}", D)); 399 EXPECT_TRUE(notMatches("struct Foo {};", D)); 400 } 401 402 TEST_F(RegistryTest, Errors) { 403 // Incorrect argument count. 404 std::unique_ptr<Diagnostics> Error(new Diagnostics()); 405 EXPECT_TRUE(constructMatcher("hasInitializer", Error.get()).isNull()); 406 EXPECT_EQ("Incorrect argument count. (Expected = 1) != (Actual = 0)", 407 Error->toString()); 408 Error.reset(new Diagnostics()); 409 EXPECT_TRUE(constructMatcher("isArrow", StringRef(), Error.get()).isNull()); 410 EXPECT_EQ("Incorrect argument count. (Expected = 0) != (Actual = 1)", 411 Error->toString()); 412 Error.reset(new Diagnostics()); 413 EXPECT_TRUE(constructMatcher("anyOf", Error.get()).isNull()); 414 EXPECT_EQ("Incorrect argument count. (Expected = (2, )) != (Actual = 0)", 415 Error->toString()); 416 Error.reset(new Diagnostics()); 417 EXPECT_TRUE(constructMatcher("unless", StringRef(), StringRef(), 418 Error.get()).isNull()); 419 EXPECT_EQ("Incorrect argument count. (Expected = (1, 1)) != (Actual = 2)", 420 Error->toString()); 421 422 // Bad argument type 423 Error.reset(new Diagnostics()); 424 EXPECT_TRUE(constructMatcher("ofClass", StringRef(), Error.get()).isNull()); 425 EXPECT_EQ("Incorrect type for arg 1. (Expected = Matcher<CXXRecordDecl>) != " 426 "(Actual = String)", 427 Error->toString()); 428 Error.reset(new Diagnostics()); 429 EXPECT_TRUE( 430 constructMatcher("cxxRecordDecl", constructMatcher("cxxRecordDecl"), 431 constructMatcher("parameterCountIs", 3), Error.get()) 432 .isNull()); 433 EXPECT_EQ("Incorrect type for arg 2. (Expected = Matcher<CXXRecordDecl>) != " 434 "(Actual = Matcher<FunctionDecl|FunctionProtoType>)", 435 Error->toString()); 436 437 // Bad argument type with variadic. 438 Error.reset(new Diagnostics()); 439 EXPECT_TRUE(constructMatcher("anyOf", StringRef(), StringRef(), 440 Error.get()).isNull()); 441 EXPECT_EQ( 442 "Incorrect type for arg 1. (Expected = Matcher<>) != (Actual = String)", 443 Error->toString()); 444 Error.reset(new Diagnostics()); 445 EXPECT_TRUE(constructMatcher( 446 "cxxRecordDecl", 447 constructMatcher("allOf", 448 constructMatcher("isDerivedFrom", StringRef("FOO")), 449 constructMatcher("isArrow")), 450 Error.get()).isNull()); 451 EXPECT_EQ("Incorrect type for arg 1. " 452 "(Expected = Matcher<CXXRecordDecl>) != " 453 "(Actual = Matcher<CXXRecordDecl|ObjCInterfaceDecl>&Matcher" 454 "<MemberExpr|UnresolvedMemberExpr|CXXDependentScopeMemberExpr>)", 455 Error->toString()); 456 } 457 458 TEST_F(RegistryTest, Completion) { 459 CompVector Comps = getCompletions(); 460 // Overloaded 461 EXPECT_TRUE(hasCompletion( 462 Comps, "hasParent(", 463 "Matcher<NestedNameSpecifierLoc|TypeLoc|Decl|...> " 464 "hasParent(Matcher<NestedNameSpecifierLoc|TypeLoc|Decl|...>)")); 465 // Variadic. 466 EXPECT_TRUE(hasCompletion(Comps, "whileStmt(", 467 "Matcher<Stmt> whileStmt(Matcher<WhileStmt>...)")); 468 // Polymorphic. 469 EXPECT_TRUE(hasCompletion( 470 Comps, "hasDescendant(", 471 "Matcher<NestedNameSpecifierLoc|QualType|TypeLoc|...> " 472 "hasDescendant(Matcher<NestedNameSpecifierLoc|QualType|TypeLoc|...>)")); 473 474 CompVector WhileComps = getCompletions("whileStmt", 0); 475 476 EXPECT_TRUE(hasCompletion(WhileComps, "hasBody(", 477 "Matcher<WhileStmt> hasBody(Matcher<Stmt>)")); 478 EXPECT_TRUE(hasCompletion( 479 WhileComps, "hasParent(", 480 "Matcher<Stmt> " 481 "hasParent(Matcher<NestedNameSpecifierLoc|TypeLoc|Decl|...>)")); 482 EXPECT_TRUE( 483 hasCompletion(WhileComps, "allOf(", "Matcher<T> allOf(Matcher<T>...)")); 484 485 EXPECT_FALSE(hasCompletion(WhileComps, "whileStmt(")); 486 EXPECT_FALSE(hasCompletion(WhileComps, "ifStmt(")); 487 488 CompVector AllOfWhileComps = 489 getCompletions("allOf", 0, "whileStmt", 0); 490 ASSERT_EQ(AllOfWhileComps.size(), WhileComps.size()); 491 EXPECT_TRUE(std::equal(WhileComps.begin(), WhileComps.end(), 492 AllOfWhileComps.begin())); 493 494 CompVector DeclWhileComps = 495 getCompletions("decl", 0, "whileStmt", 0); 496 EXPECT_EQ(0u, DeclWhileComps.size()); 497 498 CompVector NamedDeclComps = getCompletions("namedDecl", 0); 499 EXPECT_TRUE( 500 hasCompletion(NamedDeclComps, "isPublic()", "Matcher<Decl> isPublic()")); 501 EXPECT_TRUE(hasCompletion(NamedDeclComps, "hasName(\"", 502 "Matcher<NamedDecl> hasName(string)")); 503 504 // Heterogeneous overloads. 505 Comps = getCompletions("classTemplateSpecializationDecl", 0); 506 EXPECT_TRUE(hasCompletion( 507 Comps, "isSameOrDerivedFrom(", 508 "Matcher<CXXRecordDecl> isSameOrDerivedFrom(string|Matcher<NamedDecl>)")); 509 } 510 511 TEST_F(RegistryTest, MatcherBuilder) { 512 auto Ctor = *lookupMatcherCtor("mapAnyOf"); 513 EXPECT_TRUE(Registry::isBuilderMatcher(Ctor)); 514 auto BuiltCtor = Registry::buildMatcherCtor(Ctor, {}, Args(ASTNodeKind::getFromNodeKind<WhileStmt>(), ASTNodeKind::getFromNodeKind<ForStmt>()), nullptr); 515 EXPECT_TRUE(BuiltCtor.get()); 516 auto LoopMatcher = Registry::constructMatcher(BuiltCtor.get(), SourceRange(), Args(), nullptr).getTypedMatcher<Stmt>(); 517 EXPECT_TRUE(matches("void f() { for (;;) {} }", LoopMatcher)); 518 EXPECT_TRUE(matches("void f() { while (true) {} }", LoopMatcher)); 519 EXPECT_FALSE(matches("void f() { if (true) {} }", LoopMatcher)); 520 521 auto NotBuiltCtor = Registry::buildMatcherCtor(Ctor, {}, Args(ASTNodeKind::getFromNodeKind<FunctionDecl>(), ASTNodeKind::getFromNodeKind<ForStmt>()), nullptr); 522 EXPECT_FALSE(NotBuiltCtor.get()); 523 } 524 525 TEST_F(RegistryTest, NodeType) { 526 EXPECT_TRUE(Registry::nodeMatcherType(*lookupMatcherCtor("callExpr")).isSame(ASTNodeKind::getFromNodeKind<CallExpr>())); 527 EXPECT_TRUE(Registry::nodeMatcherType(*lookupMatcherCtor("has")).isNone()); 528 EXPECT_TRUE(Registry::nodeMatcherType(*lookupMatcherCtor("allOf")).isNone()); 529 } 530 531 TEST_F(RegistryTest, HasArgs) { 532 Matcher<Decl> Value = constructMatcher( 533 "decl", constructMatcher("hasAttr", StringRef("attr::WarnUnused"))) 534 .getTypedMatcher<Decl>(); 535 EXPECT_TRUE(matches("struct __attribute__((warn_unused)) X {};", Value)); 536 EXPECT_FALSE(matches("struct X {};", Value)); 537 } 538 539 TEST_F(RegistryTest, ParenExpr) { 540 Matcher<Stmt> Value = constructMatcher("parenExpr").getTypedMatcher<Stmt>(); 541 EXPECT_TRUE(matches("int i = (1);", traverse(TK_AsIs, Value))); 542 EXPECT_FALSE(matches("int i = 1;", traverse(TK_AsIs, Value))); 543 } 544 545 TEST_F(RegistryTest, EqualsMatcher) { 546 Matcher<Stmt> BooleanStmt = constructMatcher( 547 "cxxBoolLiteral", constructMatcher("equals", VariantValue(true))) 548 .getTypedMatcher<Stmt>(); 549 EXPECT_TRUE(matches("bool x = true;", BooleanStmt)); 550 EXPECT_FALSE(matches("bool x = false;", BooleanStmt)); 551 EXPECT_FALSE(matches("bool x = 0;", BooleanStmt)); 552 553 BooleanStmt = constructMatcher( 554 "cxxBoolLiteral", constructMatcher("equals", VariantValue(0))) 555 .getTypedMatcher<Stmt>(); 556 EXPECT_TRUE(matches("bool x = false;", BooleanStmt)); 557 EXPECT_FALSE(matches("bool x = true;", BooleanStmt)); 558 EXPECT_FALSE(matches("bool x = 0;", BooleanStmt)); 559 560 Matcher<Stmt> DoubleStmt = constructMatcher( 561 "floatLiteral", constructMatcher("equals", VariantValue(1.2))) 562 .getTypedMatcher<Stmt>(); 563 EXPECT_TRUE(matches("double x = 1.2;", DoubleStmt)); 564 #if 0 565 // FIXME floatLiteral matching should work regardless of suffix. 566 EXPECT_TRUE(matches("double x = 1.2f;", DoubleStmt)); 567 EXPECT_TRUE(matches("double x = 1.2l;", DoubleStmt)); 568 #endif 569 EXPECT_TRUE(matches("double x = 12e-1;", DoubleStmt)); 570 EXPECT_FALSE(matches("double x = 1.23;", DoubleStmt)); 571 572 Matcher<Stmt> IntegerStmt = constructMatcher( 573 "integerLiteral", constructMatcher("equals", VariantValue(42))) 574 .getTypedMatcher<Stmt>(); 575 EXPECT_TRUE(matches("int x = 42;", IntegerStmt)); 576 EXPECT_FALSE(matches("int x = 1;", IntegerStmt)); 577 578 Matcher<Stmt> CharStmt = constructMatcher( 579 "characterLiteral", constructMatcher("equals", VariantValue('x'))) 580 .getTypedMatcher<Stmt>(); 581 EXPECT_TRUE(matches("int x = 'x';", CharStmt)); 582 EXPECT_TRUE(matches("int x = L'x';", CharStmt)); 583 EXPECT_TRUE(matches("int x = u'x';", CharStmt)); 584 EXPECT_TRUE(matches("int x = U'x';", CharStmt)); 585 EXPECT_FALSE(matches("int x = 120;", CharStmt)); 586 } 587 588 } // end anonymous namespace 589 } // end namespace dynamic 590 } // end namespace ast_matchers 591 } // end namespace clang 592