xref: /llvm-project/clang/unittests/ASTMatchers/Dynamic/RegistryTest.cpp (revision f434c4fa3f86cacb7a9cee2f9ca827caf933fc0c)
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     return Registry::lookupMatcherCtor(MatcherName);
40   }
41 
42   VariantMatcher constructMatcher(StringRef MatcherName,
43                                   Diagnostics *Error = NULL) {
44     Diagnostics DummyError;
45     if (!Error) Error = &DummyError;
46     llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName);
47     VariantMatcher Out;
48     if (Ctor)
49       Out = Registry::constructMatcher(*Ctor, SourceRange(), Args(), Error);
50     EXPECT_EQ("", DummyError.toStringFull());
51     return Out;
52   }
53 
54   VariantMatcher constructMatcher(StringRef MatcherName,
55                                   const VariantValue &Arg1,
56                                   Diagnostics *Error = NULL) {
57     Diagnostics DummyError;
58     if (!Error) Error = &DummyError;
59     llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName);
60     VariantMatcher Out;
61     if (Ctor)
62       Out = Registry::constructMatcher(*Ctor, SourceRange(), Args(Arg1), Error);
63     EXPECT_EQ("", DummyError.toStringFull()) << MatcherName;
64     return Out;
65   }
66 
67   VariantMatcher constructMatcher(StringRef MatcherName,
68                                   const VariantValue &Arg1,
69                                   const VariantValue &Arg2,
70                                   Diagnostics *Error = NULL) {
71     Diagnostics DummyError;
72     if (!Error) Error = &DummyError;
73     llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName);
74     VariantMatcher Out;
75     if (Ctor)
76       Out = Registry::constructMatcher(*Ctor, SourceRange(), Args(Arg1, Arg2),
77                                        Error);
78     EXPECT_EQ("", DummyError.toStringFull());
79     return Out;
80   }
81 
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   }
125 };
126 
127 TEST_F(RegistryTest, CanConstructNoArgs) {
128   Matcher<Stmt> IsArrowValue = constructMatcher(
129       "memberExpr", constructMatcher("isArrow")).getTypedMatcher<Stmt>();
130   Matcher<Stmt> BoolValue =
131       constructMatcher("boolLiteral").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", std::string("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", std::string("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("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));
208 
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));
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", std::string("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       "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));
268 }
269 
270 TEST_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 
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       "constructorDecl",
303       constructMatcher(
304           "hasAnyConstructorInitializer",
305           constructMatcher("forField",
306                            constructMatcher("hasName", std::string("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", 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 
344 TEST_F(RegistryTest, VariadicOp) {
345   Matcher<Decl> D = constructMatcher(
346       "anyOf",
347       constructMatcher("recordDecl",
348                        constructMatcher("hasName", std::string("Foo"))),
349       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));
371 
372   D = recordDecl(
373       has(fieldDecl(hasName("Foo"))),
374       constructMatcher(
375           "unless",
376           constructMatcher("namedDecl",
377                            constructMatcher("hasName", std::string("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 
384 TEST_F(RegistryTest, Errors) {
385   // Incorrect argument count.
386   std::unique_ptr<Diagnostics> Error(new Diagnostics());
387   EXPECT_TRUE(constructMatcher("hasInitializer", Error.get()).isNull());
388   EXPECT_EQ("Incorrect argument count. (Expected = 1) != (Actual = 0)",
389             Error->toString());
390   Error.reset(new Diagnostics());
391   EXPECT_TRUE(constructMatcher("isArrow", std::string(), Error.get()).isNull());
392   EXPECT_EQ("Incorrect argument count. (Expected = 0) != (Actual = 1)",
393             Error->toString());
394   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());
403 
404   // Bad argument type
405   Error.reset(new Diagnostics());
406   EXPECT_TRUE(constructMatcher("ofClass", std::string(), Error.get()).isNull());
407   EXPECT_EQ("Incorrect type for arg 1. (Expected = Matcher<CXXRecordDecl>) != "
408             "(Actual = String)",
409             Error->toString());
410   Error.reset(new Diagnostics());
411   EXPECT_TRUE(constructMatcher("recordDecl", constructMatcher("recordDecl"),
412                                constructMatcher("parameterCountIs", 3),
413                                Error.get()).isNull());
414   EXPECT_EQ("Incorrect type for arg 2. (Expected = Matcher<CXXRecordDecl>) != "
415             "(Actual = Matcher<FunctionDecl>)",
416             Error->toString());
417 
418   // Bad argument type with variadic.
419   Error.reset(new Diagnostics());
420   EXPECT_TRUE(constructMatcher("anyOf", std::string(), std::string(),
421                                Error.get()).isNull());
422   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());
436 }
437 
438 TEST_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 
479 } // end anonymous namespace
480 } // end namespace dynamic
481 } // end namespace ast_matchers
482 } // end namespace clang
483