Updated to Clang 3.5a.
Change-Id: I8127eb568f674c2e72635b639a3295381fe8af82
diff --git a/unittests/ASTMatchers/Dynamic/RegistryTest.cpp b/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
index e716484..150f8c9 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,12 +35,24 @@
return Out;
}
+ llvm::Optional<MatcherCtor> lookupMatcherCtor(StringRef MatcherName,
+ Diagnostics *Error = 0) {
+ Diagnostics DummyError;
+ if (!Error) Error = &DummyError;
+ llvm::Optional<MatcherCtor> Ctor =
+ Registry::lookupMatcherCtor(MatcherName, SourceRange(), Error);
+ EXPECT_EQ("", DummyError.toStringFull());
+ return Ctor;
+ }
+
VariantMatcher constructMatcher(StringRef MatcherName,
Diagnostics *Error = NULL) {
Diagnostics DummyError;
if (!Error) Error = &DummyError;
- const VariantMatcher Out =
- Registry::constructMatcher(MatcherName, SourceRange(), Args(), Error);
+ llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName, Error);
+ VariantMatcher Out;
+ if (Ctor)
+ Out = Registry::constructMatcher(*Ctor, SourceRange(), Args(), Error);
EXPECT_EQ("", DummyError.toStringFull());
return Out;
}
@@ -51,9 +62,11 @@
Diagnostics *Error = NULL) {
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, Error);
+ VariantMatcher Out;
+ if (Ctor)
+ Out = Registry::constructMatcher(*Ctor, SourceRange(), Args(Arg1), Error);
+ EXPECT_EQ("", DummyError.toStringFull()) << MatcherName;
return Out;
}
@@ -63,11 +76,58 @@
Diagnostics *Error = NULL) {
Diagnostics DummyError;
if (!Error) Error = &DummyError;
- const VariantMatcher Out = Registry::constructMatcher(
- MatcherName, SourceRange(), Args(Arg1, Arg2), Error);
+ llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName, Error);
+ 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(
+ llvm::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 = 0) {
+ 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 +211,25 @@
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 +374,22 @@
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 +397,15 @@
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 +423,8 @@
// 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 +441,47 @@
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