blob: a1b6a93456dcc7226b8f0ea10d8124fba5305cd0 [file] [log] [blame]
Manuel Klimek24db0f02013-05-14 09:13:00 +00001//===- 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
Manuel Klimek24db0f02013-05-14 09:13:00 +000010#include "../ASTMatchersTest.h"
11#include "clang/ASTMatchers/Dynamic/Registry.h"
12#include "gtest/gtest.h"
Chandler Carruth5553d0d2014-01-07 11:51:46 +000013#include <vector>
Manuel Klimek24db0f02013-05-14 09:13:00 +000014
15namespace clang {
16namespace ast_matchers {
17namespace dynamic {
18namespace {
19
20using ast_matchers::internal::Matcher;
21
Samuel Benzaquen81ef9292013-06-20 14:28:32 +000022class 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 }
Manuel Klimek24db0f02013-05-14 09:13:00 +000037
Samuel Benzaquenf434c4f2014-04-14 13:51:21 +000038 llvm::Optional<MatcherCtor> lookupMatcherCtor(StringRef MatcherName) {
39 return Registry::lookupMatcherCtor(MatcherName);
Peter Collingbourne00cba4f2013-11-23 01:13:16 +000040 }
41
Samuel Benzaquen0239b692013-08-13 14:54:51 +000042 VariantMatcher constructMatcher(StringRef MatcherName,
Craig Topper416fa342014-06-08 08:38:12 +000043 Diagnostics *Error = nullptr) {
Samuel Benzaquen79656e12013-07-15 19:25:06 +000044 Diagnostics DummyError;
45 if (!Error) Error = &DummyError;
Samuel Benzaquenf434c4f2014-04-14 13:51:21 +000046 llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName);
Peter Collingbourne00cba4f2013-11-23 01:13:16 +000047 VariantMatcher Out;
48 if (Ctor)
49 Out = Registry::constructMatcher(*Ctor, SourceRange(), Args(), Error);
Samuel Benzaquenb8372482013-07-19 20:02:35 +000050 EXPECT_EQ("", DummyError.toStringFull());
Samuel Benzaquen79656e12013-07-15 19:25:06 +000051 return Out;
Samuel Benzaquen81ef9292013-06-20 14:28:32 +000052 }
Manuel Klimek24db0f02013-05-14 09:13:00 +000053
Samuel Benzaquen0239b692013-08-13 14:54:51 +000054 VariantMatcher constructMatcher(StringRef MatcherName,
55 const VariantValue &Arg1,
Craig Topper416fa342014-06-08 08:38:12 +000056 Diagnostics *Error = nullptr) {
Samuel Benzaquen79656e12013-07-15 19:25:06 +000057 Diagnostics DummyError;
58 if (!Error) Error = &DummyError;
Samuel Benzaquenf434c4f2014-04-14 13:51:21 +000059 llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName);
Peter Collingbourne00cba4f2013-11-23 01:13:16 +000060 VariantMatcher Out;
61 if (Ctor)
62 Out = Registry::constructMatcher(*Ctor, SourceRange(), Args(Arg1), Error);
Samuel Benzaquena0839352014-03-10 15:40:23 +000063 EXPECT_EQ("", DummyError.toStringFull()) << MatcherName;
Samuel Benzaquen79656e12013-07-15 19:25:06 +000064 return Out;
Samuel Benzaquen81ef9292013-06-20 14:28:32 +000065 }
Manuel Klimek24db0f02013-05-14 09:13:00 +000066
Samuel Benzaquen0239b692013-08-13 14:54:51 +000067 VariantMatcher constructMatcher(StringRef MatcherName,
68 const VariantValue &Arg1,
69 const VariantValue &Arg2,
Craig Topper416fa342014-06-08 08:38:12 +000070 Diagnostics *Error = nullptr) {
Samuel Benzaquen79656e12013-07-15 19:25:06 +000071 Diagnostics DummyError;
72 if (!Error) Error = &DummyError;
Samuel Benzaquenf434c4f2014-04-14 13:51:21 +000073 llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName);
Peter Collingbourne00cba4f2013-11-23 01:13:16 +000074 VariantMatcher Out;
75 if (Ctor)
76 Out = Registry::constructMatcher(*Ctor, SourceRange(), Args(Arg1, Arg2),
77 Error);
Samuel Benzaquenb8372482013-07-19 20:02:35 +000078 EXPECT_EQ("", DummyError.toStringFull());
Samuel Benzaquen79656e12013-07-15 19:25:06 +000079 return Out;
Samuel Benzaquen81ef9292013-06-20 14:28:32 +000080 }
Peter Collingbourned32e28c2014-01-23 22:48:38 +000081
82 typedef std::vector<MatcherCompletion> CompVector;
83
84 CompVector getCompletions() {
Samuel Benzaquen646f23b2014-08-12 21:11:37 +000085 std::vector<std::pair<MatcherCtor, unsigned> > Context;
86 return Registry::getMatcherCompletions(
87 Registry::getAcceptedCompletionTypes(Context));
Peter Collingbourned32e28c2014-01-23 22:48:38 +000088 }
89
90 CompVector getCompletions(StringRef MatcherName1, unsigned ArgNo1) {
91 std::vector<std::pair<MatcherCtor, unsigned> > Context;
92 llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName1);
93 if (!Ctor)
94 return CompVector();
95 Context.push_back(std::make_pair(*Ctor, ArgNo1));
Samuel Benzaquen646f23b2014-08-12 21:11:37 +000096 return Registry::getMatcherCompletions(
97 Registry::getAcceptedCompletionTypes(Context));
Peter Collingbourned32e28c2014-01-23 22:48:38 +000098 }
99
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);
104 if (!Ctor)
105 return CompVector();
106 Context.push_back(std::make_pair(*Ctor, ArgNo1));
107 Ctor = lookupMatcherCtor(MatcherName2);
108 if (!Ctor)
109 return CompVector();
110 Context.push_back(std::make_pair(*Ctor, ArgNo2));
Samuel Benzaquen646f23b2014-08-12 21:11:37 +0000111 return Registry::getMatcherCompletions(
112 Registry::getAcceptedCompletionTypes(Context));
Peter Collingbourned32e28c2014-01-23 22:48:38 +0000113 }
114
115 bool hasCompletion(const CompVector &Comps, StringRef TypedText,
Samuel Benzaquen646f23b2014-08-12 21:11:37 +0000116 StringRef MatcherDecl = StringRef()) {
Peter Collingbourned32e28c2014-01-23 22:48:38 +0000117 for (CompVector::const_iterator I = Comps.begin(), E = Comps.end(); I != E;
118 ++I) {
119 if (I->TypedText == TypedText &&
120 (MatcherDecl.empty() || I->MatcherDecl == MatcherDecl)) {
Peter Collingbourned32e28c2014-01-23 22:48:38 +0000121 return true;
122 }
123 }
124 return false;
125 }
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000126};
127
128TEST_F(RegistryTest, CanConstructNoArgs) {
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000129 Matcher<Stmt> IsArrowValue = constructMatcher(
130 "memberExpr", constructMatcher("isArrow")).getTypedMatcher<Stmt>();
131 Matcher<Stmt> BoolValue =
Aaron Ballman512fb642015-09-17 13:30:52 +0000132 constructMatcher("cxxBoolLiteral").getTypedMatcher<Stmt>();
Manuel Klimek24db0f02013-05-14 09:13:00 +0000133
134 const std::string ClassSnippet = "struct Foo { int x; };\n"
135 "Foo *foo = new Foo;\n"
136 "int i = foo->x;\n";
137 const std::string BoolSnippet = "bool Foo = true;\n";
138
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000139 EXPECT_TRUE(matches(ClassSnippet, IsArrowValue));
140 EXPECT_TRUE(matches(BoolSnippet, BoolValue));
141 EXPECT_FALSE(matches(ClassSnippet, BoolValue));
142 EXPECT_FALSE(matches(BoolSnippet, IsArrowValue));
Manuel Klimek24db0f02013-05-14 09:13:00 +0000143}
144
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000145TEST_F(RegistryTest, ConstructWithSimpleArgs) {
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000146 Matcher<Decl> Value = constructMatcher(
Yaron Keren5b816062015-07-06 08:47:15 +0000147 "namedDecl", constructMatcher("hasName", StringRef("X")))
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000148 .getTypedMatcher<Decl>();
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000149 EXPECT_TRUE(matches("class X {};", Value));
150 EXPECT_FALSE(matches("int x;", Value));
Samuel Benzaquenc31b3522013-06-04 15:46:22 +0000151
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000152 Value = functionDecl(constructMatcher("parameterCountIs", 2)
153 .getTypedMatcher<FunctionDecl>());
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000154 EXPECT_TRUE(matches("void foo(int,int);", Value));
155 EXPECT_FALSE(matches("void foo(int);", Value));
Manuel Klimek24db0f02013-05-14 09:13:00 +0000156}
157
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000158TEST_F(RegistryTest, ConstructWithMatcherArgs) {
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000159 Matcher<Decl> HasInitializerSimple = constructMatcher(
160 "varDecl", constructMatcher("hasInitializer", constructMatcher("stmt")))
161 .getTypedMatcher<Decl>();
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000162 Matcher<Decl> HasInitializerComplex = constructMatcher(
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000163 "varDecl",
164 constructMatcher("hasInitializer", constructMatcher("callExpr")))
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000165 .getTypedMatcher<Decl>();
Manuel Klimek24db0f02013-05-14 09:13:00 +0000166
167 std::string code = "int i;";
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000168 EXPECT_FALSE(matches(code, HasInitializerSimple));
169 EXPECT_FALSE(matches(code, HasInitializerComplex));
Manuel Klimek24db0f02013-05-14 09:13:00 +0000170
171 code = "int i = 1;";
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000172 EXPECT_TRUE(matches(code, HasInitializerSimple));
173 EXPECT_FALSE(matches(code, HasInitializerComplex));
Manuel Klimek24db0f02013-05-14 09:13:00 +0000174
175 code = "int y(); int i = y();";
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000176 EXPECT_TRUE(matches(code, HasInitializerSimple));
177 EXPECT_TRUE(matches(code, HasInitializerComplex));
Samuel Benzaquenc31b3522013-06-04 15:46:22 +0000178
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000179 Matcher<Decl> HasParameter =
180 functionDecl(constructMatcher(
Yaron Keren5b816062015-07-06 08:47:15 +0000181 "hasParameter", 1, constructMatcher("hasName", StringRef("x")))
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000182 .getTypedMatcher<FunctionDecl>());
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000183 EXPECT_TRUE(matches("void f(int a, int x);", HasParameter));
184 EXPECT_FALSE(matches("void f(int x, int a);", HasParameter));
Manuel Klimek24db0f02013-05-14 09:13:00 +0000185}
186
Samuel Benzaquene0b2c8e2013-07-22 16:13:57 +0000187TEST_F(RegistryTest, OverloadedMatchers) {
188 Matcher<Stmt> CallExpr0 = constructMatcher(
189 "callExpr",
190 constructMatcher("callee", constructMatcher("memberExpr",
191 constructMatcher("isArrow"))))
192 .getTypedMatcher<Stmt>();
193
194 Matcher<Stmt> CallExpr1 = constructMatcher(
195 "callExpr",
196 constructMatcher(
197 "callee",
Aaron Ballman512fb642015-09-17 13:30:52 +0000198 constructMatcher("cxxMethodDecl",
Yaron Keren5b816062015-07-06 08:47:15 +0000199 constructMatcher("hasName", StringRef("x")))))
Samuel Benzaquene0b2c8e2013-07-22 16:13:57 +0000200 .getTypedMatcher<Stmt>();
201
202 std::string Code = "class Y { public: void x(); }; void z() { Y y; y.x(); }";
203 EXPECT_FALSE(matches(Code, CallExpr0));
204 EXPECT_TRUE(matches(Code, CallExpr1));
205
206 Code = "class Z { public: void z() { this->z(); } };";
207 EXPECT_TRUE(matches(Code, CallExpr0));
208 EXPECT_FALSE(matches(Code, CallExpr1));
Samuel Benzaquena0839352014-03-10 15:40:23 +0000209
210 Matcher<Decl> DeclDecl = declaratorDecl(hasTypeLoc(
211 constructMatcher(
Yaron Keren5b816062015-07-06 08:47:15 +0000212 "loc", constructMatcher("asString", StringRef("const double *")))
Samuel Benzaquena0839352014-03-10 15:40:23 +0000213 .getTypedMatcher<TypeLoc>()));
214
215 Matcher<NestedNameSpecifierLoc> NNSL =
216 constructMatcher(
217 "loc", VariantMatcher::SingleMatcher(nestedNameSpecifier(
218 specifiesType(hasDeclaration(recordDecl(hasName("A")))))))
219 .getTypedMatcher<NestedNameSpecifierLoc>();
220
221 Code = "const double * x = 0;";
222 EXPECT_TRUE(matches(Code, DeclDecl));
223 EXPECT_FALSE(matches(Code, NNSL));
224
225 Code = "struct A { struct B {}; }; A::B a_b;";
226 EXPECT_FALSE(matches(Code, DeclDecl));
227 EXPECT_TRUE(matches(Code, NNSL));
Samuel Benzaquene0b2c8e2013-07-22 16:13:57 +0000228}
229
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000230TEST_F(RegistryTest, PolymorphicMatchers) {
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000231 const VariantMatcher IsDefinition = constructMatcher("isDefinition");
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000232 Matcher<Decl> Var =
233 constructMatcher("varDecl", IsDefinition).getTypedMatcher<Decl>();
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000234 Matcher<Decl> Class =
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000235 constructMatcher("recordDecl", IsDefinition).getTypedMatcher<Decl>();
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000236 Matcher<Decl> Func =
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000237 constructMatcher("functionDecl", IsDefinition).getTypedMatcher<Decl>();
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000238 EXPECT_TRUE(matches("int a;", Var));
239 EXPECT_FALSE(matches("extern int a;", Var));
240 EXPECT_TRUE(matches("class A {};", Class));
241 EXPECT_FALSE(matches("class A;", Class));
242 EXPECT_TRUE(matches("void f(){};", Func));
243 EXPECT_FALSE(matches("void f();", Func));
244
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000245 Matcher<Decl> Anything = constructMatcher("anything").getTypedMatcher<Decl>();
Samuel Benzaquen68cd3962013-08-29 15:39:26 +0000246 Matcher<Decl> RecordDecl = constructMatcher(
Yaron Keren5b816062015-07-06 08:47:15 +0000247 "recordDecl", constructMatcher("hasName", StringRef("Foo")),
Samuel Benzaquen68cd3962013-08-29 15:39:26 +0000248 VariantMatcher::SingleMatcher(Anything)).getTypedMatcher<Decl>();
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000249
Samuel Benzaquen68cd3962013-08-29 15:39:26 +0000250 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));
Samuel Benzaquen464c1cb2013-11-18 14:53:42 +0000256
257 Matcher<Stmt> ConstructExpr = constructMatcher(
Aaron Ballman512fb642015-09-17 13:30:52 +0000258 "cxxConstructExpr",
Samuel Benzaquen464c1cb2013-11-18 14:53:42 +0000259 constructMatcher(
260 "hasDeclaration",
261 constructMatcher(
Aaron Ballman512fb642015-09-17 13:30:52 +0000262 "cxxMethodDecl",
Samuel Benzaquen464c1cb2013-11-18 14:53:42 +0000263 constructMatcher(
Yaron Keren5b816062015-07-06 08:47:15 +0000264 "ofClass", constructMatcher("hasName", StringRef("Foo"))))))
Samuel Benzaquen464c1cb2013-11-18 14:53:42 +0000265 .getTypedMatcher<Stmt>();
266 EXPECT_FALSE(matches("class Foo { public: Foo(); };", ConstructExpr));
267 EXPECT_TRUE(
268 matches("class Foo { public: Foo(); }; Foo foo = Foo();", ConstructExpr));
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000269}
270
Samuel Benzaquen21b3da02013-07-17 15:11:30 +0000271TEST_F(RegistryTest, TemplateArgument) {
272 Matcher<Decl> HasTemplateArgument = constructMatcher(
273 "classTemplateSpecializationDecl",
274 constructMatcher(
275 "hasAnyTemplateArgument",
276 constructMatcher("refersToType",
Yaron Keren5b816062015-07-06 08:47:15 +0000277 constructMatcher("asString", StringRef("int")))))
Samuel Benzaquen21b3da02013-07-17 15:11:30 +0000278 .getTypedMatcher<Decl>();
279 EXPECT_TRUE(matches("template<typename T> class A {}; A<int> a;",
280 HasTemplateArgument));
281 EXPECT_FALSE(matches("template<typename T> class A {}; A<char> a;",
282 HasTemplateArgument));
283}
284
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000285TEST_F(RegistryTest, TypeTraversal) {
286 Matcher<Type> M = constructMatcher(
287 "pointerType",
288 constructMatcher("pointee", constructMatcher("isConstQualified"),
289 constructMatcher("isInteger"))).getTypedMatcher<Type>();
290 EXPECT_FALSE(matches("int *a;", M));
291 EXPECT_TRUE(matches("int const *b;", M));
292
293 M = constructMatcher(
294 "arrayType",
295 constructMatcher("hasElementType", constructMatcher("builtinType")))
296 .getTypedMatcher<Type>();
297 EXPECT_FALSE(matches("struct A{}; A a[7];;", M));
298 EXPECT_TRUE(matches("int b[7];", M));
299}
300
Samuel Benzaquen06e056c2013-07-17 14:28:00 +0000301TEST_F(RegistryTest, CXXCtorInitializer) {
302 Matcher<Decl> CtorDecl = constructMatcher(
Aaron Ballman512fb642015-09-17 13:30:52 +0000303 "cxxConstructorDecl",
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000304 constructMatcher(
305 "hasAnyConstructorInitializer",
306 constructMatcher("forField",
Yaron Keren5b816062015-07-06 08:47:15 +0000307 constructMatcher("hasName", StringRef("foo")))))
Samuel Benzaquen06e056c2013-07-17 14:28:00 +0000308 .getTypedMatcher<Decl>();
309 EXPECT_TRUE(matches("struct Foo { Foo() : foo(1) {} int foo; };", CtorDecl));
310 EXPECT_FALSE(matches("struct Foo { Foo() {} int foo; };", CtorDecl));
311 EXPECT_FALSE(matches("struct Foo { Foo() : bar(1) {} int bar; };", CtorDecl));
312}
313
Samuel Benzaquen7f8a5b12013-07-24 14:48:01 +0000314TEST_F(RegistryTest, Adaptative) {
315 Matcher<Decl> D = constructMatcher(
316 "recordDecl",
317 constructMatcher(
318 "has",
319 constructMatcher("recordDecl",
Yaron Keren5b816062015-07-06 08:47:15 +0000320 constructMatcher("hasName", StringRef("X")))))
Samuel Benzaquen7f8a5b12013-07-24 14:48:01 +0000321 .getTypedMatcher<Decl>();
322 EXPECT_TRUE(matches("class X {};", D));
323 EXPECT_TRUE(matches("class Y { class X {}; };", D));
324 EXPECT_FALSE(matches("class Y { class Z {}; };", D));
325
326 Matcher<Stmt> S = constructMatcher(
327 "forStmt",
328 constructMatcher(
329 "hasDescendant",
330 constructMatcher("varDecl",
Yaron Keren5b816062015-07-06 08:47:15 +0000331 constructMatcher("hasName", StringRef("X")))))
Samuel Benzaquen7f8a5b12013-07-24 14:48:01 +0000332 .getTypedMatcher<Stmt>();
333 EXPECT_TRUE(matches("void foo() { for(int X;;); }", S));
334 EXPECT_TRUE(matches("void foo() { for(;;) { int X; } }", S));
335 EXPECT_FALSE(matches("void foo() { for(;;); }", S));
336 EXPECT_FALSE(matches("void foo() { if (int X = 0){} }", S));
337
338 S = constructMatcher(
339 "compoundStmt", constructMatcher("hasParent", constructMatcher("ifStmt")))
340 .getTypedMatcher<Stmt>();
341 EXPECT_TRUE(matches("void foo() { if (true) { int x = 42; } }", S));
342 EXPECT_FALSE(matches("void foo() { if (true) return; }", S));
343}
344
Samuel Benzaquen4adca622013-08-28 18:42:04 +0000345TEST_F(RegistryTest, VariadicOp) {
346 Matcher<Decl> D = constructMatcher(
Samuel Benzaquen68cd3962013-08-29 15:39:26 +0000347 "anyOf",
348 constructMatcher("recordDecl",
Yaron Keren5b816062015-07-06 08:47:15 +0000349 constructMatcher("hasName", StringRef("Foo"))),
Samuel Benzaquena1170022014-10-06 13:14:30 +0000350 constructMatcher("functionDecl",
Yaron Keren5b816062015-07-06 08:47:15 +0000351 constructMatcher("hasName", StringRef("foo"))))
Samuel Benzaquen4adca622013-08-28 18:42:04 +0000352 .getTypedMatcher<Decl>();
353
354 EXPECT_TRUE(matches("void foo(){}", D));
355 EXPECT_TRUE(matches("struct Foo{};", D));
356 EXPECT_FALSE(matches("int i = 0;", D));
357
358 D = constructMatcher(
359 "allOf", constructMatcher("recordDecl"),
360 constructMatcher(
361 "namedDecl",
362 constructMatcher("anyOf",
Yaron Keren5b816062015-07-06 08:47:15 +0000363 constructMatcher("hasName", StringRef("Foo")),
364 constructMatcher("hasName", StringRef("Bar")))))
Samuel Benzaquen4adca622013-08-28 18:42:04 +0000365 .getTypedMatcher<Decl>();
366
367 EXPECT_FALSE(matches("void foo(){}", D));
368 EXPECT_TRUE(matches("struct Foo{};", D));
369 EXPECT_FALSE(matches("int i = 0;", D));
370 EXPECT_TRUE(matches("class Bar{};", D));
371 EXPECT_FALSE(matches("class OtherBar{};", D));
Samuel Benzaquen4d058742013-11-22 14:41:48 +0000372
Samuel Benzaquenef77f3c2013-11-22 23:05:57 +0000373 D = recordDecl(
374 has(fieldDecl(hasName("Foo"))),
Samuel Benzaquen4d058742013-11-22 14:41:48 +0000375 constructMatcher(
376 "unless",
377 constructMatcher("namedDecl",
Yaron Keren5b816062015-07-06 08:47:15 +0000378 constructMatcher("hasName", StringRef("Bar"))))
Samuel Benzaquenef77f3c2013-11-22 23:05:57 +0000379 .getTypedMatcher<Decl>());
Samuel Benzaquen4d058742013-11-22 14:41:48 +0000380
Samuel Benzaquenef77f3c2013-11-22 23:05:57 +0000381 EXPECT_FALSE(matches("class Bar{ int Foo; };", D));
382 EXPECT_TRUE(matches("class OtherBar{ int Foo; };", D));
Samuel Benzaquen20099602014-10-13 17:38:12 +0000383
384 D = constructMatcher(
Yaron Keren5b816062015-07-06 08:47:15 +0000385 "namedDecl", constructMatcher("hasName", StringRef("Foo")),
Samuel Benzaquen20099602014-10-13 17:38:12 +0000386 constructMatcher("unless", constructMatcher("recordDecl")))
387 .getTypedMatcher<Decl>();
388 EXPECT_TRUE(matches("void Foo(){}", D));
389 EXPECT_TRUE(notMatches("struct Foo {};", D));
Samuel Benzaquen4adca622013-08-28 18:42:04 +0000390}
391
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000392TEST_F(RegistryTest, Errors) {
Manuel Klimek24db0f02013-05-14 09:13:00 +0000393 // Incorrect argument count.
Ahmed Charlesb8984322014-03-07 20:03:18 +0000394 std::unique_ptr<Diagnostics> Error(new Diagnostics());
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000395 EXPECT_TRUE(constructMatcher("hasInitializer", Error.get()).isNull());
Manuel Klimek24db0f02013-05-14 09:13:00 +0000396 EXPECT_EQ("Incorrect argument count. (Expected = 1) != (Actual = 0)",
Samuel Benzaquenb8372482013-07-19 20:02:35 +0000397 Error->toString());
Manuel Klimek24db0f02013-05-14 09:13:00 +0000398 Error.reset(new Diagnostics());
Yaron Keren5b816062015-07-06 08:47:15 +0000399 EXPECT_TRUE(constructMatcher("isArrow", StringRef(), Error.get()).isNull());
Manuel Klimek24db0f02013-05-14 09:13:00 +0000400 EXPECT_EQ("Incorrect argument count. (Expected = 0) != (Actual = 1)",
Samuel Benzaquenb8372482013-07-19 20:02:35 +0000401 Error->toString());
Samuel Benzaquen4d058742013-11-22 14:41:48 +0000402 Error.reset(new Diagnostics());
403 EXPECT_TRUE(constructMatcher("anyOf", Error.get()).isNull());
404 EXPECT_EQ("Incorrect argument count. (Expected = (2, )) != (Actual = 0)",
405 Error->toString());
406 Error.reset(new Diagnostics());
Yaron Keren5b816062015-07-06 08:47:15 +0000407 EXPECT_TRUE(constructMatcher("unless", StringRef(), StringRef(),
Samuel Benzaquen4d058742013-11-22 14:41:48 +0000408 Error.get()).isNull());
409 EXPECT_EQ("Incorrect argument count. (Expected = (1, 1)) != (Actual = 2)",
410 Error->toString());
Manuel Klimek24db0f02013-05-14 09:13:00 +0000411
412 // Bad argument type
413 Error.reset(new Diagnostics());
Yaron Keren5b816062015-07-06 08:47:15 +0000414 EXPECT_TRUE(constructMatcher("ofClass", StringRef(), Error.get()).isNull());
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000415 EXPECT_EQ("Incorrect type for arg 1. (Expected = Matcher<CXXRecordDecl>) != "
416 "(Actual = String)",
Samuel Benzaquenb8372482013-07-19 20:02:35 +0000417 Error->toString());
Manuel Klimek24db0f02013-05-14 09:13:00 +0000418 Error.reset(new Diagnostics());
Aaron Ballman512fb642015-09-17 13:30:52 +0000419 EXPECT_TRUE(
420 constructMatcher("cxxRecordDecl", constructMatcher("cxxRecordDecl"),
421 constructMatcher("parameterCountIs", 3), Error.get())
422 .isNull());
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000423 EXPECT_EQ("Incorrect type for arg 2. (Expected = Matcher<CXXRecordDecl>) != "
424 "(Actual = Matcher<FunctionDecl>)",
Samuel Benzaquenb8372482013-07-19 20:02:35 +0000425 Error->toString());
Samuel Benzaquen4adca622013-08-28 18:42:04 +0000426
427 // Bad argument type with variadic.
428 Error.reset(new Diagnostics());
Yaron Keren5b816062015-07-06 08:47:15 +0000429 EXPECT_TRUE(constructMatcher("anyOf", StringRef(), StringRef(),
Samuel Benzaquen4d058742013-11-22 14:41:48 +0000430 Error.get()).isNull());
Samuel Benzaquen4adca622013-08-28 18:42:04 +0000431 EXPECT_EQ(
432 "Incorrect type for arg 1. (Expected = Matcher<>) != (Actual = String)",
433 Error->toString());
434 Error.reset(new Diagnostics());
435 EXPECT_TRUE(constructMatcher(
Aaron Ballman512fb642015-09-17 13:30:52 +0000436 "cxxRecordDecl",
Samuel Benzaquen4adca622013-08-28 18:42:04 +0000437 constructMatcher("allOf",
Yaron Keren5b816062015-07-06 08:47:15 +0000438 constructMatcher("isDerivedFrom", StringRef("FOO")),
Samuel Benzaquen4adca622013-08-28 18:42:04 +0000439 constructMatcher("isArrow")),
440 Error.get()).isNull());
441 EXPECT_EQ("Incorrect type for arg 1. "
442 "(Expected = Matcher<CXXRecordDecl>) != "
443 "(Actual = Matcher<CXXRecordDecl>&Matcher<MemberExpr>)",
444 Error->toString());
Manuel Klimek24db0f02013-05-14 09:13:00 +0000445}
446
Peter Collingbourned32e28c2014-01-23 22:48:38 +0000447TEST_F(RegistryTest, Completion) {
448 CompVector Comps = getCompletions();
Samuel Benzaquenb63c2512014-10-09 22:08:52 +0000449 // Overloaded
Benjamin Kramere8c51fd2015-10-21 10:07:26 +0000450 EXPECT_TRUE(hasCompletion(
Benjamin Kramer94355ae2015-10-23 09:04:55 +0000451 Comps, "hasParent(",
452 "Matcher<TemplateArgument|NestedNameSpecifierLoc|Decl|...> "
453 "hasParent(Matcher<TemplateArgument|NestedNameSpecifierLoc|Decl|...>)"));
Samuel Benzaquenb63c2512014-10-09 22:08:52 +0000454 // Variadic.
Peter Collingbourned32e28c2014-01-23 22:48:38 +0000455 EXPECT_TRUE(hasCompletion(Comps, "whileStmt(",
456 "Matcher<Stmt> whileStmt(Matcher<WhileStmt>...)"));
Samuel Benzaquenb63c2512014-10-09 22:08:52 +0000457 // Polymorphic.
458 EXPECT_TRUE(hasCompletion(
459 Comps, "hasDescendant(",
Benjamin Kramer998039e2015-10-21 16:33:15 +0000460 "Matcher<TemplateArgument|NestedNameSpecifier|NestedNameSpecifierLoc|...>"
461 " hasDescendant(Matcher<TemplateArgument|NestedNameSpecifier|"
Samuel Benzaquenb63c2512014-10-09 22:08:52 +0000462 "NestedNameSpecifierLoc|...>)"));
Peter Collingbourned32e28c2014-01-23 22:48:38 +0000463
464 CompVector WhileComps = getCompletions("whileStmt", 0);
465
Peter Collingbourned32e28c2014-01-23 22:48:38 +0000466 EXPECT_TRUE(hasCompletion(WhileComps, "hasBody(",
Samuel Benzaquen646f23b2014-08-12 21:11:37 +0000467 "Matcher<WhileStmt> hasBody(Matcher<Stmt>)"));
Benjamin Kramere8c51fd2015-10-21 10:07:26 +0000468 EXPECT_TRUE(hasCompletion(WhileComps, "hasParent(",
Benjamin Kramer94355ae2015-10-23 09:04:55 +0000469 "Matcher<Stmt> "
470 "hasParent(Matcher<TemplateArgument|"
471 "NestedNameSpecifierLoc|Decl|...>)"));
Samuel Benzaquen646f23b2014-08-12 21:11:37 +0000472 EXPECT_TRUE(
473 hasCompletion(WhileComps, "allOf(", "Matcher<T> allOf(Matcher<T>...)"));
Peter Collingbourned32e28c2014-01-23 22:48:38 +0000474
475 EXPECT_FALSE(hasCompletion(WhileComps, "whileStmt("));
476 EXPECT_FALSE(hasCompletion(WhileComps, "ifStmt("));
477
478 CompVector AllOfWhileComps =
479 getCompletions("allOf", 0, "whileStmt", 0);
480 ASSERT_EQ(AllOfWhileComps.size(), WhileComps.size());
481 EXPECT_TRUE(std::equal(WhileComps.begin(), WhileComps.end(),
482 AllOfWhileComps.begin()));
483
484 CompVector DeclWhileComps =
485 getCompletions("decl", 0, "whileStmt", 0);
486 EXPECT_EQ(0u, DeclWhileComps.size());
487
488 CompVector NamedDeclComps = getCompletions("namedDecl", 0);
489 EXPECT_TRUE(
490 hasCompletion(NamedDeclComps, "isPublic()", "Matcher<Decl> isPublic()"));
491 EXPECT_TRUE(hasCompletion(NamedDeclComps, "hasName(\"",
492 "Matcher<NamedDecl> hasName(string)"));
Samuel Benzaquenb63c2512014-10-09 22:08:52 +0000493
494 // Heterogeneous overloads.
495 Comps = getCompletions("classTemplateSpecializationDecl", 0);
496 EXPECT_TRUE(hasCompletion(
497 Comps, "isSameOrDerivedFrom(",
498 "Matcher<CXXRecordDecl> isSameOrDerivedFrom(string|Matcher<NamedDecl>)"));
Peter Collingbourned32e28c2014-01-23 22:48:38 +0000499}
500
Manuel Klimek3fe8a382014-08-25 11:23:50 +0000501TEST_F(RegistryTest, HasArgs) {
502 Matcher<Decl> Value = constructMatcher(
Yaron Keren5b816062015-07-06 08:47:15 +0000503 "decl", constructMatcher("hasAttr", StringRef("attr::WarnUnused")))
Manuel Klimek3fe8a382014-08-25 11:23:50 +0000504 .getTypedMatcher<Decl>();
505 EXPECT_TRUE(matches("struct __attribute__((warn_unused)) X {};", Value));
506 EXPECT_FALSE(matches("struct X {};", Value));
507}
508
Aaron Ballmane8295d72016-01-20 16:17:39 +0000509TEST_F(RegistryTest, ParenExpr) {
510 Matcher<Stmt> Value = constructMatcher("parenExpr").getTypedMatcher<Stmt>();
511 EXPECT_TRUE(matches("int i = (1);", Value));
512 EXPECT_FALSE(matches("int i = 1;", Value));
513}
514
Manuel Klimek24db0f02013-05-14 09:13:00 +0000515} // end anonymous namespace
516} // end namespace dynamic
517} // end namespace ast_matchers
518} // end namespace clang