//! Implementation of [`fmt::Display`]-like derive macros.
#[cfg(doc)] use std::fmt;
use proc_macro2::{Ident, TokenStream}; use quote::{format_ident, quote}; use syn::{
parse::{Parse, ParseStream},
parse_quote,
spanned::Spanned as _,
};
/// Type alias for an expansion context: /// - [`Attributes`]. /// - Struct/enum/union [`Ident`]. /// - Derived trait [`Ident`]. /// - Derived trait `&`[`str`]. type ExpansionCtx<'a> = (&'a Attributes, &'a Ident, &'a Ident, &'a str);
/// Expands a [`fmt::Display`]-like derive macro for the provided struct. fn expand_struct(
s: &syn::DataStruct,
(attrs, ident, trait_ident, _): ExpansionCtx<'_>,
) -> syn::Result<(Vec<syn::WherePredicate>, TokenStream)> { let s = Expansion {
attrs,
fields: &s.fields,
trait_ident,
ident,
}; 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`]-like derive macro for the provided enum. fn expand_enum(
e: &syn::DataEnum,
(attrs, _, trait_ident, trait_name): ExpansionCtx<'_>,
) -> syn::Result<(Vec<syn::WherePredicate>, TokenStream)> { if attrs.fmt.is_some() {
todo!("https://github.com/JelteF/derive_more/issues/142");
}
let (bounds, match_arms) = e.variants.iter().try_fold(
(Vec::new(), TokenStream::new()),
|(mut bounds, mut arms), variant| { let attrs = Attributes::parse_attrs(&variant.attrs, trait_name)?; let ident = &variant.ident;
if attrs.fmt.is_none()
&& variant.fields.is_empty()
&& trait_name != "Display"
{ return Err(syn::Error::new(
e.variants.span(),
format!( "implicit formatting of unit enum variant is supported \
only for `Display` macro, use `#[{}(\"...\")]` to \
explicitly specify the formatting",
trait_name_to_attribute_name(trait_name),
),
));
}
let v = Expansion {
attrs: &attrs,
fields: &variant.fields,
trait_ident,
ident,
}; let arm_body = v.generate_body()?;
bounds.extend(v.generate_bounds());
/// Helper struct to generate [`Display::fmt()`] implementation body and trait /// bounds for a struct or an enum variant. /// /// [`Display::fmt()`]: fmt::Display::fmt() #[derive(Debug)] struct Expansion<'a> { /// Derive macro [`Attributes`].
attrs: &'a Attributes,
/// Struct or enum [`Ident`].
ident: &'a Ident,
/// Struct or enum [`syn::Fields`].
fields: &'a syn::Fields,
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.