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[] = {
618RegistryMaps::~RegistryMaps() =
default;
644 auto it =
RegistryData->constructors().find(MatcherName);
645 return it ==
RegistryData->constructors().end() ? std::optional<MatcherCtor>()
650 const std::set<ASTNodeKind> &KS) {
652 for (std::set<ASTNodeKind>::const_iterator I = KS.begin(), E = KS.end();
666 ArrayRef<std::pair<MatcherCtor, unsigned>> Context) {
678 std::set<ArgKind> TypeSet;
679 for (
auto IT : InitialTypes) {
682 for (
const auto &CtxEntry : Context) {
684 unsigned ArgNumber = CtxEntry.second;
685 std::vector<ArgKind> NextTypeSet;
686 for (
const ArgKind &Kind : TypeSet) {
687 if (Kind.getArgKind() == Kind.AK_Matcher &&
689 (Ctor->
isVariadic() || ArgNumber < Ctor->getNumArgs()))
690 Ctor->
getArgKinds(Kind.getMatcherKind(), ArgNumber, NextTypeSet);
693 TypeSet.insert(NextTypeSet.begin(), NextTypeSet.end());
695 return std::vector<ArgKind>(TypeSet.begin(), TypeSet.end());
698std::vector<MatcherCompletion>
700 std::vector<MatcherCompletion> Completions;
705 StringRef Name = M.getKey();
707 std::set<ASTNodeKind> RetKinds;
710 std::vector<std::vector<ArgKind>> ArgsKinds(NumArgs);
711 unsigned MaxSpecificity = 0;
712 bool NodeArgs =
false;
713 for (
const ArgKind& Kind : AcceptedTypes) {
714 if (Kind.getArgKind() != Kind.AK_Matcher &&
715 Kind.getArgKind() != Kind.AK_Node) {
719 if (Kind.getArgKind() == Kind.AK_Node) {
721 unsigned Specificity;
724 &LeastDerivedKind)) {
725 if (MaxSpecificity < Specificity)
726 MaxSpecificity = Specificity;
727 RetKinds.insert(LeastDerivedKind);
728 for (
unsigned Arg = 0; Arg != NumArgs; ++Arg)
729 Matcher.
getArgKinds(Kind.getNodeKind(), Arg, ArgsKinds[Arg]);
734 unsigned Specificity;
737 &LeastDerivedKind)) {
738 if (MaxSpecificity < Specificity)
739 MaxSpecificity = Specificity;
740 RetKinds.insert(LeastDerivedKind);
741 for (
unsigned Arg = 0; Arg != NumArgs; ++Arg)
742 Matcher.
getArgKinds(Kind.getMatcherKind(), Arg, ArgsKinds[Arg]);
749 if (!RetKinds.empty() && MaxSpecificity > 0) {
751 llvm::raw_string_ostream OS(
Decl);
753 std::string TypedText = std::string(Name);
760 OS <<
"Matcher<T> " << Name <<
"(Matcher<T>";
762 OS <<
"Matcher<" << RetKinds <<
"> " << Name <<
"(";
763 for (
const std::vector<ArgKind> &Arg : ArgsKinds) {
764 if (&Arg != &ArgsKinds[0])
767 bool FirstArgKind =
true;
768 std::set<ASTNodeKind> MatcherKinds;
770 for (
const ArgKind &AK : Arg) {
772 MatcherKinds.insert(AK.getMatcherKind());
776 FirstArgKind =
false;
780 if (!MatcherKinds.empty()) {
781 if (!FirstArgKind) OS <<
"|";
782 OS <<
"Matcher<" << MatcherKinds <<
">";
791 if (ArgsKinds.empty())
797 Completions.emplace_back(TypedText,
Decl, MaxSpecificity);
817 if (Out.isNull())
return Out;
819 std::optional<DynTypedMatcher>
Result = Out.getSingleMatcher();
821 std::optional<DynTypedMatcher> Bound =
Result->tryBind(BindID);
826 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.