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[] = {
617RegistryMaps::~RegistryMaps() =
default;
643 auto it =
RegistryData->constructors().find(MatcherName);
644 return it ==
RegistryData->constructors().end() ? std::optional<MatcherCtor>()
649 const std::set<ASTNodeKind> &KS) {
651 for (std::set<ASTNodeKind>::const_iterator I = KS.begin(), E = KS.end();
665 ArrayRef<std::pair<MatcherCtor, unsigned>> Context) {
677 std::set<ArgKind> TypeSet;
678 for (
auto IT : InitialTypes) {
681 for (
const auto &CtxEntry : Context) {
683 unsigned ArgNumber = CtxEntry.second;
684 std::vector<ArgKind> NextTypeSet;
685 for (
const ArgKind &Kind : TypeSet) {
686 if (Kind.getArgKind() == Kind.AK_Matcher &&
688 (Ctor->
isVariadic() || ArgNumber < Ctor->getNumArgs()))
689 Ctor->
getArgKinds(Kind.getMatcherKind(), ArgNumber, NextTypeSet);
692 TypeSet.insert(NextTypeSet.begin(), NextTypeSet.end());
694 return std::vector<ArgKind>(TypeSet.begin(), TypeSet.end());
697std::vector<MatcherCompletion>
699 std::vector<MatcherCompletion> Completions;
704 StringRef Name = M.getKey();
706 std::set<ASTNodeKind> RetKinds;
709 std::vector<std::vector<ArgKind>> ArgsKinds(NumArgs);
710 unsigned MaxSpecificity = 0;
711 bool NodeArgs =
false;
712 for (
const ArgKind& Kind : AcceptedTypes) {
713 if (Kind.getArgKind() != Kind.AK_Matcher &&
714 Kind.getArgKind() != Kind.AK_Node) {
718 if (Kind.getArgKind() == Kind.AK_Node) {
720 unsigned Specificity;
723 &LeastDerivedKind)) {
724 if (MaxSpecificity < Specificity)
725 MaxSpecificity = Specificity;
726 RetKinds.insert(LeastDerivedKind);
727 for (
unsigned Arg = 0; Arg != NumArgs; ++Arg)
728 Matcher.
getArgKinds(Kind.getNodeKind(), Arg, ArgsKinds[Arg]);
733 unsigned Specificity;
736 &LeastDerivedKind)) {
737 if (MaxSpecificity < Specificity)
738 MaxSpecificity = Specificity;
739 RetKinds.insert(LeastDerivedKind);
740 for (
unsigned Arg = 0; Arg != NumArgs; ++Arg)
741 Matcher.
getArgKinds(Kind.getMatcherKind(), Arg, ArgsKinds[Arg]);
748 if (!RetKinds.empty() && MaxSpecificity > 0) {
750 llvm::raw_string_ostream OS(
Decl);
752 std::string TypedText = std::string(Name);
759 OS <<
"Matcher<T> " << Name <<
"(Matcher<T>";
761 OS <<
"Matcher<" << RetKinds <<
"> " << Name <<
"(";
762 for (
const std::vector<ArgKind> &Arg : ArgsKinds) {
763 if (&Arg != &ArgsKinds[0])
766 bool FirstArgKind =
true;
767 std::set<ASTNodeKind> MatcherKinds;
769 for (
const ArgKind &AK : Arg) {
771 MatcherKinds.insert(AK.getMatcherKind());
775 FirstArgKind =
false;
779 if (!MatcherKinds.empty()) {
780 if (!FirstArgKind) OS <<
"|";
781 OS <<
"Matcher<" << MatcherKinds <<
">";
790 if (ArgsKinds.empty())
796 Completions.emplace_back(TypedText,
Decl, MaxSpecificity);
816 if (Out.isNull())
return Out;
818 std::optional<DynTypedMatcher>
Result = Out.getSingleMatcher();
820 std::optional<DynTypedMatcher> Bound =
Result->tryBind(BindID);
825 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.