1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | #include "../ASTMatchersTest.h" |
10 | #include "clang/ASTMatchers/Dynamic/Registry.h" |
11 | #include "gtest/gtest.h" |
12 | #include <vector> |
13 | |
14 | namespace clang { |
15 | namespace ast_matchers { |
16 | namespace dynamic { |
17 | namespace { |
18 | |
19 | using ast_matchers::internal::Matcher; |
20 | |
21 | class RegistryTest : public ::testing::Test { |
22 | public: |
23 | std::vector<ParserValue> Args() { return std::vector<ParserValue>(); } |
24 | std::vector<ParserValue> Args(const VariantValue &Arg1) { |
25 | std::vector<ParserValue> Out(1); |
26 | Out[0].Value = Arg1; |
27 | return Out; |
28 | } |
29 | std::vector<ParserValue> Args(const VariantValue &Arg1, |
30 | const VariantValue &Arg2) { |
31 | std::vector<ParserValue> Out(2); |
32 | Out[0].Value = Arg1; |
33 | Out[1].Value = Arg2; |
34 | return Out; |
35 | } |
36 | |
37 | llvm::Optional<MatcherCtor> lookupMatcherCtor(StringRef MatcherName) { |
38 | return Registry::lookupMatcherCtor(MatcherName); |
39 | } |
40 | |
41 | VariantMatcher constructMatcher(StringRef MatcherName, |
42 | Diagnostics *Error = nullptr) { |
43 | Diagnostics DummyError; |
44 | if (!Error) Error = &DummyError; |
45 | llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName); |
46 | VariantMatcher Out; |
47 | if (Ctor) |
48 | Out = Registry::constructMatcher(*Ctor, SourceRange(), Args(), Error); |
49 | EXPECT_EQ("", DummyError.toStringFull()); |
50 | return Out; |
51 | } |
52 | |
53 | VariantMatcher constructMatcher(StringRef MatcherName, |
54 | const VariantValue &Arg1, |
55 | Diagnostics *Error = nullptr) { |
56 | Diagnostics DummyError; |
57 | if (!Error) Error = &DummyError; |
58 | llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName); |
59 | VariantMatcher Out; |
60 | if (Ctor) |
61 | Out = Registry::constructMatcher(*Ctor, SourceRange(), Args(Arg1), Error); |
62 | EXPECT_EQ("", DummyError.toStringFull()) << MatcherName; |
63 | return Out; |
64 | } |
65 | |
66 | VariantMatcher constructMatcher(StringRef MatcherName, |
67 | const VariantValue &Arg1, |
68 | const VariantValue &Arg2, |
69 | Diagnostics *Error = nullptr) { |
70 | Diagnostics DummyError; |
71 | if (!Error) Error = &DummyError; |
72 | llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName); |
73 | VariantMatcher Out; |
74 | if (Ctor) |
75 | Out = Registry::constructMatcher(*Ctor, SourceRange(), Args(Arg1, Arg2), |
76 | Error); |
77 | EXPECT_EQ("", DummyError.toStringFull()); |
78 | return Out; |
79 | } |
80 | |
81 | typedef std::vector<MatcherCompletion> CompVector; |
82 | |
83 | CompVector getCompletions() { |
84 | std::vector<std::pair<MatcherCtor, unsigned> > Context; |
85 | return Registry::getMatcherCompletions( |
86 | Registry::getAcceptedCompletionTypes(Context)); |
87 | } |
88 | |
89 | CompVector getCompletions(StringRef MatcherName1, unsigned ArgNo1) { |
90 | std::vector<std::pair<MatcherCtor, unsigned> > Context; |
91 | llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName1); |
92 | if (!Ctor) |
93 | return CompVector(); |
94 | Context.push_back(std::make_pair(*Ctor, ArgNo1)); |
95 | return Registry::getMatcherCompletions( |
96 | Registry::getAcceptedCompletionTypes(Context)); |
97 | } |
98 | |
99 | CompVector getCompletions(StringRef MatcherName1, unsigned ArgNo1, |
100 | StringRef MatcherName2, unsigned ArgNo2) { |
101 | std::vector<std::pair<MatcherCtor, unsigned> > Context; |
102 | llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName1); |
103 | if (!Ctor) |
104 | return CompVector(); |
105 | Context.push_back(std::make_pair(*Ctor, ArgNo1)); |
106 | Ctor = lookupMatcherCtor(MatcherName2); |
107 | if (!Ctor) |
108 | return CompVector(); |
109 | Context.push_back(std::make_pair(*Ctor, ArgNo2)); |
110 | return Registry::getMatcherCompletions( |
111 | Registry::getAcceptedCompletionTypes(Context)); |
112 | } |
113 | |
114 | bool hasCompletion(const CompVector &Comps, StringRef TypedText, |
115 | StringRef MatcherDecl = StringRef()) { |
116 | for (CompVector::const_iterator I = Comps.begin(), E = Comps.end(); I != E; |
117 | ++I) { |
118 | if (I->TypedText == TypedText && |
119 | (MatcherDecl.empty() || I->MatcherDecl == MatcherDecl)) { |
120 | return true; |
121 | } |
122 | } |
123 | return false; |
124 | } |
125 | }; |
126 | |
127 | TEST_F(RegistryTest, CanConstructNoArgs) { |
128 | Matcher<Stmt> IsArrowValue = constructMatcher( |
129 | "memberExpr", constructMatcher("isArrow")).getTypedMatcher<Stmt>(); |
130 | Matcher<Stmt> BoolValue = |
131 | constructMatcher("cxxBoolLiteral").getTypedMatcher<Stmt>(); |
132 | |
133 | const std::string ClassSnippet = "struct Foo { int x; };\n" |
134 | "Foo *foo = new Foo;\n" |
135 | "int i = foo->x;\n"; |
136 | const std::string BoolSnippet = "bool Foo = true;\n"; |
137 | |
138 | EXPECT_TRUE(matches(ClassSnippet, IsArrowValue)); |
139 | EXPECT_TRUE(matches(BoolSnippet, BoolValue)); |
140 | EXPECT_FALSE(matches(ClassSnippet, BoolValue)); |
141 | EXPECT_FALSE(matches(BoolSnippet, IsArrowValue)); |
142 | } |
143 | |
144 | TEST_F(RegistryTest, ConstructWithSimpleArgs) { |
145 | Matcher<Decl> Value = constructMatcher( |
146 | "namedDecl", constructMatcher("hasName", StringRef("X"))) |
147 | .getTypedMatcher<Decl>(); |
148 | EXPECT_TRUE(matches("class X {};", Value)); |
149 | EXPECT_FALSE(matches("int x;", Value)); |
150 | |
151 | Value = functionDecl(constructMatcher("parameterCountIs", 2) |
152 | .getTypedMatcher<FunctionDecl>()); |
153 | EXPECT_TRUE(matches("void foo(int,int);", Value)); |
154 | EXPECT_FALSE(matches("void foo(int);", Value)); |
155 | } |
156 | |
157 | TEST_F(RegistryTest, ConstructWithMatcherArgs) { |
158 | Matcher<Decl> HasInitializerSimple = constructMatcher( |
159 | "varDecl", constructMatcher("hasInitializer", constructMatcher("stmt"))) |
160 | .getTypedMatcher<Decl>(); |
161 | Matcher<Decl> HasInitializerComplex = constructMatcher( |
162 | "varDecl", |
163 | constructMatcher("hasInitializer", constructMatcher("callExpr"))) |
164 | .getTypedMatcher<Decl>(); |
165 | |
166 | std::string code = "int i;"; |
167 | EXPECT_FALSE(matches(code, HasInitializerSimple)); |
168 | EXPECT_FALSE(matches(code, HasInitializerComplex)); |
169 | |
170 | code = "int i = 1;"; |
171 | EXPECT_TRUE(matches(code, HasInitializerSimple)); |
172 | EXPECT_FALSE(matches(code, HasInitializerComplex)); |
173 | |
174 | code = "int y(); int i = y();"; |
175 | EXPECT_TRUE(matches(code, HasInitializerSimple)); |
176 | EXPECT_TRUE(matches(code, HasInitializerComplex)); |
177 | |
178 | Matcher<Decl> HasParameter = |
179 | functionDecl(constructMatcher( |
180 | "hasParameter", 1, constructMatcher("hasName", StringRef("x"))) |
181 | .getTypedMatcher<FunctionDecl>()); |
182 | EXPECT_TRUE(matches("void f(int a, int x);", HasParameter)); |
183 | EXPECT_FALSE(matches("void f(int x, int a);", HasParameter)); |
184 | } |
185 | |
186 | TEST_F(RegistryTest, OverloadedMatchers) { |
187 | Matcher<Stmt> CallExpr0 = constructMatcher( |
188 | "callExpr", |
189 | constructMatcher("callee", constructMatcher("memberExpr", |
190 | constructMatcher("isArrow")))) |
191 | .getTypedMatcher<Stmt>(); |
192 | |
193 | Matcher<Stmt> CallExpr1 = constructMatcher( |
194 | "callExpr", |
195 | constructMatcher( |
196 | "callee", |
197 | constructMatcher("cxxMethodDecl", |
198 | constructMatcher("hasName", StringRef("x"))))) |
199 | .getTypedMatcher<Stmt>(); |
200 | |
201 | 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)); |
208 | |
209 | Matcher<Decl> DeclDecl = declaratorDecl(hasTypeLoc( |
210 | constructMatcher( |
211 | "loc", constructMatcher("asString", StringRef("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)); |
227 | } |
228 | |
229 | TEST_F(RegistryTest, PolymorphicMatchers) { |
230 | const VariantMatcher IsDefinition = constructMatcher("isDefinition"); |
231 | Matcher<Decl> Var = |
232 | constructMatcher("varDecl", IsDefinition).getTypedMatcher<Decl>(); |
233 | Matcher<Decl> Class = |
234 | constructMatcher("recordDecl", IsDefinition).getTypedMatcher<Decl>(); |
235 | Matcher<Decl> Func = |
236 | constructMatcher("functionDecl", IsDefinition).getTypedMatcher<Decl>(); |
237 | 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 | |
244 | Matcher<Decl> Anything = constructMatcher("anything").getTypedMatcher<Decl>(); |
245 | Matcher<Decl> RecordDecl = constructMatcher( |
246 | "recordDecl", constructMatcher("hasName", StringRef("Foo")), |
247 | VariantMatcher::SingleMatcher(Anything)).getTypedMatcher<Decl>(); |
248 | |
249 | 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)); |
255 | |
256 | Matcher<Stmt> ConstructExpr = constructMatcher( |
257 | "cxxConstructExpr", |
258 | constructMatcher( |
259 | "hasDeclaration", |
260 | constructMatcher( |
261 | "cxxMethodDecl", |
262 | constructMatcher( |
263 | "ofClass", constructMatcher("hasName", StringRef("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)); |
268 | } |
269 | |
270 | TEST_F(RegistryTest, TemplateArgument) { |
271 | Matcher<Decl> HasTemplateArgument = constructMatcher( |
272 | "classTemplateSpecializationDecl", |
273 | constructMatcher( |
274 | "hasAnyTemplateArgument", |
275 | constructMatcher("refersToType", |
276 | constructMatcher("asString", StringRef("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 | |
284 | TEST_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 | |
300 | TEST_F(RegistryTest, CXXCtorInitializer) { |
301 | Matcher<Decl> CtorDecl = constructMatcher( |
302 | "cxxConstructorDecl", |
303 | constructMatcher( |
304 | "hasAnyConstructorInitializer", |
305 | constructMatcher("forField", |
306 | constructMatcher("hasName", StringRef("foo"))))) |
307 | .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 | |
313 | TEST_F(RegistryTest, Adaptative) { |
314 | Matcher<Decl> D = constructMatcher( |
315 | "recordDecl", |
316 | constructMatcher( |
317 | "has", |
318 | constructMatcher("recordDecl", |
319 | constructMatcher("hasName", StringRef("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", StringRef("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 | |
344 | TEST_F(RegistryTest, VariadicOp) { |
345 | Matcher<Decl> D = constructMatcher( |
346 | "anyOf", |
347 | constructMatcher("recordDecl", |
348 | constructMatcher("hasName", StringRef("Foo"))), |
349 | constructMatcher("functionDecl", |
350 | constructMatcher("hasName", StringRef("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", StringRef("Foo")), |
363 | constructMatcher("hasName", StringRef("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)); |
371 | |
372 | D = recordDecl( |
373 | has(fieldDecl(hasName("Foo"))), |
374 | constructMatcher( |
375 | "unless", |
376 | constructMatcher("namedDecl", |
377 | constructMatcher("hasName", StringRef("Bar")))) |
378 | .getTypedMatcher<Decl>()); |
379 | |
380 | EXPECT_FALSE(matches("class Bar{ int Foo; };", D)); |
381 | EXPECT_TRUE(matches("class OtherBar{ int Foo; };", D)); |
382 | |
383 | D = constructMatcher( |
384 | "namedDecl", constructMatcher("hasName", StringRef("Foo")), |
385 | constructMatcher("unless", constructMatcher("recordDecl"))) |
386 | .getTypedMatcher<Decl>(); |
387 | EXPECT_TRUE(matches("void Foo(){}", D)); |
388 | EXPECT_TRUE(notMatches("struct Foo {};", D)); |
389 | } |
390 | |
391 | TEST_F(RegistryTest, Errors) { |
392 | |
393 | std::unique_ptr<Diagnostics> Error(new Diagnostics()); |
394 | EXPECT_TRUE(constructMatcher("hasInitializer", Error.get()).isNull()); |
395 | EXPECT_EQ("Incorrect argument count. (Expected = 1) != (Actual = 0)", |
396 | Error->toString()); |
397 | Error.reset(new Diagnostics()); |
398 | EXPECT_TRUE(constructMatcher("isArrow", StringRef(), Error.get()).isNull()); |
399 | EXPECT_EQ("Incorrect argument count. (Expected = 0) != (Actual = 1)", |
400 | Error->toString()); |
401 | Error.reset(new Diagnostics()); |
402 | EXPECT_TRUE(constructMatcher("anyOf", Error.get()).isNull()); |
403 | EXPECT_EQ("Incorrect argument count. (Expected = (2, )) != (Actual = 0)", |
404 | Error->toString()); |
405 | Error.reset(new Diagnostics()); |
406 | EXPECT_TRUE(constructMatcher("unless", StringRef(), StringRef(), |
407 | Error.get()).isNull()); |
408 | EXPECT_EQ("Incorrect argument count. (Expected = (1, 1)) != (Actual = 2)", |
409 | Error->toString()); |
410 | |
411 | |
412 | Error.reset(new Diagnostics()); |
413 | EXPECT_TRUE(constructMatcher("ofClass", StringRef(), Error.get()).isNull()); |
414 | EXPECT_EQ("Incorrect type for arg 1. (Expected = Matcher<CXXRecordDecl>) != " |
415 | "(Actual = String)", |
416 | Error->toString()); |
417 | Error.reset(new Diagnostics()); |
418 | EXPECT_TRUE( |
419 | constructMatcher("cxxRecordDecl", constructMatcher("cxxRecordDecl"), |
420 | constructMatcher("parameterCountIs", 3), Error.get()) |
421 | .isNull()); |
422 | EXPECT_EQ("Incorrect type for arg 2. (Expected = Matcher<CXXRecordDecl>) != " |
423 | "(Actual = Matcher<FunctionDecl|FunctionProtoType>)", |
424 | Error->toString()); |
425 | |
426 | |
427 | Error.reset(new Diagnostics()); |
428 | EXPECT_TRUE(constructMatcher("anyOf", StringRef(), StringRef(), |
429 | Error.get()).isNull()); |
430 | EXPECT_EQ( |
431 | "Incorrect type for arg 1. (Expected = Matcher<>) != (Actual = String)", |
432 | Error->toString()); |
433 | Error.reset(new Diagnostics()); |
434 | EXPECT_TRUE(constructMatcher( |
435 | "cxxRecordDecl", |
436 | constructMatcher("allOf", |
437 | constructMatcher("isDerivedFrom", StringRef("FOO")), |
438 | constructMatcher("isArrow")), |
439 | Error.get()).isNull()); |
440 | EXPECT_EQ("Incorrect type for arg 1. " |
441 | "(Expected = Matcher<CXXRecordDecl>) != " |
442 | "(Actual = Matcher<CXXRecordDecl>&Matcher" |
443 | "<MemberExpr|UnresolvedMemberExpr|CXXDependentScopeMemberExpr>)", |
444 | Error->toString()); |
445 | } |
446 | |
447 | TEST_F(RegistryTest, Completion) { |
448 | CompVector Comps = getCompletions(); |
449 | |
450 | EXPECT_TRUE(hasCompletion( |
451 | Comps, "hasParent(", |
452 | "Matcher<NestedNameSpecifierLoc|TypeLoc|Decl|...> " |
453 | "hasParent(Matcher<NestedNameSpecifierLoc|TypeLoc|Decl|...>)")); |
454 | |
455 | EXPECT_TRUE(hasCompletion(Comps, "whileStmt(", |
456 | "Matcher<Stmt> whileStmt(Matcher<WhileStmt>...)")); |
457 | |
458 | EXPECT_TRUE(hasCompletion( |
459 | Comps, "hasDescendant(", |
460 | "Matcher<NestedNameSpecifierLoc|QualType|TypeLoc|...> " |
461 | "hasDescendant(Matcher<NestedNameSpecifierLoc|QualType|TypeLoc|...>)")); |
462 | |
463 | CompVector WhileComps = getCompletions("whileStmt", 0); |
464 | |
465 | EXPECT_TRUE(hasCompletion(WhileComps, "hasBody(", |
466 | "Matcher<WhileStmt> hasBody(Matcher<Stmt>)")); |
467 | EXPECT_TRUE(hasCompletion( |
468 | WhileComps, "hasParent(", |
469 | "Matcher<Stmt> " |
470 | "hasParent(Matcher<NestedNameSpecifierLoc|TypeLoc|Decl|...>)")); |
471 | EXPECT_TRUE( |
472 | hasCompletion(WhileComps, "allOf(", "Matcher<T> allOf(Matcher<T>...)")); |
473 | |
474 | EXPECT_FALSE(hasCompletion(WhileComps, "whileStmt(")); |
475 | EXPECT_FALSE(hasCompletion(WhileComps, "ifStmt(")); |
476 | |
477 | CompVector AllOfWhileComps = |
478 | getCompletions("allOf", 0, "whileStmt", 0); |
479 | ASSERT_EQ(AllOfWhileComps.size(), WhileComps.size()); |
480 | EXPECT_TRUE(std::equal(WhileComps.begin(), WhileComps.end(), |
481 | AllOfWhileComps.begin())); |
482 | |
483 | CompVector DeclWhileComps = |
484 | getCompletions("decl", 0, "whileStmt", 0); |
485 | EXPECT_EQ(0u, DeclWhileComps.size()); |
486 | |
487 | CompVector NamedDeclComps = getCompletions("namedDecl", 0); |
488 | EXPECT_TRUE( |
489 | hasCompletion(NamedDeclComps, "isPublic()", "Matcher<Decl> isPublic()")); |
490 | EXPECT_TRUE(hasCompletion(NamedDeclComps, "hasName(\"", |
491 | "Matcher<NamedDecl> hasName(string)")); |
492 | |
493 | |
494 | Comps = getCompletions("classTemplateSpecializationDecl", 0); |
495 | EXPECT_TRUE(hasCompletion( |
496 | Comps, "isSameOrDerivedFrom(", |
497 | "Matcher<CXXRecordDecl> isSameOrDerivedFrom(string|Matcher<NamedDecl>)")); |
498 | } |
499 | |
500 | TEST_F(RegistryTest, HasArgs) { |
501 | Matcher<Decl> Value = constructMatcher( |
502 | "decl", constructMatcher("hasAttr", StringRef("attr::WarnUnused"))) |
503 | .getTypedMatcher<Decl>(); |
504 | EXPECT_TRUE(matches("struct __attribute__((warn_unused)) X {};", Value)); |
505 | EXPECT_FALSE(matches("struct X {};", Value)); |
506 | } |
507 | |
508 | TEST_F(RegistryTest, ParenExpr) { |
509 | Matcher<Stmt> Value = constructMatcher("parenExpr").getTypedMatcher<Stmt>(); |
510 | EXPECT_TRUE(matches("int i = (1);", Value)); |
511 | EXPECT_FALSE(matches("int i = 1;", Value)); |
512 | } |
513 | |
514 | TEST_F(RegistryTest, EqualsMatcher) { |
515 | Matcher<Stmt> BooleanStmt = constructMatcher( |
516 | "cxxBoolLiteral", constructMatcher("equals", VariantValue(true))) |
517 | .getTypedMatcher<Stmt>(); |
518 | EXPECT_TRUE(matches("bool x = true;", BooleanStmt)); |
519 | EXPECT_FALSE(matches("bool x = false;", BooleanStmt)); |
520 | EXPECT_FALSE(matches("bool x = 0;", BooleanStmt)); |
521 | |
522 | BooleanStmt = constructMatcher( |
523 | "cxxBoolLiteral", constructMatcher("equals", VariantValue(0))) |
524 | .getTypedMatcher<Stmt>(); |
525 | EXPECT_TRUE(matches("bool x = false;", BooleanStmt)); |
526 | EXPECT_FALSE(matches("bool x = true;", BooleanStmt)); |
527 | EXPECT_FALSE(matches("bool x = 0;", BooleanStmt)); |
528 | |
529 | Matcher<Stmt> DoubleStmt = constructMatcher( |
530 | "floatLiteral", constructMatcher("equals", VariantValue(1.2))) |
531 | .getTypedMatcher<Stmt>(); |
532 | EXPECT_TRUE(matches("double x = 1.2;", DoubleStmt)); |
533 | #if 0 |
534 | |
535 | EXPECT_TRUE(matches("double x = 1.2f;", DoubleStmt)); |
536 | EXPECT_TRUE(matches("double x = 1.2l;", DoubleStmt)); |
537 | #endif |
538 | EXPECT_TRUE(matches("double x = 12e-1;", DoubleStmt)); |
539 | EXPECT_FALSE(matches("double x = 1.23;", DoubleStmt)); |
540 | |
541 | Matcher<Stmt> IntegerStmt = constructMatcher( |
542 | "integerLiteral", constructMatcher("equals", VariantValue(42))) |
543 | .getTypedMatcher<Stmt>(); |
544 | EXPECT_TRUE(matches("int x = 42;", IntegerStmt)); |
545 | EXPECT_FALSE(matches("int x = 1;", IntegerStmt)); |
546 | |
547 | Matcher<Stmt> CharStmt = constructMatcher( |
548 | "characterLiteral", constructMatcher("equals", VariantValue('x'))) |
549 | .getTypedMatcher<Stmt>(); |
550 | EXPECT_TRUE(matches("int x = 'x';", CharStmt)); |
551 | EXPECT_TRUE(matches("int x = L'x';", CharStmt)); |
552 | EXPECT_TRUE(matches("int x = u'x';", CharStmt)); |
553 | EXPECT_TRUE(matches("int x = U'x';", CharStmt)); |
554 | EXPECT_FALSE(matches("int x = 120;", CharStmt)); |
555 | } |
556 | |
557 | } |
558 | } |
559 | } |
560 | } |
561 | |