RegistryTest.cpp revision 6bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89
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 = NULL) { 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 = NULL) { 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 = NULL) { 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 llvm::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(), unsigned *Index = 0) { 114 for (CompVector::const_iterator I = Comps.begin(), E = Comps.end(); I != E; 115 ++I) { 116 if (I->TypedText == TypedText && 117 (MatcherDecl.empty() || I->MatcherDecl == MatcherDecl)) { 118 if (Index) 119 *Index = I - Comps.begin(); 120 return true; 121 } 122 } 123 return false; 124 } 125}; 126 127TEST_F(RegistryTest, CanConstructNoArgs) { 128 Matcher<Stmt> IsArrowValue = constructMatcher( 129 "memberExpr", constructMatcher("isArrow")).getTypedMatcher<Stmt>(); 130 Matcher<Stmt> BoolValue = 131 constructMatcher("boolLiteral").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 144TEST_F(RegistryTest, ConstructWithSimpleArgs) { 145 Matcher<Decl> Value = constructMatcher( 146 "namedDecl", constructMatcher("hasName", std::string("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 157TEST_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", std::string("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 186TEST_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("methodDecl", 198 constructMatcher("hasName", std::string("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", std::string("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 229TEST_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", std::string("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 "constructExpr", 258 constructMatcher( 259 "hasDeclaration", 260 constructMatcher( 261 "methodDecl", 262 constructMatcher( 263 "ofClass", constructMatcher("hasName", std::string("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 270TEST_F(RegistryTest, TemplateArgument) { 271 Matcher<Decl> HasTemplateArgument = constructMatcher( 272 "classTemplateSpecializationDecl", 273 constructMatcher( 274 "hasAnyTemplateArgument", 275 constructMatcher("refersToType", 276 constructMatcher("asString", std::string("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 284TEST_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 300TEST_F(RegistryTest, CXXCtorInitializer) { 301 Matcher<Decl> CtorDecl = constructMatcher( 302 "constructorDecl", 303 constructMatcher( 304 "hasAnyConstructorInitializer", 305 constructMatcher("forField", 306 constructMatcher("hasName", std::string("foo"))))) 307 .getTypedMatcher<Decl>(); 308 EXPECT_TRUE(matches("struct Foo { Foo() : foo(1) {} int foo; };", CtorDecl)); 309 EXPECT_FALSE(matches("struct Foo { Foo() {} int foo; };", CtorDecl)); 310 EXPECT_FALSE(matches("struct Foo { Foo() : bar(1) {} int bar; };", CtorDecl)); 311} 312 313TEST_F(RegistryTest, Adaptative) { 314 Matcher<Decl> D = constructMatcher( 315 "recordDecl", 316 constructMatcher( 317 "has", 318 constructMatcher("recordDecl", 319 constructMatcher("hasName", std::string("X"))))) 320 .getTypedMatcher<Decl>(); 321 EXPECT_TRUE(matches("class X {};", D)); 322 EXPECT_TRUE(matches("class Y { class X {}; };", D)); 323 EXPECT_FALSE(matches("class Y { class Z {}; };", D)); 324 325 Matcher<Stmt> S = constructMatcher( 326 "forStmt", 327 constructMatcher( 328 "hasDescendant", 329 constructMatcher("varDecl", 330 constructMatcher("hasName", std::string("X"))))) 331 .getTypedMatcher<Stmt>(); 332 EXPECT_TRUE(matches("void foo() { for(int X;;); }", S)); 333 EXPECT_TRUE(matches("void foo() { for(;;) { int X; } }", S)); 334 EXPECT_FALSE(matches("void foo() { for(;;); }", S)); 335 EXPECT_FALSE(matches("void foo() { if (int X = 0){} }", S)); 336 337 S = constructMatcher( 338 "compoundStmt", constructMatcher("hasParent", constructMatcher("ifStmt"))) 339 .getTypedMatcher<Stmt>(); 340 EXPECT_TRUE(matches("void foo() { if (true) { int x = 42; } }", S)); 341 EXPECT_FALSE(matches("void foo() { if (true) return; }", S)); 342} 343 344TEST_F(RegistryTest, VariadicOp) { 345 Matcher<Decl> D = constructMatcher( 346 "anyOf", 347 constructMatcher("recordDecl", 348 constructMatcher("hasName", std::string("Foo"))), 349 constructMatcher("namedDecl", 350 constructMatcher("hasName", std::string("foo")))) 351 .getTypedMatcher<Decl>(); 352 353 EXPECT_TRUE(matches("void foo(){}", D)); 354 EXPECT_TRUE(matches("struct Foo{};", D)); 355 EXPECT_FALSE(matches("int i = 0;", D)); 356 357 D = constructMatcher( 358 "allOf", constructMatcher("recordDecl"), 359 constructMatcher( 360 "namedDecl", 361 constructMatcher("anyOf", 362 constructMatcher("hasName", std::string("Foo")), 363 constructMatcher("hasName", std::string("Bar"))))) 364 .getTypedMatcher<Decl>(); 365 366 EXPECT_FALSE(matches("void foo(){}", D)); 367 EXPECT_TRUE(matches("struct Foo{};", D)); 368 EXPECT_FALSE(matches("int i = 0;", D)); 369 EXPECT_TRUE(matches("class Bar{};", D)); 370 EXPECT_FALSE(matches("class OtherBar{};", D)); 371 372 D = recordDecl( 373 has(fieldDecl(hasName("Foo"))), 374 constructMatcher( 375 "unless", 376 constructMatcher("namedDecl", 377 constructMatcher("hasName", std::string("Bar")))) 378 .getTypedMatcher<Decl>()); 379 380 EXPECT_FALSE(matches("class Bar{ int Foo; };", D)); 381 EXPECT_TRUE(matches("class OtherBar{ int Foo; };", D)); 382} 383 384TEST_F(RegistryTest, Errors) { 385 // Incorrect argument count. 386 std::unique_ptr<Diagnostics> Error(new Diagnostics()); 387 EXPECT_TRUE(constructMatcher("hasInitializer", Error.get()).isNull()); 388 EXPECT_EQ("Incorrect argument count. (Expected = 1) != (Actual = 0)", 389 Error->toString()); 390 Error.reset(new Diagnostics()); 391 EXPECT_TRUE(constructMatcher("isArrow", std::string(), Error.get()).isNull()); 392 EXPECT_EQ("Incorrect argument count. (Expected = 0) != (Actual = 1)", 393 Error->toString()); 394 Error.reset(new Diagnostics()); 395 EXPECT_TRUE(constructMatcher("anyOf", Error.get()).isNull()); 396 EXPECT_EQ("Incorrect argument count. (Expected = (2, )) != (Actual = 0)", 397 Error->toString()); 398 Error.reset(new Diagnostics()); 399 EXPECT_TRUE(constructMatcher("unless", std::string(), std::string(), 400 Error.get()).isNull()); 401 EXPECT_EQ("Incorrect argument count. (Expected = (1, 1)) != (Actual = 2)", 402 Error->toString()); 403 404 // Bad argument type 405 Error.reset(new Diagnostics()); 406 EXPECT_TRUE(constructMatcher("ofClass", std::string(), Error.get()).isNull()); 407 EXPECT_EQ("Incorrect type for arg 1. (Expected = Matcher<CXXRecordDecl>) != " 408 "(Actual = String)", 409 Error->toString()); 410 Error.reset(new Diagnostics()); 411 EXPECT_TRUE(constructMatcher("recordDecl", constructMatcher("recordDecl"), 412 constructMatcher("parameterCountIs", 3), 413 Error.get()).isNull()); 414 EXPECT_EQ("Incorrect type for arg 2. (Expected = Matcher<CXXRecordDecl>) != " 415 "(Actual = Matcher<FunctionDecl>)", 416 Error->toString()); 417 418 // Bad argument type with variadic. 419 Error.reset(new Diagnostics()); 420 EXPECT_TRUE(constructMatcher("anyOf", std::string(), std::string(), 421 Error.get()).isNull()); 422 EXPECT_EQ( 423 "Incorrect type for arg 1. (Expected = Matcher<>) != (Actual = String)", 424 Error->toString()); 425 Error.reset(new Diagnostics()); 426 EXPECT_TRUE(constructMatcher( 427 "recordDecl", 428 constructMatcher("allOf", 429 constructMatcher("isDerivedFrom", std::string("FOO")), 430 constructMatcher("isArrow")), 431 Error.get()).isNull()); 432 EXPECT_EQ("Incorrect type for arg 1. " 433 "(Expected = Matcher<CXXRecordDecl>) != " 434 "(Actual = Matcher<CXXRecordDecl>&Matcher<MemberExpr>)", 435 Error->toString()); 436} 437 438TEST_F(RegistryTest, Completion) { 439 CompVector Comps = getCompletions(); 440 EXPECT_TRUE(hasCompletion( 441 Comps, "hasParent(", "Matcher<Decl|Stmt> hasParent(Matcher<Decl|Stmt>)")); 442 EXPECT_TRUE(hasCompletion(Comps, "whileStmt(", 443 "Matcher<Stmt> whileStmt(Matcher<WhileStmt>...)")); 444 445 CompVector WhileComps = getCompletions("whileStmt", 0); 446 447 unsigned HasBodyIndex, HasParentIndex, AllOfIndex; 448 EXPECT_TRUE(hasCompletion(WhileComps, "hasBody(", 449 "Matcher<WhileStmt> hasBody(Matcher<Stmt>)", 450 &HasBodyIndex)); 451 EXPECT_TRUE(hasCompletion(WhileComps, "hasParent(", 452 "Matcher<Stmt> hasParent(Matcher<Decl|Stmt>)", 453 &HasParentIndex)); 454 EXPECT_TRUE(hasCompletion(WhileComps, "allOf(", 455 "Matcher<T> allOf(Matcher<T>...)", &AllOfIndex)); 456 EXPECT_GT(HasParentIndex, HasBodyIndex); 457 EXPECT_GT(AllOfIndex, HasParentIndex); 458 459 EXPECT_FALSE(hasCompletion(WhileComps, "whileStmt(")); 460 EXPECT_FALSE(hasCompletion(WhileComps, "ifStmt(")); 461 462 CompVector AllOfWhileComps = 463 getCompletions("allOf", 0, "whileStmt", 0); 464 ASSERT_EQ(AllOfWhileComps.size(), WhileComps.size()); 465 EXPECT_TRUE(std::equal(WhileComps.begin(), WhileComps.end(), 466 AllOfWhileComps.begin())); 467 468 CompVector DeclWhileComps = 469 getCompletions("decl", 0, "whileStmt", 0); 470 EXPECT_EQ(0u, DeclWhileComps.size()); 471 472 CompVector NamedDeclComps = getCompletions("namedDecl", 0); 473 EXPECT_TRUE( 474 hasCompletion(NamedDeclComps, "isPublic()", "Matcher<Decl> isPublic()")); 475 EXPECT_TRUE(hasCompletion(NamedDeclComps, "hasName(\"", 476 "Matcher<NamedDecl> hasName(string)")); 477} 478 479} // end anonymous namespace 480} // end namespace dynamic 481} // end namespace ast_matchers 482} // end namespace clang 483