RegistryTest.cpp revision 6bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89
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
15namespace clang {
16namespace ast_matchers {
17namespace dynamic {
18namespace {
19
20using ast_matchers::internal::Matcher;
21
22class 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  }
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
127TEST_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
144TEST_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
157TEST_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
186TEST_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
229TEST_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
270TEST_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
284TEST_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
300TEST_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
313TEST_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
344TEST_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
384TEST_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
438TEST_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