Index: lib/ASTMatchers/Dynamic/Registry.cpp =================================================================== --- lib/ASTMatchers/Dynamic/Registry.cpp +++ lib/ASTMatchers/Dynamic/Registry.cpp @@ -647,17 +647,79 @@ } } +llvm::Optional> +getNodeConstructorType(MatcherCtor targetCtor) { + const auto &ctors = RegistryData->nodeConstructors(); + auto it = llvm::find_if( + ctors, [targetCtor](const NodeConstructorMap::value_type &ctor) { + return ctor.second.second == targetCtor; + }); + if (it == ctors.end()) { + return llvm::None; + } + return std::make_pair(it->first, it->second.first); +} + std::vector -Registry::getMatchingMatchers(ast_type_traits::ASTNodeKind StaticType) { +getDerivedResults(ast_type_traits::ASTNodeKind StaticType, StringRef Name); + +enum MatchScope { ExactOnly, IncludeDerived }; + +std::vector +getMatchingMatchersImpl(ast_type_traits::ASTNodeKind StaticType, + MatchScope Scope) { + std::vector Result; std::vector AcceptedTypes{StaticType}; processAcceptableMatchers( - AcceptedTypes, - [&Result](StringRef Name, const MatcherDescriptor &, - std::set &, std::vector>, - unsigned) { Result.emplace_back((Name + "()").str()); }); + AcceptedTypes, [&](StringRef Name, const MatcherDescriptor &Matcher, + std::set &, + std::vector>, unsigned) { + unsigned Specificity; + ASTNodeKind LeastDerivedKind; + if (Scope == ExactOnly) { + if (Matcher.isConvertibleTo(StaticType, &Specificity, + &LeastDerivedKind) && + !LeastDerivedKind.isSame(StaticType)) + return; + } + + auto TypeForMatcherOpt = getNodeConstructorType(&Matcher); + if (TypeForMatcherOpt && + StaticType.isBaseOf(TypeForMatcherOpt->first)) { + auto Derived = getDerivedResults(TypeForMatcherOpt->first, Name); + Result.insert(Result.end(), Derived.begin(), Derived.end()); + return; + } + + Result.emplace_back((Name + "()").str()); + }); + + return Result; +} + +std::vector +getDerivedResults(ast_type_traits::ASTNodeKind StaticType, StringRef Name) { + auto NestedResult = getMatchingMatchersImpl(StaticType, ExactOnly); + + std::vector Result; + + Diagnostics DiagnosticIgnorer; + + for (const auto &item : NestedResult) { + Result.emplace_back((Name + "(" + item.MatcherString + ")").str()); + } + + return Result; +} + +std::vector +Registry::getMatchingMatchers(ast_type_traits::ASTNodeKind StaticType) { + + std::vector Result = + getMatchingMatchersImpl(StaticType, IncludeDerived); return Result; } Index: unittests/ASTMatchers/Dynamic/RegistryTest.cpp =================================================================== --- unittests/ASTMatchers/Dynamic/RegistryTest.cpp +++ unittests/ASTMatchers/Dynamic/RegistryTest.cpp @@ -461,6 +461,16 @@ "Matcher " "hasDescendant(Matcher)")); + CompVector FuncDeclComps = getCompletions("functionDecl", 0); + + EXPECT_TRUE(!FuncDeclComps.empty()); + + // Exclude bases + EXPECT_TRUE(!hasCompletion(FuncDeclComps, "namedDecl(")); + EXPECT_TRUE(!hasCompletion(FuncDeclComps, "valueDecl(")); + EXPECT_TRUE(!hasCompletion(FuncDeclComps, "declaratorDecl(")); + EXPECT_TRUE(!hasCompletion(FuncDeclComps, "functionDecl(")); + CompVector WhileComps = getCompletions("whileStmt", 0); EXPECT_TRUE(hasCompletion(WhileComps, "hasBody(", @@ -569,13 +579,13 @@ EXPECT_TRUE(Contains(Matchers, "isPublic()")); EXPECT_TRUE(Contains(Matchers, "hasName()")); EXPECT_TRUE(Contains(Matchers, "parameterCountIs()")); + EXPECT_TRUE(Contains(Matchers, "cxxMethodDecl(isOverride())")); EXPECT_FALSE(Contains(Matchers, "namedDecl()")); EXPECT_FALSE(Contains(Matchers, "valueDecl()")); EXPECT_FALSE(Contains(Matchers, "declaratorDecl()")); EXPECT_FALSE(Contains(Matchers, "functionDecl()")); - - EXPECT_TRUE(Contains(Matchers, "cxxMethodDecl()")); + EXPECT_FALSE(Contains(Matchers, "cxxMethodDecl()")); } } // end anonymous namespace