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[] = {
621RegistryMaps::~RegistryMaps() =
default;
647 auto it =
RegistryData->constructors().find(MatcherName);
648 return it ==
RegistryData->constructors().end() ? std::optional<MatcherCtor>()
653 const std::set<ASTNodeKind> &KS) {
655 for (std::set<ASTNodeKind>::const_iterator I = KS.begin(), E = KS.end();
669 ArrayRef<std::pair<MatcherCtor, unsigned>> Context) {
681 std::set<ArgKind> TypeSet;
682 for (
auto IT : InitialTypes) {
685 for (
const auto &CtxEntry : Context) {
687 unsigned ArgNumber = CtxEntry.second;
688 std::vector<ArgKind> NextTypeSet;
689 for (
const ArgKind &Kind : TypeSet) {
690 if (Kind.getArgKind() == Kind.AK_Matcher &&
692 (Ctor->
isVariadic() || ArgNumber < Ctor->getNumArgs()))
693 Ctor->
getArgKinds(Kind.getMatcherKind(), ArgNumber, NextTypeSet);
696 TypeSet.insert(NextTypeSet.begin(), NextTypeSet.end());
698 return std::vector<ArgKind>(TypeSet.begin(), TypeSet.end());
701std::vector<MatcherCompletion>
703 std::vector<MatcherCompletion> Completions;
708 StringRef Name = M.getKey();
710 std::set<ASTNodeKind> RetKinds;
713 std::vector<std::vector<ArgKind>> ArgsKinds(NumArgs);
714 unsigned MaxSpecificity = 0;
715 bool NodeArgs =
false;
716 for (
const ArgKind& Kind : AcceptedTypes) {
717 if (Kind.getArgKind() != Kind.AK_Matcher &&
718 Kind.getArgKind() != Kind.AK_Node) {
722 if (Kind.getArgKind() == Kind.AK_Node) {
724 unsigned Specificity;
727 &LeastDerivedKind)) {
728 if (MaxSpecificity < Specificity)
729 MaxSpecificity = Specificity;
730 RetKinds.insert(LeastDerivedKind);
731 for (
unsigned Arg = 0; Arg != NumArgs; ++Arg)
732 Matcher.
getArgKinds(Kind.getNodeKind(), Arg, ArgsKinds[Arg]);
737 unsigned Specificity;
740 &LeastDerivedKind)) {
741 if (MaxSpecificity < Specificity)
742 MaxSpecificity = Specificity;
743 RetKinds.insert(LeastDerivedKind);
744 for (
unsigned Arg = 0; Arg != NumArgs; ++Arg)
745 Matcher.
getArgKinds(Kind.getMatcherKind(), Arg, ArgsKinds[Arg]);
752 if (!RetKinds.empty() && MaxSpecificity > 0) {
754 llvm::raw_string_ostream OS(
Decl);
756 std::string TypedText = std::string(Name);
763 OS <<
"Matcher<T> " << Name <<
"(Matcher<T>";
765 OS <<
"Matcher<" << RetKinds <<
"> " << Name <<
"(";
766 for (
const std::vector<ArgKind> &Arg : ArgsKinds) {
767 if (&Arg != &ArgsKinds[0])
770 bool FirstArgKind =
true;
771 std::set<ASTNodeKind> MatcherKinds;
773 for (
const ArgKind &AK : Arg) {
775 MatcherKinds.insert(AK.getMatcherKind());
779 FirstArgKind =
false;
783 if (!MatcherKinds.empty()) {
784 if (!FirstArgKind) OS <<
"|";
785 OS <<
"Matcher<" << MatcherKinds <<
">";
794 if (ArgsKinds.empty())
800 Completions.emplace_back(TypedText,
Decl, MaxSpecificity);
820 if (Out.isNull())
return Out;
822 std::optional<DynTypedMatcher>
Result = Out.getSingleMatcher();
824 std::optional<DynTypedMatcher> Bound =
Result->tryBind(BindID);
829 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.