[ASTMatchers] NFC Rearrange declarations to allow more arg adapting

This commit is contained in:
Stephen Kelly 2021-01-19 20:50:54 +00:00
parent 894d88a759
commit ce24bb0edd
1 changed files with 226 additions and 228 deletions

View File

@ -1171,6 +1171,232 @@ using HasDeclarationSupportedTypes =
TemplateSpecializationType, TemplateTypeParmType, TypedefType,
UnresolvedUsingType, ObjCIvarRefExpr>;
/// A Matcher that allows binding the node it matches to an id.
///
/// BindableMatcher provides a \a bind() method that allows binding the
/// matched node to an id if the match was successful.
template <typename T> class BindableMatcher : public Matcher<T> {
public:
explicit BindableMatcher(const Matcher<T> &M) : Matcher<T>(M) {}
explicit BindableMatcher(MatcherInterface<T> *Implementation)
: Matcher<T>(Implementation) {}
/// Returns a matcher that will bind the matched node on a match.
///
/// The returned matcher is equivalent to this matcher, but will
/// bind the matched node on a match.
Matcher<T> bind(StringRef ID) const {
return DynTypedMatcher(*this)
.tryBind(ID)
->template unconditionalConvertTo<T>();
}
/// Same as Matcher<T>'s conversion operator, but enables binding on
/// the returned matcher.
operator DynTypedMatcher() const {
DynTypedMatcher Result = static_cast<const Matcher<T> &>(*this);
Result.setAllowBind(true);
return Result;
}
};
/// Matches any instance of the given NodeType.
///
/// This is useful when a matcher syntactically requires a child matcher,
/// but the context doesn't care. See for example: anything().
class TrueMatcher {
public:
using ReturnTypes = AllNodeBaseTypes;
template <typename T> operator Matcher<T>() const {
return DynTypedMatcher::trueMatcher(ASTNodeKind::getFromNodeKind<T>())
.template unconditionalConvertTo<T>();
}
};
/// Creates a Matcher<T> that matches if all inner matchers match.
template <typename T>
BindableMatcher<T>
makeAllOfComposite(ArrayRef<const Matcher<T> *> InnerMatchers) {
// For the size() == 0 case, we return a "true" matcher.
if (InnerMatchers.empty()) {
return BindableMatcher<T>(TrueMatcher());
}
// For the size() == 1 case, we simply return that one matcher.
// No need to wrap it in a variadic operation.
if (InnerMatchers.size() == 1) {
return BindableMatcher<T>(*InnerMatchers[0]);
}
using PI = llvm::pointee_iterator<const Matcher<T> *const *>;
std::vector<DynTypedMatcher> DynMatchers(PI(InnerMatchers.begin()),
PI(InnerMatchers.end()));
return BindableMatcher<T>(
DynTypedMatcher::constructVariadic(DynTypedMatcher::VO_AllOf,
ASTNodeKind::getFromNodeKind<T>(),
std::move(DynMatchers))
.template unconditionalConvertTo<T>());
}
/// Creates a Matcher<T> that matches if
/// T is dyn_cast'able into InnerT and all inner matchers match.
///
/// Returns BindableMatcher, as matchers that use dyn_cast have
/// the same object both to match on and to run submatchers on,
/// so there is no ambiguity with what gets bound.
template <typename T, typename InnerT>
BindableMatcher<T>
makeDynCastAllOfComposite(ArrayRef<const Matcher<InnerT> *> InnerMatchers) {
return BindableMatcher<T>(
makeAllOfComposite(InnerMatchers).template dynCastTo<T>());
}
/// A VariadicDynCastAllOfMatcher<SourceT, TargetT> object is a
/// variadic functor that takes a number of Matcher<TargetT> and returns a
/// Matcher<SourceT> that matches TargetT nodes that are matched by all of the
/// given matchers, if SourceT can be dynamically casted into TargetT.
///
/// For example:
/// const VariadicDynCastAllOfMatcher<Decl, CXXRecordDecl> record;
/// Creates a functor record(...) that creates a Matcher<Decl> given
/// a variable number of arguments of type Matcher<CXXRecordDecl>.
/// The returned matcher matches if the given Decl can by dynamically
/// casted to CXXRecordDecl and all given matchers match.
template <typename SourceT, typename TargetT>
class VariadicDynCastAllOfMatcher
: public VariadicFunction<BindableMatcher<SourceT>, Matcher<TargetT>,
makeDynCastAllOfComposite<SourceT, TargetT>> {
public:
VariadicDynCastAllOfMatcher() {}
};
/// A \c VariadicAllOfMatcher<T> object is a variadic functor that takes
/// a number of \c Matcher<T> and returns a \c Matcher<T> that matches \c T
/// nodes that are matched by all of the given matchers.
///
/// For example:
/// const VariadicAllOfMatcher<NestedNameSpecifier> nestedNameSpecifier;
/// Creates a functor nestedNameSpecifier(...) that creates a
/// \c Matcher<NestedNameSpecifier> given a variable number of arguments of type
/// \c Matcher<NestedNameSpecifier>.
/// The returned matcher matches if all given matchers match.
template <typename T>
class VariadicAllOfMatcher
: public VariadicFunction<BindableMatcher<T>, Matcher<T>,
makeAllOfComposite<T>> {
public:
VariadicAllOfMatcher() {}
};
/// VariadicOperatorMatcher related types.
/// @{
/// Polymorphic matcher object that uses a \c
/// DynTypedMatcher::VariadicOperator operator.
///
/// Input matchers can have any type (including other polymorphic matcher
/// types), and the actual Matcher<T> is generated on demand with an implicit
/// conversion operator.
template <typename... Ps> class VariadicOperatorMatcher {
public:
VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op, Ps &&... Params)
: Op(Op), Params(std::forward<Ps>(Params)...) {}
template <typename T> operator Matcher<T>() const {
return DynTypedMatcher::constructVariadic(
Op, ASTNodeKind::getFromNodeKind<T>(),
getMatchers<T>(std::index_sequence_for<Ps...>()))
.template unconditionalConvertTo<T>();
}
private:
// Helper method to unpack the tuple into a vector.
template <typename T, std::size_t... Is>
std::vector<DynTypedMatcher> getMatchers(std::index_sequence<Is...>) const {
return {Matcher<T>(std::get<Is>(Params))...};
}
const DynTypedMatcher::VariadicOperator Op;
std::tuple<Ps...> Params;
};
/// Overloaded function object to generate VariadicOperatorMatcher
/// objects from arbitrary matchers.
template <unsigned MinCount, unsigned MaxCount>
struct VariadicOperatorMatcherFunc {
DynTypedMatcher::VariadicOperator Op;
template <typename... Ms>
VariadicOperatorMatcher<Ms...> operator()(Ms &&... Ps) const {
static_assert(MinCount <= sizeof...(Ms) && sizeof...(Ms) <= MaxCount,
"invalid number of parameters for variadic matcher");
return VariadicOperatorMatcher<Ms...>(Op, std::forward<Ms>(Ps)...);
}
};
template <typename F, typename Tuple, std::size_t... I>
constexpr auto applyMatcherImpl(F &&f, Tuple &&args,
std::index_sequence<I...>) {
return std::forward<F>(f)(std::get<I>(std::forward<Tuple>(args))...);
}
template <typename F, typename Tuple>
constexpr auto applyMatcher(F &&f, Tuple &&args) {
return applyMatcherImpl(
std::forward<F>(f), std::forward<Tuple>(args),
std::make_index_sequence<
std::tuple_size<typename std::decay<Tuple>::type>::value>());
}
template <typename T, bool IsBaseOf, typename Head, typename Tail>
struct GetCladeImpl {
using Type = Head;
};
template <typename T, typename Head, typename Tail>
struct GetCladeImpl<T, false, Head, Tail>
: GetCladeImpl<T, std::is_base_of<typename Tail::head, T>::value,
typename Tail::head, typename Tail::tail> {};
template <typename T, typename... U>
struct GetClade : GetCladeImpl<T, false, T, AllNodeBaseTypes> {};
template <typename CladeType, typename... MatcherTypes>
struct MapAnyOfMatcherImpl {
template <typename... InnerMatchers>
BindableMatcher<CladeType>
operator()(InnerMatchers &&... InnerMatcher) const {
// TODO: Use std::apply from c++17
return VariadicAllOfMatcher<CladeType>()(applyMatcher(
internal::VariadicOperatorMatcherFunc<
0, std::numeric_limits<unsigned>::max()>{
internal::DynTypedMatcher::VO_AnyOf},
applyMatcher(
[&](auto... Matcher) {
return std::make_tuple(Matcher(
std::forward<decltype(InnerMatcher)>(InnerMatcher)...)...);
},
std::tuple<
VariadicDynCastAllOfMatcher<CladeType, MatcherTypes>...>())));
}
};
template <typename... MatcherTypes>
using MapAnyOfMatcher =
MapAnyOfMatcherImpl<typename GetClade<MatcherTypes...>::Type,
MatcherTypes...>;
template <typename... MatcherTypes> struct MapAnyOfHelper {
using CladeType = typename GetClade<MatcherTypes...>::Type;
MapAnyOfMatcher<MatcherTypes...> with;
operator BindableMatcher<CladeType>() const { return with(); }
Matcher<CladeType> bind(StringRef ID) const { return with().bind(ID); }
};
template <template <typename ToArg, typename FromArg> class ArgumentAdapterT,
typename T, typename ToTypes>
class ArgumentAdaptingMatcherFuncAdaptor {
@ -1327,51 +1553,6 @@ private:
const P2 Param2;
};
/// Matches any instance of the given NodeType.
///
/// This is useful when a matcher syntactically requires a child matcher,
/// but the context doesn't care. See for example: anything().
class TrueMatcher {
public:
using ReturnTypes = AllNodeBaseTypes;
template <typename T>
operator Matcher<T>() const {
return DynTypedMatcher::trueMatcher(ASTNodeKind::getFromNodeKind<T>())
.template unconditionalConvertTo<T>();
}
};
/// A Matcher that allows binding the node it matches to an id.
///
/// BindableMatcher provides a \a bind() method that allows binding the
/// matched node to an id if the match was successful.
template <typename T>
class BindableMatcher : public Matcher<T> {
public:
explicit BindableMatcher(const Matcher<T> &M) : Matcher<T>(M) {}
explicit BindableMatcher(MatcherInterface<T> *Implementation)
: Matcher<T>(Implementation) {}
/// Returns a matcher that will bind the matched node on a match.
///
/// The returned matcher is equivalent to this matcher, but will
/// bind the matched node on a match.
Matcher<T> bind(StringRef ID) const {
return DynTypedMatcher(*this)
.tryBind(ID)
->template unconditionalConvertTo<T>();
}
/// Same as Matcher<T>'s conversion operator, but enables binding on
/// the returned matcher.
operator DynTypedMatcher() const {
DynTypedMatcher Result = static_cast<const Matcher<T>&>(*this);
Result.setAllowBind(true);
return Result;
}
};
/// Matches nodes of type T that have child nodes of type ChildT for
/// which a specified child matcher matches.
///
@ -1415,52 +1596,6 @@ public:
}
};
/// VariadicOperatorMatcher related types.
/// @{
/// Polymorphic matcher object that uses a \c
/// DynTypedMatcher::VariadicOperator operator.
///
/// Input matchers can have any type (including other polymorphic matcher
/// types), and the actual Matcher<T> is generated on demand with an implicit
/// conversion operator.
template <typename... Ps> class VariadicOperatorMatcher {
public:
VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op, Ps &&... Params)
: Op(Op), Params(std::forward<Ps>(Params)...) {}
template <typename T> operator Matcher<T>() const {
return DynTypedMatcher::constructVariadic(
Op, ASTNodeKind::getFromNodeKind<T>(),
getMatchers<T>(std::index_sequence_for<Ps...>()))
.template unconditionalConvertTo<T>();
}
private:
// Helper method to unpack the tuple into a vector.
template <typename T, std::size_t... Is>
std::vector<DynTypedMatcher> getMatchers(std::index_sequence<Is...>) const {
return {Matcher<T>(std::get<Is>(Params))...};
}
const DynTypedMatcher::VariadicOperator Op;
std::tuple<Ps...> Params;
};
/// Overloaded function object to generate VariadicOperatorMatcher
/// objects from arbitrary matchers.
template <unsigned MinCount, unsigned MaxCount>
struct VariadicOperatorMatcherFunc {
DynTypedMatcher::VariadicOperator Op;
template <typename... Ms>
VariadicOperatorMatcher<Ms...> operator()(Ms &&... Ps) const {
static_assert(MinCount <= sizeof...(Ms) && sizeof...(Ms) <= MaxCount,
"invalid number of parameters for variadic matcher");
return VariadicOperatorMatcher<Ms...>(Op, std::forward<Ms>(Ps)...);
}
};
/// @}
template <typename T>
@ -1468,44 +1603,6 @@ inline Matcher<T> DynTypedMatcher::unconditionalConvertTo() const {
return Matcher<T>(*this);
}
/// Creates a Matcher<T> that matches if all inner matchers match.
template<typename T>
BindableMatcher<T> makeAllOfComposite(
ArrayRef<const Matcher<T> *> InnerMatchers) {
// For the size() == 0 case, we return a "true" matcher.
if (InnerMatchers.empty()) {
return BindableMatcher<T>(TrueMatcher());
}
// For the size() == 1 case, we simply return that one matcher.
// No need to wrap it in a variadic operation.
if (InnerMatchers.size() == 1) {
return BindableMatcher<T>(*InnerMatchers[0]);
}
using PI = llvm::pointee_iterator<const Matcher<T> *const *>;
std::vector<DynTypedMatcher> DynMatchers(PI(InnerMatchers.begin()),
PI(InnerMatchers.end()));
return BindableMatcher<T>(
DynTypedMatcher::constructVariadic(DynTypedMatcher::VO_AllOf,
ASTNodeKind::getFromNodeKind<T>(),
std::move(DynMatchers))
.template unconditionalConvertTo<T>());
}
/// Creates a Matcher<T> that matches if
/// T is dyn_cast'able into InnerT and all inner matchers match.
///
/// Returns BindableMatcher, as matchers that use dyn_cast have
/// the same object both to match on and to run submatchers on,
/// so there is no ambiguity with what gets bound.
template<typename T, typename InnerT>
BindableMatcher<T> makeDynCastAllOfComposite(
ArrayRef<const Matcher<InnerT> *> InnerMatchers) {
return BindableMatcher<T>(
makeAllOfComposite(InnerMatchers).template dynCastTo<T>());
}
/// Matches nodes of type T that have at least one descendant node of
/// type DescendantT for which the given inner matcher matches.
///
@ -1645,43 +1742,6 @@ inline bool ValueEqualsMatcher<FloatingLiteral, llvm::APFloat>::matchesNode(
return ExpectedValue.compare(Node.getValue()) == llvm::APFloat::cmpEqual;
}
/// A VariadicDynCastAllOfMatcher<SourceT, TargetT> object is a
/// variadic functor that takes a number of Matcher<TargetT> and returns a
/// Matcher<SourceT> that matches TargetT nodes that are matched by all of the
/// given matchers, if SourceT can be dynamically casted into TargetT.
///
/// For example:
/// const VariadicDynCastAllOfMatcher<Decl, CXXRecordDecl> record;
/// Creates a functor record(...) that creates a Matcher<Decl> given
/// a variable number of arguments of type Matcher<CXXRecordDecl>.
/// The returned matcher matches if the given Decl can by dynamically
/// casted to CXXRecordDecl and all given matchers match.
template <typename SourceT, typename TargetT>
class VariadicDynCastAllOfMatcher
: public VariadicFunction<BindableMatcher<SourceT>, Matcher<TargetT>,
makeDynCastAllOfComposite<SourceT, TargetT>> {
public:
VariadicDynCastAllOfMatcher() {}
};
/// A \c VariadicAllOfMatcher<T> object is a variadic functor that takes
/// a number of \c Matcher<T> and returns a \c Matcher<T> that matches \c T
/// nodes that are matched by all of the given matchers.
///
/// For example:
/// const VariadicAllOfMatcher<NestedNameSpecifier> nestedNameSpecifier;
/// Creates a functor nestedNameSpecifier(...) that creates a
/// \c Matcher<NestedNameSpecifier> given a variable number of arguments of type
/// \c Matcher<NestedNameSpecifier>.
/// The returned matcher matches if all given matchers match.
template <typename T>
class VariadicAllOfMatcher
: public VariadicFunction<BindableMatcher<T>, Matcher<T>,
makeAllOfComposite<T>> {
public:
VariadicAllOfMatcher() {}
};
/// Matches nodes of type \c TLoc for which the inner
/// \c Matcher<T> matches.
template <typename TLoc, typename T>
@ -2180,68 +2240,6 @@ std::shared_ptr<llvm::Regex> createAndVerifyRegex(StringRef Regex,
llvm::Regex::RegexFlags Flags,
StringRef MatcherID);
template <typename F, typename Tuple, std::size_t... I>
constexpr auto applyMatcherImpl(F &&f, Tuple &&args,
std::index_sequence<I...>) {
return std::forward<F>(f)(std::get<I>(std::forward<Tuple>(args))...);
}
template <typename F, typename Tuple>
constexpr auto applyMatcher(F &&f, Tuple &&args) {
return applyMatcherImpl(
std::forward<F>(f), std::forward<Tuple>(args),
std::make_index_sequence<
std::tuple_size<typename std::decay<Tuple>::type>::value>());
}
template <typename T, bool IsBaseOf, typename Head, typename Tail>
struct GetCladeImpl {
using Type = Head;
};
template <typename T, typename Head, typename Tail>
struct GetCladeImpl<T, false, Head, Tail>
: GetCladeImpl<T, std::is_base_of<typename Tail::head, T>::value,
typename Tail::head, typename Tail::tail> {};
template <typename T, typename... U>
struct GetClade : GetCladeImpl<T, false, T, AllNodeBaseTypes> {};
template <typename CladeType, typename... MatcherTypes>
struct MapAnyOfMatcherImpl {
template <typename... InnerMatchers>
BindableMatcher<CladeType>
operator()(InnerMatchers &&... InnerMatcher) const {
// TODO: Use std::apply from c++17
return VariadicAllOfMatcher<CladeType>()(applyMatcher(
internal::VariadicOperatorMatcherFunc<
0, std::numeric_limits<unsigned>::max()>{
internal::DynTypedMatcher::VO_AnyOf},
applyMatcher(
[&](auto... Matcher) {
return std::make_tuple(Matcher(
std::forward<decltype(InnerMatcher)>(InnerMatcher)...)...);
},
std::tuple<
VariadicDynCastAllOfMatcher<CladeType, MatcherTypes>...>())));
}
};
template <typename... MatcherTypes>
using MapAnyOfMatcher =
MapAnyOfMatcherImpl<typename GetClade<MatcherTypes...>::Type,
MatcherTypes...>;
template <typename... MatcherTypes> struct MapAnyOfHelper {
using CladeType = typename GetClade<MatcherTypes...>::Type;
MapAnyOfMatcher<MatcherTypes...> with;
operator BindableMatcher<CladeType>() const { return with(); }
Matcher<CladeType> bind(StringRef ID) const { return with().bind(ID); }
};
} // namespace internal
} // namespace ast_matchers