xref: /minix3/external/bsd/llvm/dist/clang/unittests/ASTMatchers/Dynamic/RegistryTest.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1f4a2713aSLionel Sambuc //===- unittest/ASTMatchers/Dynamic/RegistryTest.cpp - Registry unit tests -===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc //                     The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===-----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc 
10f4a2713aSLionel Sambuc #include "../ASTMatchersTest.h"
11f4a2713aSLionel Sambuc #include "clang/ASTMatchers/Dynamic/Registry.h"
12f4a2713aSLionel Sambuc #include "gtest/gtest.h"
13*0a6a1f1dSLionel Sambuc #include <vector>
14f4a2713aSLionel Sambuc 
15f4a2713aSLionel Sambuc namespace clang {
16f4a2713aSLionel Sambuc namespace ast_matchers {
17f4a2713aSLionel Sambuc namespace dynamic {
18f4a2713aSLionel Sambuc namespace {
19f4a2713aSLionel Sambuc 
20f4a2713aSLionel Sambuc using ast_matchers::internal::Matcher;
21f4a2713aSLionel Sambuc 
22f4a2713aSLionel Sambuc class RegistryTest : public ::testing::Test {
23f4a2713aSLionel Sambuc public:
Args()24f4a2713aSLionel Sambuc   std::vector<ParserValue> Args() { return std::vector<ParserValue>(); }
Args(const VariantValue & Arg1)25f4a2713aSLionel Sambuc   std::vector<ParserValue> Args(const VariantValue &Arg1) {
26f4a2713aSLionel Sambuc     std::vector<ParserValue> Out(1);
27f4a2713aSLionel Sambuc     Out[0].Value = Arg1;
28f4a2713aSLionel Sambuc     return Out;
29f4a2713aSLionel Sambuc   }
Args(const VariantValue & Arg1,const VariantValue & Arg2)30f4a2713aSLionel Sambuc   std::vector<ParserValue> Args(const VariantValue &Arg1,
31f4a2713aSLionel Sambuc                                 const VariantValue &Arg2) {
32f4a2713aSLionel Sambuc     std::vector<ParserValue> Out(2);
33f4a2713aSLionel Sambuc     Out[0].Value = Arg1;
34f4a2713aSLionel Sambuc     Out[1].Value = Arg2;
35f4a2713aSLionel Sambuc     return Out;
36f4a2713aSLionel Sambuc   }
37f4a2713aSLionel Sambuc 
lookupMatcherCtor(StringRef MatcherName)38*0a6a1f1dSLionel Sambuc   llvm::Optional<MatcherCtor> lookupMatcherCtor(StringRef MatcherName) {
39*0a6a1f1dSLionel Sambuc     return Registry::lookupMatcherCtor(MatcherName);
40*0a6a1f1dSLionel Sambuc   }
41*0a6a1f1dSLionel Sambuc 
constructMatcher(StringRef MatcherName,Diagnostics * Error=nullptr)42f4a2713aSLionel Sambuc   VariantMatcher constructMatcher(StringRef MatcherName,
43*0a6a1f1dSLionel Sambuc                                   Diagnostics *Error = nullptr) {
44f4a2713aSLionel Sambuc     Diagnostics DummyError;
45f4a2713aSLionel Sambuc     if (!Error) Error = &DummyError;
46*0a6a1f1dSLionel Sambuc     llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName);
47*0a6a1f1dSLionel Sambuc     VariantMatcher Out;
48*0a6a1f1dSLionel Sambuc     if (Ctor)
49*0a6a1f1dSLionel Sambuc       Out = Registry::constructMatcher(*Ctor, SourceRange(), Args(), Error);
50f4a2713aSLionel Sambuc     EXPECT_EQ("", DummyError.toStringFull());
51f4a2713aSLionel Sambuc     return Out;
52f4a2713aSLionel Sambuc   }
53f4a2713aSLionel Sambuc 
constructMatcher(StringRef MatcherName,const VariantValue & Arg1,Diagnostics * Error=nullptr)54f4a2713aSLionel Sambuc   VariantMatcher constructMatcher(StringRef MatcherName,
55f4a2713aSLionel Sambuc                                   const VariantValue &Arg1,
56*0a6a1f1dSLionel Sambuc                                   Diagnostics *Error = nullptr) {
57f4a2713aSLionel Sambuc     Diagnostics DummyError;
58f4a2713aSLionel Sambuc     if (!Error) Error = &DummyError;
59*0a6a1f1dSLionel Sambuc     llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName);
60*0a6a1f1dSLionel Sambuc     VariantMatcher Out;
61*0a6a1f1dSLionel Sambuc     if (Ctor)
62*0a6a1f1dSLionel Sambuc       Out = Registry::constructMatcher(*Ctor, SourceRange(), Args(Arg1), Error);
63*0a6a1f1dSLionel Sambuc     EXPECT_EQ("", DummyError.toStringFull()) << MatcherName;
64f4a2713aSLionel Sambuc     return Out;
65f4a2713aSLionel Sambuc   }
66f4a2713aSLionel Sambuc 
constructMatcher(StringRef MatcherName,const VariantValue & Arg1,const VariantValue & Arg2,Diagnostics * Error=nullptr)67f4a2713aSLionel Sambuc   VariantMatcher constructMatcher(StringRef MatcherName,
68f4a2713aSLionel Sambuc                                   const VariantValue &Arg1,
69f4a2713aSLionel Sambuc                                   const VariantValue &Arg2,
70*0a6a1f1dSLionel Sambuc                                   Diagnostics *Error = nullptr) {
71f4a2713aSLionel Sambuc     Diagnostics DummyError;
72f4a2713aSLionel Sambuc     if (!Error) Error = &DummyError;
73*0a6a1f1dSLionel Sambuc     llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName);
74*0a6a1f1dSLionel Sambuc     VariantMatcher Out;
75*0a6a1f1dSLionel Sambuc     if (Ctor)
76*0a6a1f1dSLionel Sambuc       Out = Registry::constructMatcher(*Ctor, SourceRange(), Args(Arg1, Arg2),
77*0a6a1f1dSLionel Sambuc                                        Error);
78f4a2713aSLionel Sambuc     EXPECT_EQ("", DummyError.toStringFull());
79f4a2713aSLionel Sambuc     return Out;
80f4a2713aSLionel Sambuc   }
81*0a6a1f1dSLionel Sambuc 
82*0a6a1f1dSLionel Sambuc   typedef std::vector<MatcherCompletion> CompVector;
83*0a6a1f1dSLionel Sambuc 
getCompletions()84*0a6a1f1dSLionel Sambuc   CompVector getCompletions() {
85*0a6a1f1dSLionel Sambuc     std::vector<std::pair<MatcherCtor, unsigned> > Context;
86*0a6a1f1dSLionel Sambuc     return Registry::getMatcherCompletions(
87*0a6a1f1dSLionel Sambuc         Registry::getAcceptedCompletionTypes(Context));
88*0a6a1f1dSLionel Sambuc   }
89*0a6a1f1dSLionel Sambuc 
getCompletions(StringRef MatcherName1,unsigned ArgNo1)90*0a6a1f1dSLionel Sambuc   CompVector getCompletions(StringRef MatcherName1, unsigned ArgNo1) {
91*0a6a1f1dSLionel Sambuc     std::vector<std::pair<MatcherCtor, unsigned> > Context;
92*0a6a1f1dSLionel Sambuc     llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName1);
93*0a6a1f1dSLionel Sambuc     if (!Ctor)
94*0a6a1f1dSLionel Sambuc       return CompVector();
95*0a6a1f1dSLionel Sambuc     Context.push_back(std::make_pair(*Ctor, ArgNo1));
96*0a6a1f1dSLionel Sambuc     return Registry::getMatcherCompletions(
97*0a6a1f1dSLionel Sambuc         Registry::getAcceptedCompletionTypes(Context));
98*0a6a1f1dSLionel Sambuc   }
99*0a6a1f1dSLionel Sambuc 
getCompletions(StringRef MatcherName1,unsigned ArgNo1,StringRef MatcherName2,unsigned ArgNo2)100*0a6a1f1dSLionel Sambuc   CompVector getCompletions(StringRef MatcherName1, unsigned ArgNo1,
101*0a6a1f1dSLionel Sambuc                             StringRef MatcherName2, unsigned ArgNo2) {
102*0a6a1f1dSLionel Sambuc     std::vector<std::pair<MatcherCtor, unsigned> > Context;
103*0a6a1f1dSLionel Sambuc     llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName1);
104*0a6a1f1dSLionel Sambuc     if (!Ctor)
105*0a6a1f1dSLionel Sambuc       return CompVector();
106*0a6a1f1dSLionel Sambuc     Context.push_back(std::make_pair(*Ctor, ArgNo1));
107*0a6a1f1dSLionel Sambuc     Ctor = lookupMatcherCtor(MatcherName2);
108*0a6a1f1dSLionel Sambuc     if (!Ctor)
109*0a6a1f1dSLionel Sambuc       return CompVector();
110*0a6a1f1dSLionel Sambuc     Context.push_back(std::make_pair(*Ctor, ArgNo2));
111*0a6a1f1dSLionel Sambuc     return Registry::getMatcherCompletions(
112*0a6a1f1dSLionel Sambuc         Registry::getAcceptedCompletionTypes(Context));
113*0a6a1f1dSLionel Sambuc   }
114*0a6a1f1dSLionel Sambuc 
hasCompletion(const CompVector & Comps,StringRef TypedText,StringRef MatcherDecl=StringRef ())115*0a6a1f1dSLionel Sambuc   bool hasCompletion(const CompVector &Comps, StringRef TypedText,
116*0a6a1f1dSLionel Sambuc                      StringRef MatcherDecl = StringRef()) {
117*0a6a1f1dSLionel Sambuc     for (CompVector::const_iterator I = Comps.begin(), E = Comps.end(); I != E;
118*0a6a1f1dSLionel Sambuc          ++I) {
119*0a6a1f1dSLionel Sambuc       if (I->TypedText == TypedText &&
120*0a6a1f1dSLionel Sambuc           (MatcherDecl.empty() || I->MatcherDecl == MatcherDecl)) {
121*0a6a1f1dSLionel Sambuc         return true;
122*0a6a1f1dSLionel Sambuc       }
123*0a6a1f1dSLionel Sambuc     }
124*0a6a1f1dSLionel Sambuc     return false;
125*0a6a1f1dSLionel Sambuc   }
126f4a2713aSLionel Sambuc };
127f4a2713aSLionel Sambuc 
TEST_F(RegistryTest,CanConstructNoArgs)128f4a2713aSLionel Sambuc TEST_F(RegistryTest, CanConstructNoArgs) {
129f4a2713aSLionel Sambuc   Matcher<Stmt> IsArrowValue = constructMatcher(
130f4a2713aSLionel Sambuc       "memberExpr", constructMatcher("isArrow")).getTypedMatcher<Stmt>();
131f4a2713aSLionel Sambuc   Matcher<Stmt> BoolValue =
132f4a2713aSLionel Sambuc       constructMatcher("boolLiteral").getTypedMatcher<Stmt>();
133f4a2713aSLionel Sambuc 
134f4a2713aSLionel Sambuc   const std::string ClassSnippet = "struct Foo { int x; };\n"
135f4a2713aSLionel Sambuc                                    "Foo *foo = new Foo;\n"
136f4a2713aSLionel Sambuc                                    "int i = foo->x;\n";
137f4a2713aSLionel Sambuc   const std::string BoolSnippet = "bool Foo = true;\n";
138f4a2713aSLionel Sambuc 
139f4a2713aSLionel Sambuc   EXPECT_TRUE(matches(ClassSnippet, IsArrowValue));
140f4a2713aSLionel Sambuc   EXPECT_TRUE(matches(BoolSnippet, BoolValue));
141f4a2713aSLionel Sambuc   EXPECT_FALSE(matches(ClassSnippet, BoolValue));
142f4a2713aSLionel Sambuc   EXPECT_FALSE(matches(BoolSnippet, IsArrowValue));
143f4a2713aSLionel Sambuc }
144f4a2713aSLionel Sambuc 
TEST_F(RegistryTest,ConstructWithSimpleArgs)145f4a2713aSLionel Sambuc TEST_F(RegistryTest, ConstructWithSimpleArgs) {
146f4a2713aSLionel Sambuc   Matcher<Decl> Value = constructMatcher(
147f4a2713aSLionel Sambuc       "namedDecl", constructMatcher("hasName", std::string("X")))
148f4a2713aSLionel Sambuc       .getTypedMatcher<Decl>();
149f4a2713aSLionel Sambuc   EXPECT_TRUE(matches("class X {};", Value));
150f4a2713aSLionel Sambuc   EXPECT_FALSE(matches("int x;", Value));
151f4a2713aSLionel Sambuc 
152f4a2713aSLionel Sambuc   Value = functionDecl(constructMatcher("parameterCountIs", 2)
153f4a2713aSLionel Sambuc                            .getTypedMatcher<FunctionDecl>());
154f4a2713aSLionel Sambuc   EXPECT_TRUE(matches("void foo(int,int);", Value));
155f4a2713aSLionel Sambuc   EXPECT_FALSE(matches("void foo(int);", Value));
156f4a2713aSLionel Sambuc }
157f4a2713aSLionel Sambuc 
TEST_F(RegistryTest,ConstructWithMatcherArgs)158f4a2713aSLionel Sambuc TEST_F(RegistryTest, ConstructWithMatcherArgs) {
159f4a2713aSLionel Sambuc   Matcher<Decl> HasInitializerSimple = constructMatcher(
160f4a2713aSLionel Sambuc       "varDecl", constructMatcher("hasInitializer", constructMatcher("stmt")))
161f4a2713aSLionel Sambuc       .getTypedMatcher<Decl>();
162f4a2713aSLionel Sambuc   Matcher<Decl> HasInitializerComplex = constructMatcher(
163f4a2713aSLionel Sambuc       "varDecl",
164f4a2713aSLionel Sambuc       constructMatcher("hasInitializer", constructMatcher("callExpr")))
165f4a2713aSLionel Sambuc       .getTypedMatcher<Decl>();
166f4a2713aSLionel Sambuc 
167f4a2713aSLionel Sambuc   std::string code = "int i;";
168f4a2713aSLionel Sambuc   EXPECT_FALSE(matches(code, HasInitializerSimple));
169f4a2713aSLionel Sambuc   EXPECT_FALSE(matches(code, HasInitializerComplex));
170f4a2713aSLionel Sambuc 
171f4a2713aSLionel Sambuc   code = "int i = 1;";
172f4a2713aSLionel Sambuc   EXPECT_TRUE(matches(code, HasInitializerSimple));
173f4a2713aSLionel Sambuc   EXPECT_FALSE(matches(code, HasInitializerComplex));
174f4a2713aSLionel Sambuc 
175f4a2713aSLionel Sambuc   code = "int y(); int i = y();";
176f4a2713aSLionel Sambuc   EXPECT_TRUE(matches(code, HasInitializerSimple));
177f4a2713aSLionel Sambuc   EXPECT_TRUE(matches(code, HasInitializerComplex));
178f4a2713aSLionel Sambuc 
179f4a2713aSLionel Sambuc   Matcher<Decl> HasParameter =
180f4a2713aSLionel Sambuc       functionDecl(constructMatcher(
181f4a2713aSLionel Sambuc           "hasParameter", 1, constructMatcher("hasName", std::string("x")))
182f4a2713aSLionel Sambuc                        .getTypedMatcher<FunctionDecl>());
183f4a2713aSLionel Sambuc   EXPECT_TRUE(matches("void f(int a, int x);", HasParameter));
184f4a2713aSLionel Sambuc   EXPECT_FALSE(matches("void f(int x, int a);", HasParameter));
185f4a2713aSLionel Sambuc }
186f4a2713aSLionel Sambuc 
TEST_F(RegistryTest,OverloadedMatchers)187f4a2713aSLionel Sambuc TEST_F(RegistryTest, OverloadedMatchers) {
188f4a2713aSLionel Sambuc   Matcher<Stmt> CallExpr0 = constructMatcher(
189f4a2713aSLionel Sambuc       "callExpr",
190f4a2713aSLionel Sambuc       constructMatcher("callee", constructMatcher("memberExpr",
191f4a2713aSLionel Sambuc                                                   constructMatcher("isArrow"))))
192f4a2713aSLionel Sambuc       .getTypedMatcher<Stmt>();
193f4a2713aSLionel Sambuc 
194f4a2713aSLionel Sambuc   Matcher<Stmt> CallExpr1 = constructMatcher(
195f4a2713aSLionel Sambuc       "callExpr",
196f4a2713aSLionel Sambuc       constructMatcher(
197f4a2713aSLionel Sambuc           "callee",
198f4a2713aSLionel Sambuc           constructMatcher("methodDecl",
199f4a2713aSLionel Sambuc                            constructMatcher("hasName", std::string("x")))))
200f4a2713aSLionel Sambuc       .getTypedMatcher<Stmt>();
201f4a2713aSLionel Sambuc 
202f4a2713aSLionel Sambuc   std::string Code = "class Y { public: void x(); }; void z() { Y y; y.x(); }";
203f4a2713aSLionel Sambuc   EXPECT_FALSE(matches(Code, CallExpr0));
204f4a2713aSLionel Sambuc   EXPECT_TRUE(matches(Code, CallExpr1));
205f4a2713aSLionel Sambuc 
206f4a2713aSLionel Sambuc   Code = "class Z { public: void z() { this->z(); } };";
207f4a2713aSLionel Sambuc   EXPECT_TRUE(matches(Code, CallExpr0));
208f4a2713aSLionel Sambuc   EXPECT_FALSE(matches(Code, CallExpr1));
209*0a6a1f1dSLionel Sambuc 
210*0a6a1f1dSLionel Sambuc   Matcher<Decl> DeclDecl = declaratorDecl(hasTypeLoc(
211*0a6a1f1dSLionel Sambuc       constructMatcher(
212*0a6a1f1dSLionel Sambuc           "loc", constructMatcher("asString", std::string("const double *")))
213*0a6a1f1dSLionel Sambuc           .getTypedMatcher<TypeLoc>()));
214*0a6a1f1dSLionel Sambuc 
215*0a6a1f1dSLionel Sambuc   Matcher<NestedNameSpecifierLoc> NNSL =
216*0a6a1f1dSLionel Sambuc       constructMatcher(
217*0a6a1f1dSLionel Sambuc           "loc", VariantMatcher::SingleMatcher(nestedNameSpecifier(
218*0a6a1f1dSLionel Sambuc                      specifiesType(hasDeclaration(recordDecl(hasName("A")))))))
219*0a6a1f1dSLionel Sambuc           .getTypedMatcher<NestedNameSpecifierLoc>();
220*0a6a1f1dSLionel Sambuc 
221*0a6a1f1dSLionel Sambuc   Code = "const double * x = 0;";
222*0a6a1f1dSLionel Sambuc   EXPECT_TRUE(matches(Code, DeclDecl));
223*0a6a1f1dSLionel Sambuc   EXPECT_FALSE(matches(Code, NNSL));
224*0a6a1f1dSLionel Sambuc 
225*0a6a1f1dSLionel Sambuc   Code = "struct A { struct B {}; }; A::B a_b;";
226*0a6a1f1dSLionel Sambuc   EXPECT_FALSE(matches(Code, DeclDecl));
227*0a6a1f1dSLionel Sambuc   EXPECT_TRUE(matches(Code, NNSL));
228f4a2713aSLionel Sambuc }
229f4a2713aSLionel Sambuc 
TEST_F(RegistryTest,PolymorphicMatchers)230f4a2713aSLionel Sambuc TEST_F(RegistryTest, PolymorphicMatchers) {
231f4a2713aSLionel Sambuc   const VariantMatcher IsDefinition = constructMatcher("isDefinition");
232f4a2713aSLionel Sambuc   Matcher<Decl> Var =
233f4a2713aSLionel Sambuc       constructMatcher("varDecl", IsDefinition).getTypedMatcher<Decl>();
234f4a2713aSLionel Sambuc   Matcher<Decl> Class =
235f4a2713aSLionel Sambuc       constructMatcher("recordDecl", IsDefinition).getTypedMatcher<Decl>();
236f4a2713aSLionel Sambuc   Matcher<Decl> Func =
237f4a2713aSLionel Sambuc       constructMatcher("functionDecl", IsDefinition).getTypedMatcher<Decl>();
238f4a2713aSLionel Sambuc   EXPECT_TRUE(matches("int a;", Var));
239f4a2713aSLionel Sambuc   EXPECT_FALSE(matches("extern int a;", Var));
240f4a2713aSLionel Sambuc   EXPECT_TRUE(matches("class A {};", Class));
241f4a2713aSLionel Sambuc   EXPECT_FALSE(matches("class A;", Class));
242f4a2713aSLionel Sambuc   EXPECT_TRUE(matches("void f(){};", Func));
243f4a2713aSLionel Sambuc   EXPECT_FALSE(matches("void f();", Func));
244f4a2713aSLionel Sambuc 
245f4a2713aSLionel Sambuc   Matcher<Decl> Anything = constructMatcher("anything").getTypedMatcher<Decl>();
246f4a2713aSLionel Sambuc   Matcher<Decl> RecordDecl = constructMatcher(
247f4a2713aSLionel Sambuc       "recordDecl", constructMatcher("hasName", std::string("Foo")),
248f4a2713aSLionel Sambuc       VariantMatcher::SingleMatcher(Anything)).getTypedMatcher<Decl>();
249f4a2713aSLionel Sambuc 
250f4a2713aSLionel Sambuc   EXPECT_TRUE(matches("int Foo;", Anything));
251f4a2713aSLionel Sambuc   EXPECT_TRUE(matches("class Foo {};", Anything));
252f4a2713aSLionel Sambuc   EXPECT_TRUE(matches("void Foo(){};", Anything));
253f4a2713aSLionel Sambuc   EXPECT_FALSE(matches("int Foo;", RecordDecl));
254f4a2713aSLionel Sambuc   EXPECT_TRUE(matches("class Foo {};", RecordDecl));
255f4a2713aSLionel Sambuc   EXPECT_FALSE(matches("void Foo(){};", RecordDecl));
256f4a2713aSLionel Sambuc 
257f4a2713aSLionel Sambuc   Matcher<Stmt> ConstructExpr = constructMatcher(
258f4a2713aSLionel Sambuc       "constructExpr",
259f4a2713aSLionel Sambuc       constructMatcher(
260f4a2713aSLionel Sambuc           "hasDeclaration",
261f4a2713aSLionel Sambuc           constructMatcher(
262f4a2713aSLionel Sambuc               "methodDecl",
263f4a2713aSLionel Sambuc               constructMatcher(
264f4a2713aSLionel Sambuc                   "ofClass", constructMatcher("hasName", std::string("Foo"))))))
265f4a2713aSLionel Sambuc                                     .getTypedMatcher<Stmt>();
266f4a2713aSLionel Sambuc   EXPECT_FALSE(matches("class Foo { public: Foo(); };", ConstructExpr));
267f4a2713aSLionel Sambuc   EXPECT_TRUE(
268f4a2713aSLionel Sambuc       matches("class Foo { public: Foo(); }; Foo foo = Foo();", ConstructExpr));
269f4a2713aSLionel Sambuc }
270f4a2713aSLionel Sambuc 
TEST_F(RegistryTest,TemplateArgument)271f4a2713aSLionel Sambuc TEST_F(RegistryTest, TemplateArgument) {
272f4a2713aSLionel Sambuc   Matcher<Decl> HasTemplateArgument = constructMatcher(
273f4a2713aSLionel Sambuc       "classTemplateSpecializationDecl",
274f4a2713aSLionel Sambuc       constructMatcher(
275f4a2713aSLionel Sambuc           "hasAnyTemplateArgument",
276f4a2713aSLionel Sambuc           constructMatcher("refersToType",
277f4a2713aSLionel Sambuc                            constructMatcher("asString", std::string("int")))))
278f4a2713aSLionel Sambuc       .getTypedMatcher<Decl>();
279f4a2713aSLionel Sambuc   EXPECT_TRUE(matches("template<typename T> class A {}; A<int> a;",
280f4a2713aSLionel Sambuc                       HasTemplateArgument));
281f4a2713aSLionel Sambuc   EXPECT_FALSE(matches("template<typename T> class A {}; A<char> a;",
282f4a2713aSLionel Sambuc                        HasTemplateArgument));
283f4a2713aSLionel Sambuc }
284f4a2713aSLionel Sambuc 
TEST_F(RegistryTest,TypeTraversal)285f4a2713aSLionel Sambuc TEST_F(RegistryTest, TypeTraversal) {
286f4a2713aSLionel Sambuc   Matcher<Type> M = constructMatcher(
287f4a2713aSLionel Sambuc       "pointerType",
288f4a2713aSLionel Sambuc       constructMatcher("pointee", constructMatcher("isConstQualified"),
289f4a2713aSLionel Sambuc                        constructMatcher("isInteger"))).getTypedMatcher<Type>();
290f4a2713aSLionel Sambuc   EXPECT_FALSE(matches("int *a;", M));
291f4a2713aSLionel Sambuc   EXPECT_TRUE(matches("int const *b;", M));
292f4a2713aSLionel Sambuc 
293f4a2713aSLionel Sambuc   M = constructMatcher(
294f4a2713aSLionel Sambuc       "arrayType",
295f4a2713aSLionel Sambuc       constructMatcher("hasElementType", constructMatcher("builtinType")))
296f4a2713aSLionel Sambuc       .getTypedMatcher<Type>();
297f4a2713aSLionel Sambuc   EXPECT_FALSE(matches("struct A{}; A a[7];;", M));
298f4a2713aSLionel Sambuc   EXPECT_TRUE(matches("int b[7];", M));
299f4a2713aSLionel Sambuc }
300f4a2713aSLionel Sambuc 
TEST_F(RegistryTest,CXXCtorInitializer)301f4a2713aSLionel Sambuc TEST_F(RegistryTest, CXXCtorInitializer) {
302f4a2713aSLionel Sambuc   Matcher<Decl> CtorDecl = constructMatcher(
303f4a2713aSLionel Sambuc       "constructorDecl",
304f4a2713aSLionel Sambuc       constructMatcher(
305f4a2713aSLionel Sambuc           "hasAnyConstructorInitializer",
306f4a2713aSLionel Sambuc           constructMatcher("forField",
307f4a2713aSLionel Sambuc                            constructMatcher("hasName", std::string("foo")))))
308f4a2713aSLionel Sambuc       .getTypedMatcher<Decl>();
309f4a2713aSLionel Sambuc   EXPECT_TRUE(matches("struct Foo { Foo() : foo(1) {} int foo; };", CtorDecl));
310f4a2713aSLionel Sambuc   EXPECT_FALSE(matches("struct Foo { Foo() {} int foo; };", CtorDecl));
311f4a2713aSLionel Sambuc   EXPECT_FALSE(matches("struct Foo { Foo() : bar(1) {} int bar; };", CtorDecl));
312f4a2713aSLionel Sambuc }
313f4a2713aSLionel Sambuc 
TEST_F(RegistryTest,Adaptative)314f4a2713aSLionel Sambuc TEST_F(RegistryTest, Adaptative) {
315f4a2713aSLionel Sambuc   Matcher<Decl> D = constructMatcher(
316f4a2713aSLionel Sambuc       "recordDecl",
317f4a2713aSLionel Sambuc       constructMatcher(
318f4a2713aSLionel Sambuc           "has",
319f4a2713aSLionel Sambuc           constructMatcher("recordDecl",
320f4a2713aSLionel Sambuc                            constructMatcher("hasName", std::string("X")))))
321f4a2713aSLionel Sambuc       .getTypedMatcher<Decl>();
322f4a2713aSLionel Sambuc   EXPECT_TRUE(matches("class X {};", D));
323f4a2713aSLionel Sambuc   EXPECT_TRUE(matches("class Y { class X {}; };", D));
324f4a2713aSLionel Sambuc   EXPECT_FALSE(matches("class Y { class Z {}; };", D));
325f4a2713aSLionel Sambuc 
326f4a2713aSLionel Sambuc   Matcher<Stmt> S = constructMatcher(
327f4a2713aSLionel Sambuc       "forStmt",
328f4a2713aSLionel Sambuc       constructMatcher(
329f4a2713aSLionel Sambuc           "hasDescendant",
330f4a2713aSLionel Sambuc           constructMatcher("varDecl",
331f4a2713aSLionel Sambuc                            constructMatcher("hasName", std::string("X")))))
332f4a2713aSLionel Sambuc       .getTypedMatcher<Stmt>();
333f4a2713aSLionel Sambuc   EXPECT_TRUE(matches("void foo() { for(int X;;); }", S));
334f4a2713aSLionel Sambuc   EXPECT_TRUE(matches("void foo() { for(;;) { int X; } }", S));
335f4a2713aSLionel Sambuc   EXPECT_FALSE(matches("void foo() { for(;;); }", S));
336f4a2713aSLionel Sambuc   EXPECT_FALSE(matches("void foo() { if (int X = 0){} }", S));
337f4a2713aSLionel Sambuc 
338f4a2713aSLionel Sambuc   S = constructMatcher(
339f4a2713aSLionel Sambuc       "compoundStmt", constructMatcher("hasParent", constructMatcher("ifStmt")))
340f4a2713aSLionel Sambuc       .getTypedMatcher<Stmt>();
341f4a2713aSLionel Sambuc   EXPECT_TRUE(matches("void foo() { if (true) { int x = 42; } }", S));
342f4a2713aSLionel Sambuc   EXPECT_FALSE(matches("void foo() { if (true) return; }", S));
343f4a2713aSLionel Sambuc }
344f4a2713aSLionel Sambuc 
TEST_F(RegistryTest,VariadicOp)345f4a2713aSLionel Sambuc TEST_F(RegistryTest, VariadicOp) {
346f4a2713aSLionel Sambuc   Matcher<Decl> D = constructMatcher(
347f4a2713aSLionel Sambuc       "anyOf",
348f4a2713aSLionel Sambuc       constructMatcher("recordDecl",
349f4a2713aSLionel Sambuc                        constructMatcher("hasName", std::string("Foo"))),
350*0a6a1f1dSLionel Sambuc       constructMatcher("functionDecl",
351f4a2713aSLionel Sambuc                        constructMatcher("hasName", std::string("foo"))))
352f4a2713aSLionel Sambuc       .getTypedMatcher<Decl>();
353f4a2713aSLionel Sambuc 
354f4a2713aSLionel Sambuc   EXPECT_TRUE(matches("void foo(){}", D));
355f4a2713aSLionel Sambuc   EXPECT_TRUE(matches("struct Foo{};", D));
356f4a2713aSLionel Sambuc   EXPECT_FALSE(matches("int i = 0;", D));
357f4a2713aSLionel Sambuc 
358f4a2713aSLionel Sambuc   D = constructMatcher(
359f4a2713aSLionel Sambuc       "allOf", constructMatcher("recordDecl"),
360f4a2713aSLionel Sambuc       constructMatcher(
361f4a2713aSLionel Sambuc           "namedDecl",
362f4a2713aSLionel Sambuc           constructMatcher("anyOf",
363f4a2713aSLionel Sambuc                            constructMatcher("hasName", std::string("Foo")),
364f4a2713aSLionel Sambuc                            constructMatcher("hasName", std::string("Bar")))))
365f4a2713aSLionel Sambuc       .getTypedMatcher<Decl>();
366f4a2713aSLionel Sambuc 
367f4a2713aSLionel Sambuc   EXPECT_FALSE(matches("void foo(){}", D));
368f4a2713aSLionel Sambuc   EXPECT_TRUE(matches("struct Foo{};", D));
369f4a2713aSLionel Sambuc   EXPECT_FALSE(matches("int i = 0;", D));
370f4a2713aSLionel Sambuc   EXPECT_TRUE(matches("class Bar{};", D));
371f4a2713aSLionel Sambuc   EXPECT_FALSE(matches("class OtherBar{};", D));
372*0a6a1f1dSLionel Sambuc 
373*0a6a1f1dSLionel Sambuc   D = recordDecl(
374*0a6a1f1dSLionel Sambuc       has(fieldDecl(hasName("Foo"))),
375*0a6a1f1dSLionel Sambuc       constructMatcher(
376*0a6a1f1dSLionel Sambuc           "unless",
377*0a6a1f1dSLionel Sambuc           constructMatcher("namedDecl",
378*0a6a1f1dSLionel Sambuc                            constructMatcher("hasName", std::string("Bar"))))
379*0a6a1f1dSLionel Sambuc           .getTypedMatcher<Decl>());
380*0a6a1f1dSLionel Sambuc 
381*0a6a1f1dSLionel Sambuc   EXPECT_FALSE(matches("class Bar{ int Foo; };", D));
382*0a6a1f1dSLionel Sambuc   EXPECT_TRUE(matches("class OtherBar{ int Foo; };", D));
383*0a6a1f1dSLionel Sambuc 
384*0a6a1f1dSLionel Sambuc   D = constructMatcher(
385*0a6a1f1dSLionel Sambuc           "namedDecl", constructMatcher("hasName", std::string("Foo")),
386*0a6a1f1dSLionel Sambuc           constructMatcher("unless", constructMatcher("recordDecl")))
387*0a6a1f1dSLionel Sambuc           .getTypedMatcher<Decl>();
388*0a6a1f1dSLionel Sambuc   EXPECT_TRUE(matches("void Foo(){}", D));
389*0a6a1f1dSLionel Sambuc   EXPECT_TRUE(notMatches("struct Foo {};", D));
390f4a2713aSLionel Sambuc }
391f4a2713aSLionel Sambuc 
TEST_F(RegistryTest,Errors)392f4a2713aSLionel Sambuc TEST_F(RegistryTest, Errors) {
393f4a2713aSLionel Sambuc   // Incorrect argument count.
394*0a6a1f1dSLionel Sambuc   std::unique_ptr<Diagnostics> Error(new Diagnostics());
395f4a2713aSLionel Sambuc   EXPECT_TRUE(constructMatcher("hasInitializer", Error.get()).isNull());
396f4a2713aSLionel Sambuc   EXPECT_EQ("Incorrect argument count. (Expected = 1) != (Actual = 0)",
397f4a2713aSLionel Sambuc             Error->toString());
398f4a2713aSLionel Sambuc   Error.reset(new Diagnostics());
399f4a2713aSLionel Sambuc   EXPECT_TRUE(constructMatcher("isArrow", std::string(), Error.get()).isNull());
400f4a2713aSLionel Sambuc   EXPECT_EQ("Incorrect argument count. (Expected = 0) != (Actual = 1)",
401f4a2713aSLionel Sambuc             Error->toString());
402*0a6a1f1dSLionel Sambuc   Error.reset(new Diagnostics());
403*0a6a1f1dSLionel Sambuc   EXPECT_TRUE(constructMatcher("anyOf", Error.get()).isNull());
404*0a6a1f1dSLionel Sambuc   EXPECT_EQ("Incorrect argument count. (Expected = (2, )) != (Actual = 0)",
405*0a6a1f1dSLionel Sambuc             Error->toString());
406*0a6a1f1dSLionel Sambuc   Error.reset(new Diagnostics());
407*0a6a1f1dSLionel Sambuc   EXPECT_TRUE(constructMatcher("unless", std::string(), std::string(),
408*0a6a1f1dSLionel Sambuc                                Error.get()).isNull());
409*0a6a1f1dSLionel Sambuc   EXPECT_EQ("Incorrect argument count. (Expected = (1, 1)) != (Actual = 2)",
410*0a6a1f1dSLionel Sambuc             Error->toString());
411f4a2713aSLionel Sambuc 
412f4a2713aSLionel Sambuc   // Bad argument type
413f4a2713aSLionel Sambuc   Error.reset(new Diagnostics());
414f4a2713aSLionel Sambuc   EXPECT_TRUE(constructMatcher("ofClass", std::string(), Error.get()).isNull());
415f4a2713aSLionel Sambuc   EXPECT_EQ("Incorrect type for arg 1. (Expected = Matcher<CXXRecordDecl>) != "
416f4a2713aSLionel Sambuc             "(Actual = String)",
417f4a2713aSLionel Sambuc             Error->toString());
418f4a2713aSLionel Sambuc   Error.reset(new Diagnostics());
419f4a2713aSLionel Sambuc   EXPECT_TRUE(constructMatcher("recordDecl", constructMatcher("recordDecl"),
420f4a2713aSLionel Sambuc                                constructMatcher("parameterCountIs", 3),
421f4a2713aSLionel Sambuc                                Error.get()).isNull());
422f4a2713aSLionel Sambuc   EXPECT_EQ("Incorrect type for arg 2. (Expected = Matcher<CXXRecordDecl>) != "
423f4a2713aSLionel Sambuc             "(Actual = Matcher<FunctionDecl>)",
424f4a2713aSLionel Sambuc             Error->toString());
425f4a2713aSLionel Sambuc 
426f4a2713aSLionel Sambuc   // Bad argument type with variadic.
427f4a2713aSLionel Sambuc   Error.reset(new Diagnostics());
428*0a6a1f1dSLionel Sambuc   EXPECT_TRUE(constructMatcher("anyOf", std::string(), std::string(),
429*0a6a1f1dSLionel Sambuc                                Error.get()).isNull());
430f4a2713aSLionel Sambuc   EXPECT_EQ(
431f4a2713aSLionel Sambuc       "Incorrect type for arg 1. (Expected = Matcher<>) != (Actual = String)",
432f4a2713aSLionel Sambuc       Error->toString());
433f4a2713aSLionel Sambuc   Error.reset(new Diagnostics());
434f4a2713aSLionel Sambuc   EXPECT_TRUE(constructMatcher(
435f4a2713aSLionel Sambuc       "recordDecl",
436f4a2713aSLionel Sambuc       constructMatcher("allOf",
437f4a2713aSLionel Sambuc                        constructMatcher("isDerivedFrom", std::string("FOO")),
438f4a2713aSLionel Sambuc                        constructMatcher("isArrow")),
439f4a2713aSLionel Sambuc       Error.get()).isNull());
440f4a2713aSLionel Sambuc   EXPECT_EQ("Incorrect type for arg 1. "
441f4a2713aSLionel Sambuc             "(Expected = Matcher<CXXRecordDecl>) != "
442f4a2713aSLionel Sambuc             "(Actual = Matcher<CXXRecordDecl>&Matcher<MemberExpr>)",
443f4a2713aSLionel Sambuc             Error->toString());
444f4a2713aSLionel Sambuc }
445f4a2713aSLionel Sambuc 
TEST_F(RegistryTest,Completion)446*0a6a1f1dSLionel Sambuc TEST_F(RegistryTest, Completion) {
447*0a6a1f1dSLionel Sambuc   CompVector Comps = getCompletions();
448*0a6a1f1dSLionel Sambuc   // Overloaded
449*0a6a1f1dSLionel Sambuc   EXPECT_TRUE(hasCompletion(
450*0a6a1f1dSLionel Sambuc       Comps, "hasParent(", "Matcher<Decl|Stmt> hasParent(Matcher<Decl|Stmt>)"));
451*0a6a1f1dSLionel Sambuc   // Variadic.
452*0a6a1f1dSLionel Sambuc   EXPECT_TRUE(hasCompletion(Comps, "whileStmt(",
453*0a6a1f1dSLionel Sambuc                             "Matcher<Stmt> whileStmt(Matcher<WhileStmt>...)"));
454*0a6a1f1dSLionel Sambuc   // Polymorphic.
455*0a6a1f1dSLionel Sambuc   EXPECT_TRUE(hasCompletion(
456*0a6a1f1dSLionel Sambuc       Comps, "hasDescendant(",
457*0a6a1f1dSLionel Sambuc       "Matcher<NestedNameSpecifier|NestedNameSpecifierLoc|QualType|...> "
458*0a6a1f1dSLionel Sambuc       "hasDescendant(Matcher<CXXCtorInitializer|NestedNameSpecifier|"
459*0a6a1f1dSLionel Sambuc       "NestedNameSpecifierLoc|...>)"));
460*0a6a1f1dSLionel Sambuc 
461*0a6a1f1dSLionel Sambuc   CompVector WhileComps = getCompletions("whileStmt", 0);
462*0a6a1f1dSLionel Sambuc 
463*0a6a1f1dSLionel Sambuc   EXPECT_TRUE(hasCompletion(WhileComps, "hasBody(",
464*0a6a1f1dSLionel Sambuc                             "Matcher<WhileStmt> hasBody(Matcher<Stmt>)"));
465*0a6a1f1dSLionel Sambuc   EXPECT_TRUE(hasCompletion(WhileComps, "hasParent(",
466*0a6a1f1dSLionel Sambuc                             "Matcher<Stmt> hasParent(Matcher<Decl|Stmt>)"));
467*0a6a1f1dSLionel Sambuc   EXPECT_TRUE(
468*0a6a1f1dSLionel Sambuc       hasCompletion(WhileComps, "allOf(", "Matcher<T> allOf(Matcher<T>...)"));
469*0a6a1f1dSLionel Sambuc 
470*0a6a1f1dSLionel Sambuc   EXPECT_FALSE(hasCompletion(WhileComps, "whileStmt("));
471*0a6a1f1dSLionel Sambuc   EXPECT_FALSE(hasCompletion(WhileComps, "ifStmt("));
472*0a6a1f1dSLionel Sambuc 
473*0a6a1f1dSLionel Sambuc   CompVector AllOfWhileComps =
474*0a6a1f1dSLionel Sambuc       getCompletions("allOf", 0, "whileStmt", 0);
475*0a6a1f1dSLionel Sambuc   ASSERT_EQ(AllOfWhileComps.size(), WhileComps.size());
476*0a6a1f1dSLionel Sambuc   EXPECT_TRUE(std::equal(WhileComps.begin(), WhileComps.end(),
477*0a6a1f1dSLionel Sambuc                          AllOfWhileComps.begin()));
478*0a6a1f1dSLionel Sambuc 
479*0a6a1f1dSLionel Sambuc   CompVector DeclWhileComps =
480*0a6a1f1dSLionel Sambuc       getCompletions("decl", 0, "whileStmt", 0);
481*0a6a1f1dSLionel Sambuc   EXPECT_EQ(0u, DeclWhileComps.size());
482*0a6a1f1dSLionel Sambuc 
483*0a6a1f1dSLionel Sambuc   CompVector NamedDeclComps = getCompletions("namedDecl", 0);
484*0a6a1f1dSLionel Sambuc   EXPECT_TRUE(
485*0a6a1f1dSLionel Sambuc       hasCompletion(NamedDeclComps, "isPublic()", "Matcher<Decl> isPublic()"));
486*0a6a1f1dSLionel Sambuc   EXPECT_TRUE(hasCompletion(NamedDeclComps, "hasName(\"",
487*0a6a1f1dSLionel Sambuc                             "Matcher<NamedDecl> hasName(string)"));
488*0a6a1f1dSLionel Sambuc 
489*0a6a1f1dSLionel Sambuc   // Heterogeneous overloads.
490*0a6a1f1dSLionel Sambuc   Comps = getCompletions("classTemplateSpecializationDecl", 0);
491*0a6a1f1dSLionel Sambuc   EXPECT_TRUE(hasCompletion(
492*0a6a1f1dSLionel Sambuc       Comps, "isSameOrDerivedFrom(",
493*0a6a1f1dSLionel Sambuc       "Matcher<CXXRecordDecl> isSameOrDerivedFrom(string|Matcher<NamedDecl>)"));
494*0a6a1f1dSLionel Sambuc }
495*0a6a1f1dSLionel Sambuc 
TEST_F(RegistryTest,HasArgs)496*0a6a1f1dSLionel Sambuc TEST_F(RegistryTest, HasArgs) {
497*0a6a1f1dSLionel Sambuc   Matcher<Decl> Value = constructMatcher(
498*0a6a1f1dSLionel Sambuc       "decl", constructMatcher("hasAttr", std::string("attr::WarnUnused")))
499*0a6a1f1dSLionel Sambuc       .getTypedMatcher<Decl>();
500*0a6a1f1dSLionel Sambuc   EXPECT_TRUE(matches("struct __attribute__((warn_unused)) X {};", Value));
501*0a6a1f1dSLionel Sambuc   EXPECT_FALSE(matches("struct X {};", Value));
502*0a6a1f1dSLionel Sambuc }
503*0a6a1f1dSLionel Sambuc 
504f4a2713aSLionel Sambuc } // end anonymous namespace
505f4a2713aSLionel Sambuc } // end namespace dynamic
506f4a2713aSLionel Sambuc } // end namespace ast_matchers
507f4a2713aSLionel Sambuc } // end namespace clang
508