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[] = {
616RegistryMaps::~RegistryMaps() =
default;
642 auto it =
RegistryData->constructors().find(MatcherName);
643 return it ==
RegistryData->constructors().end() ? std::optional<MatcherCtor>()
648 const std::set<ASTNodeKind> &KS) {
650 for (std::set<ASTNodeKind>::const_iterator I = KS.begin(), E = KS.end();
664 ArrayRef<std::pair<MatcherCtor, unsigned>> Context) {
676 std::set<ArgKind> TypeSet;
677 for (
auto IT : InitialTypes) {
680 for (
const auto &CtxEntry : Context) {
682 unsigned ArgNumber = CtxEntry.second;
683 std::vector<ArgKind> NextTypeSet;
684 for (
const ArgKind &Kind : TypeSet) {
685 if (Kind.getArgKind() == Kind.AK_Matcher &&
687 (Ctor->
isVariadic() || ArgNumber < Ctor->getNumArgs()))
688 Ctor->
getArgKinds(Kind.getMatcherKind(), ArgNumber, NextTypeSet);
691 TypeSet.insert(NextTypeSet.begin(), NextTypeSet.end());
693 return std::vector<ArgKind>(TypeSet.begin(), TypeSet.end());
696std::vector<MatcherCompletion>
698 std::vector<MatcherCompletion> Completions;
703 StringRef Name = M.getKey();
705 std::set<ASTNodeKind> RetKinds;
708 std::vector<std::vector<ArgKind>> ArgsKinds(NumArgs);
709 unsigned MaxSpecificity = 0;
710 bool NodeArgs =
false;
711 for (
const ArgKind& Kind : AcceptedTypes) {
712 if (Kind.getArgKind() != Kind.AK_Matcher &&
713 Kind.getArgKind() != Kind.AK_Node) {
717 if (Kind.getArgKind() == Kind.AK_Node) {
719 unsigned Specificity;
722 &LeastDerivedKind)) {
723 if (MaxSpecificity < Specificity)
724 MaxSpecificity = Specificity;
725 RetKinds.insert(LeastDerivedKind);
726 for (
unsigned Arg = 0; Arg != NumArgs; ++Arg)
727 Matcher.
getArgKinds(Kind.getNodeKind(), Arg, ArgsKinds[Arg]);
732 unsigned Specificity;
735 &LeastDerivedKind)) {
736 if (MaxSpecificity < Specificity)
737 MaxSpecificity = Specificity;
738 RetKinds.insert(LeastDerivedKind);
739 for (
unsigned Arg = 0; Arg != NumArgs; ++Arg)
740 Matcher.
getArgKinds(Kind.getMatcherKind(), Arg, ArgsKinds[Arg]);
747 if (!RetKinds.empty() && MaxSpecificity > 0) {
749 llvm::raw_string_ostream OS(
Decl);
751 std::string TypedText = std::string(Name);
758 OS <<
"Matcher<T> " << Name <<
"(Matcher<T>";
760 OS <<
"Matcher<" << RetKinds <<
"> " << Name <<
"(";
761 for (
const std::vector<ArgKind> &Arg : ArgsKinds) {
762 if (&Arg != &ArgsKinds[0])
765 bool FirstArgKind =
true;
766 std::set<ASTNodeKind> MatcherKinds;
768 for (
const ArgKind &AK : Arg) {
770 MatcherKinds.insert(AK.getMatcherKind());
774 FirstArgKind =
false;
778 if (!MatcherKinds.empty()) {
779 if (!FirstArgKind) OS <<
"|";
780 OS <<
"Matcher<" << MatcherKinds <<
">";
789 if (ArgsKinds.empty())
795 Completions.emplace_back(TypedText,
Decl, MaxSpecificity);
815 if (Out.isNull())
return Out;
817 std::optional<DynTypedMatcher>
Result = Out.getSingleMatcher();
819 std::optional<DynTypedMatcher> Bound =
Result->tryBind(BindID);
824 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.