Index: lib/ASTMatchers/Dynamic/Registry.cpp =================================================================== --- lib/ASTMatchers/Dynamic/Registry.cpp +++ lib/ASTMatchers/Dynamic/Registry.cpp @@ -638,8 +638,26 @@ } } +using SR = ast_matchers::dynamic::SourceRange; + +llvm::Optional> +getNodeConstructorType(MatcherCtor targetCtor) { + auto const &ctors = RegistryData->nodeConstructors(); + + for (auto ctor : ctors) { + if (ctor.second.second == targetCtor) + return std::make_pair(ctor.first, ctor.second.first); + } + return llvm::None; +} + std::vector -Registry::getMatchingMatchers(ast_type_traits::ASTNodeKind StaticType) { +getDerivedResults(ast_type_traits::ASTNodeKind StaticType, StringRef Name); + +std::vector +getMatchingMatchersImpl(ast_type_traits::ASTNodeKind StaticType, + bool ExactOnly = false) { + std::vector Result; // Exclude matchers which can't unambiguously @@ -683,9 +701,33 @@ std::vector AcceptedTypes{StaticType}; processAcceptableMatchers( - AcceptedTypes, [&Result](StringRef Name, const MatcherDescriptor &, - std::set &, - std::vector>, unsigned) { + AcceptedTypes, [&](StringRef Name, const MatcherDescriptor &Matcher, + std::set &, + std::vector>, unsigned) { + { + unsigned Specificity; + ASTNodeKind LeastDerivedKind; + if (ExactOnly) { + auto IsConvertible = Matcher.isConvertibleTo( + StaticType, &Specificity, &LeastDerivedKind); + if (IsConvertible && !LeastDerivedKind.isSame(StaticType)) + return; + } + } + + { + auto TypeForMatcherOpt = getNodeConstructorType(&Matcher); + if (TypeForMatcherOpt) { + if (StaticType.isBaseOf(TypeForMatcherOpt->first)) { + auto DerivedResults = + getDerivedResults(TypeForMatcherOpt->first, Name); + Result.insert(Result.end(), DerivedResults.begin(), + DerivedResults.end()); + return; + } + } + } + if (!std::binary_search(ExcludedMatchers.begin(), ExcludedMatchers.end(), Name)) { Result.emplace_back((Name + "()").str()); @@ -695,6 +737,34 @@ return Result; } +std::vector +getDerivedResults(ast_type_traits::ASTNodeKind StaticType, StringRef Name) { + auto NestedResult = getMatchingMatchersImpl(StaticType, true); + + std::vector Result; + + Diagnostics DiagnosticIgnorer; + + for (auto item : NestedResult) { + + auto nestedMatcherName = item.MatcherString; + + nestedMatcherName = Name.str() + "(" + nestedMatcherName + ")"; + + Result.emplace_back(nestedMatcherName); + } + + return Result; +} + +std::vector +Registry::getMatchingMatchers(ast_type_traits::ASTNodeKind StaticType) { + + std::vector Result = getMatchingMatchersImpl(StaticType); + + 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 @@ -461,6 +461,17 @@ "Matcher " "hasDescendant(Matcher)")); + CompVector FuncDeclComps = getCompletions("functionDecl", 0); + + EXPECT_TRUE(!FuncDeclComps.empty()); + + // Exclude bases and self + EXPECT_TRUE(!hasCompletion(FuncDeclComps, "decl(")); + 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(", @@ -571,14 +582,14 @@ EXPECT_TRUE(Contains(Matchers, "hasType()")); EXPECT_TRUE(Contains(Matchers, "hasTypeLoc()")); EXPECT_TRUE(Contains(Matchers, "parameterCountIs()")); + EXPECT_TRUE(Contains(Matchers, "cxxMethodDecl(isOverride())")); 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()")); + EXPECT_TRUE(!Contains(Matchers, "cxxMethodDecl()")); EXPECT_TRUE(!Contains(Matchers, "has()")); }