Introduce Registry::getCompletions.
This returns a list of valid (and useful) completions for a context (a list
of outer matchers), ordered by decreasing relevance then alphabetically. It
will be used by the matcher parser to implement completion.
Differential Revision: http://llvm-reviews.chandlerc.com/D2210
llvm-svn: 199950
diff --git a/clang/unittests/ASTMatchers/Dynamic/RegistryTest.cpp b/clang/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
index c260b46..8426649 100644
--- a/clang/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
+++ b/clang/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
@@ -84,6 +84,50 @@
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) {
@@ -378,6 +422,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