Index: lib/ASTMatchers/Dynamic/Registry.cpp =================================================================== --- lib/ASTMatchers/Dynamic/Registry.cpp +++ lib/ASTMatchers/Dynamic/Registry.cpp @@ -561,9 +561,8 @@ return std::vector(TypeSet.begin(), TypeSet.end()); } -std::vector -Registry::getMatcherCompletions(ArrayRef AcceptedTypes) { - std::vector Completions; +template +void processAcceptableMatchers(ArrayRef AcceptedTypes, T func) { // Search the registry for acceptable matchers. for (const auto &M : RegistryData->constructors()) { @@ -593,49 +592,65 @@ } if (!RetKinds.empty() && MaxSpecificity > 0) { - std::string Decl; - llvm::raw_string_ostream OS(Decl); - - if (IsPolymorphic) { - OS << "Matcher " << Name << "(Matcher"; - } else { - OS << "Matcher<" << RetKinds << "> " << Name << "("; - for (const std::vector &Arg : ArgsKinds) { - if (&Arg != &ArgsKinds[0]) - OS << ", "; - - 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(); + func(Name, Matcher, RetKinds, ArgsKinds, MaxSpecificity); + } + } +} + +std::vector +Registry::getMatcherCompletions(ArrayRef AcceptedTypes) { + std::vector Completions; + + processAcceptableMatchers( + AcceptedTypes, + [&Completions](StringRef Name, const MatcherDescriptor &Matcher, + std::set &RetKinds, + std::vector> ArgsKinds, + unsigned MaxSpecificity) { + std::string Decl; + llvm::raw_string_ostream OS(Decl); + + if (Matcher.isPolymorphic()) { + OS << "Matcher " << Name << "(Matcher"; + } else { + OS << "Matcher<" << RetKinds << "> " << Name << "("; + for (const std::vector &Arg : ArgsKinds) { + if (&Arg != &ArgsKinds[0]) + OS << ", "; + + 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 << ">"; } - } - if (!MatcherKinds.empty()) { - if (!FirstArgKind) OS << "|"; - OS << "Matcher<" << MatcherKinds << ">"; } } - } - if (Matcher.isVariadic()) - OS << "..."; - OS << ")"; - - std::string TypedText = Name; - TypedText += "("; - if (ArgsKinds.empty()) - TypedText += ")"; - else if (ArgsKinds[0][0].getArgKind() == ArgKind::AK_String) - TypedText += "\""; - - Completions.emplace_back(TypedText, OS.str(), MaxSpecificity); - } - } + if (Matcher.isVariadic()) + OS << "..."; + OS << ")"; + + std::string TypedText = Name; + TypedText += "("; + if (ArgsKinds.empty()) + TypedText += ")"; + else if (ArgsKinds[0][0].getArgKind() == ArgKind::AK_String) + TypedText += "\""; + + Completions.emplace_back(TypedText, OS.str(), MaxSpecificity); + }); return Completions; }