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