blob: 8426649d3e6589a49a671aa119fdcba687ace1c8 [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
Peter Collingbourne00cba4f2013-11-23 01:13:16 +000038 llvm::Optional<MatcherCtor> lookupMatcherCtor(StringRef MatcherName,
39 Diagnostics *Error = 0) {
40 Diagnostics DummyError;
41 if (!Error) Error = &DummyError;
42 llvm::Optional<MatcherCtor> Ctor =
43 Registry::lookupMatcherCtor(MatcherName, SourceRange(), Error);
44 EXPECT_EQ("", DummyError.toStringFull());
45 return Ctor;
46 }
47
Samuel Benzaquen0239b692013-08-13 14:54:51 +000048 VariantMatcher constructMatcher(StringRef MatcherName,
49 Diagnostics *Error = NULL) {
Samuel Benzaquen79656e12013-07-15 19:25:06 +000050 Diagnostics DummyError;
51 if (!Error) Error = &DummyError;
Peter Collingbourne00cba4f2013-11-23 01:13:16 +000052 llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName, Error);
53 VariantMatcher Out;
54 if (Ctor)
55 Out = Registry::constructMatcher(*Ctor, SourceRange(), Args(), Error);
Samuel Benzaquenb8372482013-07-19 20:02:35 +000056 EXPECT_EQ("", DummyError.toStringFull());
Samuel Benzaquen79656e12013-07-15 19:25:06 +000057 return Out;
Samuel Benzaquen81ef9292013-06-20 14:28:32 +000058 }
Manuel Klimek24db0f02013-05-14 09:13:00 +000059
Samuel Benzaquen0239b692013-08-13 14:54:51 +000060 VariantMatcher constructMatcher(StringRef MatcherName,
61 const VariantValue &Arg1,
62 Diagnostics *Error = NULL) {
Samuel Benzaquen79656e12013-07-15 19:25:06 +000063 Diagnostics DummyError;
64 if (!Error) Error = &DummyError;
Peter Collingbourne00cba4f2013-11-23 01:13:16 +000065 llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName, Error);
66 VariantMatcher Out;
67 if (Ctor)
68 Out = Registry::constructMatcher(*Ctor, SourceRange(), Args(Arg1), Error);
Samuel Benzaquenb8372482013-07-19 20:02:35 +000069 EXPECT_EQ("", DummyError.toStringFull());
Samuel Benzaquen79656e12013-07-15 19:25:06 +000070 return Out;
Samuel Benzaquen81ef9292013-06-20 14:28:32 +000071 }
Manuel Klimek24db0f02013-05-14 09:13:00 +000072
Samuel Benzaquen0239b692013-08-13 14:54:51 +000073 VariantMatcher constructMatcher(StringRef MatcherName,
74 const VariantValue &Arg1,
75 const VariantValue &Arg2,
76 Diagnostics *Error = NULL) {
Samuel Benzaquen79656e12013-07-15 19:25:06 +000077 Diagnostics DummyError;
78 if (!Error) Error = &DummyError;
Peter Collingbourne00cba4f2013-11-23 01:13:16 +000079 llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName, Error);
80 VariantMatcher Out;
81 if (Ctor)
82 Out = Registry::constructMatcher(*Ctor, SourceRange(), Args(Arg1, Arg2),
83 Error);
Samuel Benzaquenb8372482013-07-19 20:02:35 +000084 EXPECT_EQ("", DummyError.toStringFull());
Samuel Benzaquen79656e12013-07-15 19:25:06 +000085 return Out;
Samuel Benzaquen81ef9292013-06-20 14:28:32 +000086 }
Peter Collingbourned32e28c2014-01-23 22:48:38 +000087
88 typedef std::vector<MatcherCompletion> CompVector;
89
90 CompVector getCompletions() {
91 return Registry::getCompletions(
92 llvm::ArrayRef<std::pair<MatcherCtor, unsigned> >());
93 }
94
95 CompVector getCompletions(StringRef MatcherName1, unsigned ArgNo1) {
96 std::vector<std::pair<MatcherCtor, unsigned> > Context;
97 llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName1);
98 if (!Ctor)
99 return CompVector();
100 Context.push_back(std::make_pair(*Ctor, ArgNo1));
101 return Registry::getCompletions(Context);
102 }
103
104 CompVector getCompletions(StringRef MatcherName1, unsigned ArgNo1,
105 StringRef MatcherName2, unsigned ArgNo2) {
106 std::vector<std::pair<MatcherCtor, unsigned> > Context;
107 llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName1);
108 if (!Ctor)
109 return CompVector();
110 Context.push_back(std::make_pair(*Ctor, ArgNo1));
111 Ctor = lookupMatcherCtor(MatcherName2);
112 if (!Ctor)
113 return CompVector();
114 Context.push_back(std::make_pair(*Ctor, ArgNo2));
115 return Registry::getCompletions(Context);
116 }
117
118 bool hasCompletion(const CompVector &Comps, StringRef TypedText,
119 StringRef MatcherDecl = StringRef(), unsigned *Index = 0) {
120 for (CompVector::const_iterator I = Comps.begin(), E = Comps.end(); I != E;
121 ++I) {
122 if (I->TypedText == TypedText &&
123 (MatcherDecl.empty() || I->MatcherDecl == MatcherDecl)) {
124 if (Index)
125 *Index = I - Comps.begin();
126 return true;
127 }
128 }
129 return false;
130 }
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000131};
132
133TEST_F(RegistryTest, CanConstructNoArgs) {
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000134 Matcher<Stmt> IsArrowValue = constructMatcher(
135 "memberExpr", constructMatcher("isArrow")).getTypedMatcher<Stmt>();
136 Matcher<Stmt> BoolValue =
137 constructMatcher("boolLiteral").getTypedMatcher<Stmt>();
Manuel Klimek24db0f02013-05-14 09:13:00 +0000138
139 const std::string ClassSnippet = "struct Foo { int x; };\n"
140 "Foo *foo = new Foo;\n"
141 "int i = foo->x;\n";
142 const std::string BoolSnippet = "bool Foo = true;\n";
143
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000144 EXPECT_TRUE(matches(ClassSnippet, IsArrowValue));
145 EXPECT_TRUE(matches(BoolSnippet, BoolValue));
146 EXPECT_FALSE(matches(ClassSnippet, BoolValue));
147 EXPECT_FALSE(matches(BoolSnippet, IsArrowValue));
Manuel Klimek24db0f02013-05-14 09:13:00 +0000148}
149
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000150TEST_F(RegistryTest, ConstructWithSimpleArgs) {
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000151 Matcher<Decl> Value = constructMatcher(
152 "namedDecl", constructMatcher("hasName", std::string("X")))
153 .getTypedMatcher<Decl>();
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000154 EXPECT_TRUE(matches("class X {};", Value));
155 EXPECT_FALSE(matches("int x;", Value));
Samuel Benzaquenc31b3522013-06-04 15:46:22 +0000156
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000157 Value = functionDecl(constructMatcher("parameterCountIs", 2)
158 .getTypedMatcher<FunctionDecl>());
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000159 EXPECT_TRUE(matches("void foo(int,int);", Value));
160 EXPECT_FALSE(matches("void foo(int);", Value));
Manuel Klimek24db0f02013-05-14 09:13:00 +0000161}
162
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000163TEST_F(RegistryTest, ConstructWithMatcherArgs) {
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000164 Matcher<Decl> HasInitializerSimple = constructMatcher(
165 "varDecl", constructMatcher("hasInitializer", constructMatcher("stmt")))
166 .getTypedMatcher<Decl>();
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000167 Matcher<Decl> HasInitializerComplex = constructMatcher(
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000168 "varDecl",
169 constructMatcher("hasInitializer", constructMatcher("callExpr")))
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000170 .getTypedMatcher<Decl>();
Manuel Klimek24db0f02013-05-14 09:13:00 +0000171
172 std::string code = "int i;";
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000173 EXPECT_FALSE(matches(code, HasInitializerSimple));
174 EXPECT_FALSE(matches(code, HasInitializerComplex));
Manuel Klimek24db0f02013-05-14 09:13:00 +0000175
176 code = "int i = 1;";
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000177 EXPECT_TRUE(matches(code, HasInitializerSimple));
178 EXPECT_FALSE(matches(code, HasInitializerComplex));
Manuel Klimek24db0f02013-05-14 09:13:00 +0000179
180 code = "int y(); int i = y();";
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000181 EXPECT_TRUE(matches(code, HasInitializerSimple));
182 EXPECT_TRUE(matches(code, HasInitializerComplex));
Samuel Benzaquenc31b3522013-06-04 15:46:22 +0000183
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000184 Matcher<Decl> HasParameter =
185 functionDecl(constructMatcher(
186 "hasParameter", 1, constructMatcher("hasName", std::string("x")))
187 .getTypedMatcher<FunctionDecl>());
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000188 EXPECT_TRUE(matches("void f(int a, int x);", HasParameter));
189 EXPECT_FALSE(matches("void f(int x, int a);", HasParameter));
Manuel Klimek24db0f02013-05-14 09:13:00 +0000190}
191
Samuel Benzaquene0b2c8e2013-07-22 16:13:57 +0000192TEST_F(RegistryTest, OverloadedMatchers) {
193 Matcher<Stmt> CallExpr0 = constructMatcher(
194 "callExpr",
195 constructMatcher("callee", constructMatcher("memberExpr",
196 constructMatcher("isArrow"))))
197 .getTypedMatcher<Stmt>();
198
199 Matcher<Stmt> CallExpr1 = constructMatcher(
200 "callExpr",
201 constructMatcher(
202 "callee",
203 constructMatcher("methodDecl",
204 constructMatcher("hasName", std::string("x")))))
205 .getTypedMatcher<Stmt>();
206
207 std::string Code = "class Y { public: void x(); }; void z() { Y y; y.x(); }";
208 EXPECT_FALSE(matches(Code, CallExpr0));
209 EXPECT_TRUE(matches(Code, CallExpr1));
210
211 Code = "class Z { public: void z() { this->z(); } };";
212 EXPECT_TRUE(matches(Code, CallExpr0));
213 EXPECT_FALSE(matches(Code, CallExpr1));
214}
215
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000216TEST_F(RegistryTest, PolymorphicMatchers) {
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000217 const VariantMatcher IsDefinition = constructMatcher("isDefinition");
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000218 Matcher<Decl> Var =
219 constructMatcher("varDecl", IsDefinition).getTypedMatcher<Decl>();
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000220 Matcher<Decl> Class =
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000221 constructMatcher("recordDecl", IsDefinition).getTypedMatcher<Decl>();
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000222 Matcher<Decl> Func =
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000223 constructMatcher("functionDecl", IsDefinition).getTypedMatcher<Decl>();
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000224 EXPECT_TRUE(matches("int a;", Var));
225 EXPECT_FALSE(matches("extern int a;", Var));
226 EXPECT_TRUE(matches("class A {};", Class));
227 EXPECT_FALSE(matches("class A;", Class));
228 EXPECT_TRUE(matches("void f(){};", Func));
229 EXPECT_FALSE(matches("void f();", Func));
230
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000231 Matcher<Decl> Anything = constructMatcher("anything").getTypedMatcher<Decl>();
Samuel Benzaquen68cd3962013-08-29 15:39:26 +0000232 Matcher<Decl> RecordDecl = constructMatcher(
233 "recordDecl", constructMatcher("hasName", std::string("Foo")),
234 VariantMatcher::SingleMatcher(Anything)).getTypedMatcher<Decl>();
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000235
Samuel Benzaquen68cd3962013-08-29 15:39:26 +0000236 EXPECT_TRUE(matches("int Foo;", Anything));
237 EXPECT_TRUE(matches("class Foo {};", Anything));
238 EXPECT_TRUE(matches("void Foo(){};", Anything));
239 EXPECT_FALSE(matches("int Foo;", RecordDecl));
240 EXPECT_TRUE(matches("class Foo {};", RecordDecl));
241 EXPECT_FALSE(matches("void Foo(){};", RecordDecl));
Samuel Benzaquen464c1cb2013-11-18 14:53:42 +0000242
243 Matcher<Stmt> ConstructExpr = constructMatcher(
244 "constructExpr",
245 constructMatcher(
246 "hasDeclaration",
247 constructMatcher(
248 "methodDecl",
249 constructMatcher(
250 "ofClass", constructMatcher("hasName", std::string("Foo"))))))
251 .getTypedMatcher<Stmt>();
252 EXPECT_FALSE(matches("class Foo { public: Foo(); };", ConstructExpr));
253 EXPECT_TRUE(
254 matches("class Foo { public: Foo(); }; Foo foo = Foo();", ConstructExpr));
Samuel Benzaquenc6f2c9b2013-06-21 15:51:31 +0000255}
256
Samuel Benzaquen21b3da02013-07-17 15:11:30 +0000257TEST_F(RegistryTest, TemplateArgument) {
258 Matcher<Decl> HasTemplateArgument = constructMatcher(
259 "classTemplateSpecializationDecl",
260 constructMatcher(
261 "hasAnyTemplateArgument",
262 constructMatcher("refersToType",
263 constructMatcher("asString", std::string("int")))))
264 .getTypedMatcher<Decl>();
265 EXPECT_TRUE(matches("template<typename T> class A {}; A<int> a;",
266 HasTemplateArgument));
267 EXPECT_FALSE(matches("template<typename T> class A {}; A<char> a;",
268 HasTemplateArgument));
269}
270
Samuel Benzaquen79656e12013-07-15 19:25:06 +0000271TEST_F(RegistryTest, TypeTraversal) {
272 Matcher<Type> M = constructMatcher(
273 "pointerType",
274 constructMatcher("pointee", constructMatcher("isConstQualified"),
275 constructMatcher("isInteger"))).getTypedMatcher<Type>();
276 EXPECT_FALSE(matches("int *a;", M));
277 EXPECT_TRUE(matches("int const *b;", M));
278
279 M = constructMatcher(
280 "arrayType",
281 constructMatcher("hasElementType", constructMatcher("builtinType")))
282 .getTypedMatcher<Type>();
283 EXPECT_FALSE(matches("struct A{}; A a[7];;", M));
284 EXPECT_TRUE(matches("int b[7];", M));
285}
286
Samuel Benzaquen06e056c2013-07-17 14:28:00 +0000287TEST_F(RegistryTest, CXXCtorInitializer) {
288 Matcher<Decl> CtorDecl = constructMatcher(
289 "constructorDecl",
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000290 constructMatcher(
291 "hasAnyConstructorInitializer",
292 constructMatcher("forField",
293 constructMatcher("hasName", std::string("foo")))))
Samuel Benzaquen06e056c2013-07-17 14:28:00 +0000294 .getTypedMatcher<Decl>();
295 EXPECT_TRUE(matches("struct Foo { Foo() : foo(1) {} int foo; };", CtorDecl));
296 EXPECT_FALSE(matches("struct Foo { Foo() {} int foo; };", CtorDecl));
297 EXPECT_FALSE(matches("struct Foo { Foo() : bar(1) {} int bar; };", CtorDecl));
298}
299
Samuel Benzaquen7f8a5b12013-07-24 14:48:01 +0000300TEST_F(RegistryTest, Adaptative) {
301 Matcher<Decl> D = constructMatcher(
302 "recordDecl",
303 constructMatcher(
304 "has",
305 constructMatcher("recordDecl",
306 constructMatcher("hasName", std::string("X")))))
307 .getTypedMatcher<Decl>();
308 EXPECT_TRUE(matches("class X {};", D));
309 EXPECT_TRUE(matches("class Y { class X {}; };", D));
310 EXPECT_FALSE(matches("class Y { class Z {}; };", D));
311
312 Matcher<Stmt> S = constructMatcher(
313 "forStmt",
314 constructMatcher(
315 "hasDescendant",
316 constructMatcher("varDecl",
317 constructMatcher("hasName", std::string("X")))))
318 .getTypedMatcher<Stmt>();
319 EXPECT_TRUE(matches("void foo() { for(int X;;); }", S));
320 EXPECT_TRUE(matches("void foo() { for(;;) { int X; } }", S));
321 EXPECT_FALSE(matches("void foo() { for(;;); }", S));
322 EXPECT_FALSE(matches("void foo() { if (int X = 0){} }", S));
323
324 S = constructMatcher(
325 "compoundStmt", constructMatcher("hasParent", constructMatcher("ifStmt")))
326 .getTypedMatcher<Stmt>();
327 EXPECT_TRUE(matches("void foo() { if (true) { int x = 42; } }", S));
328 EXPECT_FALSE(matches("void foo() { if (true) return; }", S));
329}
330
Samuel Benzaquen4adca622013-08-28 18:42:04 +0000331TEST_F(RegistryTest, VariadicOp) {
332 Matcher<Decl> D = constructMatcher(
Samuel Benzaquen68cd3962013-08-29 15:39:26 +0000333 "anyOf",
334 constructMatcher("recordDecl",
335 constructMatcher("hasName", std::string("Foo"))),
Samuel Benzaquen4adca622013-08-28 18:42:04 +0000336 constructMatcher("namedDecl",
337 constructMatcher("hasName", std::string("foo"))))
338 .getTypedMatcher<Decl>();
339
340 EXPECT_TRUE(matches("void foo(){}", D));
341 EXPECT_TRUE(matches("struct Foo{};", D));
342 EXPECT_FALSE(matches("int i = 0;", D));
343
344 D = constructMatcher(
345 "allOf", constructMatcher("recordDecl"),
346 constructMatcher(
347 "namedDecl",
348 constructMatcher("anyOf",
349 constructMatcher("hasName", std::string("Foo")),
350 constructMatcher("hasName", std::string("Bar")))))
351 .getTypedMatcher<Decl>();
352
353 EXPECT_FALSE(matches("void foo(){}", D));
354 EXPECT_TRUE(matches("struct Foo{};", D));
355 EXPECT_FALSE(matches("int i = 0;", D));
356 EXPECT_TRUE(matches("class Bar{};", D));
357 EXPECT_FALSE(matches("class OtherBar{};", D));
Samuel Benzaquen4d058742013-11-22 14:41:48 +0000358
Samuel Benzaquenef77f3c2013-11-22 23:05:57 +0000359 D = recordDecl(
360 has(fieldDecl(hasName("Foo"))),
Samuel Benzaquen4d058742013-11-22 14:41:48 +0000361 constructMatcher(
362 "unless",
363 constructMatcher("namedDecl",
Samuel Benzaquenef77f3c2013-11-22 23:05:57 +0000364 constructMatcher("hasName", std::string("Bar"))))
365 .getTypedMatcher<Decl>());
Samuel Benzaquen4d058742013-11-22 14:41:48 +0000366
Samuel Benzaquenef77f3c2013-11-22 23:05:57 +0000367 EXPECT_FALSE(matches("class Bar{ int Foo; };", D));
368 EXPECT_TRUE(matches("class OtherBar{ int Foo; };", D));
Samuel Benzaquen4adca622013-08-28 18:42:04 +0000369}
370
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000371TEST_F(RegistryTest, Errors) {
Manuel Klimek24db0f02013-05-14 09:13:00 +0000372 // Incorrect argument count.
373 OwningPtr<Diagnostics> Error(new Diagnostics());
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000374 EXPECT_TRUE(constructMatcher("hasInitializer", Error.get()).isNull());
Manuel Klimek24db0f02013-05-14 09:13:00 +0000375 EXPECT_EQ("Incorrect argument count. (Expected = 1) != (Actual = 0)",
Samuel Benzaquenb8372482013-07-19 20:02:35 +0000376 Error->toString());
Manuel Klimek24db0f02013-05-14 09:13:00 +0000377 Error.reset(new Diagnostics());
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000378 EXPECT_TRUE(constructMatcher("isArrow", std::string(), Error.get()).isNull());
Manuel Klimek24db0f02013-05-14 09:13:00 +0000379 EXPECT_EQ("Incorrect argument count. (Expected = 0) != (Actual = 1)",
Samuel Benzaquenb8372482013-07-19 20:02:35 +0000380 Error->toString());
Samuel Benzaquen4d058742013-11-22 14:41:48 +0000381 Error.reset(new Diagnostics());
382 EXPECT_TRUE(constructMatcher("anyOf", Error.get()).isNull());
383 EXPECT_EQ("Incorrect argument count. (Expected = (2, )) != (Actual = 0)",
384 Error->toString());
385 Error.reset(new Diagnostics());
386 EXPECT_TRUE(constructMatcher("unless", std::string(), std::string(),
387 Error.get()).isNull());
388 EXPECT_EQ("Incorrect argument count. (Expected = (1, 1)) != (Actual = 2)",
389 Error->toString());
Manuel Klimek24db0f02013-05-14 09:13:00 +0000390
391 // Bad argument type
392 Error.reset(new Diagnostics());
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000393 EXPECT_TRUE(constructMatcher("ofClass", std::string(), Error.get()).isNull());
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000394 EXPECT_EQ("Incorrect type for arg 1. (Expected = Matcher<CXXRecordDecl>) != "
395 "(Actual = String)",
Samuel Benzaquenb8372482013-07-19 20:02:35 +0000396 Error->toString());
Manuel Klimek24db0f02013-05-14 09:13:00 +0000397 Error.reset(new Diagnostics());
Samuel Benzaquen0239b692013-08-13 14:54:51 +0000398 EXPECT_TRUE(constructMatcher("recordDecl", constructMatcher("recordDecl"),
399 constructMatcher("parameterCountIs", 3),
400 Error.get()).isNull());
Samuel Benzaquen81ef9292013-06-20 14:28:32 +0000401 EXPECT_EQ("Incorrect type for arg 2. (Expected = Matcher<CXXRecordDecl>) != "
402 "(Actual = Matcher<FunctionDecl>)",
Samuel Benzaquenb8372482013-07-19 20:02:35 +0000403 Error->toString());
Samuel Benzaquen4adca622013-08-28 18:42:04 +0000404
405 // Bad argument type with variadic.
406 Error.reset(new Diagnostics());
Samuel Benzaquen4d058742013-11-22 14:41:48 +0000407 EXPECT_TRUE(constructMatcher("anyOf", std::string(), std::string(),
408 Error.get()).isNull());
Samuel Benzaquen4adca622013-08-28 18:42:04 +0000409 EXPECT_EQ(
410 "Incorrect type for arg 1. (Expected = Matcher<>) != (Actual = String)",
411 Error->toString());
412 Error.reset(new Diagnostics());
413 EXPECT_TRUE(constructMatcher(
414 "recordDecl",
415 constructMatcher("allOf",
416 constructMatcher("isDerivedFrom", std::string("FOO")),
417 constructMatcher("isArrow")),
418 Error.get()).isNull());
419 EXPECT_EQ("Incorrect type for arg 1. "
420 "(Expected = Matcher<CXXRecordDecl>) != "
421 "(Actual = Matcher<CXXRecordDecl>&Matcher<MemberExpr>)",
422 Error->toString());
Manuel Klimek24db0f02013-05-14 09:13:00 +0000423}
424
Peter Collingbourned32e28c2014-01-23 22:48:38 +0000425TEST_F(RegistryTest, Completion) {
426 CompVector Comps = getCompletions();
427 EXPECT_TRUE(hasCompletion(
428 Comps, "hasParent(", "Matcher<Decl|Stmt> hasParent(Matcher<Decl|Stmt>)"));
429 EXPECT_TRUE(hasCompletion(Comps, "whileStmt(",
430 "Matcher<Stmt> whileStmt(Matcher<WhileStmt>...)"));
431
432 CompVector WhileComps = getCompletions("whileStmt", 0);
433
434 unsigned HasBodyIndex, HasParentIndex, AllOfIndex;
435 EXPECT_TRUE(hasCompletion(WhileComps, "hasBody(",
436 "Matcher<WhileStmt> hasBody(Matcher<Stmt>)",
437 &HasBodyIndex));
438 EXPECT_TRUE(hasCompletion(WhileComps, "hasParent(",
439 "Matcher<Stmt> hasParent(Matcher<Decl|Stmt>)",
440 &HasParentIndex));
441 EXPECT_TRUE(hasCompletion(WhileComps, "allOf(",
442 "Matcher<T> allOf(Matcher<T>...)", &AllOfIndex));
443 EXPECT_GT(HasParentIndex, HasBodyIndex);
444 EXPECT_GT(AllOfIndex, HasParentIndex);
445
446 EXPECT_FALSE(hasCompletion(WhileComps, "whileStmt("));
447 EXPECT_FALSE(hasCompletion(WhileComps, "ifStmt("));
448
449 CompVector AllOfWhileComps =
450 getCompletions("allOf", 0, "whileStmt", 0);
451 ASSERT_EQ(AllOfWhileComps.size(), WhileComps.size());
452 EXPECT_TRUE(std::equal(WhileComps.begin(), WhileComps.end(),
453 AllOfWhileComps.begin()));
454
455 CompVector DeclWhileComps =
456 getCompletions("decl", 0, "whileStmt", 0);
457 EXPECT_EQ(0u, DeclWhileComps.size());
458
459 CompVector NamedDeclComps = getCompletions("namedDecl", 0);
460 EXPECT_TRUE(
461 hasCompletion(NamedDeclComps, "isPublic()", "Matcher<Decl> isPublic()"));
462 EXPECT_TRUE(hasCompletion(NamedDeclComps, "hasName(\"",
463 "Matcher<NamedDecl> hasName(string)"));
464}
465
Manuel Klimek24db0f02013-05-14 09:13:00 +0000466} // end anonymous namespace
467} // end namespace dynamic
468} // end namespace ast_matchers
469} // end namespace clang