From: Samuel Benzaquen Date: Thu, 9 Oct 2014 22:08:52 +0000 (+0000) Subject: Fix completion logic to allow for heterogeneous argument types in matcher overloads. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=768b9300b5549a0d1a0ecb670c6e1d21d42cf9f7;p=clang Fix completion logic to allow for heterogeneous argument types in matcher overloads. Summary: There was an assumption that there were no matchers that were overloaded on matchers and other types of arguments. This assumption was broken recently with the addition of new matcher overloads. Fixes http://llvm.org/PR21226 Reviewers: pcc Subscribers: klimek, cfe-commits Differential Revision: http://reviews.llvm.org/D5711 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@219450 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/ASTMatchers/Dynamic/Registry.cpp b/lib/ASTMatchers/Dynamic/Registry.cpp index 5672169d3d..b92e8ef6bf 100644 --- a/lib/ASTMatchers/Dynamic/Registry.cpp +++ b/lib/ASTMatchers/Dynamic/Registry.cpp @@ -443,17 +443,22 @@ Registry::getMatcherCompletions(ArrayRef AcceptedTypes) { for (const std::vector &Arg : ArgsKinds) { if (&Arg != &ArgsKinds[0]) OS << ", "; - // This currently assumes that a matcher may not overload a - // non-matcher, and all non-matcher overloads have identical - // arguments. - if (Arg[0].getArgKind() == ArgKind::AK_Matcher) { - std::set MatcherKinds; - std::transform(Arg.begin(), Arg.end(), - std::inserter(MatcherKinds, MatcherKinds.end()), - std::mem_fun_ref(&ArgKind::getMatcherKind)); + + bool FirstArgKind = true; + std::set 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 << "|"; OS << "Matcher<" << MatcherKinds << ">"; - } else { - OS << Arg[0].asString(); } } } diff --git a/unittests/ASTMatchers/Dynamic/RegistryTest.cpp b/unittests/ASTMatchers/Dynamic/RegistryTest.cpp index 824b310442..9011b3f65e 100644 --- a/unittests/ASTMatchers/Dynamic/RegistryTest.cpp +++ b/unittests/ASTMatchers/Dynamic/RegistryTest.cpp @@ -438,10 +438,18 @@ TEST_F(RegistryTest, Errors) { TEST_F(RegistryTest, Completion) { CompVector Comps = getCompletions(); + // Overloaded EXPECT_TRUE(hasCompletion( Comps, "hasParent(", "Matcher hasParent(Matcher)")); + // Variadic. EXPECT_TRUE(hasCompletion(Comps, "whileStmt(", "Matcher whileStmt(Matcher...)")); + // Polymorphic. + EXPECT_TRUE(hasCompletion( + Comps, "hasDescendant(", + "Matcher " + "hasDescendant(Matcher)")); CompVector WhileComps = getCompletions("whileStmt", 0); @@ -470,6 +478,12 @@ TEST_F(RegistryTest, Completion) { hasCompletion(NamedDeclComps, "isPublic()", "Matcher isPublic()")); EXPECT_TRUE(hasCompletion(NamedDeclComps, "hasName(\"", "Matcher hasName(string)")); + + // Heterogeneous overloads. + Comps = getCompletions("classTemplateSpecializationDecl", 0); + EXPECT_TRUE(hasCompletion( + Comps, "isSameOrDerivedFrom(", + "Matcher isSameOrDerivedFrom(string|Matcher)")); } TEST_F(RegistryTest, HasArgs) {