/// Expands a [`fmt::Debug`] derive macro for the provided struct. /// /// [`fmt::Debug`]: std::fmt::Debug fn expand_struct(
attrs: ContainerAttributes,
ident: &syn::Ident,
s: &syn::DataStruct,
type_params: &[&syn::Ident],
attr_name: &syn::Ident,
) -> syn::Result<(Vec<syn::WherePredicate>, TokenStream)> { let s = Expansion {
attr: &attrs,
fields: &s.fields,
type_params,
ident,
attr_name,
};
s.validate_attrs()?; let bounds = s.generate_bounds()?; let body = s.generate_body()?;
let vars = s.fields.iter().enumerate().map(|(i, f)| { let var = f.ident.clone().unwrap_or_else(|| format_ident!("_{i}")); let member = f
.ident
.clone()
.map_or_else(|| syn::Member::Unnamed(i.into()), syn::Member::Named);
quote! { let#var = &self.#member; }
});
let body = quote! { #(#vars )* #body
};
Ok((bounds, body))
}
/// Expands a [`fmt::Debug`] derive macro for the provided enum. /// /// [`fmt::Debug`]: std::fmt::Debug fn expand_enum( mut attrs: ContainerAttributes,
e: &syn::DataEnum,
type_params: &[&syn::Ident],
attr_name: &syn::Ident,
) -> syn::Result<(Vec<syn::WherePredicate>, TokenStream)> { iflet Some(enum_fmt) = attrs.fmt.as_ref() { return Err(syn::Error::new_spanned(
enum_fmt,
format!( "`#[{attr_name}(\"...\", ...)]` attribute is not allowed on enum, place it on its \
variants instead",
),
));
}
let (bounds, match_arms) = e.variants.iter().try_fold(
(Vec::new(), TokenStream::new()),
|(mut bounds, mut arms), variant| { let ident = &variant.ident;
let body = match_arms
.is_empty()
.then(|| quote! { match *self {} })
.unwrap_or_else(|| quote! { matchself { #match_arms } });
Ok((bounds, body))
}
/// Representation of a [`fmt::Debug`] derive macro field attribute. /// /// ```rust,ignore /// #[debug(skip)] /// #[debug("<fmt-literal>", <fmt-args>)] /// ``` /// /// [`fmt::Debug`]: std::fmt::Debug type FieldAttribute = Either<attr::Skip, FmtAttribute>;
/// Helper struct to generate [`Debug::fmt()`] implementation body and trait /// bounds for a struct or an enum variant. /// /// [`Debug::fmt()`]: std::fmt::Debug::fmt() #[derive(Debug)] struct Expansion<'a> {
attr: &'a ContainerAttributes,
/// Struct or enum [`Ident`](struct@syn::Ident).
ident: &'a syn::Ident,
/// Struct or enum [`syn::Fields`].
fields: &'a syn::Fields,
/// Type parameters in this struct or enum.
type_params: &'a [&'a syn::Ident],
/// Name of the attributes, considered by this macro.
attr_name: &'a syn::Ident,
}
impl Expansion<'_> { /// Validates attributes of this [`Expansion`] to be consistent. fn validate_attrs(&self) -> syn::Result<()> { ifself.attr.fmt.is_some() { for field_attr inself
.fields
.iter()
.map(|f| FieldAttribute::parse_attrs(&f.attrs, self.attr_name))
{ iflet Some(FieldAttribute::Right(fmt_attr)) =
field_attr?.map(Spanning::into_inner)
{ return Err(syn::Error::new_spanned(
fmt_attr, "`#[debug(...)]` attributes are not allowed on fields when \
`#[debug(\"...\", ...)]` is specified on struct or variant",
));
}
}
}
Ok(())
}
/// Generates [`Debug::fmt()`] implementation for a struct or an enum variant. /// /// [`Debug::fmt()`]: std::fmt::Debug::fmt() fn generate_body(&self) -> syn::Result<TokenStream> { iflet Some(fmt) = &self.attr.fmt { return Ok( iflet Some((expr, trait_ident)) =
fmt.transparent_call_on_fields(self.fields)
{
quote! { derive_more::core::fmt::#trait_ident::fmt(#expr, __derive_more_f) }
} else { let deref_args = fmt.additional_deref_args(self.fields);
/// Generates trait bounds for a struct or an enum variant. fn generate_bounds(&self) -> syn::Result<Vec<syn::WherePredicate>> { letmut out = self.attr.bounds.0.clone().into_iter().collect::<Vec<_>>();
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.