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[] = {
615RegistryMaps::~RegistryMaps() =
default;
641 auto it =
RegistryData->constructors().find(MatcherName);
642 return it ==
RegistryData->constructors().end() ? std::optional<MatcherCtor>()
647 const std::set<ASTNodeKind> &KS) {
649 for (std::set<ASTNodeKind>::const_iterator I = KS.begin(), E = KS.end();
663 ArrayRef<std::pair<MatcherCtor, unsigned>> Context) {
675 std::set<ArgKind> TypeSet;
676 for (
auto IT : InitialTypes) {
679 for (
const auto &CtxEntry : Context) {
681 unsigned ArgNumber = CtxEntry.second;
682 std::vector<ArgKind> NextTypeSet;
683 for (
const ArgKind &Kind : TypeSet) {
684 if (Kind.getArgKind() == Kind.AK_Matcher &&
686 (Ctor->
isVariadic() || ArgNumber < Ctor->getNumArgs()))
687 Ctor->
getArgKinds(Kind.getMatcherKind(), ArgNumber, NextTypeSet);
690 TypeSet.insert(NextTypeSet.begin(), NextTypeSet.end());
692 return std::vector<ArgKind>(TypeSet.begin(), TypeSet.end());
695std::vector<MatcherCompletion>
697 std::vector<MatcherCompletion> Completions;
702 StringRef Name = M.getKey();
704 std::set<ASTNodeKind> RetKinds;
707 std::vector<std::vector<ArgKind>> ArgsKinds(NumArgs);
708 unsigned MaxSpecificity = 0;
709 bool NodeArgs =
false;
710 for (
const ArgKind& Kind : AcceptedTypes) {
711 if (Kind.getArgKind() != Kind.AK_Matcher &&
712 Kind.getArgKind() != Kind.AK_Node) {
716 if (Kind.getArgKind() == Kind.AK_Node) {
718 unsigned Specificity;
721 &LeastDerivedKind)) {
722 if (MaxSpecificity < Specificity)
723 MaxSpecificity = Specificity;
724 RetKinds.insert(LeastDerivedKind);
725 for (
unsigned Arg = 0; Arg != NumArgs; ++Arg)
726 Matcher.
getArgKinds(Kind.getNodeKind(), Arg, ArgsKinds[Arg]);
731 unsigned Specificity;
734 &LeastDerivedKind)) {
735 if (MaxSpecificity < Specificity)
736 MaxSpecificity = Specificity;
737 RetKinds.insert(LeastDerivedKind);
738 for (
unsigned Arg = 0; Arg != NumArgs; ++Arg)
739 Matcher.
getArgKinds(Kind.getMatcherKind(), Arg, ArgsKinds[Arg]);
746 if (!RetKinds.empty() && MaxSpecificity > 0) {
748 llvm::raw_string_ostream OS(
Decl);
750 std::string TypedText = std::string(Name);
757 OS <<
"Matcher<T> " << Name <<
"(Matcher<T>";
759 OS <<
"Matcher<" << RetKinds <<
"> " << Name <<
"(";
760 for (
const std::vector<ArgKind> &Arg : ArgsKinds) {
761 if (&Arg != &ArgsKinds[0])
764 bool FirstArgKind =
true;
765 std::set<ASTNodeKind> MatcherKinds;
767 for (
const ArgKind &AK : Arg) {
769 MatcherKinds.insert(AK.getMatcherKind());
773 FirstArgKind =
false;
777 if (!MatcherKinds.empty()) {
778 if (!FirstArgKind) OS <<
"|";
779 OS <<
"Matcher<" << MatcherKinds <<
">";
788 if (ArgsKinds.empty())
794 Completions.emplace_back(TypedText,
Decl, MaxSpecificity);
814 if (Out.isNull())
return Out;
816 std::optional<DynTypedMatcher>
Result = Out.getSingleMatcher();
818 std::optional<DynTypedMatcher> Bound =
Result->tryBind(BindID);
823 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.