1 //===- unittest/ASTMatchers/Dynamic/RegistryTest.cpp - Registry unit tests -===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===-----------------------------------------------------------------------===//
10 #include "../ASTMatchersTest.h"
11 #include "clang/ASTMatchers/Dynamic/Registry.h"
12 #include "gtest/gtest.h"
16 namespace ast_matchers {
20 using ast_matchers::internal::Matcher;
22 class RegistryTest : public ::testing::Test {
24 std::vector<ParserValue> Args() { return std::vector<ParserValue>(); }
25 std::vector<ParserValue> Args(const VariantValue &Arg1) {
26 std::vector<ParserValue> Out(1);
30 std::vector<ParserValue> Args(const VariantValue &Arg1,
31 const VariantValue &Arg2) {
32 std::vector<ParserValue> Out(2);
38 llvm::Optional<MatcherCtor> lookupMatcherCtor(StringRef MatcherName) {
39 return Registry::lookupMatcherCtor(MatcherName);
42 VariantMatcher constructMatcher(StringRef MatcherName,
43 Diagnostics *Error = nullptr) {
44 Diagnostics DummyError;
45 if (!Error) Error = &DummyError;
46 llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName);
49 Out = Registry::constructMatcher(*Ctor, SourceRange(), Args(), Error);
50 EXPECT_EQ("", DummyError.toStringFull());
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);
62 Out = Registry::constructMatcher(*Ctor, SourceRange(), Args(Arg1), Error);
63 EXPECT_EQ("", DummyError.toStringFull()) << MatcherName;
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);
76 Out = Registry::constructMatcher(*Ctor, SourceRange(), Args(Arg1, Arg2),
78 EXPECT_EQ("", DummyError.toStringFull());
82 typedef std::vector<MatcherCompletion> CompVector;
84 CompVector getCompletions() {
85 std::vector<std::pair<MatcherCtor, unsigned> > Context;
86 return Registry::getMatcherCompletions(
87 Registry::getAcceptedCompletionTypes(Context));
90 CompVector getCompletions(StringRef MatcherName1, unsigned ArgNo1) {
91 std::vector<std::pair<MatcherCtor, unsigned> > Context;
92 llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName1);
95 Context.push_back(std::make_pair(*Ctor, ArgNo1));
96 return Registry::getMatcherCompletions(
97 Registry::getAcceptedCompletionTypes(Context));
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);
106 Context.push_back(std::make_pair(*Ctor, ArgNo1));
107 Ctor = lookupMatcherCtor(MatcherName2);
110 Context.push_back(std::make_pair(*Ctor, ArgNo2));
111 return Registry::getMatcherCompletions(
112 Registry::getAcceptedCompletionTypes(Context));
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;
119 if (I->TypedText == TypedText &&
120 (MatcherDecl.empty() || I->MatcherDecl == MatcherDecl)) {
128 TEST_F(RegistryTest, CanConstructNoArgs) {
129 Matcher<Stmt> IsArrowValue = constructMatcher(
130 "memberExpr", constructMatcher("isArrow")).getTypedMatcher<Stmt>();
131 Matcher<Stmt> BoolValue =
132 constructMatcher("boolLiteral").getTypedMatcher<Stmt>();
134 const std::string ClassSnippet = "struct Foo { int x; };\n"
135 "Foo *foo = new Foo;\n"
137 const std::string BoolSnippet = "bool Foo = true;\n";
139 EXPECT_TRUE(matches(ClassSnippet, IsArrowValue));
140 EXPECT_TRUE(matches(BoolSnippet, BoolValue));
141 EXPECT_FALSE(matches(ClassSnippet, BoolValue));
142 EXPECT_FALSE(matches(BoolSnippet, IsArrowValue));
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));
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));
158 TEST_F(RegistryTest, ConstructWithMatcherArgs) {
159 Matcher<Decl> HasInitializerSimple = constructMatcher(
160 "varDecl", constructMatcher("hasInitializer", constructMatcher("stmt")))
161 .getTypedMatcher<Decl>();
162 Matcher<Decl> HasInitializerComplex = constructMatcher(
164 constructMatcher("hasInitializer", constructMatcher("callExpr")))
165 .getTypedMatcher<Decl>();
167 std::string code = "int i;";
168 EXPECT_FALSE(matches(code, HasInitializerSimple));
169 EXPECT_FALSE(matches(code, HasInitializerComplex));
172 EXPECT_TRUE(matches(code, HasInitializerSimple));
173 EXPECT_FALSE(matches(code, HasInitializerComplex));
175 code = "int y(); int i = y();";
176 EXPECT_TRUE(matches(code, HasInitializerSimple));
177 EXPECT_TRUE(matches(code, HasInitializerComplex));
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));
187 TEST_F(RegistryTest, OverloadedMatchers) {
188 Matcher<Stmt> CallExpr0 = constructMatcher(
190 constructMatcher("callee", constructMatcher("memberExpr",
191 constructMatcher("isArrow"))))
192 .getTypedMatcher<Stmt>();
194 Matcher<Stmt> CallExpr1 = constructMatcher(
198 constructMatcher("methodDecl",
199 constructMatcher("hasName", StringRef("x")))))
200 .getTypedMatcher<Stmt>();
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));
206 Code = "class Z { public: void z() { this->z(); } };";
207 EXPECT_TRUE(matches(Code, CallExpr0));
208 EXPECT_FALSE(matches(Code, CallExpr1));
210 Matcher<Decl> DeclDecl = declaratorDecl(hasTypeLoc(
212 "loc", constructMatcher("asString", StringRef("const double *")))
213 .getTypedMatcher<TypeLoc>()));
215 Matcher<NestedNameSpecifierLoc> NNSL =
217 "loc", VariantMatcher::SingleMatcher(nestedNameSpecifier(
218 specifiesType(hasDeclaration(recordDecl(hasName("A")))))))
219 .getTypedMatcher<NestedNameSpecifierLoc>();
221 Code = "const double * x = 0;";
222 EXPECT_TRUE(matches(Code, DeclDecl));
223 EXPECT_FALSE(matches(Code, NNSL));
225 Code = "struct A { struct B {}; }; A::B a_b;";
226 EXPECT_FALSE(matches(Code, DeclDecl));
227 EXPECT_TRUE(matches(Code, NNSL));
230 TEST_F(RegistryTest, PolymorphicMatchers) {
231 const VariantMatcher IsDefinition = constructMatcher("isDefinition");
233 constructMatcher("varDecl", IsDefinition).getTypedMatcher<Decl>();
234 Matcher<Decl> Class =
235 constructMatcher("recordDecl", IsDefinition).getTypedMatcher<Decl>();
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));
245 Matcher<Decl> Anything = constructMatcher("anything").getTypedMatcher<Decl>();
246 Matcher<Decl> RecordDecl = constructMatcher(
247 "recordDecl", constructMatcher("hasName", StringRef("Foo")),
248 VariantMatcher::SingleMatcher(Anything)).getTypedMatcher<Decl>();
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));
257 Matcher<Stmt> ConstructExpr = constructMatcher(
264 "ofClass", constructMatcher("hasName", StringRef("Foo"))))))
265 .getTypedMatcher<Stmt>();
266 EXPECT_FALSE(matches("class Foo { public: Foo(); };", ConstructExpr));
268 matches("class Foo { public: Foo(); }; Foo foo = Foo();", ConstructExpr));
271 TEST_F(RegistryTest, TemplateArgument) {
272 Matcher<Decl> HasTemplateArgument = constructMatcher(
273 "classTemplateSpecializationDecl",
275 "hasAnyTemplateArgument",
276 constructMatcher("refersToType",
277 constructMatcher("asString", StringRef("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));
285 TEST_F(RegistryTest, TypeTraversal) {
286 Matcher<Type> M = constructMatcher(
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));
293 M = constructMatcher(
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));
301 TEST_F(RegistryTest, CXXCtorInitializer) {
302 Matcher<Decl> CtorDecl = constructMatcher(
305 "hasAnyConstructorInitializer",
306 constructMatcher("forField",
307 constructMatcher("hasName", StringRef("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));
314 TEST_F(RegistryTest, Adaptative) {
315 Matcher<Decl> D = constructMatcher(
319 constructMatcher("recordDecl",
320 constructMatcher("hasName", StringRef("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));
326 Matcher<Stmt> S = constructMatcher(
330 constructMatcher("varDecl",
331 constructMatcher("hasName", StringRef("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));
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));
345 TEST_F(RegistryTest, VariadicOp) {
346 Matcher<Decl> D = constructMatcher(
348 constructMatcher("recordDecl",
349 constructMatcher("hasName", StringRef("Foo"))),
350 constructMatcher("functionDecl",
351 constructMatcher("hasName", StringRef("foo"))))
352 .getTypedMatcher<Decl>();
354 EXPECT_TRUE(matches("void foo(){}", D));
355 EXPECT_TRUE(matches("struct Foo{};", D));
356 EXPECT_FALSE(matches("int i = 0;", D));
358 D = constructMatcher(
359 "allOf", constructMatcher("recordDecl"),
362 constructMatcher("anyOf",
363 constructMatcher("hasName", StringRef("Foo")),
364 constructMatcher("hasName", StringRef("Bar")))))
365 .getTypedMatcher<Decl>();
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));
374 has(fieldDecl(hasName("Foo"))),
377 constructMatcher("namedDecl",
378 constructMatcher("hasName", StringRef("Bar"))))
379 .getTypedMatcher<Decl>());
381 EXPECT_FALSE(matches("class Bar{ int Foo; };", D));
382 EXPECT_TRUE(matches("class OtherBar{ int Foo; };", D));
384 D = constructMatcher(
385 "namedDecl", constructMatcher("hasName", StringRef("Foo")),
386 constructMatcher("unless", constructMatcher("recordDecl")))
387 .getTypedMatcher<Decl>();
388 EXPECT_TRUE(matches("void Foo(){}", D));
389 EXPECT_TRUE(notMatches("struct Foo {};", D));
392 TEST_F(RegistryTest, Errors) {
393 // Incorrect argument count.
394 std::unique_ptr<Diagnostics> Error(new Diagnostics());
395 EXPECT_TRUE(constructMatcher("hasInitializer", Error.get()).isNull());
396 EXPECT_EQ("Incorrect argument count. (Expected = 1) != (Actual = 0)",
398 Error.reset(new Diagnostics());
399 EXPECT_TRUE(constructMatcher("isArrow", StringRef(), Error.get()).isNull());
400 EXPECT_EQ("Incorrect argument count. (Expected = 0) != (Actual = 1)",
402 Error.reset(new Diagnostics());
403 EXPECT_TRUE(constructMatcher("anyOf", Error.get()).isNull());
404 EXPECT_EQ("Incorrect argument count. (Expected = (2, )) != (Actual = 0)",
406 Error.reset(new Diagnostics());
407 EXPECT_TRUE(constructMatcher("unless", StringRef(), StringRef(),
408 Error.get()).isNull());
409 EXPECT_EQ("Incorrect argument count. (Expected = (1, 1)) != (Actual = 2)",
413 Error.reset(new Diagnostics());
414 EXPECT_TRUE(constructMatcher("ofClass", StringRef(), Error.get()).isNull());
415 EXPECT_EQ("Incorrect type for arg 1. (Expected = Matcher<CXXRecordDecl>) != "
418 Error.reset(new Diagnostics());
419 EXPECT_TRUE(constructMatcher("recordDecl", constructMatcher("recordDecl"),
420 constructMatcher("parameterCountIs", 3),
421 Error.get()).isNull());
422 EXPECT_EQ("Incorrect type for arg 2. (Expected = Matcher<CXXRecordDecl>) != "
423 "(Actual = Matcher<FunctionDecl>)",
426 // Bad argument type with variadic.
427 Error.reset(new Diagnostics());
428 EXPECT_TRUE(constructMatcher("anyOf", StringRef(), StringRef(),
429 Error.get()).isNull());
431 "Incorrect type for arg 1. (Expected = Matcher<>) != (Actual = String)",
433 Error.reset(new Diagnostics());
434 EXPECT_TRUE(constructMatcher(
436 constructMatcher("allOf",
437 constructMatcher("isDerivedFrom", StringRef("FOO")),
438 constructMatcher("isArrow")),
439 Error.get()).isNull());
440 EXPECT_EQ("Incorrect type for arg 1. "
441 "(Expected = Matcher<CXXRecordDecl>) != "
442 "(Actual = Matcher<CXXRecordDecl>&Matcher<MemberExpr>)",
446 TEST_F(RegistryTest, Completion) {
447 CompVector Comps = getCompletions();
449 EXPECT_TRUE(hasCompletion(
450 Comps, "hasParent(", "Matcher<Decl|Stmt> hasParent(Matcher<Decl|Stmt>)"));
452 EXPECT_TRUE(hasCompletion(Comps, "whileStmt(",
453 "Matcher<Stmt> whileStmt(Matcher<WhileStmt>...)"));
455 EXPECT_TRUE(hasCompletion(
456 Comps, "hasDescendant(",
457 "Matcher<NestedNameSpecifier|NestedNameSpecifierLoc|QualType|...> "
458 "hasDescendant(Matcher<CXXCtorInitializer|NestedNameSpecifier|"
459 "NestedNameSpecifierLoc|...>)"));
461 CompVector WhileComps = getCompletions("whileStmt", 0);
463 EXPECT_TRUE(hasCompletion(WhileComps, "hasBody(",
464 "Matcher<WhileStmt> hasBody(Matcher<Stmt>)"));
465 EXPECT_TRUE(hasCompletion(WhileComps, "hasParent(",
466 "Matcher<Stmt> hasParent(Matcher<Decl|Stmt>)"));
468 hasCompletion(WhileComps, "allOf(", "Matcher<T> allOf(Matcher<T>...)"));
470 EXPECT_FALSE(hasCompletion(WhileComps, "whileStmt("));
471 EXPECT_FALSE(hasCompletion(WhileComps, "ifStmt("));
473 CompVector AllOfWhileComps =
474 getCompletions("allOf", 0, "whileStmt", 0);
475 ASSERT_EQ(AllOfWhileComps.size(), WhileComps.size());
476 EXPECT_TRUE(std::equal(WhileComps.begin(), WhileComps.end(),
477 AllOfWhileComps.begin()));
479 CompVector DeclWhileComps =
480 getCompletions("decl", 0, "whileStmt", 0);
481 EXPECT_EQ(0u, DeclWhileComps.size());
483 CompVector NamedDeclComps = getCompletions("namedDecl", 0);
485 hasCompletion(NamedDeclComps, "isPublic()", "Matcher<Decl> isPublic()"));
486 EXPECT_TRUE(hasCompletion(NamedDeclComps, "hasName(\"",
487 "Matcher<NamedDecl> hasName(string)"));
489 // Heterogeneous overloads.
490 Comps = getCompletions("classTemplateSpecializationDecl", 0);
491 EXPECT_TRUE(hasCompletion(
492 Comps, "isSameOrDerivedFrom(",
493 "Matcher<CXXRecordDecl> isSameOrDerivedFrom(string|Matcher<NamedDecl>)"));
496 TEST_F(RegistryTest, HasArgs) {
497 Matcher<Decl> Value = constructMatcher(
498 "decl", constructMatcher("hasAttr", StringRef("attr::WarnUnused")))
499 .getTypedMatcher<Decl>();
500 EXPECT_TRUE(matches("struct __attribute__((warn_unused)) X {};", Value));
501 EXPECT_FALSE(matches("struct X {};", Value));
504 } // end anonymous namespace
505 } // end namespace dynamic
506 } // end namespace ast_matchers
507 } // end namespace clang