Skip to content

Commit

Permalink
Some corrections [skip ci]
Browse files Browse the repository at this point in the history
  • Loading branch information
tyranron committed Apr 5, 2024
1 parent 0d394aa commit 5bb1b07
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 19 deletions.
38 changes: 21 additions & 17 deletions impl/src/fmt/display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ pub fn expand(input: &syn::DeriveInput, trait_name: &str) -> syn::Result<TokenSt
let trait_ident = format_ident!("{trait_name}");
let ident = &input.ident;

let ctx = (&attrs, ident, &trait_ident, &attr_name);
let ctx = (attrs, ident, &trait_ident, &attr_name);
let (bounds, body) = match &input.data {
syn::Data::Struct(s) => expand_struct(s, ctx),
syn::Data::Enum(e) => expand_enum(e, ctx),
Expand Down Expand Up @@ -68,7 +68,7 @@ pub fn expand(input: &syn::DeriveInput, trait_name: &str) -> syn::Result<TokenSt
///
/// [`syn::Ident`]: struct@syn::Ident
type ExpansionCtx<'a> = (
&'a ContainerAttributes,
ContainerAttributes,
&'a syn::Ident,
&'a syn::Ident,
&'a syn::Ident,
Expand All @@ -79,29 +79,33 @@ fn expand_struct(
s: &syn::DataStruct,
(attrs, ident, trait_ident, _): ExpansionCtx<'_>,
) -> syn::Result<(Vec<syn::WherePredicate>, TokenStream)> {
let s = Expansion {
let mut s = Expansion {
attrs,
fields: &s.fields,
trait_ident,
ident,
};

// It's important to generate bounds first, before we're going to modify the `fmt` expression.
let bounds = s.generate_bounds();
let body = s.generate_body()?;

let vars = s.fields.iter().enumerate().map(|(i, f)| {
let args = 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;
parse_quote! {
#var = self.#member
}
});
if let Some(fmt_attr) = &mut s.attrs.fmt {
fmt_attr.append_args(args);
}
let fmt_expr = s.generate_expr()?;

let body = quote! {
#( #vars )*
#body
#fmt_expr
};

Ok((bounds, body))
Expand Down Expand Up @@ -138,12 +142,12 @@ fn expand_enum(
}

let v = Expansion {
attrs: &attrs,
attrs,
fields: &variant.fields,
trait_ident,
ident,
};
let arm_body = v.generate_body()?;
let arm_body = v.generate_expr()?;
bounds.extend(v.generate_bounds());

let fields_idents =
Expand Down Expand Up @@ -199,7 +203,7 @@ fn expand_union(
#[derive(Debug)]
struct Expansion<'a> {
/// Derive macro [`ContainerAttributes`].
attrs: &'a ContainerAttributes,
attrs: ContainerAttributes,

/// Struct or enum [`syn::Ident`].
///
Expand All @@ -216,16 +220,15 @@ struct Expansion<'a> {
}

impl<'a> Expansion<'a> {
/// Generates [`Display::fmt()`] implementation for a struct or an enum variant.
/// Generates [`Display::fmt()`] implementation expression for a struct or an enum variant.
///
/// # Errors
///
/// In case [`FmtAttribute`] is [`None`] and [`syn::Fields`] length is
/// greater than 1.
/// In case [`FmtAttribute`] is [`None`] and [`syn::Fields`] length is greater than 1.
///
/// [`Display::fmt()`]: fmt::Display::fmt()
/// [`FmtAttribute`]: super::FmtAttribute
fn generate_body(&self) -> syn::Result<TokenStream> {
fn generate_expr(&self) -> syn::Result<TokenStream> {
match &self.attrs.fmt {
Some(fmt) => {
Ok(if let Some((expr, trait_ident)) = fmt.transparent_call() {
Expand All @@ -246,7 +249,8 @@ impl<'a> Expansion<'a> {
.fields
.iter()
.next()
.unwrap_or_else(|| unreachable!("count() == 1"));
.unwrap_or_else(|| unreachable!("fields.len() == 1"));
// TODO: Re-check `fmt::Pointer` scenario?
let ident = field.ident.clone().unwrap_or_else(|| format_ident!("_0"));
let trait_ident = self.trait_ident;

Expand Down
18 changes: 16 additions & 2 deletions impl/src/fmt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,21 @@ impl ToTokens for FmtAttribute {
}

impl FmtAttribute {
// TODO:
fn append_args(&mut self, more: impl IntoIterator<Item = FmtArgument>) {
let more = more
.into_iter()
.filter(|new| {
new.alias.is_none()
|| self
.args
.iter()
.all(|old| old.alias.is_none() || old.alias != new.alias)
})
.collect::<Vec<_>>();
self.args.extend(more);
}

/// Checks whether this [`FmtAttribute`] can be replaced with a transparent delegation (calling
/// a formatting trait directly instead of interpolation syntax).
///
Expand Down Expand Up @@ -278,8 +293,7 @@ impl FmtAttribute {
}
}

/// Representation of a [named parameter][1] (`identifier '=' expression`) in
/// in a [`FmtAttribute`].
/// Representation of a [named parameter][1] (`identifier '=' expression`) in a [`FmtAttribute`].
///
/// [1]: https://doc.rust-lang.org/stable/std/fmt/index.html#named-parameters
#[derive(Debug)]
Expand Down

0 comments on commit 5bb1b07

Please sign in to comment.