20#include "llvm/ADT/StringMap.h"
21#include "llvm/ADT/StringRef.h"
22#include "llvm/Support/ManagedStatic.h"
23#include "llvm/Support/raw_ostream.h"
41 llvm::StringMap<std::unique_ptr<const MatcherDescriptor>>;
48 const ConstructorMap &constructors()
const {
return Constructors; }
51 void registerMatcher(StringRef MatcherName,
52 std::unique_ptr<MatcherDescriptor> Callback);
54 ConstructorMap Constructors;
59void RegistryMaps::registerMatcher(
60 StringRef MatcherName, std::unique_ptr<MatcherDescriptor> Callback) {
61 assert(!Constructors.contains(MatcherName));
62 Constructors[MatcherName] = std::move(Callback);
65#define REGISTER_MATCHER(name) \
66 registerMatcher(#name, internal::makeMatcherAutoMarshall( \
67 ::clang::ast_matchers::name, #name));
69#define REGISTER_MATCHER_OVERLOAD(name) \
70 registerMatcher(#name, \
71 std::make_unique<internal::OverloadedMatcherDescriptor>(name##Callbacks))
73#define SPECIFIC_MATCHER_OVERLOAD(name, Id) \
74 static_cast<::clang::ast_matchers::name##_Type##Id>( \
75 ::clang::ast_matchers::name)
77#define MATCHER_OVERLOAD_ENTRY(name, Id) \
78 internal::makeMatcherAutoMarshall(SPECIFIC_MATCHER_OVERLOAD(name, Id), \
81#define REGISTER_OVERLOADED_2(name) \
83 std::unique_ptr<MatcherDescriptor> name##Callbacks[] = { \
84 MATCHER_OVERLOAD_ENTRY(name, 0), \
85 MATCHER_OVERLOAD_ENTRY(name, 1)}; \
86 REGISTER_MATCHER_OVERLOAD(name); \
89#define REGISTER_REGEX_MATCHER(name) \
90 registerMatcher(#name, internal::makeMatcherRegexMarshall(name, name))
94RegistryMaps::RegistryMaps() {
103 registerMatcher(
"mapAnyOf",
104 std::make_unique<internal::MapAnyOfBuilderDescriptor>());
118 std::unique_ptr<MatcherDescriptor> equalsCallbacks[] = {
623RegistryMaps::~RegistryMaps() =
default;
649 auto it =
RegistryData->constructors().find(MatcherName);
650 return it ==
RegistryData->constructors().end() ? std::optional<MatcherCtor>()
655 const std::set<ASTNodeKind> &KS) {
657 for (std::set<ASTNodeKind>::const_iterator I = KS.begin(), E = KS.end();
671 ArrayRef<std::pair<MatcherCtor, unsigned>> Context) {
683 std::set<ArgKind> TypeSet;
684 for (
auto IT : InitialTypes) {
687 for (
const auto &CtxEntry : Context) {
689 unsigned ArgNumber = CtxEntry.second;
690 std::vector<ArgKind> NextTypeSet;
691 for (
const ArgKind &Kind : TypeSet) {
692 if (Kind.getArgKind() == Kind.AK_Matcher &&
694 (Ctor->
isVariadic() || ArgNumber < Ctor->getNumArgs()))
695 Ctor->
getArgKinds(Kind.getMatcherKind(), ArgNumber, NextTypeSet);
698 TypeSet.insert(NextTypeSet.begin(), NextTypeSet.end());
700 return std::vector<ArgKind>(TypeSet.begin(), TypeSet.end());
703std::vector<MatcherCompletion>
705 std::vector<MatcherCompletion> Completions;
710 StringRef Name = M.getKey();
712 std::set<ASTNodeKind> RetKinds;
715 std::vector<std::vector<ArgKind>> ArgsKinds(NumArgs);
716 unsigned MaxSpecificity = 0;
717 bool NodeArgs =
false;
718 for (
const ArgKind& Kind : AcceptedTypes) {
719 if (Kind.getArgKind() != Kind.AK_Matcher &&
720 Kind.getArgKind() != Kind.AK_Node) {
724 if (Kind.getArgKind() == Kind.AK_Node) {
726 unsigned Specificity;
729 &LeastDerivedKind)) {
730 if (MaxSpecificity < Specificity)
731 MaxSpecificity = Specificity;
732 RetKinds.insert(LeastDerivedKind);
733 for (
unsigned Arg = 0; Arg != NumArgs; ++Arg)
734 Matcher.
getArgKinds(Kind.getNodeKind(), Arg, ArgsKinds[Arg]);
739 unsigned Specificity;
742 &LeastDerivedKind)) {
743 if (MaxSpecificity < Specificity)
744 MaxSpecificity = Specificity;
745 RetKinds.insert(LeastDerivedKind);
746 for (
unsigned Arg = 0; Arg != NumArgs; ++Arg)
747 Matcher.
getArgKinds(Kind.getMatcherKind(), Arg, ArgsKinds[Arg]);
754 if (!RetKinds.empty() && MaxSpecificity > 0) {
756 llvm::raw_string_ostream OS(
Decl);
758 std::string TypedText = std::string(Name);
765 OS <<
"Matcher<T> " << Name <<
"(Matcher<T>";
767 OS <<
"Matcher<" << RetKinds <<
"> " << Name <<
"(";
768 for (
const std::vector<ArgKind> &Arg : ArgsKinds) {
769 if (&Arg != &ArgsKinds[0])
772 bool FirstArgKind =
true;
773 std::set<ASTNodeKind> MatcherKinds;
775 for (
const ArgKind &AK : Arg) {
777 MatcherKinds.insert(AK.getMatcherKind());
781 FirstArgKind =
false;
785 if (!MatcherKinds.empty()) {
786 if (!FirstArgKind) OS <<
"|";
787 OS <<
"Matcher<" << MatcherKinds <<
">";
796 if (ArgsKinds.empty())
802 Completions.emplace_back(TypedText,
Decl, MaxSpecificity);
822 if (Out.isNull())
return Out;
824 std::optional<DynTypedMatcher>
Result = Out.getSingleMatcher();
826 std::optional<DynTypedMatcher> Bound =
Result->tryBind(BindID);
831 Error->addError(NameRange,
Error->ET_RegistryNotBindable);
Diagnostics class to manage error messages.
static bool hasDefinition(const ObjCObjectPointerType *ObjPtr)
static bool isExternC(const NamedDecl *ND)
Functions templates and classes to wrap matcher construct functions.
#define MATCHER_OVERLOAD_ENTRY(name, Id)
#define REGISTER_MATCHER_OVERLOAD(name)
#define REGISTER_MATCHER(name)
#define REGISTER_REGEX_MATCHER(name)
#define REGISTER_OVERLOADED_2(name)
Registry of all known matchers.
static bool hasAttr(const Decl *D, bool IgnoreImplicitAttr)
static constexpr ASTNodeKind getFromNodeKind()
Construct an identifier for T.
Decl - This represents one declaration (or definition), e.g.
static ArgKind MakeMatcherArg(ASTNodeKind MatcherKind)
Constructor for matcher types.
Helper class to manage error messages.
Matcher descriptor interface.
virtual void getArgKinds(ASTNodeKind ThisKind, unsigned ArgNo, std::vector< ArgKind > &ArgKinds) const =0
Given that the matcher is being converted to type ThisKind, append the set of argument types accepted...
virtual bool isPolymorphic() const
Returns whether the matcher will, given a matcher of any type T, yield a matcher of type T.
virtual bool isVariadic() const =0
Returns whether the matcher is variadic.
virtual unsigned getNumArgs() const =0
Returns the number of arguments accepted by the matcher if not variadic.
virtual bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity=nullptr, ASTNodeKind *LeastDerivedKind=nullptr) const =0
Returns whether this matcher is convertible to the given type.
static std::vector< ArgKind > getAcceptedCompletionTypes(llvm::ArrayRef< std::pair< MatcherCtor, unsigned > > Context)
Compute the list of completion types for Context.
static bool isBuilderMatcher(MatcherCtor Ctor)
static ASTNodeKind nodeMatcherType(MatcherCtor)
static std::optional< MatcherCtor > lookupMatcherCtor(StringRef MatcherName)
Look up a matcher in the registry by name,.
static internal::MatcherDescriptorPtr buildMatcherCtor(MatcherCtor, SourceRange NameRange, ArrayRef< ParserValue > Args, Diagnostics *Error)
static std::vector< MatcherCompletion > getMatcherCompletions(ArrayRef< ArgKind > AcceptedTypes)
Compute the list of completions that match any of AcceptedTypes.
static VariantMatcher constructBoundMatcher(MatcherCtor Ctor, SourceRange NameRange, StringRef BindID, ArrayRef< ParserValue > Args, Diagnostics *Error)
Construct a matcher from the registry and bind it.
static VariantMatcher constructMatcher(MatcherCtor Ctor, SourceRange NameRange, ArrayRef< ParserValue > Args, Diagnostics *Error)
Construct a matcher from the registry.
A variant matcher object.
static VariantMatcher SingleMatcher(const DynTypedMatcher &Matcher)
Clones the provided matcher.
A smart (owning) pointer for MatcherDescriptor.
MatcherDescriptorPtr(MatcherDescriptor *)
Matcher descriptor interface.
virtual bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity=nullptr, ASTNodeKind *LeastDerivedKind=nullptr) const =0
Returns whether this matcher is convertible to the given type.
virtual bool isBuilderMatcher() const
virtual void getArgKinds(ASTNodeKind ThisKind, unsigned ArgNo, std::vector< ArgKind > &ArgKinds) const =0
Given that the matcher is being converted to type ThisKind, append the set of argument types accepted...
virtual std::unique_ptr< MatcherDescriptor > buildMatcherCtor(SourceRange NameRange, ArrayRef< ParserValue > Args, Diagnostics *Error) const
virtual bool isVariadic() const =0
Returns whether the matcher is variadic.
virtual ASTNodeKind nodeMatcherType() const
virtual VariantMatcher create(SourceRange NameRange, ArrayRef< ParserValue > Args, Diagnostics *Error) const =0
static llvm::ManagedStatic< RegistryMaps > RegistryData
static llvm::raw_ostream & operator<<(llvm::raw_ostream &OS, const std::set< ASTNodeKind > &KS)
const internal::MatcherDescriptor * MatcherCtor
The JSON file list parser is used to communicate input to InstallAPI.
@ Result
The result type of a method or function.