xref: /llvm-project/clang/unittests/ASTMatchers/Dynamic/RegistryTest.cpp (revision b17baa1db613a2ce777aa122feb87488750a64d0)
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   Matcher<Stmt> ObjCMsgExpr =
202       constructMatcher(
203           "objcMessageExpr",
204           constructMatcher(
205               "callee",
206               constructMatcher("objcMethodDecl",
207                                constructMatcher("hasName", StringRef("x")))))
208           .getTypedMatcher<Stmt>();
209 
210   std::string Code = "class Y { public: void x(); }; void z() { Y y; y.x(); }";
211   EXPECT_FALSE(matches(Code, CallExpr0));
212   EXPECT_TRUE(matches(Code, CallExpr1));
213   EXPECT_FALSE(matches(Code, ObjCMsgExpr));
214 
215   Code = "class Z { public: void z() { this->z(); } };";
216   EXPECT_TRUE(matches(Code, CallExpr0));
217   EXPECT_FALSE(matches(Code, CallExpr1));
218   EXPECT_FALSE(matches(Code, ObjCMsgExpr));
219 
220   Code = "@interface I "
221          "+ (void)x; "
222          "@end\n"
223          "int main() { [I x]; }";
224   EXPECT_FALSE(matchesObjC(Code, CallExpr0));
225   EXPECT_FALSE(matchesObjC(Code, CallExpr1));
226   EXPECT_TRUE(matchesObjC(Code, ObjCMsgExpr));
227 
228   Matcher<Decl> DeclDecl = declaratorDecl(hasTypeLoc(
229       constructMatcher(
230           "loc", constructMatcher("asString", StringRef("const double *")))
231           .getTypedMatcher<TypeLoc>()));
232 
233   Matcher<NestedNameSpecifierLoc> NNSL =
234       constructMatcher(
235           "loc", VariantMatcher::SingleMatcher(nestedNameSpecifier(
236                      specifiesType(hasDeclaration(recordDecl(hasName("A")))))))
237           .getTypedMatcher<NestedNameSpecifierLoc>();
238 
239   Code = "const double * x = 0;";
240   EXPECT_TRUE(matches(Code, DeclDecl));
241   EXPECT_FALSE(matches(Code, NNSL));
242 
243   Code = "struct A { struct B {}; }; A::B a_b;";
244   EXPECT_FALSE(matches(Code, DeclDecl));
245   EXPECT_TRUE(matches(Code, NNSL));
246 }
247 
248 TEST_F(RegistryTest, PolymorphicMatchers) {
249   const VariantMatcher IsDefinition = constructMatcher("isDefinition");
250   Matcher<Decl> Var =
251       constructMatcher("varDecl", IsDefinition).getTypedMatcher<Decl>();
252   Matcher<Decl> Class =
253       constructMatcher("recordDecl", IsDefinition).getTypedMatcher<Decl>();
254   Matcher<Decl> Func =
255       constructMatcher("functionDecl", IsDefinition).getTypedMatcher<Decl>();
256   EXPECT_TRUE(matches("int a;", Var));
257   EXPECT_FALSE(matches("extern int a;", Var));
258   EXPECT_TRUE(matches("class A {};", Class));
259   EXPECT_FALSE(matches("class A;", Class));
260   EXPECT_TRUE(matches("void f(){};", Func));
261   EXPECT_FALSE(matches("void f();", Func));
262 
263   Matcher<Decl> Anything = constructMatcher("anything").getTypedMatcher<Decl>();
264   Matcher<Decl> RecordDecl = constructMatcher(
265       "recordDecl", constructMatcher("hasName", StringRef("Foo")),
266       VariantMatcher::SingleMatcher(Anything)).getTypedMatcher<Decl>();
267 
268   EXPECT_TRUE(matches("int Foo;", Anything));
269   EXPECT_TRUE(matches("class Foo {};", Anything));
270   EXPECT_TRUE(matches("void Foo(){};", Anything));
271   EXPECT_FALSE(matches("int Foo;", RecordDecl));
272   EXPECT_TRUE(matches("class Foo {};", RecordDecl));
273   EXPECT_FALSE(matches("void Foo(){};", RecordDecl));
274 
275   Matcher<Stmt> ConstructExpr = constructMatcher(
276       "cxxConstructExpr",
277       constructMatcher(
278           "hasDeclaration",
279           constructMatcher(
280               "cxxMethodDecl",
281               constructMatcher(
282                   "ofClass", constructMatcher("hasName", StringRef("Foo"))))))
283                                     .getTypedMatcher<Stmt>();
284   EXPECT_FALSE(matches("class Foo { public: Foo(); };", ConstructExpr));
285   EXPECT_TRUE(
286       matches("class Foo { public: Foo(); }; Foo foo = Foo();", ConstructExpr));
287 }
288 
289 TEST_F(RegistryTest, TemplateArgument) {
290   Matcher<Decl> HasTemplateArgument = constructMatcher(
291       "classTemplateSpecializationDecl",
292       constructMatcher(
293           "hasAnyTemplateArgument",
294           constructMatcher("refersToType",
295                            constructMatcher("asString", StringRef("int")))))
296       .getTypedMatcher<Decl>();
297   EXPECT_TRUE(matches("template<typename T> class A {}; A<int> a;",
298                       HasTemplateArgument));
299   EXPECT_FALSE(matches("template<typename T> class A {}; A<char> a;",
300                        HasTemplateArgument));
301 }
302 
303 TEST_F(RegistryTest, TypeTraversal) {
304   Matcher<Type> M = constructMatcher(
305       "pointerType",
306       constructMatcher("pointee", constructMatcher("isConstQualified"),
307                        constructMatcher("isInteger"))).getTypedMatcher<Type>();
308   EXPECT_FALSE(matches("int *a;", M));
309   EXPECT_TRUE(matches("int const *b;", M));
310 
311   M = constructMatcher(
312       "arrayType",
313       constructMatcher("hasElementType", constructMatcher("builtinType")))
314       .getTypedMatcher<Type>();
315   EXPECT_FALSE(matches("struct A{}; A a[7];;", M));
316   EXPECT_TRUE(matches("int b[7];", M));
317 }
318 
319 TEST_F(RegistryTest, CXXBaseSpecifier) {
320   // TODO: rewrite with top-level cxxBaseSpecifier matcher when available
321   DeclarationMatcher ClassHasAnyDirectBase =
322       constructMatcher("cxxRecordDecl",
323                        constructMatcher("hasDirectBase",
324                                         constructMatcher("cxxBaseSpecifier")))
325           .getTypedMatcher<Decl>();
326   EXPECT_TRUE(matches("class X {}; class Y : X {};", ClassHasAnyDirectBase));
327   EXPECT_TRUE(notMatches("class X {};", ClassHasAnyDirectBase));
328 }
329 
330 TEST_F(RegistryTest, CXXCtorInitializer) {
331   Matcher<Decl> CtorDecl = constructMatcher(
332       "cxxConstructorDecl",
333       constructMatcher(
334           "hasAnyConstructorInitializer",
335           constructMatcher("forField",
336                            constructMatcher("hasName", StringRef("foo")))))
337       .getTypedMatcher<Decl>();
338   EXPECT_TRUE(matches("struct Foo { Foo() : foo(1) {} int foo; };", CtorDecl));
339   EXPECT_FALSE(matches("struct Foo { Foo() {} int foo; };", CtorDecl));
340   EXPECT_FALSE(matches("struct Foo { Foo() : bar(1) {} int bar; };", CtorDecl));
341 }
342 
343 TEST_F(RegistryTest, Adaptative) {
344   Matcher<Decl> D = constructMatcher(
345       "recordDecl",
346       constructMatcher(
347           "has",
348           constructMatcher("recordDecl",
349                            constructMatcher("hasName", StringRef("X")))))
350       .getTypedMatcher<Decl>();
351   EXPECT_TRUE(matches("class X {};", D));
352   EXPECT_TRUE(matches("class Y { class X {}; };", D));
353   EXPECT_FALSE(matches("class Y { class Z {}; };", D));
354 
355   Matcher<Stmt> S = constructMatcher(
356       "forStmt",
357       constructMatcher(
358           "hasDescendant",
359           constructMatcher("varDecl",
360                            constructMatcher("hasName", StringRef("X")))))
361       .getTypedMatcher<Stmt>();
362   EXPECT_TRUE(matches("void foo() { for(int X;;); }", S));
363   EXPECT_TRUE(matches("void foo() { for(;;) { int X; } }", S));
364   EXPECT_FALSE(matches("void foo() { for(;;); }", S));
365   EXPECT_FALSE(matches("void foo() { if (int X = 0){} }", S));
366 
367   S = constructMatcher(
368       "compoundStmt", constructMatcher("hasParent", constructMatcher("ifStmt")))
369       .getTypedMatcher<Stmt>();
370   EXPECT_TRUE(matches("void foo() { if (true) { int x = 42; } }", S));
371   EXPECT_FALSE(matches("void foo() { if (true) return; }", S));
372 }
373 
374 TEST_F(RegistryTest, VariadicOp) {
375   Matcher<Decl> D = constructMatcher(
376       "anyOf",
377       constructMatcher("recordDecl",
378                        constructMatcher("hasName", StringRef("Foo"))),
379       constructMatcher("functionDecl",
380                        constructMatcher("hasName", StringRef("foo"))))
381       .getTypedMatcher<Decl>();
382 
383   EXPECT_TRUE(matches("void foo(){}", D));
384   EXPECT_TRUE(matches("struct Foo{};", D));
385   EXPECT_FALSE(matches("int i = 0;", D));
386 
387   D = constructMatcher(
388       "allOf", constructMatcher("recordDecl"),
389       constructMatcher(
390           "namedDecl",
391           constructMatcher("anyOf",
392                            constructMatcher("hasName", StringRef("Foo")),
393                            constructMatcher("hasName", StringRef("Bar")))))
394       .getTypedMatcher<Decl>();
395 
396   EXPECT_FALSE(matches("void foo(){}", D));
397   EXPECT_TRUE(matches("struct Foo{};", D));
398   EXPECT_FALSE(matches("int i = 0;", D));
399   EXPECT_TRUE(matches("class Bar{};", D));
400   EXPECT_FALSE(matches("class OtherBar{};", D));
401 
402   D = recordDecl(
403       has(fieldDecl(hasName("Foo"))),
404       constructMatcher(
405           "unless",
406           constructMatcher("namedDecl",
407                            constructMatcher("hasName", StringRef("Bar"))))
408           .getTypedMatcher<Decl>());
409 
410   EXPECT_FALSE(matches("class Bar{ int Foo; };", D));
411   EXPECT_TRUE(matches("class OtherBar{ int Foo; };", D));
412 
413   D = constructMatcher(
414           "namedDecl", constructMatcher("hasName", StringRef("Foo")),
415           constructMatcher("unless", constructMatcher("recordDecl")))
416           .getTypedMatcher<Decl>();
417   EXPECT_TRUE(matches("void Foo(){}", D));
418   EXPECT_TRUE(notMatches("struct Foo {};", D));
419 }
420 
421 TEST_F(RegistryTest, Errors) {
422   // Incorrect argument count.
423   std::unique_ptr<Diagnostics> Error(new Diagnostics());
424   EXPECT_TRUE(constructMatcher("hasInitializer", Error.get()).isNull());
425   EXPECT_EQ("Incorrect argument count. (Expected = 1) != (Actual = 0)",
426             Error->toString());
427   Error.reset(new Diagnostics());
428   EXPECT_TRUE(constructMatcher("isArrow", StringRef(), Error.get()).isNull());
429   EXPECT_EQ("Incorrect argument count. (Expected = 0) != (Actual = 1)",
430             Error->toString());
431   Error.reset(new Diagnostics());
432   EXPECT_TRUE(constructMatcher("anyOf", Error.get()).isNull());
433   EXPECT_EQ("Incorrect argument count. (Expected = (2, )) != (Actual = 0)",
434             Error->toString());
435   Error.reset(new Diagnostics());
436   EXPECT_TRUE(constructMatcher("unless", StringRef(), StringRef(),
437                                Error.get()).isNull());
438   EXPECT_EQ("Incorrect argument count. (Expected = (1, 1)) != (Actual = 2)",
439             Error->toString());
440 
441   // Bad argument type
442   Error.reset(new Diagnostics());
443   EXPECT_TRUE(constructMatcher("ofClass", StringRef(), Error.get()).isNull());
444   EXPECT_EQ("Incorrect type for arg 1. (Expected = Matcher<CXXRecordDecl>) != "
445             "(Actual = String)",
446             Error->toString());
447   Error.reset(new Diagnostics());
448   EXPECT_TRUE(
449       constructMatcher("cxxRecordDecl", constructMatcher("cxxRecordDecl"),
450                        constructMatcher("parameterCountIs", 3), Error.get())
451           .isNull());
452   EXPECT_EQ("Incorrect type for arg 2. (Expected = Matcher<CXXRecordDecl>) != "
453             "(Actual = Matcher<FunctionDecl|FunctionProtoType>)",
454             Error->toString());
455 
456   // Bad argument type with variadic.
457   Error.reset(new Diagnostics());
458   EXPECT_TRUE(constructMatcher("anyOf", StringRef(), StringRef(),
459                                Error.get()).isNull());
460   EXPECT_EQ(
461       "Incorrect type for arg 1. (Expected = Matcher<>) != (Actual = String)",
462       Error->toString());
463   Error.reset(new Diagnostics());
464   EXPECT_TRUE(constructMatcher(
465       "cxxRecordDecl",
466       constructMatcher("allOf",
467                        constructMatcher("isDerivedFrom", StringRef("FOO")),
468                        constructMatcher("isArrow")),
469       Error.get()).isNull());
470   EXPECT_EQ("Incorrect type for arg 1. "
471             "(Expected = Matcher<CXXRecordDecl>) != "
472             "(Actual = Matcher<CXXRecordDecl|ObjCInterfaceDecl>&Matcher"
473             "<MemberExpr|UnresolvedMemberExpr|CXXDependentScopeMemberExpr>)",
474             Error->toString());
475 }
476 
477 TEST_F(RegistryTest, Completion) {
478   CompVector Comps = getCompletions();
479   // Overloaded
480   EXPECT_TRUE(hasCompletion(
481       Comps, "hasParent(",
482       "Matcher<NestedNameSpecifierLoc|TypeLoc|Decl|...> "
483       "hasParent(Matcher<NestedNameSpecifierLoc|TypeLoc|Decl|...>)"));
484   // Variadic.
485   EXPECT_TRUE(hasCompletion(Comps, "whileStmt(",
486                             "Matcher<Stmt> whileStmt(Matcher<WhileStmt>...)"));
487   // Polymorphic.
488   EXPECT_TRUE(hasCompletion(
489       Comps, "hasDescendant(",
490       "Matcher<NestedNameSpecifierLoc|QualType|TypeLoc|...> "
491       "hasDescendant(Matcher<NestedNameSpecifierLoc|QualType|TypeLoc|...>)"));
492 
493   CompVector WhileComps = getCompletions("whileStmt", 0);
494 
495   EXPECT_TRUE(hasCompletion(WhileComps, "hasBody(",
496                             "Matcher<WhileStmt> hasBody(Matcher<Stmt>)"));
497   EXPECT_TRUE(hasCompletion(
498       WhileComps, "hasParent(",
499       "Matcher<Stmt> "
500       "hasParent(Matcher<NestedNameSpecifierLoc|TypeLoc|Decl|...>)"));
501   EXPECT_TRUE(
502       hasCompletion(WhileComps, "allOf(", "Matcher<T> allOf(Matcher<T>...)"));
503 
504   EXPECT_FALSE(hasCompletion(WhileComps, "whileStmt("));
505   EXPECT_FALSE(hasCompletion(WhileComps, "ifStmt("));
506 
507   CompVector AllOfWhileComps =
508       getCompletions("allOf", 0, "whileStmt", 0);
509   ASSERT_EQ(AllOfWhileComps.size(), WhileComps.size());
510   EXPECT_TRUE(std::equal(WhileComps.begin(), WhileComps.end(),
511                          AllOfWhileComps.begin()));
512 
513   CompVector DeclWhileComps =
514       getCompletions("decl", 0, "whileStmt", 0);
515   EXPECT_EQ(0u, DeclWhileComps.size());
516 
517   CompVector NamedDeclComps = getCompletions("namedDecl", 0);
518   EXPECT_TRUE(
519       hasCompletion(NamedDeclComps, "isPublic()", "Matcher<Decl> isPublic()"));
520   EXPECT_TRUE(hasCompletion(NamedDeclComps, "hasName(\"",
521                             "Matcher<NamedDecl> hasName(string)"));
522 
523   // Heterogeneous overloads.
524   Comps = getCompletions("classTemplateSpecializationDecl", 0);
525   EXPECT_TRUE(hasCompletion(
526       Comps, "isSameOrDerivedFrom(",
527       "Matcher<CXXRecordDecl> isSameOrDerivedFrom(string|Matcher<NamedDecl>)"));
528 }
529 
530 TEST_F(RegistryTest, MatcherBuilder) {
531   auto Ctor = *lookupMatcherCtor("mapAnyOf");
532   EXPECT_TRUE(Registry::isBuilderMatcher(Ctor));
533   auto BuiltCtor = Registry::buildMatcherCtor(Ctor, {}, Args(ASTNodeKind::getFromNodeKind<WhileStmt>(), ASTNodeKind::getFromNodeKind<ForStmt>()), nullptr);
534   EXPECT_TRUE(BuiltCtor.get());
535   auto LoopMatcher = Registry::constructMatcher(BuiltCtor.get(), SourceRange(), Args(), nullptr).getTypedMatcher<Stmt>();
536   EXPECT_TRUE(matches("void f() { for (;;) {} }", LoopMatcher));
537   EXPECT_TRUE(matches("void f() { while (true) {} }", LoopMatcher));
538   EXPECT_FALSE(matches("void f() { if (true) {} }", LoopMatcher));
539 
540   auto NotBuiltCtor = Registry::buildMatcherCtor(Ctor, {}, Args(ASTNodeKind::getFromNodeKind<FunctionDecl>(), ASTNodeKind::getFromNodeKind<ForStmt>()), nullptr);
541   EXPECT_FALSE(NotBuiltCtor.get());
542 }
543 
544 TEST_F(RegistryTest, NodeType) {
545   EXPECT_TRUE(Registry::nodeMatcherType(*lookupMatcherCtor("callExpr")).isSame(ASTNodeKind::getFromNodeKind<CallExpr>()));
546   EXPECT_TRUE(Registry::nodeMatcherType(*lookupMatcherCtor("has")).isNone());
547   EXPECT_TRUE(Registry::nodeMatcherType(*lookupMatcherCtor("allOf")).isNone());
548 }
549 
550 TEST_F(RegistryTest, HasArgs) {
551   Matcher<Decl> Value = constructMatcher(
552       "decl", constructMatcher("hasAttr", StringRef("attr::WarnUnused")))
553       .getTypedMatcher<Decl>();
554   EXPECT_TRUE(matches("struct __attribute__((warn_unused)) X {};", Value));
555   EXPECT_FALSE(matches("struct X {};", Value));
556 }
557 
558 TEST_F(RegistryTest, ParenExpr) {
559   Matcher<Stmt> Value = constructMatcher("parenExpr").getTypedMatcher<Stmt>();
560   EXPECT_TRUE(matches("int i = (1);", traverse(TK_AsIs, Value)));
561   EXPECT_FALSE(matches("int i = 1;", traverse(TK_AsIs, Value)));
562 }
563 
564 TEST_F(RegistryTest, EqualsMatcher) {
565   Matcher<Stmt> BooleanStmt = constructMatcher(
566       "cxxBoolLiteral", constructMatcher("equals", VariantValue(true)))
567       .getTypedMatcher<Stmt>();
568   EXPECT_TRUE(matches("bool x = true;", BooleanStmt));
569   EXPECT_FALSE(matches("bool x = false;", BooleanStmt));
570   EXPECT_FALSE(matches("bool x = 0;", BooleanStmt));
571 
572   BooleanStmt = constructMatcher(
573       "cxxBoolLiteral", constructMatcher("equals", VariantValue(0)))
574       .getTypedMatcher<Stmt>();
575   EXPECT_TRUE(matches("bool x = false;", BooleanStmt));
576   EXPECT_FALSE(matches("bool x = true;", BooleanStmt));
577   EXPECT_FALSE(matches("bool x = 0;", BooleanStmt));
578 
579   Matcher<Stmt> DoubleStmt = constructMatcher(
580       "floatLiteral", constructMatcher("equals", VariantValue(1.2)))
581       .getTypedMatcher<Stmt>();
582   EXPECT_TRUE(matches("double x = 1.2;", DoubleStmt));
583 #if 0
584   // FIXME floatLiteral matching should work regardless of suffix.
585   EXPECT_TRUE(matches("double x = 1.2f;", DoubleStmt));
586   EXPECT_TRUE(matches("double x = 1.2l;", DoubleStmt));
587 #endif
588   EXPECT_TRUE(matches("double x = 12e-1;", DoubleStmt));
589   EXPECT_FALSE(matches("double x = 1.23;", DoubleStmt));
590 
591   Matcher<Stmt> IntegerStmt = constructMatcher(
592       "integerLiteral", constructMatcher("equals", VariantValue(42)))
593       .getTypedMatcher<Stmt>();
594   EXPECT_TRUE(matches("int x = 42;", IntegerStmt));
595   EXPECT_FALSE(matches("int x = 1;", IntegerStmt));
596 
597   Matcher<Stmt> CharStmt = constructMatcher(
598       "characterLiteral", constructMatcher("equals", VariantValue('x')))
599       .getTypedMatcher<Stmt>();
600   EXPECT_TRUE(matches("int x = 'x';", CharStmt));
601   EXPECT_TRUE(matches("int x = L'x';", CharStmt));
602   EXPECT_TRUE(matches("int x = u'x';", CharStmt));
603   EXPECT_TRUE(matches("int x = U'x';", CharStmt));
604   EXPECT_FALSE(matches("int x = 120;", CharStmt));
605 }
606 
607 } // end anonymous namespace
608 } // end namespace dynamic
609 } // end namespace ast_matchers
610 } // end namespace clang
611