blob: abacb6fe7d47f42cc93f71502e3890168d1b1f66 [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,
43 Diagnostics *Error = NULL) {
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,
56 Diagnostics *Error = NULL) {
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,
70 Diagnostics *Error = NULL) {
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() {
85 return Registry::getCompletions(
86 llvm::ArrayRef<std::pair<MatcherCtor, unsigned> >());
87 }
88
89 CompVector getCompletions(StringRef MatcherName1, unsigned ArgNo1) {
90 std::vector<std::pair<MatcherCtor, unsigned> > Context;
91 llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName1);
92 if (!Ctor)
93 return CompVector();
94 Context.push_back(std::make_pair(*Ctor, ArgNo1));
95 return Registry::getCompletions(Context);
96 }
97
98 CompVector getCompletions(StringRef MatcherName1, unsigned ArgNo1,
99 StringRef MatcherName2, unsigned ArgNo2) {
100 std::vector<std::pair<MatcherCtor, unsigned> > Context;
101 llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName1);
102 if (!Ctor)
103 return CompVector();
104 Context.push_back(std::make_pair(*Ctor, ArgNo1));
105 Ctor = lookupMatcherCtor(MatcherName2);
106 if (!Ctor)
107 return CompVector();
108 Context.push_back(std::make_pair(*Ctor, ArgNo2));
109 return Registry::getCompletions(Context);
110 }
111
112 bool hasCompletion(const CompVector &Comps, StringRef TypedText,
113 StringRef MatcherDecl = StringRef(), unsigned *Index = 0) {
114 for (CompVector::const_iterator I = Comps.begin(), E = Comps.end(); I != E;
115 ++I) {
116 if (I->TypedText == TypedText &&
117 (MatcherDecl.empty() || I->MatcherDecl == MatcherDecl)) {
118 if (Index)
119 *Index = I - Comps.begin();
120 return true;
121 }
122 }
123 return false;
124 }
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000125};
126
127TEST_F(RegistryTest, CanConstructNoArgs) {
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000128 Matcher<Stmt> IsArrowValue = constructMatcher(
129 "memberExpr", constructMatcher("isArrow")).getTypedMatcher<Stmt>();
130 Matcher<Stmt> BoolValue =
131 constructMatcher("boolLiteral").getTypedMatcher<Stmt>();
Manuel Klimek24db0f02013-05-14 09:13:00 +0000132
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
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000138 EXPECT_TRUE(matches(ClassSnippet, IsArrowValue));
139 EXPECT_TRUE(matches(BoolSnippet, BoolValue));
140 EXPECT_FALSE(matches(ClassSnippet, BoolValue));
141 EXPECT_FALSE(matches(BoolSnippet, IsArrowValue));
Manuel Klimek24db0f02013-05-14 09:13:00 +0000142}
143
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000144TEST_F(RegistryTest, ConstructWithSimpleArgs) {
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000145 Matcher<Decl> Value = constructMatcher(
146 "namedDecl", constructMatcher("hasName", std::string("X")))
147 .getTypedMatcher<Decl>();
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000148 EXPECT_TRUE(matches("class X {};", Value));
149 EXPECT_FALSE(matches("int x;", Value));
Samuel Benzaquenc31b3522013-06-04 15:46:22 +0000150
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000151 Value = functionDecl(constructMatcher("parameterCountIs", 2)
152 .getTypedMatcher<FunctionDecl>());
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000153 EXPECT_TRUE(matches("void foo(int,int);", Value));
154 EXPECT_FALSE(matches("void foo(int);", Value));
Manuel Klimek24db0f02013-05-14 09:13:00 +0000155}
156
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000157TEST_F(RegistryTest, ConstructWithMatcherArgs) {
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000158 Matcher<Decl> HasInitializerSimple = constructMatcher(
159 "varDecl", constructMatcher("hasInitializer", constructMatcher("stmt")))
160 .getTypedMatcher<Decl>();
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000161 Matcher<Decl> HasInitializerComplex = constructMatcher(
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000162 "varDecl",
163 constructMatcher("hasInitializer", constructMatcher("callExpr")))
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000164 .getTypedMatcher<Decl>();
Manuel Klimek24db0f02013-05-14 09:13:00 +0000165
166 std::string code = "int i;";
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000167 EXPECT_FALSE(matches(code, HasInitializerSimple));
168 EXPECT_FALSE(matches(code, HasInitializerComplex));
Manuel Klimek24db0f02013-05-14 09:13:00 +0000169
170 code = "int i = 1;";
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000171 EXPECT_TRUE(matches(code, HasInitializerSimple));
172 EXPECT_FALSE(matches(code, HasInitializerComplex));
Manuel Klimek24db0f02013-05-14 09:13:00 +0000173
174 code = "int y(); int i = y();";
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000175 EXPECT_TRUE(matches(code, HasInitializerSimple));
176 EXPECT_TRUE(matches(code, HasInitializerComplex));
Samuel Benzaquenc31b3522013-06-04 15:46:22 +0000177
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000178 Matcher<Decl> HasParameter =
179 functionDecl(constructMatcher(
180 "hasParameter", 1, constructMatcher("hasName", std::string("x")))
181 .getTypedMatcher<FunctionDecl>());
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000182 EXPECT_TRUE(matches("void f(int a, int x);", HasParameter));
183 EXPECT_FALSE(matches("void f(int x, int a);", HasParameter));
Manuel Klimek24db0f02013-05-14 09:13:00 +0000184}
185
Samuel Benzaquene0b2c8e2013-07-22 16:13:57 +0000186TEST_F(RegistryTest, OverloadedMatchers) {
187 Matcher<Stmt> CallExpr0 = constructMatcher(
188 "callExpr",
189 constructMatcher("callee", constructMatcher("memberExpr",
190 constructMatcher("isArrow"))))
191 .getTypedMatcher<Stmt>();
192
193 Matcher<Stmt> CallExpr1 = constructMatcher(
194 "callExpr",
195 constructMatcher(
196 "callee",
197 constructMatcher("methodDecl",
198 constructMatcher("hasName", std::string("x")))))
199 .getTypedMatcher<Stmt>();
200
201 std::string Code = "class Y { public: void x(); }; void z() { Y y; y.x(); }";
202 EXPECT_FALSE(matches(Code, CallExpr0));
203 EXPECT_TRUE(matches(Code, CallExpr1));
204
205 Code = "class Z { public: void z() { this->z(); } };";
206 EXPECT_TRUE(matches(Code, CallExpr0));
207 EXPECT_FALSE(matches(Code, CallExpr1));
Samuel Benzaquena0839352014-03-10 15:40:23 +0000208
209 Matcher<Decl> DeclDecl = declaratorDecl(hasTypeLoc(
210 constructMatcher(
211 "loc", constructMatcher("asString", std::string("const double *")))
212 .getTypedMatcher<TypeLoc>()));
213
214 Matcher<NestedNameSpecifierLoc> NNSL =
215 constructMatcher(
216 "loc", VariantMatcher::SingleMatcher(nestedNameSpecifier(
217 specifiesType(hasDeclaration(recordDecl(hasName("A")))))))
218 .getTypedMatcher<NestedNameSpecifierLoc>();
219
220 Code = "const double * x = 0;";
221 EXPECT_TRUE(matches(Code, DeclDecl));
222 EXPECT_FALSE(matches(Code, NNSL));
223
224 Code = "struct A { struct B {}; }; A::B a_b;";
225 EXPECT_FALSE(matches(Code, DeclDecl));
226 EXPECT_TRUE(matches(Code, NNSL));
Samuel Benzaquene0b2c8e2013-07-22 16:13:57 +0000227}
228
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000229TEST_F(RegistryTest, PolymorphicMatchers) {
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000230 const VariantMatcher IsDefinition = constructMatcher("isDefinition");
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000231 Matcher<Decl> Var =
232 constructMatcher("varDecl", IsDefinition).getTypedMatcher<Decl>();
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000233 Matcher<Decl> Class =
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000234 constructMatcher("recordDecl", IsDefinition).getTypedMatcher<Decl>();
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000235 Matcher<Decl> Func =
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000236 constructMatcher("functionDecl", IsDefinition).getTypedMatcher<Decl>();
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000237 EXPECT_TRUE(matches("int a;", Var));
238 EXPECT_FALSE(matches("extern int a;", Var));
239 EXPECT_TRUE(matches("class A {};", Class));
240 EXPECT_FALSE(matches("class A;", Class));
241 EXPECT_TRUE(matches("void f(){};", Func));
242 EXPECT_FALSE(matches("void f();", Func));
243
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000244 Matcher<Decl> Anything = constructMatcher("anything").getTypedMatcher<Decl>();
Samuel Benzaquen68cd3962013-08-29 15:39:26 +0000245 Matcher<Decl> RecordDecl = constructMatcher(
246 "recordDecl", constructMatcher("hasName", std::string("Foo")),
247 VariantMatcher::SingleMatcher(Anything)).getTypedMatcher<Decl>();
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000248
Samuel Benzaquen68cd3962013-08-29 15:39:26 +0000249 EXPECT_TRUE(matches("int Foo;", Anything));
250 EXPECT_TRUE(matches("class Foo {};", Anything));
251 EXPECT_TRUE(matches("void Foo(){};", Anything));
252 EXPECT_FALSE(matches("int Foo;", RecordDecl));
253 EXPECT_TRUE(matches("class Foo {};", RecordDecl));
254 EXPECT_FALSE(matches("void Foo(){};", RecordDecl));
Samuel Benzaquen464c1cb2013-11-18 14:53:42 +0000255
256 Matcher<Stmt> ConstructExpr = constructMatcher(
257 "constructExpr",
258 constructMatcher(
259 "hasDeclaration",
260 constructMatcher(
261 "methodDecl",
262 constructMatcher(
263 "ofClass", constructMatcher("hasName", std::string("Foo"))))))
264 .getTypedMatcher<Stmt>();
265 EXPECT_FALSE(matches("class Foo { public: Foo(); };", ConstructExpr));
266 EXPECT_TRUE(
267 matches("class Foo { public: Foo(); }; Foo foo = Foo();", ConstructExpr));
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000268}
269
Samuel Benzaquen21b3da02013-07-17 15:11:30 +0000270TEST_F(RegistryTest, TemplateArgument) {
271 Matcher<Decl> HasTemplateArgument = constructMatcher(
272 "classTemplateSpecializationDecl",
273 constructMatcher(
274 "hasAnyTemplateArgument",
275 constructMatcher("refersToType",
276 constructMatcher("asString", std::string("int")))))
277 .getTypedMatcher<Decl>();
278 EXPECT_TRUE(matches("template<typename T> class A {}; A<int> a;",
279 HasTemplateArgument));
280 EXPECT_FALSE(matches("template<typename T> class A {}; A<char> a;",
281 HasTemplateArgument));
282}
283
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000284TEST_F(RegistryTest, TypeTraversal) {
285 Matcher<Type> M = constructMatcher(
286 "pointerType",
287 constructMatcher("pointee", constructMatcher("isConstQualified"),
288 constructMatcher("isInteger"))).getTypedMatcher<Type>();
289 EXPECT_FALSE(matches("int *a;", M));
290 EXPECT_TRUE(matches("int const *b;", M));
291
292 M = constructMatcher(
293 "arrayType",
294 constructMatcher("hasElementType", constructMatcher("builtinType")))
295 .getTypedMatcher<Type>();
296 EXPECT_FALSE(matches("struct A{}; A a[7];;", M));
297 EXPECT_TRUE(matches("int b[7];", M));
298}
299
Samuel Benzaquen06e056c2013-07-17 14:28:00 +0000300TEST_F(RegistryTest, CXXCtorInitializer) {
301 Matcher<Decl> CtorDecl = constructMatcher(
302 "constructorDecl",
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000303 constructMatcher(
304 "hasAnyConstructorInitializer",
305 constructMatcher("forField",
306 constructMatcher("hasName", std::string("foo")))))
Samuel Benzaquen06e056c2013-07-17 14:28:00 +0000307 .getTypedMatcher<Decl>();
308 EXPECT_TRUE(matches("struct Foo { Foo() : foo(1) {} int foo; };", CtorDecl));
309 EXPECT_FALSE(matches("struct Foo { Foo() {} int foo; };", CtorDecl));
310 EXPECT_FALSE(matches("struct Foo { Foo() : bar(1) {} int bar; };", CtorDecl));
311}
312
Samuel Benzaquen7f8a5b12013-07-24 14:48:01 +0000313TEST_F(RegistryTest, Adaptative) {
314 Matcher<Decl> D = constructMatcher(
315 "recordDecl",
316 constructMatcher(
317 "has",
318 constructMatcher("recordDecl",
319 constructMatcher("hasName", std::string("X")))))
320 .getTypedMatcher<Decl>();
321 EXPECT_TRUE(matches("class X {};", D));
322 EXPECT_TRUE(matches("class Y { class X {}; };", D));
323 EXPECT_FALSE(matches("class Y { class Z {}; };", D));
324
325 Matcher<Stmt> S = constructMatcher(
326 "forStmt",
327 constructMatcher(
328 "hasDescendant",
329 constructMatcher("varDecl",
330 constructMatcher("hasName", std::string("X")))))
331 .getTypedMatcher<Stmt>();
332 EXPECT_TRUE(matches("void foo() { for(int X;;); }", S));
333 EXPECT_TRUE(matches("void foo() { for(;;) { int X; } }", S));
334 EXPECT_FALSE(matches("void foo() { for(;;); }", S));
335 EXPECT_FALSE(matches("void foo() { if (int X = 0){} }", S));
336
337 S = constructMatcher(
338 "compoundStmt", constructMatcher("hasParent", constructMatcher("ifStmt")))
339 .getTypedMatcher<Stmt>();
340 EXPECT_TRUE(matches("void foo() { if (true) { int x = 42; } }", S));
341 EXPECT_FALSE(matches("void foo() { if (true) return; }", S));
342}
343
Samuel Benzaquen4adca622013-08-28 18:42:04 +0000344TEST_F(RegistryTest, VariadicOp) {
345 Matcher<Decl> D = constructMatcher(
Samuel Benzaquen68cd3962013-08-29 15:39:26 +0000346 "anyOf",
347 constructMatcher("recordDecl",
348 constructMatcher("hasName", std::string("Foo"))),
Samuel Benzaquen4adca622013-08-28 18:42:04 +0000349 constructMatcher("namedDecl",
350 constructMatcher("hasName", std::string("foo"))))
351 .getTypedMatcher<Decl>();
352
353 EXPECT_TRUE(matches("void foo(){}", D));
354 EXPECT_TRUE(matches("struct Foo{};", D));
355 EXPECT_FALSE(matches("int i = 0;", D));
356
357 D = constructMatcher(
358 "allOf", constructMatcher("recordDecl"),
359 constructMatcher(
360 "namedDecl",
361 constructMatcher("anyOf",
362 constructMatcher("hasName", std::string("Foo")),
363 constructMatcher("hasName", std::string("Bar")))))
364 .getTypedMatcher<Decl>();
365
366 EXPECT_FALSE(matches("void foo(){}", D));
367 EXPECT_TRUE(matches("struct Foo{};", D));
368 EXPECT_FALSE(matches("int i = 0;", D));
369 EXPECT_TRUE(matches("class Bar{};", D));
370 EXPECT_FALSE(matches("class OtherBar{};", D));
Samuel Benzaquen4d058742013-11-22 14:41:48 +0000371
Samuel Benzaquenef77f3c2013-11-22 23:05:57 +0000372 D = recordDecl(
373 has(fieldDecl(hasName("Foo"))),
Samuel Benzaquen4d058742013-11-22 14:41:48 +0000374 constructMatcher(
375 "unless",
376 constructMatcher("namedDecl",
Samuel Benzaquenef77f3c2013-11-22 23:05:57 +0000377 constructMatcher("hasName", std::string("Bar"))))
378 .getTypedMatcher<Decl>());
Samuel Benzaquen4d058742013-11-22 14:41:48 +0000379
Samuel Benzaquenef77f3c2013-11-22 23:05:57 +0000380 EXPECT_FALSE(matches("class Bar{ int Foo; };", D));
381 EXPECT_TRUE(matches("class OtherBar{ int Foo; };", D));
Samuel Benzaquen4adca622013-08-28 18:42:04 +0000382}
383
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000384TEST_F(RegistryTest, Errors) {
Manuel Klimek24db0f02013-05-14 09:13:00 +0000385 // Incorrect argument count.
Ahmed Charlesb8984322014-03-07 20:03:18 +0000386 std::unique_ptr<Diagnostics> Error(new Diagnostics());
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000387 EXPECT_TRUE(constructMatcher("hasInitializer", Error.get()).isNull());
Manuel Klimek24db0f02013-05-14 09:13:00 +0000388 EXPECT_EQ("Incorrect argument count. (Expected = 1) != (Actual = 0)",
Samuel Benzaquenb8372482013-07-19 20:02:35 +0000389 Error->toString());
Manuel Klimek24db0f02013-05-14 09:13:00 +0000390 Error.reset(new Diagnostics());
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000391 EXPECT_TRUE(constructMatcher("isArrow", std::string(), Error.get()).isNull());
Manuel Klimek24db0f02013-05-14 09:13:00 +0000392 EXPECT_EQ("Incorrect argument count. (Expected = 0) != (Actual = 1)",
Samuel Benzaquenb8372482013-07-19 20:02:35 +0000393 Error->toString());
Samuel Benzaquen4d058742013-11-22 14:41:48 +0000394 Error.reset(new Diagnostics());
395 EXPECT_TRUE(constructMatcher("anyOf", Error.get()).isNull());
396 EXPECT_EQ("Incorrect argument count. (Expected = (2, )) != (Actual = 0)",
397 Error->toString());
398 Error.reset(new Diagnostics());
399 EXPECT_TRUE(constructMatcher("unless", std::string(), std::string(),
400 Error.get()).isNull());
401 EXPECT_EQ("Incorrect argument count. (Expected = (1, 1)) != (Actual = 2)",
402 Error->toString());
Manuel Klimek24db0f02013-05-14 09:13:00 +0000403
404 // Bad argument type
405 Error.reset(new Diagnostics());
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000406 EXPECT_TRUE(constructMatcher("ofClass", std::string(), Error.get()).isNull());
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000407 EXPECT_EQ("Incorrect type for arg 1. (Expected = Matcher<CXXRecordDecl>) != "
408 "(Actual = String)",
Samuel Benzaquenb8372482013-07-19 20:02:35 +0000409 Error->toString());
Manuel Klimek24db0f02013-05-14 09:13:00 +0000410 Error.reset(new Diagnostics());
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000411 EXPECT_TRUE(constructMatcher("recordDecl", constructMatcher("recordDecl"),
412 constructMatcher("parameterCountIs", 3),
413 Error.get()).isNull());
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000414 EXPECT_EQ("Incorrect type for arg 2. (Expected = Matcher<CXXRecordDecl>) != "
415 "(Actual = Matcher<FunctionDecl>)",
Samuel Benzaquenb8372482013-07-19 20:02:35 +0000416 Error->toString());
Samuel Benzaquen4adca622013-08-28 18:42:04 +0000417
418 // Bad argument type with variadic.
419 Error.reset(new Diagnostics());
Samuel Benzaquen4d058742013-11-22 14:41:48 +0000420 EXPECT_TRUE(constructMatcher("anyOf", std::string(), std::string(),
421 Error.get()).isNull());
Samuel Benzaquen4adca622013-08-28 18:42:04 +0000422 EXPECT_EQ(
423 "Incorrect type for arg 1. (Expected = Matcher<>) != (Actual = String)",
424 Error->toString());
425 Error.reset(new Diagnostics());
426 EXPECT_TRUE(constructMatcher(
427 "recordDecl",
428 constructMatcher("allOf",
429 constructMatcher("isDerivedFrom", std::string("FOO")),
430 constructMatcher("isArrow")),
431 Error.get()).isNull());
432 EXPECT_EQ("Incorrect type for arg 1. "
433 "(Expected = Matcher<CXXRecordDecl>) != "
434 "(Actual = Matcher<CXXRecordDecl>&Matcher<MemberExpr>)",
435 Error->toString());
Manuel Klimek24db0f02013-05-14 09:13:00 +0000436}
437
Peter Collingbourned32e28c2014-01-23 22:48:38 +0000438TEST_F(RegistryTest, Completion) {
439 CompVector Comps = getCompletions();
440 EXPECT_TRUE(hasCompletion(
441 Comps, "hasParent(", "Matcher<Decl|Stmt> hasParent(Matcher<Decl|Stmt>)"));
442 EXPECT_TRUE(hasCompletion(Comps, "whileStmt(",
443 "Matcher<Stmt> whileStmt(Matcher<WhileStmt>...)"));
444
445 CompVector WhileComps = getCompletions("whileStmt", 0);
446
447 unsigned HasBodyIndex, HasParentIndex, AllOfIndex;
448 EXPECT_TRUE(hasCompletion(WhileComps, "hasBody(",
449 "Matcher<WhileStmt> hasBody(Matcher<Stmt>)",
450 &HasBodyIndex));
451 EXPECT_TRUE(hasCompletion(WhileComps, "hasParent(",
452 "Matcher<Stmt> hasParent(Matcher<Decl|Stmt>)",
453 &HasParentIndex));
454 EXPECT_TRUE(hasCompletion(WhileComps, "allOf(",
455 "Matcher<T> allOf(Matcher<T>...)", &AllOfIndex));
456 EXPECT_GT(HasParentIndex, HasBodyIndex);
457 EXPECT_GT(AllOfIndex, HasParentIndex);
458
459 EXPECT_FALSE(hasCompletion(WhileComps, "whileStmt("));
460 EXPECT_FALSE(hasCompletion(WhileComps, "ifStmt("));
461
462 CompVector AllOfWhileComps =
463 getCompletions("allOf", 0, "whileStmt", 0);
464 ASSERT_EQ(AllOfWhileComps.size(), WhileComps.size());
465 EXPECT_TRUE(std::equal(WhileComps.begin(), WhileComps.end(),
466 AllOfWhileComps.begin()));
467
468 CompVector DeclWhileComps =
469 getCompletions("decl", 0, "whileStmt", 0);
470 EXPECT_EQ(0u, DeclWhileComps.size());
471
472 CompVector NamedDeclComps = getCompletions("namedDecl", 0);
473 EXPECT_TRUE(
474 hasCompletion(NamedDeclComps, "isPublic()", "Matcher<Decl> isPublic()"));
475 EXPECT_TRUE(hasCompletion(NamedDeclComps, "hasName(\"",
476 "Matcher<NamedDecl> hasName(string)"));
477}
478
Manuel Klimek24db0f02013-05-14 09:13:00 +0000479} // end anonymous namespace
480} // end namespace dynamic
481} // end namespace ast_matchers
482} // end namespace clang