diff options
Diffstat (limited to 'unittests/ASTMatchers/Dynamic/RegistryTest.cpp')
-rw-r--r-- | unittests/ASTMatchers/Dynamic/RegistryTest.cpp | 164 |
1 files changed, 150 insertions, 14 deletions
diff --git a/unittests/ASTMatchers/Dynamic/RegistryTest.cpp b/unittests/ASTMatchers/Dynamic/RegistryTest.cpp index e716484e207f..e659b3a733d6 100644 --- a/unittests/ASTMatchers/Dynamic/RegistryTest.cpp +++ b/unittests/ASTMatchers/Dynamic/RegistryTest.cpp @@ -7,11 +7,10 @@ // //===-----------------------------------------------------------------------===// -#include <vector> - #include "../ASTMatchersTest.h" #include "clang/ASTMatchers/Dynamic/Registry.h" #include "gtest/gtest.h" +#include <vector> namespace clang { namespace ast_matchers { @@ -36,38 +35,94 @@ public: return Out; } + llvm::Optional<MatcherCtor> lookupMatcherCtor(StringRef MatcherName) { + return Registry::lookupMatcherCtor(MatcherName); + } + VariantMatcher constructMatcher(StringRef MatcherName, - Diagnostics *Error = NULL) { + Diagnostics *Error = nullptr) { Diagnostics DummyError; if (!Error) Error = &DummyError; - const VariantMatcher Out = - Registry::constructMatcher(MatcherName, SourceRange(), Args(), Error); + llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName); + VariantMatcher Out; + if (Ctor) + Out = Registry::constructMatcher(*Ctor, SourceRange(), Args(), Error); EXPECT_EQ("", DummyError.toStringFull()); return Out; } VariantMatcher constructMatcher(StringRef MatcherName, const VariantValue &Arg1, - Diagnostics *Error = NULL) { + Diagnostics *Error = nullptr) { Diagnostics DummyError; if (!Error) Error = &DummyError; - const VariantMatcher Out = Registry::constructMatcher( - MatcherName, SourceRange(), Args(Arg1), Error); - EXPECT_EQ("", DummyError.toStringFull()); + llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName); + VariantMatcher Out; + if (Ctor) + Out = Registry::constructMatcher(*Ctor, SourceRange(), Args(Arg1), Error); + EXPECT_EQ("", DummyError.toStringFull()) << MatcherName; return Out; } VariantMatcher constructMatcher(StringRef MatcherName, const VariantValue &Arg1, const VariantValue &Arg2, - Diagnostics *Error = NULL) { + Diagnostics *Error = nullptr) { Diagnostics DummyError; if (!Error) Error = &DummyError; - const VariantMatcher Out = Registry::constructMatcher( - MatcherName, SourceRange(), Args(Arg1, Arg2), Error); + llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName); + VariantMatcher Out; + if (Ctor) + Out = Registry::constructMatcher(*Ctor, SourceRange(), Args(Arg1, Arg2), + Error); EXPECT_EQ("", DummyError.toStringFull()); return Out; } + + typedef std::vector<MatcherCompletion> CompVector; + + CompVector getCompletions() { + return Registry::getCompletions( + ArrayRef<std::pair<MatcherCtor, unsigned> >()); + } + + CompVector getCompletions(StringRef MatcherName1, unsigned ArgNo1) { + std::vector<std::pair<MatcherCtor, unsigned> > Context; + llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName1); + if (!Ctor) + return CompVector(); + Context.push_back(std::make_pair(*Ctor, ArgNo1)); + return Registry::getCompletions(Context); + } + + CompVector getCompletions(StringRef MatcherName1, unsigned ArgNo1, + StringRef MatcherName2, unsigned ArgNo2) { + std::vector<std::pair<MatcherCtor, unsigned> > Context; + llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName1); + if (!Ctor) + return CompVector(); + Context.push_back(std::make_pair(*Ctor, ArgNo1)); + Ctor = lookupMatcherCtor(MatcherName2); + if (!Ctor) + return CompVector(); + Context.push_back(std::make_pair(*Ctor, ArgNo2)); + return Registry::getCompletions(Context); + } + + bool hasCompletion(const CompVector &Comps, StringRef TypedText, + StringRef MatcherDecl = StringRef(), + unsigned *Index = nullptr) { + for (CompVector::const_iterator I = Comps.begin(), E = Comps.end(); I != E; + ++I) { + if (I->TypedText == TypedText && + (MatcherDecl.empty() || I->MatcherDecl == MatcherDecl)) { + if (Index) + *Index = I - Comps.begin(); + return true; + } + } + return false; + } }; TEST_F(RegistryTest, CanConstructNoArgs) { @@ -151,6 +206,25 @@ TEST_F(RegistryTest, OverloadedMatchers) { Code = "class Z { public: void z() { this->z(); } };"; EXPECT_TRUE(matches(Code, CallExpr0)); EXPECT_FALSE(matches(Code, CallExpr1)); + + Matcher<Decl> DeclDecl = declaratorDecl(hasTypeLoc( + constructMatcher( + "loc", constructMatcher("asString", std::string("const double *"))) + .getTypedMatcher<TypeLoc>())); + + Matcher<NestedNameSpecifierLoc> NNSL = + constructMatcher( + "loc", VariantMatcher::SingleMatcher(nestedNameSpecifier( + specifiesType(hasDeclaration(recordDecl(hasName("A"))))))) + .getTypedMatcher<NestedNameSpecifierLoc>(); + + Code = "const double * x = 0;"; + EXPECT_TRUE(matches(Code, DeclDecl)); + EXPECT_FALSE(matches(Code, NNSL)); + + Code = "struct A { struct B {}; }; A::B a_b;"; + EXPECT_FALSE(matches(Code, DeclDecl)); + EXPECT_TRUE(matches(Code, NNSL)); } TEST_F(RegistryTest, PolymorphicMatchers) { @@ -295,11 +369,22 @@ TEST_F(RegistryTest, VariadicOp) { EXPECT_FALSE(matches("int i = 0;", D)); EXPECT_TRUE(matches("class Bar{};", D)); EXPECT_FALSE(matches("class OtherBar{};", D)); + + D = recordDecl( + has(fieldDecl(hasName("Foo"))), + constructMatcher( + "unless", + constructMatcher("namedDecl", + constructMatcher("hasName", std::string("Bar")))) + .getTypedMatcher<Decl>()); + + EXPECT_FALSE(matches("class Bar{ int Foo; };", D)); + EXPECT_TRUE(matches("class OtherBar{ int Foo; };", D)); } TEST_F(RegistryTest, Errors) { // Incorrect argument count. - OwningPtr<Diagnostics> Error(new Diagnostics()); + std::unique_ptr<Diagnostics> Error(new Diagnostics()); EXPECT_TRUE(constructMatcher("hasInitializer", Error.get()).isNull()); EXPECT_EQ("Incorrect argument count. (Expected = 1) != (Actual = 0)", Error->toString()); @@ -307,6 +392,15 @@ TEST_F(RegistryTest, Errors) { EXPECT_TRUE(constructMatcher("isArrow", std::string(), Error.get()).isNull()); EXPECT_EQ("Incorrect argument count. (Expected = 0) != (Actual = 1)", Error->toString()); + Error.reset(new Diagnostics()); + EXPECT_TRUE(constructMatcher("anyOf", Error.get()).isNull()); + EXPECT_EQ("Incorrect argument count. (Expected = (2, )) != (Actual = 0)", + Error->toString()); + Error.reset(new Diagnostics()); + EXPECT_TRUE(constructMatcher("unless", std::string(), std::string(), + Error.get()).isNull()); + EXPECT_EQ("Incorrect argument count. (Expected = (1, 1)) != (Actual = 2)", + Error->toString()); // Bad argument type Error.reset(new Diagnostics()); @@ -324,7 +418,8 @@ TEST_F(RegistryTest, Errors) { // Bad argument type with variadic. Error.reset(new Diagnostics()); - EXPECT_TRUE(constructMatcher("anyOf", std::string(), Error.get()).isNull()); + EXPECT_TRUE(constructMatcher("anyOf", std::string(), std::string(), + Error.get()).isNull()); EXPECT_EQ( "Incorrect type for arg 1. (Expected = Matcher<>) != (Actual = String)", Error->toString()); @@ -341,6 +436,47 @@ TEST_F(RegistryTest, Errors) { Error->toString()); } +TEST_F(RegistryTest, Completion) { + CompVector Comps = getCompletions(); + EXPECT_TRUE(hasCompletion( + Comps, "hasParent(", "Matcher<Decl|Stmt> hasParent(Matcher<Decl|Stmt>)")); + EXPECT_TRUE(hasCompletion(Comps, "whileStmt(", + "Matcher<Stmt> whileStmt(Matcher<WhileStmt>...)")); + + CompVector WhileComps = getCompletions("whileStmt", 0); + + unsigned HasBodyIndex, HasParentIndex, AllOfIndex; + EXPECT_TRUE(hasCompletion(WhileComps, "hasBody(", + "Matcher<WhileStmt> hasBody(Matcher<Stmt>)", + &HasBodyIndex)); + EXPECT_TRUE(hasCompletion(WhileComps, "hasParent(", + "Matcher<Stmt> hasParent(Matcher<Decl|Stmt>)", + &HasParentIndex)); + EXPECT_TRUE(hasCompletion(WhileComps, "allOf(", + "Matcher<T> allOf(Matcher<T>...)", &AllOfIndex)); + EXPECT_GT(HasParentIndex, HasBodyIndex); + EXPECT_GT(AllOfIndex, HasParentIndex); + + EXPECT_FALSE(hasCompletion(WhileComps, "whileStmt(")); + EXPECT_FALSE(hasCompletion(WhileComps, "ifStmt(")); + + CompVector AllOfWhileComps = + getCompletions("allOf", 0, "whileStmt", 0); + ASSERT_EQ(AllOfWhileComps.size(), WhileComps.size()); + EXPECT_TRUE(std::equal(WhileComps.begin(), WhileComps.end(), + AllOfWhileComps.begin())); + + CompVector DeclWhileComps = + getCompletions("decl", 0, "whileStmt", 0); + EXPECT_EQ(0u, DeclWhileComps.size()); + + CompVector NamedDeclComps = getCompletions("namedDecl", 0); + EXPECT_TRUE( + hasCompletion(NamedDeclComps, "isPublic()", "Matcher<Decl> isPublic()")); + EXPECT_TRUE(hasCompletion(NamedDeclComps, "hasName(\"", + "Matcher<NamedDecl> hasName(string)")); +} + } // end anonymous namespace } // end namespace dynamic } // end namespace ast_matchers |