Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Break out distribute_and_unnest_attrs #243

Merged
merged 4 commits into from
Mar 21, 2022
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
102 changes: 49 additions & 53 deletions derive_builder_core/src/macro_options/darling_opts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,37 +254,52 @@ pub struct Field {
}

impl Field {
/// Remove the `builder_field_attr(...)` packaging around an attribute
/// Populate `self.field_attrs` and `self.setter_attrs` by draining `self.attrs`
fn unnest_attrs(mut self) -> darling::Result<Self> {
let mut errors = vec![];

for attr in self.attrs.drain(..) {
let unnest = {
if attr.path.is_ident("builder_field_attr") {
Some(&mut self.field_attrs)
} else if attr.path.is_ident("builder_setter_attr") {
Some(&mut self.setter_attrs)
} else {
None
}
};
if let Some(unnest) = unnest {
match unnest_from_one_attribute(attr) {
Ok(n) => unnest.push(n),
Err(e) => errors.push(e),
}
} else {
self.field_attrs.push(attr.clone());
self.setter_attrs.push(attr);
}
}
distribute_and_unnest_attrs(
&mut self.attrs,
&mut [
("builder_field_attr", &mut self.field_attrs),
("builder_setter_attr", &mut self.setter_attrs),
],
)?;
Ok(self)
}
}

if !errors.is_empty() {
return Err(darling::Error::multiple(errors));
/// Handles incoming attributes from darling and assigns them to decoratee attribute lists
///
/// `outputs` lists each pass-through attribute name, and the corresponding decoratee attribute list.
/// Matching atttributes are unnested and applied to the specific decoratee;
/// Other attributes are not unnested, and simply copied for each decoratee.
ijackson marked this conversation as resolved.
Show resolved Hide resolved
fn distribute_and_unnest_attrs(
input: &mut Vec<Attribute>,
outputs: &mut [(&'static str, &mut Vec<Attribute>)],
) -> darling::Result<()> {
let mut errors = vec![];

ijackson marked this conversation as resolved.
Show resolved Hide resolved
for attr in input.drain(..) {
let unnest = outputs
ijackson marked this conversation as resolved.
Show resolved Hide resolved
.iter_mut()
.find(|(ptattr, _)| attr.path.is_ident(ptattr));

if let Some((_, unnest)) = unnest {
match unnest_from_one_attribute(attr) {
Ok(n) => unnest.push(n),
Err(e) => errors.push(e),
}
} else {
for (_, output) in outputs.iter_mut() {
output.push(attr.clone());
}
}
}

Ok(self)
if !errors.is_empty() {
return Err(darling::Error::multiple(errors));
}

Ok(())
}

fn unnest_from_one_attribute(attr: syn::Attribute) -> darling::Result<Attribute> {
Expand Down Expand Up @@ -438,34 +453,15 @@ impl FlagVisibility for Options {
}

impl Options {
/// Remove the `builder_struct_attr(...)` packaging around an attribute
/// Populate `self.struct_attrs` and `self.impl_attrs` by draining `self.attrs`
fn unnest_attrs(mut self) -> darling::Result<Self> {
let mut errors = vec![];

for attr in self.attrs.drain(..) {
let unnest = {
if attr.path.is_ident("builder_struct_attr") {
Some(&mut self.struct_attrs)
} else if attr.path.is_ident("builder_impl_attr") {
Some(&mut self.impl_attrs)
} else {
None
}
};
if let Some(unnest) = unnest {
match unnest_from_one_attribute(attr) {
Ok(n) => unnest.push(n),
Err(e) => errors.push(e),
}
} else {
self.struct_attrs.push(attr.clone());
self.impl_attrs.push(attr);
}
}

if !errors.is_empty() {
return Err(darling::Error::multiple(errors));
}
distribute_and_unnest_attrs(
&mut self.attrs,
&mut [
("builder_struct_attr", &mut self.struct_attrs),
("builder_impl_attr", &mut self.impl_attrs),
],
)?;

Ok(self)
}
Expand Down