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 15namespace clang { 16namespace ast_matchers { 17namespace dynamic { 18namespace { 19 20using ast_matchers::internal::Matcher; 21 22class RegistryTest : public ::testing::Test { 23public: 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 return Registry::getCompletions( 86 ArrayRef<std::pair<MatcherCtor, unsigned> >()); 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::getCompletions(Context); 96 } 97 98 CompVector getCompletions(StringRef MatcherName1, unsigned ArgNo1, 99 StringRef MatcherName2, unsigned ArgNo2) { 100 std::vector<std::pair<MatcherCtor, unsigned> > Context; 101 llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName1); 102 if (!Ctor) 103 return CompVector(); 104 Context.push_back(std::make_pair(*Ctor, ArgNo1)); 105 Ctor = lookupMatcherCtor(MatcherName2); 106 if (!Ctor) 107 return CompVector(); 108 Context.push_back(std::make_pair(*Ctor, ArgNo2)); 109 return Registry::getCompletions(Context); 110 } 111 112 bool hasCompletion(const CompVector &Comps, StringRef TypedText, 113 StringRef MatcherDecl = StringRef(), 114 unsigned *Index = nullptr) { 115 for (CompVector::const_iterator I = Comps.begin(), E = Comps.end(); I != E; 116 ++I) { 117 if (I->TypedText == TypedText && 118 (MatcherDecl.empty() || I->MatcherDecl == MatcherDecl)) { 119 if (Index) 120 *Index = I - Comps.begin(); 121 return true; 122 } 123 } 124 return false; 125 } 126}; 127 128TEST_F(RegistryTest, CanConstructNoArgs) { 129 Matcher<Stmt> IsArrowValue = constructMatcher( 130 "memberExpr", constructMatcher("isArrow")).getTypedMatcher<Stmt>(); 131 Matcher<Stmt> BoolValue = 132 constructMatcher("boolLiteral").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 145TEST_F(RegistryTest, ConstructWithSimpleArgs) { 146 Matcher<Decl> Value = constructMatcher( 147 "namedDecl", constructMatcher("hasName", std::string("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 158TEST_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", std::string("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 187TEST_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("methodDecl", 199 constructMatcher("hasName", std::string("x"))))) 200 .getTypedMatcher<Stmt>(); 201 202 std::string Code = "class Y { public: void x(); }; void z() { Y y; y.x(); }"; 203 EXPECT_FALSE(matches(Code, CallExpr0)); 204 EXPECT_TRUE(matches(Code, CallExpr1)); 205 206 Code = "class Z { public: void z() { this->z(); } };"; 207 EXPECT_TRUE(matches(Code, CallExpr0)); 208 EXPECT_FALSE(matches(Code, CallExpr1)); 209 210 Matcher<Decl> DeclDecl = declaratorDecl(hasTypeLoc( 211 constructMatcher( 212 "loc", constructMatcher("asString", std::string("const double *"))) 213 .getTypedMatcher<TypeLoc>())); 214 215 Matcher<NestedNameSpecifierLoc> NNSL = 216 constructMatcher( 217 "loc", VariantMatcher::SingleMatcher(nestedNameSpecifier( 218 specifiesType(hasDeclaration(recordDecl(hasName("A"))))))) 219 .getTypedMatcher<NestedNameSpecifierLoc>(); 220 221 Code = "const double * x = 0;"; 222 EXPECT_TRUE(matches(Code, DeclDecl)); 223 EXPECT_FALSE(matches(Code, NNSL)); 224 225 Code = "struct A { struct B {}; }; A::B a_b;"; 226 EXPECT_FALSE(matches(Code, DeclDecl)); 227 EXPECT_TRUE(matches(Code, NNSL)); 228} 229 230TEST_F(RegistryTest, PolymorphicMatchers) { 231 const VariantMatcher IsDefinition = constructMatcher("isDefinition"); 232 Matcher<Decl> Var = 233 constructMatcher("varDecl", IsDefinition).getTypedMatcher<Decl>(); 234 Matcher<Decl> Class = 235 constructMatcher("recordDecl", IsDefinition).getTypedMatcher<Decl>(); 236 Matcher<Decl> Func = 237 constructMatcher("functionDecl", IsDefinition).getTypedMatcher<Decl>(); 238 EXPECT_TRUE(matches("int a;", Var)); 239 EXPECT_FALSE(matches("extern int a;", Var)); 240 EXPECT_TRUE(matches("class A {};", Class)); 241 EXPECT_FALSE(matches("class A;", Class)); 242 EXPECT_TRUE(matches("void f(){};", Func)); 243 EXPECT_FALSE(matches("void f();", Func)); 244 245 Matcher<Decl> Anything = constructMatcher("anything").getTypedMatcher<Decl>(); 246 Matcher<Decl> RecordDecl = constructMatcher( 247 "recordDecl", constructMatcher("hasName", std::string("Foo")), 248 VariantMatcher::SingleMatcher(Anything)).getTypedMatcher<Decl>(); 249 250 EXPECT_TRUE(matches("int Foo;", Anything)); 251 EXPECT_TRUE(matches("class Foo {};", Anything)); 252 EXPECT_TRUE(matches("void Foo(){};", Anything)); 253 EXPECT_FALSE(matches("int Foo;", RecordDecl)); 254 EXPECT_TRUE(matches("class Foo {};", RecordDecl)); 255 EXPECT_FALSE(matches("void Foo(){};", RecordDecl)); 256 257 Matcher<Stmt> ConstructExpr = constructMatcher( 258 "constructExpr", 259 constructMatcher( 260 "hasDeclaration", 261 constructMatcher( 262 "methodDecl", 263 constructMatcher( 264 "ofClass", constructMatcher("hasName", std::string("Foo")))))) 265 .getTypedMatcher<Stmt>(); 266 EXPECT_FALSE(matches("class Foo { public: Foo(); };", ConstructExpr)); 267 EXPECT_TRUE( 268 matches("class Foo { public: Foo(); }; Foo foo = Foo();", ConstructExpr)); 269} 270 271TEST_F(RegistryTest, TemplateArgument) { 272 Matcher<Decl> HasTemplateArgument = constructMatcher( 273 "classTemplateSpecializationDecl", 274 constructMatcher( 275 "hasAnyTemplateArgument", 276 constructMatcher("refersToType", 277 constructMatcher("asString", std::string("int"))))) 278 .getTypedMatcher<Decl>(); 279 EXPECT_TRUE(matches("template<typename T> class A {}; A<int> a;", 280 HasTemplateArgument)); 281 EXPECT_FALSE(matches("template<typename T> class A {}; A<char> a;", 282 HasTemplateArgument)); 283} 284 285TEST_F(RegistryTest, TypeTraversal) { 286 Matcher<Type> M = constructMatcher( 287 "pointerType", 288 constructMatcher("pointee", constructMatcher("isConstQualified"), 289 constructMatcher("isInteger"))).getTypedMatcher<Type>(); 290 EXPECT_FALSE(matches("int *a;", M)); 291 EXPECT_TRUE(matches("int const *b;", M)); 292 293 M = constructMatcher( 294 "arrayType", 295 constructMatcher("hasElementType", constructMatcher("builtinType"))) 296 .getTypedMatcher<Type>(); 297 EXPECT_FALSE(matches("struct A{}; A a[7];;", M)); 298 EXPECT_TRUE(matches("int b[7];", M)); 299} 300 301TEST_F(RegistryTest, CXXCtorInitializer) { 302 Matcher<Decl> CtorDecl = constructMatcher( 303 "constructorDecl", 304 constructMatcher( 305 "hasAnyConstructorInitializer", 306 constructMatcher("forField", 307 constructMatcher("hasName", std::string("foo"))))) 308 .getTypedMatcher<Decl>(); 309 EXPECT_TRUE(matches("struct Foo { Foo() : foo(1) {} int foo; };", CtorDecl)); 310 EXPECT_FALSE(matches("struct Foo { Foo() {} int foo; };", CtorDecl)); 311 EXPECT_FALSE(matches("struct Foo { Foo() : bar(1) {} int bar; };", CtorDecl)); 312} 313 314TEST_F(RegistryTest, Adaptative) { 315 Matcher<Decl> D = constructMatcher( 316 "recordDecl", 317 constructMatcher( 318 "has", 319 constructMatcher("recordDecl", 320 constructMatcher("hasName", std::string("X"))))) 321 .getTypedMatcher<Decl>(); 322 EXPECT_TRUE(matches("class X {};", D)); 323 EXPECT_TRUE(matches("class Y { class X {}; };", D)); 324 EXPECT_FALSE(matches("class Y { class Z {}; };", D)); 325 326 Matcher<Stmt> S = constructMatcher( 327 "forStmt", 328 constructMatcher( 329 "hasDescendant", 330 constructMatcher("varDecl", 331 constructMatcher("hasName", std::string("X"))))) 332 .getTypedMatcher<Stmt>(); 333 EXPECT_TRUE(matches("void foo() { for(int X;;); }", S)); 334 EXPECT_TRUE(matches("void foo() { for(;;) { int X; } }", S)); 335 EXPECT_FALSE(matches("void foo() { for(;;); }", S)); 336 EXPECT_FALSE(matches("void foo() { if (int X = 0){} }", S)); 337 338 S = constructMatcher( 339 "compoundStmt", constructMatcher("hasParent", constructMatcher("ifStmt"))) 340 .getTypedMatcher<Stmt>(); 341 EXPECT_TRUE(matches("void foo() { if (true) { int x = 42; } }", S)); 342 EXPECT_FALSE(matches("void foo() { if (true) return; }", S)); 343} 344 345TEST_F(RegistryTest, VariadicOp) { 346 Matcher<Decl> D = constructMatcher( 347 "anyOf", 348 constructMatcher("recordDecl", 349 constructMatcher("hasName", std::string("Foo"))), 350 constructMatcher("namedDecl", 351 constructMatcher("hasName", std::string("foo")))) 352 .getTypedMatcher<Decl>(); 353 354 EXPECT_TRUE(matches("void foo(){}", D)); 355 EXPECT_TRUE(matches("struct Foo{};", D)); 356 EXPECT_FALSE(matches("int i = 0;", D)); 357 358 D = constructMatcher( 359 "allOf", constructMatcher("recordDecl"), 360 constructMatcher( 361 "namedDecl", 362 constructMatcher("anyOf", 363 constructMatcher("hasName", std::string("Foo")), 364 constructMatcher("hasName", std::string("Bar"))))) 365 .getTypedMatcher<Decl>(); 366 367 EXPECT_FALSE(matches("void foo(){}", D)); 368 EXPECT_TRUE(matches("struct Foo{};", D)); 369 EXPECT_FALSE(matches("int i = 0;", D)); 370 EXPECT_TRUE(matches("class Bar{};", D)); 371 EXPECT_FALSE(matches("class OtherBar{};", D)); 372 373 D = recordDecl( 374 has(fieldDecl(hasName("Foo"))), 375 constructMatcher( 376 "unless", 377 constructMatcher("namedDecl", 378 constructMatcher("hasName", std::string("Bar")))) 379 .getTypedMatcher<Decl>()); 380 381 EXPECT_FALSE(matches("class Bar{ int Foo; };", D)); 382 EXPECT_TRUE(matches("class OtherBar{ int Foo; };", D)); 383} 384 385TEST_F(RegistryTest, Errors) { 386 // Incorrect argument count. 387 std::unique_ptr<Diagnostics> Error(new Diagnostics()); 388 EXPECT_TRUE(constructMatcher("hasInitializer", Error.get()).isNull()); 389 EXPECT_EQ("Incorrect argument count. (Expected = 1) != (Actual = 0)", 390 Error->toString()); 391 Error.reset(new Diagnostics()); 392 EXPECT_TRUE(constructMatcher("isArrow", std::string(), Error.get()).isNull()); 393 EXPECT_EQ("Incorrect argument count. (Expected = 0) != (Actual = 1)", 394 Error->toString()); 395 Error.reset(new Diagnostics()); 396 EXPECT_TRUE(constructMatcher("anyOf", Error.get()).isNull()); 397 EXPECT_EQ("Incorrect argument count. (Expected = (2, )) != (Actual = 0)", 398 Error->toString()); 399 Error.reset(new Diagnostics()); 400 EXPECT_TRUE(constructMatcher("unless", std::string(), std::string(), 401 Error.get()).isNull()); 402 EXPECT_EQ("Incorrect argument count. (Expected = (1, 1)) != (Actual = 2)", 403 Error->toString()); 404 405 // Bad argument type 406 Error.reset(new Diagnostics()); 407 EXPECT_TRUE(constructMatcher("ofClass", std::string(), Error.get()).isNull()); 408 EXPECT_EQ("Incorrect type for arg 1. (Expected = Matcher<CXXRecordDecl>) != " 409 "(Actual = String)", 410 Error->toString()); 411 Error.reset(new Diagnostics()); 412 EXPECT_TRUE(constructMatcher("recordDecl", constructMatcher("recordDecl"), 413 constructMatcher("parameterCountIs", 3), 414 Error.get()).isNull()); 415 EXPECT_EQ("Incorrect type for arg 2. (Expected = Matcher<CXXRecordDecl>) != " 416 "(Actual = Matcher<FunctionDecl>)", 417 Error->toString()); 418 419 // Bad argument type with variadic. 420 Error.reset(new Diagnostics()); 421 EXPECT_TRUE(constructMatcher("anyOf", std::string(), std::string(), 422 Error.get()).isNull()); 423 EXPECT_EQ( 424 "Incorrect type for arg 1. (Expected = Matcher<>) != (Actual = String)", 425 Error->toString()); 426 Error.reset(new Diagnostics()); 427 EXPECT_TRUE(constructMatcher( 428 "recordDecl", 429 constructMatcher("allOf", 430 constructMatcher("isDerivedFrom", std::string("FOO")), 431 constructMatcher("isArrow")), 432 Error.get()).isNull()); 433 EXPECT_EQ("Incorrect type for arg 1. " 434 "(Expected = Matcher<CXXRecordDecl>) != " 435 "(Actual = Matcher<CXXRecordDecl>&Matcher<MemberExpr>)", 436 Error->toString()); 437} 438 439TEST_F(RegistryTest, Completion) { 440 CompVector Comps = getCompletions(); 441 EXPECT_TRUE(hasCompletion( 442 Comps, "hasParent(", "Matcher<Decl|Stmt> hasParent(Matcher<Decl|Stmt>)")); 443 EXPECT_TRUE(hasCompletion(Comps, "whileStmt(", 444 "Matcher<Stmt> whileStmt(Matcher<WhileStmt>...)")); 445 446 CompVector WhileComps = getCompletions("whileStmt", 0); 447 448 unsigned HasBodyIndex, HasParentIndex, AllOfIndex; 449 EXPECT_TRUE(hasCompletion(WhileComps, "hasBody(", 450 "Matcher<WhileStmt> hasBody(Matcher<Stmt>)", 451 &HasBodyIndex)); 452 EXPECT_TRUE(hasCompletion(WhileComps, "hasParent(", 453 "Matcher<Stmt> hasParent(Matcher<Decl|Stmt>)", 454 &HasParentIndex)); 455 EXPECT_TRUE(hasCompletion(WhileComps, "allOf(", 456 "Matcher<T> allOf(Matcher<T>...)", &AllOfIndex)); 457 EXPECT_GT(HasParentIndex, HasBodyIndex); 458 EXPECT_GT(AllOfIndex, HasParentIndex); 459 460 EXPECT_FALSE(hasCompletion(WhileComps, "whileStmt(")); 461 EXPECT_FALSE(hasCompletion(WhileComps, "ifStmt(")); 462 463 CompVector AllOfWhileComps = 464 getCompletions("allOf", 0, "whileStmt", 0); 465 ASSERT_EQ(AllOfWhileComps.size(), WhileComps.size()); 466 EXPECT_TRUE(std::equal(WhileComps.begin(), WhileComps.end(), 467 AllOfWhileComps.begin())); 468 469 CompVector DeclWhileComps = 470 getCompletions("decl", 0, "whileStmt", 0); 471 EXPECT_EQ(0u, DeclWhileComps.size()); 472 473 CompVector NamedDeclComps = getCompletions("namedDecl", 0); 474 EXPECT_TRUE( 475 hasCompletion(NamedDeclComps, "isPublic()", "Matcher<Decl> isPublic()")); 476 EXPECT_TRUE(hasCompletion(NamedDeclComps, "hasName(\"", 477 "Matcher<NamedDecl> hasName(string)")); 478} 479 480} // end anonymous namespace 481} // end namespace dynamic 482} // end namespace ast_matchers 483} // end namespace clang 484