bool IsPolymorphic = Matcher.isPolymorphic();
std::vector<std::vector<ArgKind>> ArgsKinds(NumArgs);
unsigned MaxSpecificity = 0;
+ bool NodeArgs = false;
for (const ArgKind& Kind : AcceptedTypes) {
- if (Kind.getArgKind() != Kind.AK_Matcher)
+ if (Kind.getArgKind() != Kind.AK_Matcher &&
+ Kind.getArgKind() != Kind.AK_Node) {
continue;
- unsigned Specificity;
- ASTNodeKind LeastDerivedKind;
- if (Matcher.isConvertibleTo(Kind.getMatcherKind(), &Specificity,
- &LeastDerivedKind)) {
- if (MaxSpecificity < Specificity)
- MaxSpecificity = Specificity;
- RetKinds.insert(LeastDerivedKind);
- for (unsigned Arg = 0; Arg != NumArgs; ++Arg)
- Matcher.getArgKinds(Kind.getMatcherKind(), Arg, ArgsKinds[Arg]);
- if (IsPolymorphic)
- break;
+ }
+
+ if (Kind.getArgKind() == Kind.AK_Node) {
+ NodeArgs = true;
+ unsigned Specificity;
+ ASTNodeKind LeastDerivedKind;
+ if (Matcher.isConvertibleTo(Kind.getNodeKind(), &Specificity,
+ &LeastDerivedKind)) {
+ if (MaxSpecificity < Specificity)
+ MaxSpecificity = Specificity;
+ RetKinds.insert(LeastDerivedKind);
+ for (unsigned Arg = 0; Arg != NumArgs; ++Arg)
+ Matcher.getArgKinds(Kind.getNodeKind(), Arg, ArgsKinds[Arg]);
+ if (IsPolymorphic)
+ break;
+ }
+ } else {
+ unsigned Specificity;
+ ASTNodeKind LeastDerivedKind;
+ if (Matcher.isConvertibleTo(Kind.getMatcherKind(), &Specificity,
+ &LeastDerivedKind)) {
+ if (MaxSpecificity < Specificity)
+ MaxSpecificity = Specificity;
+ RetKinds.insert(LeastDerivedKind);
+ for (unsigned Arg = 0; Arg != NumArgs; ++Arg)
+ Matcher.getArgKinds(Kind.getMatcherKind(), Arg, ArgsKinds[Arg]);
+ if (IsPolymorphic)
+ break;
+ }
}
}
std::string Decl;
llvm::raw_string_ostream OS(Decl);
- if (IsPolymorphic) {
- OS << "Matcher<T> " << Name << "(Matcher<T>";
+ std::string TypedText = std::string(Name);
+
+ if (NodeArgs) {
+ OS << Name;
} else {
- OS << "Matcher<" << RetKinds << "> " << Name << "(";
- for (const std::vector<ArgKind> &Arg : ArgsKinds) {
- if (&Arg != &ArgsKinds[0])
- OS << ", ";
-
- bool FirstArgKind = true;
- std::set<ASTNodeKind> MatcherKinds;
- // Two steps. First all non-matchers, then matchers only.
- for (const ArgKind &AK : Arg) {
- if (AK.getArgKind() == ArgKind::AK_Matcher) {
- MatcherKinds.insert(AK.getMatcherKind());
- } else {
+
+ if (IsPolymorphic) {
+ OS << "Matcher<T> " << Name << "(Matcher<T>";
+ } else {
+ OS << "Matcher<" << RetKinds << "> " << Name << "(";
+ for (const std::vector<ArgKind> &Arg : ArgsKinds) {
+ if (&Arg != &ArgsKinds[0])
+ OS << ", ";
+
+ bool FirstArgKind = true;
+ std::set<ASTNodeKind> MatcherKinds;
+ // Two steps. First all non-matchers, then matchers only.
+ for (const ArgKind &AK : Arg) {
+ if (AK.getArgKind() == ArgKind::AK_Matcher) {
+ MatcherKinds.insert(AK.getMatcherKind());
+ } else {
+ if (!FirstArgKind)
+ OS << "|";
+ FirstArgKind = false;
+ OS << AK.asString();
+ }
+ }
+ if (!MatcherKinds.empty()) {
if (!FirstArgKind) OS << "|";
- FirstArgKind = false;
- OS << AK.asString();
+ OS << "Matcher<" << MatcherKinds << ">";
}
}
- if (!MatcherKinds.empty()) {
- if (!FirstArgKind) OS << "|";
- OS << "Matcher<" << MatcherKinds << ">";
- }
}
+ if (Matcher.isVariadic())
+ OS << "...";
+ OS << ")";
+
+ TypedText += "(";
+ if (ArgsKinds.empty())
+ TypedText += ")";
+ else if (ArgsKinds[0][0].getArgKind() == ArgKind::AK_String)
+ TypedText += "\"";
}
- if (Matcher.isVariadic())
- OS << "...";
- OS << ")";
-
- std::string TypedText = std::string(Name);
- TypedText += "(";
- if (ArgsKinds.empty())
- TypedText += ")";
- else if (ArgsKinds[0][0].getArgKind() == ArgKind::AK_String)
- TypedText += "\"";
Completions.emplace_back(TypedText, OS.str(), MaxSpecificity);
}
ASSERT_EQ(1u, Comps.size());
EXPECT_EQ("bind(\"", Comps[0].TypedText);
EXPECT_EQ("bind", Comps[0].MatcherDecl);
+
+ Code = "mapAny";
+ Comps = Parser::completeExpression(Code, 6);
+ ASSERT_EQ(1u, Comps.size());
+ EXPECT_EQ("Of(", Comps[0].TypedText);
+ EXPECT_EQ("Matcher<NestedNameSpecifierLoc|QualType|TypeLoc|...> "
+ "mapAnyOf(NestedNameSpecifierLoc|QualType|TypeLoc|"
+ "NestedNameSpecifier|Decl|Stmt|Type...)",
+ Comps[0].MatcherDecl);
+
+ Code = "mapAnyOf(ifStmt).";
+ Comps = Parser::completeExpression(Code, 17);
+ ASSERT_EQ(2u, Comps.size());
+ EXPECT_EQ("bind(\"", Comps[0].TypedText);
+ EXPECT_EQ("bind", Comps[0].MatcherDecl);
+ EXPECT_EQ("with(", Comps[1].TypedText);
+ EXPECT_EQ("with", Comps[1].MatcherDecl);
+
+ Code = "mapAnyOf(ifS";
+ Comps = Parser::completeExpression(Code, 12);
+ ASSERT_EQ(1u, Comps.size());
+ EXPECT_EQ("tmt", Comps[0].TypedText);
+ EXPECT_EQ("ifStmt", Comps[0].MatcherDecl);
}
TEST(ParserTest, CompletionNamedValues) {