1 //===- unittest/ASTMatchers/Dynamic/RegistryTest.cpp - Registry unit tests -===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===-----------------------------------------------------------------------===//
9 #include "../ASTMatchersTest.h"
10 #include "clang/ASTMatchers/Dynamic/Registry.h"
11 #include "gtest/gtest.h"
16 namespace ast_matchers
{
20 using ast_matchers::internal::Matcher
;
22 class RegistryTest
: public ::testing::Test
{
24 std::vector
<ParserValue
> Args() { return std::vector
<ParserValue
>(); }
25 std::vector
<ParserValue
> Args(const VariantValue
&Arg1
) {
26 std::vector
<ParserValue
> Out(1);
30 std::vector
<ParserValue
> Args(const VariantValue
&Arg1
,
31 const VariantValue
&Arg2
) {
32 std::vector
<ParserValue
> Out(2);
38 std::optional
<MatcherCtor
> lookupMatcherCtor(StringRef MatcherName
) {
39 return Registry::lookupMatcherCtor(MatcherName
);
42 VariantMatcher
constructMatcher(StringRef MatcherName
,
43 Diagnostics
*Error
= nullptr) {
44 Diagnostics DummyError
;
45 if (!Error
) Error
= &DummyError
;
46 std::optional
<MatcherCtor
> Ctor
= lookupMatcherCtor(MatcherName
);
49 Out
= Registry::constructMatcher(*Ctor
, SourceRange(), Args(), Error
);
50 EXPECT_EQ("", DummyError
.toStringFull());
54 VariantMatcher
constructMatcher(StringRef MatcherName
,
55 const VariantValue
&Arg1
,
56 Diagnostics
*Error
= nullptr) {
57 Diagnostics DummyError
;
58 if (!Error
) Error
= &DummyError
;
59 std::optional
<MatcherCtor
> Ctor
= lookupMatcherCtor(MatcherName
);
62 Out
= Registry::constructMatcher(*Ctor
, SourceRange(), Args(Arg1
), Error
);
63 EXPECT_EQ("", DummyError
.toStringFull()) << MatcherName
;
67 VariantMatcher
constructMatcher(StringRef MatcherName
,
68 const VariantValue
&Arg1
,
69 const VariantValue
&Arg2
,
70 Diagnostics
*Error
= nullptr) {
71 Diagnostics DummyError
;
72 if (!Error
) Error
= &DummyError
;
73 std::optional
<MatcherCtor
> Ctor
= lookupMatcherCtor(MatcherName
);
76 Out
= Registry::constructMatcher(*Ctor
, SourceRange(), Args(Arg1
, Arg2
),
78 EXPECT_EQ("", DummyError
.toStringFull());
82 typedef std::vector
<MatcherCompletion
> CompVector
;
84 CompVector
getCompletions() {
85 std::vector
<std::pair
<MatcherCtor
, unsigned> > Context
;
86 return Registry::getMatcherCompletions(
87 Registry::getAcceptedCompletionTypes(Context
));
90 CompVector
getCompletions(StringRef MatcherName1
, unsigned ArgNo1
) {
91 std::vector
<std::pair
<MatcherCtor
, unsigned> > Context
;
92 std::optional
<MatcherCtor
> Ctor
= lookupMatcherCtor(MatcherName1
);
95 Context
.push_back(std::make_pair(*Ctor
, ArgNo1
));
96 return Registry::getMatcherCompletions(
97 Registry::getAcceptedCompletionTypes(Context
));
100 CompVector
getCompletions(StringRef MatcherName1
, unsigned ArgNo1
,
101 StringRef MatcherName2
, unsigned ArgNo2
) {
102 std::vector
<std::pair
<MatcherCtor
, unsigned> > Context
;
103 std::optional
<MatcherCtor
> Ctor
= lookupMatcherCtor(MatcherName1
);
106 Context
.push_back(std::make_pair(*Ctor
, ArgNo1
));
107 Ctor
= lookupMatcherCtor(MatcherName2
);
110 Context
.push_back(std::make_pair(*Ctor
, ArgNo2
));
111 return Registry::getMatcherCompletions(
112 Registry::getAcceptedCompletionTypes(Context
));
115 bool hasCompletion(const CompVector
&Comps
, StringRef TypedText
,
116 StringRef MatcherDecl
= StringRef()) {
117 for (CompVector::const_iterator I
= Comps
.begin(), E
= Comps
.end(); I
!= E
;
119 if (I
->TypedText
== TypedText
&&
120 (MatcherDecl
.empty() || I
->MatcherDecl
== MatcherDecl
)) {
128 TEST_F(RegistryTest
, CanConstructNoArgs
) {
129 Matcher
<Stmt
> IsArrowValue
= constructMatcher(
130 "memberExpr", constructMatcher("isArrow")).getTypedMatcher
<Stmt
>();
131 Matcher
<Stmt
> BoolValue
=
132 constructMatcher("cxxBoolLiteral").getTypedMatcher
<Stmt
>();
134 const std::string ClassSnippet
= "struct Foo { int x; };\n"
135 "Foo *foo = new Foo;\n"
137 const std::string BoolSnippet
= "bool Foo = true;\n";
139 EXPECT_TRUE(matches(ClassSnippet
, IsArrowValue
));
140 EXPECT_TRUE(matches(BoolSnippet
, BoolValue
));
141 EXPECT_FALSE(matches(ClassSnippet
, BoolValue
));
142 EXPECT_FALSE(matches(BoolSnippet
, IsArrowValue
));
145 TEST_F(RegistryTest
, ConstructWithSimpleArgs
) {
146 Matcher
<Decl
> Value
= constructMatcher(
147 "namedDecl", constructMatcher("hasName", StringRef("X")))
148 .getTypedMatcher
<Decl
>();
149 EXPECT_TRUE(matches("class X {};", Value
));
150 EXPECT_FALSE(matches("int x;", Value
));
152 Value
= functionDecl(constructMatcher("parameterCountIs", 2)
153 .getTypedMatcher
<FunctionDecl
>());
154 EXPECT_TRUE(matches("void foo(int,int);", Value
));
155 EXPECT_FALSE(matches("void foo(int);", Value
));
158 TEST_F(RegistryTest
, ConstructWithMatcherArgs
) {
159 Matcher
<Decl
> HasInitializerSimple
= constructMatcher(
160 "varDecl", constructMatcher("hasInitializer", constructMatcher("stmt")))
161 .getTypedMatcher
<Decl
>();
162 Matcher
<Decl
> HasInitializerComplex
= constructMatcher(
164 constructMatcher("hasInitializer", constructMatcher("callExpr")))
165 .getTypedMatcher
<Decl
>();
167 std::string code
= "int i;";
168 EXPECT_FALSE(matches(code
, HasInitializerSimple
));
169 EXPECT_FALSE(matches(code
, HasInitializerComplex
));
172 EXPECT_TRUE(matches(code
, HasInitializerSimple
));
173 EXPECT_FALSE(matches(code
, HasInitializerComplex
));
175 code
= "int y(); int i = y();";
176 EXPECT_TRUE(matches(code
, HasInitializerSimple
));
177 EXPECT_TRUE(matches(code
, HasInitializerComplex
));
179 Matcher
<Decl
> HasParameter
=
180 functionDecl(constructMatcher(
181 "hasParameter", 1, constructMatcher("hasName", StringRef("x")))
182 .getTypedMatcher
<FunctionDecl
>());
183 EXPECT_TRUE(matches("void f(int a, int x);", HasParameter
));
184 EXPECT_FALSE(matches("void f(int x, int a);", HasParameter
));
187 TEST_F(RegistryTest
, OverloadedMatchers
) {
188 Matcher
<Stmt
> CallExpr0
= constructMatcher(
190 constructMatcher("callee", constructMatcher("memberExpr",
191 constructMatcher("isArrow"))))
192 .getTypedMatcher
<Stmt
>();
194 Matcher
<Stmt
> CallExpr1
= constructMatcher(
198 constructMatcher("cxxMethodDecl",
199 constructMatcher("hasName", StringRef("x")))))
200 .getTypedMatcher
<Stmt
>();
202 Matcher
<Stmt
> ObjCMsgExpr
=
207 constructMatcher("objcMethodDecl",
208 constructMatcher("hasName", StringRef("x")))))
209 .getTypedMatcher
<Stmt
>();
211 std::string Code
= "class Y { public: void x(); }; void z() { Y y; y.x(); }";
212 EXPECT_FALSE(matches(Code
, CallExpr0
));
213 EXPECT_TRUE(matches(Code
, CallExpr1
));
214 EXPECT_FALSE(matches(Code
, ObjCMsgExpr
));
216 Code
= "class Z { public: void z() { this->z(); } };";
217 EXPECT_TRUE(matches(Code
, CallExpr0
));
218 EXPECT_FALSE(matches(Code
, CallExpr1
));
219 EXPECT_FALSE(matches(Code
, ObjCMsgExpr
));
221 Code
= "@interface I "
224 "int main() { [I x]; }";
225 EXPECT_FALSE(matchesObjC(Code
, CallExpr0
));
226 EXPECT_FALSE(matchesObjC(Code
, CallExpr1
));
227 EXPECT_TRUE(matchesObjC(Code
, ObjCMsgExpr
));
229 Matcher
<Decl
> DeclDecl
= declaratorDecl(hasTypeLoc(
231 "loc", constructMatcher("asString", StringRef("const double *")))
232 .getTypedMatcher
<TypeLoc
>()));
234 Matcher
<NestedNameSpecifierLoc
> NNSL
=
236 "loc", VariantMatcher::SingleMatcher(nestedNameSpecifier(
237 specifiesType(hasDeclaration(recordDecl(hasName("A")))))))
238 .getTypedMatcher
<NestedNameSpecifierLoc
>();
240 Code
= "const double * x = 0;";
241 EXPECT_TRUE(matches(Code
, DeclDecl
));
242 EXPECT_FALSE(matches(Code
, NNSL
));
244 Code
= "struct A { struct B {}; }; A::B a_b;";
245 EXPECT_FALSE(matches(Code
, DeclDecl
));
246 EXPECT_TRUE(matches(Code
, NNSL
));
249 TEST_F(RegistryTest
, PolymorphicMatchers
) {
250 const VariantMatcher IsDefinition
= constructMatcher("isDefinition");
252 constructMatcher("varDecl", IsDefinition
).getTypedMatcher
<Decl
>();
253 Matcher
<Decl
> Class
=
254 constructMatcher("recordDecl", IsDefinition
).getTypedMatcher
<Decl
>();
256 constructMatcher("functionDecl", IsDefinition
).getTypedMatcher
<Decl
>();
257 EXPECT_TRUE(matches("int a;", Var
));
258 EXPECT_FALSE(matches("extern int a;", Var
));
259 EXPECT_TRUE(matches("class A {};", Class
));
260 EXPECT_FALSE(matches("class A;", Class
));
261 EXPECT_TRUE(matches("void f(){};", Func
));
262 EXPECT_FALSE(matches("void f();", Func
));
264 Matcher
<Decl
> Anything
= constructMatcher("anything").getTypedMatcher
<Decl
>();
265 Matcher
<Decl
> RecordDecl
= constructMatcher(
266 "recordDecl", constructMatcher("hasName", StringRef("Foo")),
267 VariantMatcher::SingleMatcher(Anything
)).getTypedMatcher
<Decl
>();
269 EXPECT_TRUE(matches("int Foo;", Anything
));
270 EXPECT_TRUE(matches("class Foo {};", Anything
));
271 EXPECT_TRUE(matches("void Foo(){};", Anything
));
272 EXPECT_FALSE(matches("int Foo;", RecordDecl
));
273 EXPECT_TRUE(matches("class Foo {};", RecordDecl
));
274 EXPECT_FALSE(matches("void Foo(){};", RecordDecl
));
276 Matcher
<Stmt
> ConstructExpr
= constructMatcher(
283 "ofClass", constructMatcher("hasName", StringRef("Foo"))))))
284 .getTypedMatcher
<Stmt
>();
285 EXPECT_FALSE(matches("class Foo { public: Foo(); };", ConstructExpr
));
287 matches("class Foo { public: Foo(); }; Foo foo = Foo();", ConstructExpr
));
290 TEST_F(RegistryTest
, TemplateArgument
) {
291 Matcher
<Decl
> HasTemplateArgument
= constructMatcher(
292 "classTemplateSpecializationDecl",
294 "hasAnyTemplateArgument",
295 constructMatcher("refersToType",
296 constructMatcher("asString", StringRef("int")))))
297 .getTypedMatcher
<Decl
>();
298 EXPECT_TRUE(matches("template<typename T> class A {}; A<int> a;",
299 HasTemplateArgument
));
300 EXPECT_FALSE(matches("template<typename T> class A {}; A<char> a;",
301 HasTemplateArgument
));
304 TEST_F(RegistryTest
, TypeTraversal
) {
305 Matcher
<Type
> M
= constructMatcher(
307 constructMatcher("pointee", constructMatcher("isConstQualified"),
308 constructMatcher("isInteger"))).getTypedMatcher
<Type
>();
309 EXPECT_FALSE(matches("int *a;", M
));
310 EXPECT_TRUE(matches("int const *b;", M
));
312 M
= constructMatcher(
314 constructMatcher("hasElementType", constructMatcher("builtinType")))
315 .getTypedMatcher
<Type
>();
316 EXPECT_FALSE(matches("struct A{}; A a[7];;", M
));
317 EXPECT_TRUE(matches("int b[7];", M
));
320 TEST_F(RegistryTest
, CXXBaseSpecifier
) {
321 // TODO: rewrite with top-level cxxBaseSpecifier matcher when available
322 DeclarationMatcher ClassHasAnyDirectBase
=
323 constructMatcher("cxxRecordDecl",
324 constructMatcher("hasDirectBase",
325 constructMatcher("cxxBaseSpecifier")))
326 .getTypedMatcher
<Decl
>();
327 EXPECT_TRUE(matches("class X {}; class Y : X {};", ClassHasAnyDirectBase
));
328 EXPECT_TRUE(notMatches("class X {};", ClassHasAnyDirectBase
));
331 TEST_F(RegistryTest
, CXXCtorInitializer
) {
332 Matcher
<Decl
> CtorDecl
= constructMatcher(
333 "cxxConstructorDecl",
335 "hasAnyConstructorInitializer",
336 constructMatcher("forField",
337 constructMatcher("hasName", StringRef("foo")))))
338 .getTypedMatcher
<Decl
>();
339 EXPECT_TRUE(matches("struct Foo { Foo() : foo(1) {} int foo; };", CtorDecl
));
340 EXPECT_FALSE(matches("struct Foo { Foo() {} int foo; };", CtorDecl
));
341 EXPECT_FALSE(matches("struct Foo { Foo() : bar(1) {} int bar; };", CtorDecl
));
344 TEST_F(RegistryTest
, Adaptative
) {
345 Matcher
<Decl
> D
= constructMatcher(
349 constructMatcher("recordDecl",
350 constructMatcher("hasName", StringRef("X")))))
351 .getTypedMatcher
<Decl
>();
352 EXPECT_TRUE(matches("class X {};", D
));
353 EXPECT_TRUE(matches("class Y { class X {}; };", D
));
354 EXPECT_FALSE(matches("class Y { class Z {}; };", D
));
356 Matcher
<Stmt
> S
= constructMatcher(
360 constructMatcher("varDecl",
361 constructMatcher("hasName", StringRef("X")))))
362 .getTypedMatcher
<Stmt
>();
363 EXPECT_TRUE(matches("void foo() { for(int X;;); }", S
));
364 EXPECT_TRUE(matches("void foo() { for(;;) { int X; } }", S
));
365 EXPECT_FALSE(matches("void foo() { for(;;); }", S
));
366 EXPECT_FALSE(matches("void foo() { if (int X = 0){} }", S
));
368 S
= constructMatcher(
369 "compoundStmt", constructMatcher("hasParent", constructMatcher("ifStmt")))
370 .getTypedMatcher
<Stmt
>();
371 EXPECT_TRUE(matches("void foo() { if (true) { int x = 42; } }", S
));
372 EXPECT_FALSE(matches("void foo() { if (true) return; }", S
));
375 TEST_F(RegistryTest
, VariadicOp
) {
376 Matcher
<Decl
> D
= constructMatcher(
378 constructMatcher("recordDecl",
379 constructMatcher("hasName", StringRef("Foo"))),
380 constructMatcher("functionDecl",
381 constructMatcher("hasName", StringRef("foo"))))
382 .getTypedMatcher
<Decl
>();
384 EXPECT_TRUE(matches("void foo(){}", D
));
385 EXPECT_TRUE(matches("struct Foo{};", D
));
386 EXPECT_FALSE(matches("int i = 0;", D
));
388 D
= constructMatcher(
389 "allOf", constructMatcher("recordDecl"),
392 constructMatcher("anyOf",
393 constructMatcher("hasName", StringRef("Foo")),
394 constructMatcher("hasName", StringRef("Bar")))))
395 .getTypedMatcher
<Decl
>();
397 EXPECT_FALSE(matches("void foo(){}", D
));
398 EXPECT_TRUE(matches("struct Foo{};", D
));
399 EXPECT_FALSE(matches("int i = 0;", D
));
400 EXPECT_TRUE(matches("class Bar{};", D
));
401 EXPECT_FALSE(matches("class OtherBar{};", D
));
404 has(fieldDecl(hasName("Foo"))),
407 constructMatcher("namedDecl",
408 constructMatcher("hasName", StringRef("Bar"))))
409 .getTypedMatcher
<Decl
>());
411 EXPECT_FALSE(matches("class Bar{ int Foo; };", D
));
412 EXPECT_TRUE(matches("class OtherBar{ int Foo; };", D
));
414 D
= constructMatcher(
415 "namedDecl", constructMatcher("hasName", StringRef("Foo")),
416 constructMatcher("unless", constructMatcher("recordDecl")))
417 .getTypedMatcher
<Decl
>();
418 EXPECT_TRUE(matches("void Foo(){}", D
));
419 EXPECT_TRUE(notMatches("struct Foo {};", D
));
422 TEST_F(RegistryTest
, Errors
) {
423 // Incorrect argument count.
424 std::unique_ptr
<Diagnostics
> Error(new Diagnostics());
425 EXPECT_TRUE(constructMatcher("hasInitializer", Error
.get()).isNull());
426 EXPECT_EQ("Incorrect argument count. (Expected = 1) != (Actual = 0)",
428 Error
.reset(new Diagnostics());
429 EXPECT_TRUE(constructMatcher("isArrow", StringRef(), Error
.get()).isNull());
430 EXPECT_EQ("Incorrect argument count. (Expected = 0) != (Actual = 1)",
432 Error
.reset(new Diagnostics());
433 EXPECT_TRUE(constructMatcher("anyOf", Error
.get()).isNull());
434 EXPECT_EQ("Incorrect argument count. (Expected = (2, )) != (Actual = 0)",
436 Error
.reset(new Diagnostics());
437 EXPECT_TRUE(constructMatcher("unless", StringRef(), StringRef(),
438 Error
.get()).isNull());
439 EXPECT_EQ("Incorrect argument count. (Expected = (1, 1)) != (Actual = 2)",
443 Error
.reset(new Diagnostics());
444 EXPECT_TRUE(constructMatcher("ofClass", StringRef(), Error
.get()).isNull());
445 EXPECT_EQ("Incorrect type for arg 1. (Expected = Matcher<CXXRecordDecl>) != "
448 Error
.reset(new Diagnostics());
450 constructMatcher("cxxRecordDecl", constructMatcher("cxxRecordDecl"),
451 constructMatcher("parameterCountIs", 3), Error
.get())
453 EXPECT_EQ("Incorrect type for arg 2. (Expected = Matcher<CXXRecordDecl>) != "
454 "(Actual = Matcher<FunctionDecl|FunctionProtoType>)",
457 // Bad argument type with variadic.
458 Error
.reset(new Diagnostics());
459 EXPECT_TRUE(constructMatcher("anyOf", StringRef(), StringRef(),
460 Error
.get()).isNull());
462 "Incorrect type for arg 1. (Expected = Matcher<>) != (Actual = String)",
464 Error
.reset(new Diagnostics());
465 EXPECT_TRUE(constructMatcher(
467 constructMatcher("allOf",
468 constructMatcher("isDerivedFrom", StringRef("FOO")),
469 constructMatcher("isArrow")),
470 Error
.get()).isNull());
471 EXPECT_EQ("Incorrect type for arg 1. "
472 "(Expected = Matcher<CXXRecordDecl>) != "
473 "(Actual = Matcher<CXXRecordDecl|ObjCInterfaceDecl>&Matcher"
474 "<MemberExpr|UnresolvedMemberExpr|CXXDependentScopeMemberExpr>)",
478 TEST_F(RegistryTest
, Completion
) {
479 CompVector Comps
= getCompletions();
481 EXPECT_TRUE(hasCompletion(
483 "Matcher<NestedNameSpecifierLoc|TypeLoc|Decl|...> "
484 "hasParent(Matcher<NestedNameSpecifierLoc|TypeLoc|Decl|...>)"));
486 EXPECT_TRUE(hasCompletion(Comps
, "whileStmt(",
487 "Matcher<Stmt> whileStmt(Matcher<WhileStmt>...)"));
489 EXPECT_TRUE(hasCompletion(
490 Comps
, "hasDescendant(",
491 "Matcher<NestedNameSpecifierLoc|QualType|TypeLoc|...> "
492 "hasDescendant(Matcher<NestedNameSpecifierLoc|QualType|TypeLoc|...>)"));
494 CompVector WhileComps
= getCompletions("whileStmt", 0);
496 EXPECT_TRUE(hasCompletion(WhileComps
, "hasBody(",
497 "Matcher<WhileStmt> hasBody(Matcher<Stmt>)"));
498 EXPECT_TRUE(hasCompletion(
499 WhileComps
, "hasParent(",
501 "hasParent(Matcher<NestedNameSpecifierLoc|TypeLoc|Decl|...>)"));
503 hasCompletion(WhileComps
, "allOf(", "Matcher<T> allOf(Matcher<T>...)"));
505 EXPECT_FALSE(hasCompletion(WhileComps
, "whileStmt("));
506 EXPECT_FALSE(hasCompletion(WhileComps
, "ifStmt("));
508 CompVector AllOfWhileComps
=
509 getCompletions("allOf", 0, "whileStmt", 0);
510 ASSERT_EQ(AllOfWhileComps
.size(), WhileComps
.size());
511 EXPECT_TRUE(std::equal(WhileComps
.begin(), WhileComps
.end(),
512 AllOfWhileComps
.begin()));
514 CompVector DeclWhileComps
=
515 getCompletions("decl", 0, "whileStmt", 0);
516 EXPECT_EQ(0u, DeclWhileComps
.size());
518 CompVector NamedDeclComps
= getCompletions("namedDecl", 0);
520 hasCompletion(NamedDeclComps
, "isPublic()", "Matcher<Decl> isPublic()"));
521 EXPECT_TRUE(hasCompletion(NamedDeclComps
, "hasName(\"",
522 "Matcher<NamedDecl> hasName(string)"));
524 // Heterogeneous overloads.
525 Comps
= getCompletions("classTemplateSpecializationDecl", 0);
526 EXPECT_TRUE(hasCompletion(
527 Comps
, "isSameOrDerivedFrom(",
528 "Matcher<CXXRecordDecl> isSameOrDerivedFrom(string|Matcher<NamedDecl>)"));
531 TEST_F(RegistryTest
, MatcherBuilder
) {
532 auto Ctor
= *lookupMatcherCtor("mapAnyOf");
533 EXPECT_TRUE(Registry::isBuilderMatcher(Ctor
));
534 auto BuiltCtor
= Registry::buildMatcherCtor(Ctor
, {}, Args(ASTNodeKind::getFromNodeKind
<WhileStmt
>(), ASTNodeKind::getFromNodeKind
<ForStmt
>()), nullptr);
535 EXPECT_TRUE(BuiltCtor
.get());
536 auto LoopMatcher
= Registry::constructMatcher(BuiltCtor
.get(), SourceRange(), Args(), nullptr).getTypedMatcher
<Stmt
>();
537 EXPECT_TRUE(matches("void f() { for (;;) {} }", LoopMatcher
));
538 EXPECT_TRUE(matches("void f() { while (true) {} }", LoopMatcher
));
539 EXPECT_FALSE(matches("void f() { if (true) {} }", LoopMatcher
));
541 auto NotBuiltCtor
= Registry::buildMatcherCtor(Ctor
, {}, Args(ASTNodeKind::getFromNodeKind
<FunctionDecl
>(), ASTNodeKind::getFromNodeKind
<ForStmt
>()), nullptr);
542 EXPECT_FALSE(NotBuiltCtor
.get());
545 TEST_F(RegistryTest
, NodeType
) {
546 EXPECT_TRUE(Registry::nodeMatcherType(*lookupMatcherCtor("callExpr")).isSame(ASTNodeKind::getFromNodeKind
<CallExpr
>()));
547 EXPECT_TRUE(Registry::nodeMatcherType(*lookupMatcherCtor("has")).isNone());
548 EXPECT_TRUE(Registry::nodeMatcherType(*lookupMatcherCtor("allOf")).isNone());
551 TEST_F(RegistryTest
, HasArgs
) {
552 Matcher
<Decl
> Value
= constructMatcher(
553 "decl", constructMatcher("hasAttr", StringRef("attr::WarnUnused")))
554 .getTypedMatcher
<Decl
>();
555 EXPECT_TRUE(matches("struct __attribute__((warn_unused)) X {};", Value
));
556 EXPECT_FALSE(matches("struct X {};", Value
));
559 TEST_F(RegistryTest
, ParenExpr
) {
560 Matcher
<Stmt
> Value
= constructMatcher("parenExpr").getTypedMatcher
<Stmt
>();
561 EXPECT_TRUE(matches("int i = (1);", traverse(TK_AsIs
, Value
)));
562 EXPECT_FALSE(matches("int i = 1;", traverse(TK_AsIs
, Value
)));
565 TEST_F(RegistryTest
, EqualsMatcher
) {
566 Matcher
<Stmt
> BooleanStmt
= constructMatcher(
567 "cxxBoolLiteral", constructMatcher("equals", VariantValue(true)))
568 .getTypedMatcher
<Stmt
>();
569 EXPECT_TRUE(matches("bool x = true;", BooleanStmt
));
570 EXPECT_FALSE(matches("bool x = false;", BooleanStmt
));
571 EXPECT_FALSE(matches("bool x = 0;", BooleanStmt
));
573 BooleanStmt
= constructMatcher(
574 "cxxBoolLiteral", constructMatcher("equals", VariantValue(0)))
575 .getTypedMatcher
<Stmt
>();
576 EXPECT_TRUE(matches("bool x = false;", BooleanStmt
));
577 EXPECT_FALSE(matches("bool x = true;", BooleanStmt
));
578 EXPECT_FALSE(matches("bool x = 0;", BooleanStmt
));
580 Matcher
<Stmt
> DoubleStmt
= constructMatcher(
581 "floatLiteral", constructMatcher("equals", VariantValue(1.2)))
582 .getTypedMatcher
<Stmt
>();
583 EXPECT_TRUE(matches("double x = 1.2;", DoubleStmt
));
585 // FIXME floatLiteral matching should work regardless of suffix.
586 EXPECT_TRUE(matches("double x = 1.2f;", DoubleStmt
));
587 EXPECT_TRUE(matches("double x = 1.2l;", DoubleStmt
));
589 EXPECT_TRUE(matches("double x = 12e-1;", DoubleStmt
));
590 EXPECT_FALSE(matches("double x = 1.23;", DoubleStmt
));
592 Matcher
<Stmt
> IntegerStmt
= constructMatcher(
593 "integerLiteral", constructMatcher("equals", VariantValue(42)))
594 .getTypedMatcher
<Stmt
>();
595 EXPECT_TRUE(matches("int x = 42;", IntegerStmt
));
596 EXPECT_FALSE(matches("int x = 1;", IntegerStmt
));
598 Matcher
<Stmt
> CharStmt
= constructMatcher(
599 "characterLiteral", constructMatcher("equals", VariantValue('x')))
600 .getTypedMatcher
<Stmt
>();
601 EXPECT_TRUE(matches("int x = 'x';", CharStmt
));
602 EXPECT_TRUE(matches("int x = L'x';", CharStmt
));
603 EXPECT_TRUE(matches("int x = u'x';", CharStmt
));
604 EXPECT_TRUE(matches("int x = U'x';", CharStmt
));
605 EXPECT_FALSE(matches("int x = 120;", CharStmt
));
608 } // end anonymous namespace
609 } // end namespace dynamic
610 } // end namespace ast_matchers
611 } // end namespace clang