Index: include/clang/ASTMatchers/Dynamic/Registry.h =================================================================== --- include/clang/ASTMatchers/Dynamic/Registry.h +++ include/clang/ASTMatchers/Dynamic/Registry.h @@ -63,6 +63,12 @@ unsigned Specificity; }; +struct MatchingMatcher { + MatchingMatcher(std::string MatcherString) + : MatcherString(std::move(MatcherString)) {} + std::string MatcherString; +}; + class Registry { public: Registry() = delete; @@ -96,6 +102,11 @@ static std::vector getMatcherCompletions(ArrayRef AcceptedTypes); + /// Compute matchers which can be used within a matcher of + /// type @p StaticType. + static std::vector + getMatchingMatchers(ast_type_traits::ASTNodeKind StaticType); + /// Construct a matcher from the registry. /// /// \param Ctor The matcher constructor to instantiate. Index: lib/ASTMatchers/Dynamic/Registry.cpp =================================================================== --- lib/ASTMatchers/Dynamic/Registry.cpp +++ lib/ASTMatchers/Dynamic/Registry.cpp @@ -597,6 +597,24 @@ } } +std::vector +Registry::getMatchingMatchers(ast_type_traits::ASTNodeKind StaticType) { + std::vector Result; + + std::vector AcceptedTypes; + AcceptedTypes.push_back(StaticType); + + processAcceptableMatchers( + AcceptedTypes, [&Result](StringRef Name, const MatcherDescriptor &Matcher, + std::set &RetKinds, + std::vector> ArgsKinds, + unsigned MaxSpecificity) { + Result.emplace_back((Name + "()").str()); + }); + + return Result; +} + std::vector Registry::getMatcherCompletions(ArrayRef AcceptedTypes) { std::vector Completions; Index: unittests/ASTMatchers/Dynamic/RegistryTest.cpp =================================================================== --- unittests/ASTMatchers/Dynamic/RegistryTest.cpp +++ unittests/ASTMatchers/Dynamic/RegistryTest.cpp @@ -555,6 +555,32 @@ EXPECT_FALSE(matches("int x = 120;", CharStmt)); } +TEST_F(RegistryTest, MatchingMatchers) { + + auto Matchers = Registry::getMatchingMatchers( + ast_type_traits::ASTNodeKind::getFromNodeKind()); + + auto Contains = [](std::vector const &C, StringRef Name) { + return std::find_if(C.begin(), C.end(), [Name](const MatchingMatcher &M) { + return M.MatcherString == Name; + }) != C.end(); + }; + + EXPECT_TRUE(Contains(Matchers, "isPublic()")); + EXPECT_TRUE(Contains(Matchers, "hasName()")); + EXPECT_TRUE(Contains(Matchers, "hasType()")); + EXPECT_TRUE(Contains(Matchers, "hasTypeLoc()")); + EXPECT_TRUE(Contains(Matchers, "parameterCountIs()")); + + EXPECT_TRUE(!Contains(Matchers, "decl()")); + EXPECT_TRUE(!Contains(Matchers, "namedDecl()")); + EXPECT_TRUE(!Contains(Matchers, "valueDecl()")); + EXPECT_TRUE(!Contains(Matchers, "declaratorDecl()")); + EXPECT_TRUE(!Contains(Matchers, "functionDecl()")); + + EXPECT_TRUE(Contains(Matchers, "cxxMethodDecl()")); +} + } // end anonymous namespace } // end namespace dynamic } // end namespace ast_matchers