// SPDX-License-Identifier: LGPL-3.0-or-later // See Notices.txt for copyright information pub(crate) trait DoFold { fn do_fold(self, state: &mut State) -> Self; } impl, State: ?Sized + syn::fold::Fold> DoFold for Box { fn do_fold(mut self, state: &mut State) -> Self { *self = T::do_fold(*self, state); self } } impl, State: ?Sized + syn::fold::Fold> DoFold for Option { fn do_fold(self, state: &mut State) -> Self { self.map(|v| T::do_fold(v, state)) } } impl, State: ?Sized + syn::fold::Fold> DoFold for Vec { fn do_fold(self, state: &mut State) -> Self { Vec::from_iter(self.into_iter().map(|v| T::do_fold(v, state))) } } impl, P: DoFold, State: ?Sized + syn::fold::Fold> DoFold for Punctuated { fn do_fold(self, state: &mut State) -> Self { Punctuated::from_iter(self.into_pairs().map(|v| { let (v, p) = v.into_tuple().do_fold(state); Pair::new(v, p) })) } } macro_rules! impl_fold_tuple { ($($var0:ident: $T0:ident, $($var:ident: $T:ident,)*)?) => { $(impl_fold_tuple!($($var: $T,)*);)? impl_fold_tuple!(@impl $($var0: $T0, $($var: $T,)*)?); }; (@impl $($var:ident: $T:ident,)*) => { impl,)*> DoFold for ($($T,)*) { #[allow(clippy::unused_unit)] fn do_fold(self, state: &mut State) -> Self { let _ = state; let ($($var,)*) = self; $(let $var = $var.do_fold(state);)* ($($var,)*) } } }; } impl_fold_tuple!( v0: T0, v1: T1, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6, v7: T7, v8: T8, v9: T9, v10: T10, v11: T11, ); macro_rules! no_op_fold { ($ty:ty) => { impl $crate::fold::DoFold for $ty { fn do_fold(self, _state: &mut State) -> Self { self } } }; } pub(crate) use no_op_fold; macro_rules! impl_fold { ( struct $Struct:ident<$($T:ident,)*> $(where ($($where:tt)*))? { $($field:ident: $field_ty:ty,)* } ) => { impl $crate::fold::DoFold for $Struct<$($T,)*> where $($T: $crate::fold::DoFold,)* $($where)* { fn do_fold(self, state: &mut State) -> Self { let _ = state; let Self { $($field,)* } = self; Self { $($field: <$field_ty as $crate::fold::DoFold>::do_fold($field, state),)* } } } }; ( struct $Struct:ident<$($T:ident,)*>( $field0_ty:ty $(,)? ) $(where ($($where:tt)*))?; ) => { impl $crate::fold::DoFold for $Struct<$($T,)*> where $($T: $crate::fold::DoFold,)* $($where)* { fn do_fold(self, state: &mut State) -> Self { let _ = state; let Self( v0, ) = self; Self( <$field0_ty as $crate::fold::DoFold>::do_fold(v0, state), ) } } }; ( enum $Enum:ident<$($T:ident,)*> $(where ($($where:tt)*))? { $($Variant:ident $({ $($brace_field:ident: $brace_field_ty:ty,)* })? $(( $($paren_field_ty:ty),* $(,)? ))?,)* } ) => { impl $crate::fold::DoFold for $Enum<$($T,)*> where $($T: $crate::fold::DoFold,)* $($where)* { fn do_fold(self, state: &mut State) -> Self { let _ = state; $crate::fold::impl_fold! { @enum_variants self, state => () $($Variant $({ $($brace_field: $brace_field_ty,)* })? $(( $($paren_field_ty,)* ))?,)* } } } }; ( @enum_variants $self:expr, $state:expr => ($($generated_arms:tt)*) ) => { match $self { $($generated_arms)* } }; ( @enum_variants $self:expr, $state:expr => ($($generated_arms:tt)*) $Variant:ident { $($field:tt: $field_ty:ty,)* }, $($rest:tt)* ) => { $crate::fold::impl_fold! { @enum_variants $self, $state => ( $($generated_arms)* Self::$Variant { $($field,)* } => Self::$Variant { $($field: <$field_ty as $crate::fold::DoFold>::do_fold($field, $state),)* }, ) $($rest)* } }; ( @enum_variants $self:expr, $state:expr => ($($generated_arms:tt)*) $Variant:ident( $field0_ty:ty $(,)? ), $($rest:tt)* ) => { $crate::fold::impl_fold! { @enum_variants $self, $state => ( $($generated_arms)* Self::$Variant(v0) => Self::$Variant( <$field0_ty as $crate::fold::DoFold>::do_fold(v0, $state), ), ) $($rest)* } }; } pub(crate) use impl_fold; use syn::punctuated::{Pair, Punctuated}; macro_rules! forward_fold { ($ty:ty => $fn:ident) => { impl DoFold for $ty { fn do_fold(self, state: &mut State) -> Self { ::$fn(state, self) } } }; } forward_fold!(syn::Attribute => fold_attribute); forward_fold!(syn::AttrStyle => fold_attr_style); forward_fold!(syn::Expr => fold_expr); forward_fold!(syn::ExprArray => fold_expr_array); forward_fold!(syn::ExprCall => fold_expr_call); forward_fold!(syn::ExprIf => fold_expr_if); forward_fold!(syn::ExprMatch => fold_expr_match); forward_fold!(syn::ExprPath => fold_expr_path); forward_fold!(syn::ExprStruct => fold_expr_struct); forward_fold!(syn::ExprTuple => fold_expr_tuple); forward_fold!(syn::Ident => fold_ident); forward_fold!(syn::Member => fold_member); forward_fold!(syn::Path => fold_path); forward_fold!(syn::Type => fold_type); forward_fold!(syn::TypePath => fold_type_path); forward_fold!(syn::WherePredicate => fold_where_predicate); no_op_fold!(syn::parse::Nothing); no_op_fold!(syn::token::Brace); no_op_fold!(syn::token::Bracket); no_op_fold!(syn::token::Paren); no_op_fold!(syn::Token![_]); no_op_fold!(syn::Token![,]); no_op_fold!(syn::Token![;]); no_op_fold!(syn::Token![:]); no_op_fold!(syn::Token![..]); no_op_fold!(syn::Token![.]); no_op_fold!(syn::Token![#]); no_op_fold!(syn::Token![=]); no_op_fold!(syn::Token![=>]); no_op_fold!(syn::Token![|]); no_op_fold!(syn::Token![enum]); no_op_fold!(syn::Token![extern]); no_op_fold!(syn::Token![let]); no_op_fold!(syn::Token![mut]); no_op_fold!(syn::Token![struct]); no_op_fold!(syn::Token![where]);