brintos

brintos / llvm-project-archived public Read only

0
0
Text · 23.6 KiB · 013bb91 Raw
612 lines · cpp
1//===- RegistryTest.cpp - Registry unit tests -----------------------------===//2//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "../ASTMatchersTest.h"10#include "clang/ASTMatchers/Dynamic/Registry.h"11#include "gtest/gtest.h"12#include <optional>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  std::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    std::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    std::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    std::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    std::vector<std::pair<MatcherCtor, unsigned> > Context;86    return Registry::getMatcherCompletions(87        Registry::getAcceptedCompletionTypes(Context));88  }89 90  CompVector getCompletions(StringRef MatcherName1, unsigned ArgNo1) {91    std::vector<std::pair<MatcherCtor, unsigned> > Context;92    std::optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName1);93    if (!Ctor)94      return CompVector();95    Context.push_back(std::make_pair(*Ctor, ArgNo1));96    return Registry::getMatcherCompletions(97        Registry::getAcceptedCompletionTypes(Context));98  }99 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);104    if (!Ctor)105      return CompVector();106    Context.push_back(std::make_pair(*Ctor, ArgNo1));107    Ctor = lookupMatcherCtor(MatcherName2);108    if (!Ctor)109      return CompVector();110    Context.push_back(std::make_pair(*Ctor, ArgNo2));111    return Registry::getMatcherCompletions(112        Registry::getAcceptedCompletionTypes(Context));113  }114 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;118         ++I) {119      if (I->TypedText == TypedText &&120          (MatcherDecl.empty() || I->MatcherDecl == MatcherDecl)) {121        return true;122      }123    }124    return false;125  }126};127 128TEST_F(RegistryTest, CanConstructNoArgs) {129  Matcher<Stmt> IsArrowValue = constructMatcher(130      "memberExpr", constructMatcher("isArrow")).getTypedMatcher<Stmt>();131  Matcher<Stmt> BoolValue =132      constructMatcher("cxxBoolLiteral").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 145TEST_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));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 158TEST_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", 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));185}186 187TEST_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("cxxMethodDecl",199                           constructMatcher("hasName", StringRef("x")))))200      .getTypedMatcher<Stmt>();201 202  Matcher<Stmt> ObjCMsgExpr =203      constructMatcher(204          "objcMessageExpr",205          constructMatcher(206              "callee",207              constructMatcher("objcMethodDecl",208                               constructMatcher("hasName", StringRef("x")))))209          .getTypedMatcher<Stmt>();210 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));215 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));220 221  Code = "@interface I "222         "+ (void)x; "223         "@end\n"224         "int main() { [I x]; }";225  EXPECT_FALSE(matchesObjC(Code, CallExpr0));226  EXPECT_FALSE(matchesObjC(Code, CallExpr1));227  EXPECT_TRUE(matchesObjC(Code, ObjCMsgExpr));228 229  Matcher<Decl> DeclDecl = declaratorDecl(hasTypeLoc(230      constructMatcher(231          "loc", constructMatcher("asString", StringRef("const double *")))232          .getTypedMatcher<TypeLoc>()));233 234  Matcher<NestedNameSpecifierLoc> NNSL =235      constructMatcher(236          "loc", VariantMatcher::SingleMatcher(nestedNameSpecifier(237                     specifiesType(hasDeclaration(recordDecl(hasName("A")))))))238          .getTypedMatcher<NestedNameSpecifierLoc>();239 240  Code = "const double * x = 0;";241  EXPECT_TRUE(matches(Code, DeclDecl));242  EXPECT_FALSE(matches(Code, NNSL));243 244  Code = "struct A { struct B {}; }; A::B a_b;";245  EXPECT_FALSE(matches(Code, DeclDecl));246  EXPECT_TRUE(matches(Code, NNSL));247}248 249TEST_F(RegistryTest, PolymorphicMatchers) {250  const VariantMatcher IsDefinition = constructMatcher("isDefinition");251  Matcher<Decl> Var =252      constructMatcher("varDecl", IsDefinition).getTypedMatcher<Decl>();253  Matcher<Decl> Class =254      constructMatcher("recordDecl", IsDefinition).getTypedMatcher<Decl>();255  Matcher<Decl> Func =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));263 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>();268 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));275 276  Matcher<Stmt> ConstructExpr = constructMatcher(277      "cxxConstructExpr",278      constructMatcher(279          "hasDeclaration",280          constructMatcher(281              "cxxMethodDecl",282              constructMatcher(283                  "ofClass", constructMatcher("hasName", StringRef("Foo"))))))284                                    .getTypedMatcher<Stmt>();285  EXPECT_FALSE(matches("class Foo { public: Foo(); };", ConstructExpr));286  EXPECT_TRUE(287      matches("class Foo { public: Foo(); }; Foo foo = Foo();", ConstructExpr));288}289 290TEST_F(RegistryTest, TemplateArgument) {291  Matcher<Decl> HasTemplateArgument = constructMatcher(292      "classTemplateSpecializationDecl",293      constructMatcher(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));302}303 304TEST_F(RegistryTest, TypeTraversal) {305  Matcher<Type> M = constructMatcher(306      "pointerType",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));311 312  M = constructMatcher(313      "arrayType",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));318}319 320TEST_F(RegistryTest, CXXBaseSpecifier) {321  // TODO: rewrite with top-level cxxBaseSpecifier matcher when available322  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));329}330 331TEST_F(RegistryTest, CXXCtorInitializer) {332  Matcher<Decl> CtorDecl = constructMatcher(333      "cxxConstructorDecl",334      constructMatcher(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));342}343 344TEST_F(RegistryTest, Adaptative) {345  Matcher<Decl> D = constructMatcher(346      "recordDecl",347      constructMatcher(348          "has",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));355 356  Matcher<Stmt> S = constructMatcher(357      "forStmt",358      constructMatcher(359          "hasDescendant",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));367 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));373}374 375TEST_F(RegistryTest, VariadicOp) {376  Matcher<Decl> D = constructMatcher(377      "anyOf",378      constructMatcher("recordDecl",379                       constructMatcher("hasName", StringRef("Foo"))),380      constructMatcher("functionDecl",381                       constructMatcher("hasName", StringRef("foo"))))382      .getTypedMatcher<Decl>();383 384  EXPECT_TRUE(matches("void foo(){}", D));385  EXPECT_TRUE(matches("struct Foo{};", D));386  EXPECT_FALSE(matches("int i = 0;", D));387 388  D = constructMatcher(389      "allOf", constructMatcher("recordDecl"),390      constructMatcher(391          "namedDecl",392          constructMatcher("anyOf",393                           constructMatcher("hasName", StringRef("Foo")),394                           constructMatcher("hasName", StringRef("Bar")))))395      .getTypedMatcher<Decl>();396 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));402 403  D = recordDecl(404      has(fieldDecl(hasName("Foo"))),405      constructMatcher(406          "unless",407          constructMatcher("namedDecl",408                           constructMatcher("hasName", StringRef("Bar"))))409          .getTypedMatcher<Decl>());410 411  EXPECT_FALSE(matches("class Bar{ int Foo; };", D));412  EXPECT_TRUE(matches("class OtherBar{ int Foo; };", D));413 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));420}421 422TEST_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)",427            Error->toString());428  Error.reset(new Diagnostics());429  EXPECT_TRUE(constructMatcher("isArrow", StringRef(), Error.get()).isNull());430  EXPECT_EQ("Incorrect argument count. (Expected = 0) != (Actual = 1)",431            Error->toString());432  Error.reset(new Diagnostics());433  EXPECT_TRUE(constructMatcher("anyOf", Error.get()).isNull());434  EXPECT_EQ("Incorrect argument count. (Expected = (2, )) != (Actual = 0)",435            Error->toString());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)",440            Error->toString());441 442  // Bad argument type443  Error.reset(new Diagnostics());444  EXPECT_TRUE(constructMatcher("ofClass", StringRef(), Error.get()).isNull());445  EXPECT_EQ("Incorrect type for arg 1. (Expected = Matcher<CXXRecordDecl>) != "446            "(Actual = String)",447            Error->toString());448  Error.reset(new Diagnostics());449  EXPECT_TRUE(450      constructMatcher("cxxRecordDecl", constructMatcher("cxxRecordDecl"),451                       constructMatcher("parameterCountIs", 3), Error.get())452          .isNull());453  EXPECT_EQ("Incorrect type for arg 2. (Expected = Matcher<CXXRecordDecl>) != "454            "(Actual = Matcher<FunctionDecl|FunctionProtoType>)",455            Error->toString());456 457  // Bad argument type with variadic.458  Error.reset(new Diagnostics());459  EXPECT_TRUE(constructMatcher("anyOf", StringRef(), StringRef(),460                               Error.get()).isNull());461  EXPECT_EQ(462      "Incorrect type for arg 1. (Expected = Matcher<>) != (Actual = String)",463      Error->toString());464  Error.reset(new Diagnostics());465  EXPECT_TRUE(constructMatcher(466      "cxxRecordDecl",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>)",475            Error->toString());476}477 478TEST_F(RegistryTest, Completion) {479  CompVector Comps = getCompletions();480  // Overloaded481  EXPECT_TRUE(hasCompletion(482      Comps, "hasParent(",483      "Matcher<NestedNameSpecifierLoc|TypeLoc|Decl|...> "484      "hasParent(Matcher<NestedNameSpecifierLoc|TypeLoc|Decl|...>)"));485  // Variadic.486  EXPECT_TRUE(hasCompletion(Comps, "whileStmt(",487                            "Matcher<Stmt> whileStmt(Matcher<WhileStmt>...)"));488  // Polymorphic.489  EXPECT_TRUE(hasCompletion(490      Comps, "hasDescendant(",491      "Matcher<NestedNameSpecifierLoc|QualType|TypeLoc|...> "492      "hasDescendant(Matcher<NestedNameSpecifierLoc|QualType|TypeLoc|...>)"));493 494  CompVector WhileComps = getCompletions("whileStmt", 0);495 496  EXPECT_TRUE(hasCompletion(WhileComps, "hasBody(",497                            "Matcher<WhileStmt> hasBody(Matcher<Stmt>)"));498  EXPECT_TRUE(hasCompletion(499      WhileComps, "hasParent(",500      "Matcher<Stmt> "501      "hasParent(Matcher<NestedNameSpecifierLoc|TypeLoc|Decl|...>)"));502  EXPECT_TRUE(503      hasCompletion(WhileComps, "allOf(", "Matcher<T> allOf(Matcher<T>...)"));504 505  EXPECT_FALSE(hasCompletion(WhileComps, "whileStmt("));506  EXPECT_FALSE(hasCompletion(WhileComps, "ifStmt("));507 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()));513 514  CompVector DeclWhileComps =515      getCompletions("decl", 0, "whileStmt", 0);516  EXPECT_EQ(0u, DeclWhileComps.size());517 518  CompVector NamedDeclComps = getCompletions("namedDecl", 0);519  EXPECT_TRUE(520      hasCompletion(NamedDeclComps, "isPublic()", "Matcher<Decl> isPublic()"));521  EXPECT_TRUE(hasCompletion(NamedDeclComps, "hasName(\"",522                            "Matcher<NamedDecl> hasName(string)"));523 524  // Heterogeneous overloads.525  Comps = getCompletions("classTemplateSpecializationDecl", 0);526  EXPECT_TRUE(hasCompletion(527      Comps, "isSameOrDerivedFrom(",528      "Matcher<CXXRecordDecl> isSameOrDerivedFrom(string|Matcher<NamedDecl>)"));529}530 531TEST_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));540 541  auto NotBuiltCtor = Registry::buildMatcherCtor(Ctor, {}, Args(ASTNodeKind::getFromNodeKind<FunctionDecl>(), ASTNodeKind::getFromNodeKind<ForStmt>()), nullptr);542  EXPECT_FALSE(NotBuiltCtor.get());543}544 545TEST_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());549}550 551TEST_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));557}558 559TEST_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)));563}564 565TEST_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));572 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));579 580  Matcher<Stmt> DoubleStmt = constructMatcher(581      "floatLiteral", constructMatcher("equals", VariantValue(1.2)))582      .getTypedMatcher<Stmt>();583  EXPECT_TRUE(matches("double x = 1.2;", DoubleStmt));584#if 0585  // 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));588#endif589  EXPECT_TRUE(matches("double x = 12e-1;", DoubleStmt));590  EXPECT_FALSE(matches("double x = 1.23;", DoubleStmt));591 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));597 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));606}607 608} // end anonymous namespace609} // end namespace dynamic610} // end namespace ast_matchers611} // end namespace clang612