Home | History | Annotate | Download | only in Dynamic
      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 = nullptr) {
     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 = nullptr) {
     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 = nullptr) {
     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         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(),
    114                      unsigned *Index = nullptr) {
    115     for (CompVector::const_iterator I = Comps.begin(), E = Comps.end(); I != E;
    116          ++I) {
    117       if (I->TypedText == TypedText &&
    118           (MatcherDecl.empty() || I->MatcherDecl == MatcherDecl)) {
    119         if (Index)
    120           *Index = I - Comps.begin();
    121         return true;
    122       }
    123     }
    124     return false;
    125   }
    126 };
    127 
    128 TEST_F(RegistryTest, CanConstructNoArgs) {
    129   Matcher<Stmt> IsArrowValue = constructMatcher(
    130       "memberExpr", constructMatcher("isArrow")).getTypedMatcher<Stmt>();
    131   Matcher<Stmt> BoolValue =
    132       constructMatcher("boolLiteral").getTypedMatcher<Stmt>();
    133 
    134   const std::string ClassSnippet = "struct Foo { int x; };\n"
    135                                    "Foo *foo = new Foo;\n"
    136                                    "int i = foo->x;\n";
    137   const std::string BoolSnippet = "bool Foo = true;\n";
    138 
    139   EXPECT_TRUE(matches(ClassSnippet, IsArrowValue));
    140   EXPECT_TRUE(matches(BoolSnippet, BoolValue));
    141   EXPECT_FALSE(matches(ClassSnippet, BoolValue));
    142   EXPECT_FALSE(matches(BoolSnippet, IsArrowValue));
    143 }
    144 
    145 TEST_F(RegistryTest, ConstructWithSimpleArgs) {
    146   Matcher<Decl> Value = constructMatcher(
    147       "namedDecl", constructMatcher("hasName", std::string("X")))
    148       .getTypedMatcher<Decl>();
    149   EXPECT_TRUE(matches("class X {};", Value));
    150   EXPECT_FALSE(matches("int x;", Value));
    151 
    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));
    156 }
    157 
    158 TEST_F(RegistryTest, ConstructWithMatcherArgs) {
    159   Matcher<Decl> HasInitializerSimple = constructMatcher(
    160       "varDecl", constructMatcher("hasInitializer", constructMatcher("stmt")))
    161       .getTypedMatcher<Decl>();
    162   Matcher<Decl> HasInitializerComplex = constructMatcher(
    163       "varDecl",
    164       constructMatcher("hasInitializer", constructMatcher("callExpr")))
    165       .getTypedMatcher<Decl>();
    166 
    167   std::string code = "int i;";
    168   EXPECT_FALSE(matches(code, HasInitializerSimple));
    169   EXPECT_FALSE(matches(code, HasInitializerComplex));
    170 
    171   code = "int i = 1;";
    172   EXPECT_TRUE(matches(code, HasInitializerSimple));
    173   EXPECT_FALSE(matches(code, HasInitializerComplex));
    174 
    175   code = "int y(); int i = y();";
    176   EXPECT_TRUE(matches(code, HasInitializerSimple));
    177   EXPECT_TRUE(matches(code, HasInitializerComplex));
    178 
    179   Matcher<Decl> HasParameter =
    180       functionDecl(constructMatcher(
    181           "hasParameter", 1, constructMatcher("hasName", std::string("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));
    185 }
    186 
    187 TEST_F(RegistryTest, OverloadedMatchers) {
    188   Matcher<Stmt> CallExpr0 = constructMatcher(
    189       "callExpr",
    190       constructMatcher("callee", constructMatcher("memberExpr",
    191                                                   constructMatcher("isArrow"))))
    192       .getTypedMatcher<Stmt>();
    193 
    194   Matcher<Stmt> CallExpr1 = constructMatcher(
    195       "callExpr",
    196       constructMatcher(
    197           "callee",
    198           constructMatcher("methodDecl",
    199                            constructMatcher("hasName", std::string("x")))))
    200       .getTypedMatcher<Stmt>();
    201 
    202   std::string Code = "class Y { public: void x(); }; void z() { Y y; y.x(); }";
    203   EXPECT_FALSE(matches(Code, CallExpr0));
    204   EXPECT_TRUE(matches(Code, CallExpr1));
    205 
    206   Code = "class Z { public: void z() { this->z(); } };";
    207   EXPECT_TRUE(matches(Code, CallExpr0));
    208   EXPECT_FALSE(matches(Code, CallExpr1));
    209 
    210   Matcher<Decl> DeclDecl = declaratorDecl(hasTypeLoc(
    211       constructMatcher(
    212           "loc", constructMatcher("asString", std::string("const double *")))
    213           .getTypedMatcher<TypeLoc>()));
    214 
    215   Matcher<NestedNameSpecifierLoc> NNSL =
    216       constructMatcher(
    217           "loc", VariantMatcher::SingleMatcher(nestedNameSpecifier(
    218                      specifiesType(hasDeclaration(recordDecl(hasName("A")))))))
    219           .getTypedMatcher<NestedNameSpecifierLoc>();
    220 
    221   Code = "const double * x = 0;";
    222   EXPECT_TRUE(matches(Code, DeclDecl));
    223   EXPECT_FALSE(matches(Code, NNSL));
    224 
    225   Code = "struct A { struct B {}; }; A::B a_b;";
    226   EXPECT_FALSE(matches(Code, DeclDecl));
    227   EXPECT_TRUE(matches(Code, NNSL));
    228 }
    229 
    230 TEST_F(RegistryTest, PolymorphicMatchers) {
    231   const VariantMatcher IsDefinition = constructMatcher("isDefinition");
    232   Matcher<Decl> Var =
    233       constructMatcher("varDecl", IsDefinition).getTypedMatcher<Decl>();
    234   Matcher<Decl> Class =
    235       constructMatcher("recordDecl", IsDefinition).getTypedMatcher<Decl>();
    236   Matcher<Decl> Func =
    237       constructMatcher("functionDecl", IsDefinition).getTypedMatcher<Decl>();
    238   EXPECT_TRUE(matches("int a;", Var));
    239   EXPECT_FALSE(matches("extern int a;", Var));
    240   EXPECT_TRUE(matches("class A {};", Class));
    241   EXPECT_FALSE(matches("class A;", Class));
    242   EXPECT_TRUE(matches("void f(){};", Func));
    243   EXPECT_FALSE(matches("void f();", Func));
    244 
    245   Matcher<Decl> Anything = constructMatcher("anything").getTypedMatcher<Decl>();
    246   Matcher<Decl> RecordDecl = constructMatcher(
    247       "recordDecl", constructMatcher("hasName", std::string("Foo")),
    248       VariantMatcher::SingleMatcher(Anything)).getTypedMatcher<Decl>();
    249 
    250   EXPECT_TRUE(matches("int Foo;", Anything));
    251   EXPECT_TRUE(matches("class Foo {};", Anything));
    252   EXPECT_TRUE(matches("void Foo(){};", Anything));
    253   EXPECT_FALSE(matches("int Foo;", RecordDecl));
    254   EXPECT_TRUE(matches("class Foo {};", RecordDecl));
    255   EXPECT_FALSE(matches("void Foo(){};", RecordDecl));
    256 
    257   Matcher<Stmt> ConstructExpr = constructMatcher(
    258       "constructExpr",
    259       constructMatcher(
    260           "hasDeclaration",
    261           constructMatcher(
    262               "methodDecl",
    263               constructMatcher(
    264                   "ofClass", constructMatcher("hasName", std::string("Foo"))))))
    265                                     .getTypedMatcher<Stmt>();
    266   EXPECT_FALSE(matches("class Foo { public: Foo(); };", ConstructExpr));
    267   EXPECT_TRUE(
    268       matches("class Foo { public: Foo(); }; Foo foo = Foo();", ConstructExpr));
    269 }
    270 
    271 TEST_F(RegistryTest, TemplateArgument) {
    272   Matcher<Decl> HasTemplateArgument = constructMatcher(
    273       "classTemplateSpecializationDecl",
    274       constructMatcher(
    275           "hasAnyTemplateArgument",
    276           constructMatcher("refersToType",
    277                            constructMatcher("asString", std::string("int")))))
    278       .getTypedMatcher<Decl>();
    279   EXPECT_TRUE(matches("template<typename T> class A {}; A<int> a;",
    280                       HasTemplateArgument));
    281   EXPECT_FALSE(matches("template<typename T> class A {}; A<char> a;",
    282                        HasTemplateArgument));
    283 }
    284 
    285 TEST_F(RegistryTest, TypeTraversal) {
    286   Matcher<Type> M = constructMatcher(
    287       "pointerType",
    288       constructMatcher("pointee", constructMatcher("isConstQualified"),
    289                        constructMatcher("isInteger"))).getTypedMatcher<Type>();
    290   EXPECT_FALSE(matches("int *a;", M));
    291   EXPECT_TRUE(matches("int const *b;", M));
    292 
    293   M = constructMatcher(
    294       "arrayType",
    295       constructMatcher("hasElementType", constructMatcher("builtinType")))
    296       .getTypedMatcher<Type>();
    297   EXPECT_FALSE(matches("struct A{}; A a[7];;", M));
    298   EXPECT_TRUE(matches("int b[7];", M));
    299 }
    300 
    301 TEST_F(RegistryTest, CXXCtorInitializer) {
    302   Matcher<Decl> CtorDecl = constructMatcher(
    303       "constructorDecl",
    304       constructMatcher(
    305           "hasAnyConstructorInitializer",
    306           constructMatcher("forField",
    307                            constructMatcher("hasName", std::string("foo")))))
    308       .getTypedMatcher<Decl>();
    309   EXPECT_TRUE(matches("struct Foo { Foo() : foo(1) {} int foo; };", CtorDecl));
    310   EXPECT_FALSE(matches("struct Foo { Foo() {} int foo; };", CtorDecl));
    311   EXPECT_FALSE(matches("struct Foo { Foo() : bar(1) {} int bar; };", CtorDecl));
    312 }
    313 
    314 TEST_F(RegistryTest, Adaptative) {
    315   Matcher<Decl> D = constructMatcher(
    316       "recordDecl",
    317       constructMatcher(
    318           "has",
    319           constructMatcher("recordDecl",
    320                            constructMatcher("hasName", std::string("X")))))
    321       .getTypedMatcher<Decl>();
    322   EXPECT_TRUE(matches("class X {};", D));
    323   EXPECT_TRUE(matches("class Y { class X {}; };", D));
    324   EXPECT_FALSE(matches("class Y { class Z {}; };", D));
    325 
    326   Matcher<Stmt> S = constructMatcher(
    327       "forStmt",
    328       constructMatcher(
    329           "hasDescendant",
    330           constructMatcher("varDecl",
    331                            constructMatcher("hasName", std::string("X")))))
    332       .getTypedMatcher<Stmt>();
    333   EXPECT_TRUE(matches("void foo() { for(int X;;); }", S));
    334   EXPECT_TRUE(matches("void foo() { for(;;) { int X; } }", S));
    335   EXPECT_FALSE(matches("void foo() { for(;;); }", S));
    336   EXPECT_FALSE(matches("void foo() { if (int X = 0){} }", S));
    337 
    338   S = constructMatcher(
    339       "compoundStmt", constructMatcher("hasParent", constructMatcher("ifStmt")))
    340       .getTypedMatcher<Stmt>();
    341   EXPECT_TRUE(matches("void foo() { if (true) { int x = 42; } }", S));
    342   EXPECT_FALSE(matches("void foo() { if (true) return; }", S));
    343 }
    344 
    345 TEST_F(RegistryTest, VariadicOp) {
    346   Matcher<Decl> D = constructMatcher(
    347       "anyOf",
    348       constructMatcher("recordDecl",
    349                        constructMatcher("hasName", std::string("Foo"))),
    350       constructMatcher("namedDecl",
    351                        constructMatcher("hasName", std::string("foo"))))
    352       .getTypedMatcher<Decl>();
    353 
    354   EXPECT_TRUE(matches("void foo(){}", D));
    355   EXPECT_TRUE(matches("struct Foo{};", D));
    356   EXPECT_FALSE(matches("int i = 0;", D));
    357 
    358   D = constructMatcher(
    359       "allOf", constructMatcher("recordDecl"),
    360       constructMatcher(
    361           "namedDecl",
    362           constructMatcher("anyOf",
    363                            constructMatcher("hasName", std::string("Foo")),
    364                            constructMatcher("hasName", std::string("Bar")))))
    365       .getTypedMatcher<Decl>();
    366 
    367   EXPECT_FALSE(matches("void foo(){}", D));
    368   EXPECT_TRUE(matches("struct Foo{};", D));
    369   EXPECT_FALSE(matches("int i = 0;", D));
    370   EXPECT_TRUE(matches("class Bar{};", D));
    371   EXPECT_FALSE(matches("class OtherBar{};", D));
    372 
    373   D = recordDecl(
    374       has(fieldDecl(hasName("Foo"))),
    375       constructMatcher(
    376           "unless",
    377           constructMatcher("namedDecl",
    378                            constructMatcher("hasName", std::string("Bar"))))
    379           .getTypedMatcher<Decl>());
    380 
    381   EXPECT_FALSE(matches("class Bar{ int Foo; };", D));
    382   EXPECT_TRUE(matches("class OtherBar{ int Foo; };", D));
    383 }
    384 
    385 TEST_F(RegistryTest, Errors) {
    386   // Incorrect argument count.
    387   std::unique_ptr<Diagnostics> Error(new Diagnostics());
    388   EXPECT_TRUE(constructMatcher("hasInitializer", Error.get()).isNull());
    389   EXPECT_EQ("Incorrect argument count. (Expected = 1) != (Actual = 0)",
    390             Error->toString());
    391   Error.reset(new Diagnostics());
    392   EXPECT_TRUE(constructMatcher("isArrow", std::string(), Error.get()).isNull());
    393   EXPECT_EQ("Incorrect argument count. (Expected = 0) != (Actual = 1)",
    394             Error->toString());
    395   Error.reset(new Diagnostics());
    396   EXPECT_TRUE(constructMatcher("anyOf", Error.get()).isNull());
    397   EXPECT_EQ("Incorrect argument count. (Expected = (2, )) != (Actual = 0)",
    398             Error->toString());
    399   Error.reset(new Diagnostics());
    400   EXPECT_TRUE(constructMatcher("unless", std::string(), std::string(),
    401                                Error.get()).isNull());
    402   EXPECT_EQ("Incorrect argument count. (Expected = (1, 1)) != (Actual = 2)",
    403             Error->toString());
    404 
    405   // Bad argument type
    406   Error.reset(new Diagnostics());
    407   EXPECT_TRUE(constructMatcher("ofClass", std::string(), Error.get()).isNull());
    408   EXPECT_EQ("Incorrect type for arg 1. (Expected = Matcher<CXXRecordDecl>) != "
    409             "(Actual = String)",
    410             Error->toString());
    411   Error.reset(new Diagnostics());
    412   EXPECT_TRUE(constructMatcher("recordDecl", constructMatcher("recordDecl"),
    413                                constructMatcher("parameterCountIs", 3),
    414                                Error.get()).isNull());
    415   EXPECT_EQ("Incorrect type for arg 2. (Expected = Matcher<CXXRecordDecl>) != "
    416             "(Actual = Matcher<FunctionDecl>)",
    417             Error->toString());
    418 
    419   // Bad argument type with variadic.
    420   Error.reset(new Diagnostics());
    421   EXPECT_TRUE(constructMatcher("anyOf", std::string(), std::string(),
    422                                Error.get()).isNull());
    423   EXPECT_EQ(
    424       "Incorrect type for arg 1. (Expected = Matcher<>) != (Actual = String)",
    425       Error->toString());
    426   Error.reset(new Diagnostics());
    427   EXPECT_TRUE(constructMatcher(
    428       "recordDecl",
    429       constructMatcher("allOf",
    430                        constructMatcher("isDerivedFrom", std::string("FOO")),
    431                        constructMatcher("isArrow")),
    432       Error.get()).isNull());
    433   EXPECT_EQ("Incorrect type for arg 1. "
    434             "(Expected = Matcher<CXXRecordDecl>) != "
    435             "(Actual = Matcher<CXXRecordDecl>&Matcher<MemberExpr>)",
    436             Error->toString());
    437 }
    438 
    439 TEST_F(RegistryTest, Completion) {
    440   CompVector Comps = getCompletions();
    441   EXPECT_TRUE(hasCompletion(
    442       Comps, "hasParent(", "Matcher<Decl|Stmt> hasParent(Matcher<Decl|Stmt>)"));
    443   EXPECT_TRUE(hasCompletion(Comps, "whileStmt(",
    444                             "Matcher<Stmt> whileStmt(Matcher<WhileStmt>...)"));
    445 
    446   CompVector WhileComps = getCompletions("whileStmt", 0);
    447 
    448   unsigned HasBodyIndex, HasParentIndex, AllOfIndex;
    449   EXPECT_TRUE(hasCompletion(WhileComps, "hasBody(",
    450                             "Matcher<WhileStmt> hasBody(Matcher<Stmt>)",
    451                             &HasBodyIndex));
    452   EXPECT_TRUE(hasCompletion(WhileComps, "hasParent(",
    453                             "Matcher<Stmt> hasParent(Matcher<Decl|Stmt>)",
    454                             &HasParentIndex));
    455   EXPECT_TRUE(hasCompletion(WhileComps, "allOf(",
    456                             "Matcher<T> allOf(Matcher<T>...)", &AllOfIndex));
    457   EXPECT_GT(HasParentIndex, HasBodyIndex);
    458   EXPECT_GT(AllOfIndex, HasParentIndex);
    459 
    460   EXPECT_FALSE(hasCompletion(WhileComps, "whileStmt("));
    461   EXPECT_FALSE(hasCompletion(WhileComps, "ifStmt("));
    462 
    463   CompVector AllOfWhileComps =
    464       getCompletions("allOf", 0, "whileStmt", 0);
    465   ASSERT_EQ(AllOfWhileComps.size(), WhileComps.size());
    466   EXPECT_TRUE(std::equal(WhileComps.begin(), WhileComps.end(),
    467                          AllOfWhileComps.begin()));
    468 
    469   CompVector DeclWhileComps =
    470       getCompletions("decl", 0, "whileStmt", 0);
    471   EXPECT_EQ(0u, DeclWhileComps.size());
    472 
    473   CompVector NamedDeclComps = getCompletions("namedDecl", 0);
    474   EXPECT_TRUE(
    475       hasCompletion(NamedDeclComps, "isPublic()", "Matcher<Decl> isPublic()"));
    476   EXPECT_TRUE(hasCompletion(NamedDeclComps, "hasName(\"",
    477                             "Matcher<NamedDecl> hasName(string)"));
    478 }
    479 
    480 } // end anonymous namespace
    481 } // end namespace dynamic
    482 } // end namespace ast_matchers
    483 } // end namespace clang
    484