xref: /llvm-project/clang/unittests/ASTMatchers/Dynamic/RegistryTest.cpp (revision a083935d0ab092d801c726ade8f2d16ea0ca9ba1)
1 //===- 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 
10 #include "../ASTMatchersTest.h"
11 #include "clang/ASTMatchers/Dynamic/Registry.h"
12 #include "gtest/gtest.h"
13 #include <vector>
14 
15 namespace clang {
16 namespace ast_matchers {
17 namespace dynamic {
18 namespace {
19 
20 using ast_matchers::internal::Matcher;
21 
22 class RegistryTest : public ::testing::Test {
23 public:
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   }
37 
38   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 
48   VariantMatcher constructMatcher(StringRef MatcherName,
49                                   Diagnostics *Error = NULL) {
50     Diagnostics DummyError;
51     if (!Error) Error = &DummyError;
52     llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName, Error);
53     VariantMatcher Out;
54     if (Ctor)
55       Out = Registry::constructMatcher(*Ctor, SourceRange(), Args(), Error);
56     EXPECT_EQ("", DummyError.toStringFull());
57     return Out;
58   }
59 
60   VariantMatcher constructMatcher(StringRef MatcherName,
61                                   const VariantValue &Arg1,
62                                   Diagnostics *Error = NULL) {
63     Diagnostics DummyError;
64     if (!Error) Error = &DummyError;
65     llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName, Error);
66     VariantMatcher Out;
67     if (Ctor)
68       Out = Registry::constructMatcher(*Ctor, SourceRange(), Args(Arg1), Error);
69     EXPECT_EQ("", DummyError.toStringFull()) << MatcherName;
70     return Out;
71   }
72 
73   VariantMatcher constructMatcher(StringRef MatcherName,
74                                   const VariantValue &Arg1,
75                                   const VariantValue &Arg2,
76                                   Diagnostics *Error = NULL) {
77     Diagnostics DummyError;
78     if (!Error) Error = &DummyError;
79     llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName, Error);
80     VariantMatcher Out;
81     if (Ctor)
82       Out = Registry::constructMatcher(*Ctor, SourceRange(), Args(Arg1, Arg2),
83                                        Error);
84     EXPECT_EQ("", DummyError.toStringFull());
85     return Out;
86   }
87 
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   }
131 };
132 
133 TEST_F(RegistryTest, CanConstructNoArgs) {
134   Matcher<Stmt> IsArrowValue = constructMatcher(
135       "memberExpr", constructMatcher("isArrow")).getTypedMatcher<Stmt>();
136   Matcher<Stmt> BoolValue =
137       constructMatcher("boolLiteral").getTypedMatcher<Stmt>();
138 
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 
144   EXPECT_TRUE(matches(ClassSnippet, IsArrowValue));
145   EXPECT_TRUE(matches(BoolSnippet, BoolValue));
146   EXPECT_FALSE(matches(ClassSnippet, BoolValue));
147   EXPECT_FALSE(matches(BoolSnippet, IsArrowValue));
148 }
149 
150 TEST_F(RegistryTest, ConstructWithSimpleArgs) {
151   Matcher<Decl> Value = constructMatcher(
152       "namedDecl", constructMatcher("hasName", std::string("X")))
153       .getTypedMatcher<Decl>();
154   EXPECT_TRUE(matches("class X {};", Value));
155   EXPECT_FALSE(matches("int x;", Value));
156 
157   Value = functionDecl(constructMatcher("parameterCountIs", 2)
158                            .getTypedMatcher<FunctionDecl>());
159   EXPECT_TRUE(matches("void foo(int,int);", Value));
160   EXPECT_FALSE(matches("void foo(int);", Value));
161 }
162 
163 TEST_F(RegistryTest, ConstructWithMatcherArgs) {
164   Matcher<Decl> HasInitializerSimple = constructMatcher(
165       "varDecl", constructMatcher("hasInitializer", constructMatcher("stmt")))
166       .getTypedMatcher<Decl>();
167   Matcher<Decl> HasInitializerComplex = constructMatcher(
168       "varDecl",
169       constructMatcher("hasInitializer", constructMatcher("callExpr")))
170       .getTypedMatcher<Decl>();
171 
172   std::string code = "int i;";
173   EXPECT_FALSE(matches(code, HasInitializerSimple));
174   EXPECT_FALSE(matches(code, HasInitializerComplex));
175 
176   code = "int i = 1;";
177   EXPECT_TRUE(matches(code, HasInitializerSimple));
178   EXPECT_FALSE(matches(code, HasInitializerComplex));
179 
180   code = "int y(); int i = y();";
181   EXPECT_TRUE(matches(code, HasInitializerSimple));
182   EXPECT_TRUE(matches(code, HasInitializerComplex));
183 
184   Matcher<Decl> HasParameter =
185       functionDecl(constructMatcher(
186           "hasParameter", 1, constructMatcher("hasName", std::string("x")))
187                        .getTypedMatcher<FunctionDecl>());
188   EXPECT_TRUE(matches("void f(int a, int x);", HasParameter));
189   EXPECT_FALSE(matches("void f(int x, int a);", HasParameter));
190 }
191 
192 TEST_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   Matcher<Decl> DeclDecl = declaratorDecl(hasTypeLoc(
216       constructMatcher(
217           "loc", constructMatcher("asString", std::string("const double *")))
218           .getTypedMatcher<TypeLoc>()));
219 
220   Matcher<NestedNameSpecifierLoc> NNSL =
221       constructMatcher(
222           "loc", VariantMatcher::SingleMatcher(nestedNameSpecifier(
223                      specifiesType(hasDeclaration(recordDecl(hasName("A")))))))
224           .getTypedMatcher<NestedNameSpecifierLoc>();
225 
226   Code = "const double * x = 0;";
227   EXPECT_TRUE(matches(Code, DeclDecl));
228   EXPECT_FALSE(matches(Code, NNSL));
229 
230   Code = "struct A { struct B {}; }; A::B a_b;";
231   EXPECT_FALSE(matches(Code, DeclDecl));
232   EXPECT_TRUE(matches(Code, NNSL));
233 }
234 
235 TEST_F(RegistryTest, PolymorphicMatchers) {
236   const VariantMatcher IsDefinition = constructMatcher("isDefinition");
237   Matcher<Decl> Var =
238       constructMatcher("varDecl", IsDefinition).getTypedMatcher<Decl>();
239   Matcher<Decl> Class =
240       constructMatcher("recordDecl", IsDefinition).getTypedMatcher<Decl>();
241   Matcher<Decl> Func =
242       constructMatcher("functionDecl", IsDefinition).getTypedMatcher<Decl>();
243   EXPECT_TRUE(matches("int a;", Var));
244   EXPECT_FALSE(matches("extern int a;", Var));
245   EXPECT_TRUE(matches("class A {};", Class));
246   EXPECT_FALSE(matches("class A;", Class));
247   EXPECT_TRUE(matches("void f(){};", Func));
248   EXPECT_FALSE(matches("void f();", Func));
249 
250   Matcher<Decl> Anything = constructMatcher("anything").getTypedMatcher<Decl>();
251   Matcher<Decl> RecordDecl = constructMatcher(
252       "recordDecl", constructMatcher("hasName", std::string("Foo")),
253       VariantMatcher::SingleMatcher(Anything)).getTypedMatcher<Decl>();
254 
255   EXPECT_TRUE(matches("int Foo;", Anything));
256   EXPECT_TRUE(matches("class Foo {};", Anything));
257   EXPECT_TRUE(matches("void Foo(){};", Anything));
258   EXPECT_FALSE(matches("int Foo;", RecordDecl));
259   EXPECT_TRUE(matches("class Foo {};", RecordDecl));
260   EXPECT_FALSE(matches("void Foo(){};", RecordDecl));
261 
262   Matcher<Stmt> ConstructExpr = constructMatcher(
263       "constructExpr",
264       constructMatcher(
265           "hasDeclaration",
266           constructMatcher(
267               "methodDecl",
268               constructMatcher(
269                   "ofClass", constructMatcher("hasName", std::string("Foo"))))))
270                                     .getTypedMatcher<Stmt>();
271   EXPECT_FALSE(matches("class Foo { public: Foo(); };", ConstructExpr));
272   EXPECT_TRUE(
273       matches("class Foo { public: Foo(); }; Foo foo = Foo();", ConstructExpr));
274 }
275 
276 TEST_F(RegistryTest, TemplateArgument) {
277   Matcher<Decl> HasTemplateArgument = constructMatcher(
278       "classTemplateSpecializationDecl",
279       constructMatcher(
280           "hasAnyTemplateArgument",
281           constructMatcher("refersToType",
282                            constructMatcher("asString", std::string("int")))))
283       .getTypedMatcher<Decl>();
284   EXPECT_TRUE(matches("template<typename T> class A {}; A<int> a;",
285                       HasTemplateArgument));
286   EXPECT_FALSE(matches("template<typename T> class A {}; A<char> a;",
287                        HasTemplateArgument));
288 }
289 
290 TEST_F(RegistryTest, TypeTraversal) {
291   Matcher<Type> M = constructMatcher(
292       "pointerType",
293       constructMatcher("pointee", constructMatcher("isConstQualified"),
294                        constructMatcher("isInteger"))).getTypedMatcher<Type>();
295   EXPECT_FALSE(matches("int *a;", M));
296   EXPECT_TRUE(matches("int const *b;", M));
297 
298   M = constructMatcher(
299       "arrayType",
300       constructMatcher("hasElementType", constructMatcher("builtinType")))
301       .getTypedMatcher<Type>();
302   EXPECT_FALSE(matches("struct A{}; A a[7];;", M));
303   EXPECT_TRUE(matches("int b[7];", M));
304 }
305 
306 TEST_F(RegistryTest, CXXCtorInitializer) {
307   Matcher<Decl> CtorDecl = constructMatcher(
308       "constructorDecl",
309       constructMatcher(
310           "hasAnyConstructorInitializer",
311           constructMatcher("forField",
312                            constructMatcher("hasName", std::string("foo")))))
313       .getTypedMatcher<Decl>();
314   EXPECT_TRUE(matches("struct Foo { Foo() : foo(1) {} int foo; };", CtorDecl));
315   EXPECT_FALSE(matches("struct Foo { Foo() {} int foo; };", CtorDecl));
316   EXPECT_FALSE(matches("struct Foo { Foo() : bar(1) {} int bar; };", CtorDecl));
317 }
318 
319 TEST_F(RegistryTest, Adaptative) {
320   Matcher<Decl> D = constructMatcher(
321       "recordDecl",
322       constructMatcher(
323           "has",
324           constructMatcher("recordDecl",
325                            constructMatcher("hasName", std::string("X")))))
326       .getTypedMatcher<Decl>();
327   EXPECT_TRUE(matches("class X {};", D));
328   EXPECT_TRUE(matches("class Y { class X {}; };", D));
329   EXPECT_FALSE(matches("class Y { class Z {}; };", D));
330 
331   Matcher<Stmt> S = constructMatcher(
332       "forStmt",
333       constructMatcher(
334           "hasDescendant",
335           constructMatcher("varDecl",
336                            constructMatcher("hasName", std::string("X")))))
337       .getTypedMatcher<Stmt>();
338   EXPECT_TRUE(matches("void foo() { for(int X;;); }", S));
339   EXPECT_TRUE(matches("void foo() { for(;;) { int X; } }", S));
340   EXPECT_FALSE(matches("void foo() { for(;;); }", S));
341   EXPECT_FALSE(matches("void foo() { if (int X = 0){} }", S));
342 
343   S = constructMatcher(
344       "compoundStmt", constructMatcher("hasParent", constructMatcher("ifStmt")))
345       .getTypedMatcher<Stmt>();
346   EXPECT_TRUE(matches("void foo() { if (true) { int x = 42; } }", S));
347   EXPECT_FALSE(matches("void foo() { if (true) return; }", S));
348 }
349 
350 TEST_F(RegistryTest, VariadicOp) {
351   Matcher<Decl> D = constructMatcher(
352       "anyOf",
353       constructMatcher("recordDecl",
354                        constructMatcher("hasName", std::string("Foo"))),
355       constructMatcher("namedDecl",
356                        constructMatcher("hasName", std::string("foo"))))
357       .getTypedMatcher<Decl>();
358 
359   EXPECT_TRUE(matches("void foo(){}", D));
360   EXPECT_TRUE(matches("struct Foo{};", D));
361   EXPECT_FALSE(matches("int i = 0;", D));
362 
363   D = constructMatcher(
364       "allOf", constructMatcher("recordDecl"),
365       constructMatcher(
366           "namedDecl",
367           constructMatcher("anyOf",
368                            constructMatcher("hasName", std::string("Foo")),
369                            constructMatcher("hasName", std::string("Bar")))))
370       .getTypedMatcher<Decl>();
371 
372   EXPECT_FALSE(matches("void foo(){}", D));
373   EXPECT_TRUE(matches("struct Foo{};", D));
374   EXPECT_FALSE(matches("int i = 0;", D));
375   EXPECT_TRUE(matches("class Bar{};", D));
376   EXPECT_FALSE(matches("class OtherBar{};", D));
377 
378   D = recordDecl(
379       has(fieldDecl(hasName("Foo"))),
380       constructMatcher(
381           "unless",
382           constructMatcher("namedDecl",
383                            constructMatcher("hasName", std::string("Bar"))))
384           .getTypedMatcher<Decl>());
385 
386   EXPECT_FALSE(matches("class Bar{ int Foo; };", D));
387   EXPECT_TRUE(matches("class OtherBar{ int Foo; };", D));
388 }
389 
390 TEST_F(RegistryTest, Errors) {
391   // Incorrect argument count.
392   std::unique_ptr<Diagnostics> Error(new Diagnostics());
393   EXPECT_TRUE(constructMatcher("hasInitializer", Error.get()).isNull());
394   EXPECT_EQ("Incorrect argument count. (Expected = 1) != (Actual = 0)",
395             Error->toString());
396   Error.reset(new Diagnostics());
397   EXPECT_TRUE(constructMatcher("isArrow", std::string(), Error.get()).isNull());
398   EXPECT_EQ("Incorrect argument count. (Expected = 0) != (Actual = 1)",
399             Error->toString());
400   Error.reset(new Diagnostics());
401   EXPECT_TRUE(constructMatcher("anyOf", Error.get()).isNull());
402   EXPECT_EQ("Incorrect argument count. (Expected = (2, )) != (Actual = 0)",
403             Error->toString());
404   Error.reset(new Diagnostics());
405   EXPECT_TRUE(constructMatcher("unless", std::string(), std::string(),
406                                Error.get()).isNull());
407   EXPECT_EQ("Incorrect argument count. (Expected = (1, 1)) != (Actual = 2)",
408             Error->toString());
409 
410   // Bad argument type
411   Error.reset(new Diagnostics());
412   EXPECT_TRUE(constructMatcher("ofClass", std::string(), Error.get()).isNull());
413   EXPECT_EQ("Incorrect type for arg 1. (Expected = Matcher<CXXRecordDecl>) != "
414             "(Actual = String)",
415             Error->toString());
416   Error.reset(new Diagnostics());
417   EXPECT_TRUE(constructMatcher("recordDecl", constructMatcher("recordDecl"),
418                                constructMatcher("parameterCountIs", 3),
419                                Error.get()).isNull());
420   EXPECT_EQ("Incorrect type for arg 2. (Expected = Matcher<CXXRecordDecl>) != "
421             "(Actual = Matcher<FunctionDecl>)",
422             Error->toString());
423 
424   // Bad argument type with variadic.
425   Error.reset(new Diagnostics());
426   EXPECT_TRUE(constructMatcher("anyOf", std::string(), std::string(),
427                                Error.get()).isNull());
428   EXPECT_EQ(
429       "Incorrect type for arg 1. (Expected = Matcher<>) != (Actual = String)",
430       Error->toString());
431   Error.reset(new Diagnostics());
432   EXPECT_TRUE(constructMatcher(
433       "recordDecl",
434       constructMatcher("allOf",
435                        constructMatcher("isDerivedFrom", std::string("FOO")),
436                        constructMatcher("isArrow")),
437       Error.get()).isNull());
438   EXPECT_EQ("Incorrect type for arg 1. "
439             "(Expected = Matcher<CXXRecordDecl>) != "
440             "(Actual = Matcher<CXXRecordDecl>&Matcher<MemberExpr>)",
441             Error->toString());
442 }
443 
444 TEST_F(RegistryTest, Completion) {
445   CompVector Comps = getCompletions();
446   EXPECT_TRUE(hasCompletion(
447       Comps, "hasParent(", "Matcher<Decl|Stmt> hasParent(Matcher<Decl|Stmt>)"));
448   EXPECT_TRUE(hasCompletion(Comps, "whileStmt(",
449                             "Matcher<Stmt> whileStmt(Matcher<WhileStmt>...)"));
450 
451   CompVector WhileComps = getCompletions("whileStmt", 0);
452 
453   unsigned HasBodyIndex, HasParentIndex, AllOfIndex;
454   EXPECT_TRUE(hasCompletion(WhileComps, "hasBody(",
455                             "Matcher<WhileStmt> hasBody(Matcher<Stmt>)",
456                             &HasBodyIndex));
457   EXPECT_TRUE(hasCompletion(WhileComps, "hasParent(",
458                             "Matcher<Stmt> hasParent(Matcher<Decl|Stmt>)",
459                             &HasParentIndex));
460   EXPECT_TRUE(hasCompletion(WhileComps, "allOf(",
461                             "Matcher<T> allOf(Matcher<T>...)", &AllOfIndex));
462   EXPECT_GT(HasParentIndex, HasBodyIndex);
463   EXPECT_GT(AllOfIndex, HasParentIndex);
464 
465   EXPECT_FALSE(hasCompletion(WhileComps, "whileStmt("));
466   EXPECT_FALSE(hasCompletion(WhileComps, "ifStmt("));
467 
468   CompVector AllOfWhileComps =
469       getCompletions("allOf", 0, "whileStmt", 0);
470   ASSERT_EQ(AllOfWhileComps.size(), WhileComps.size());
471   EXPECT_TRUE(std::equal(WhileComps.begin(), WhileComps.end(),
472                          AllOfWhileComps.begin()));
473 
474   CompVector DeclWhileComps =
475       getCompletions("decl", 0, "whileStmt", 0);
476   EXPECT_EQ(0u, DeclWhileComps.size());
477 
478   CompVector NamedDeclComps = getCompletions("namedDecl", 0);
479   EXPECT_TRUE(
480       hasCompletion(NamedDeclComps, "isPublic()", "Matcher<Decl> isPublic()"));
481   EXPECT_TRUE(hasCompletion(NamedDeclComps, "hasName(\"",
482                             "Matcher<NamedDecl> hasName(string)"));
483 }
484 
485 } // end anonymous namespace
486 } // end namespace dynamic
487 } // end namespace ast_matchers
488 } // end namespace clang
489