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

Optionally transform Extend fields to add items one by one #46

Draft
wants to merge 19 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
486480b
Rudimentarily adjusted parser to accept `strip_extend` with optional …
Tamschi Jan 16, 2021
c824836
Implement `strip_extend` proof of concept
Tamschi Jan 17, 2021
03e0e58
Rework `strip_extend` into `strip_collection`, which has stricter typ…
Tamschi Jan 18, 2021
b19a01b
Use `FromIterator` to create initial stripped collection iff neither …
Tamschi Jan 18, 2021
4376566
Accept any valid `Extend::extend` parameter in repeat setter calls
Tamschi Jan 18, 2021
8e4b301
Accept e.g. `strip_collection(from_first = |first| vec![first])` inst…
Tamschi Jan 22, 2021
7635462
Merge branch 'master' into extend-field-buildup
Tamschi Feb 8, 2021
a3d3e31
Rework `strip_collection` into `extend`, allow extending with an iter…
Tamschi Feb 4, 2021
c9bba54
Accept any matching `IntoIterator` instead of just matching `Iterator…
Tamschi Feb 8, 2021
586d3dc
Add some `extend` tests, fix issues with type inference and improve c…
Tamschi Feb 13, 2021
23ca53a
Ignore field default in automatic extend initialisers
Tamschi Feb 13, 2021
094a827
Add generics support in combination with `extend`
Tamschi Feb 13, 2021
4a2afb0
Remove extra parentheses
Tamschi Feb 13, 2021
a3006a1
Support combining `strip_option` and `extend` on the same field
Tamschi Feb 13, 2021
9bb9dbf
cargo +nightly fmt
Tamschi Feb 13, 2021
4c67cf4
Assert `strip_option` flag inside `type_from_inside_option`
Tamschi Feb 13, 2021
c8abc4d
Mention single item setter name in `early_build_error_message`
Tamschi Feb 14, 2021
8cc816a
Merge branch 'master' into extend-field-buildup
Tamschi Jun 22, 2021
3a8ff5f
Merge remote-tracking branch 'upstream/master' into extend-field-buildup
Tamschi Nov 11, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions src/field_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,20 @@ impl<'a> FieldInfo<'a> {
syn::GenericParam::Type(self.generic_ident.clone().into())
}

pub fn item_name(&self) -> String {
self.builder_attr
.setter
.extend
.as_ref()
.expect("Tried to retrieve item_name() on FieldInfo without extend.")
.item_name
.as_ref()
.map_or_else(
|| self.name.to_string().trim_start().trim_start_matches("r#").to_string() + "_item",
|item_name| item_name.to_string(),
)
}

pub fn type_ident(&self) -> syn::Type {
ident_to_type(self.generic_ident.clone())
}
Expand Down
15 changes: 7 additions & 8 deletions src/struct_info.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use proc_macro2::{Span, TokenStream};
use quote::{quote, quote_spanned, ToTokens};
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tend to use quote_spanned quite often even when it's not strictly necessary, since it tends to make for better error locations.

My earlier hack with #[forbid(unused_variables)] is gone, of course, but this should still flag some type/trait errors on the field itself or the matching attribute or attribute parameter.

use std::fmt::Write;
use syn::{parse::Error, spanned::Spanned};

use crate::field_info::{Configured, ExtendField, FieldBuilderAttr, FieldInfo, SetterSettings};
Expand Down Expand Up @@ -287,7 +288,7 @@ impl<'a> StructInfo<'a> {
keyword_span,
from_first,
from_iter,
item_name,
item_name: _,
}) = &field.builder_attr.setter.extend
{
// Changing the builder field type entirely here (instead of just the argument) means there
Expand All @@ -299,12 +300,7 @@ impl<'a> StructInfo<'a> {
field_type
};

let item_name = item_name.clone().unwrap_or_else(|| {
syn::Ident::new(
(field.name.to_string() + "_item").trim_start().trim_start_matches("r#"),
field.name.span(),
)
});
let item_name = syn::Ident::new(&field.item_name(), field.name.span());

let descructuring = descructuring.collect::<Vec<_>>();
let reconstructing = reconstructing.collect::<Vec<_>>();
Expand Down Expand Up @@ -609,7 +605,10 @@ impl<'a> StructInfo<'a> {
),
proc_macro2::Span::call_site(),
);
let early_build_error_message = format!("Missing required field {}", field_name);
let mut early_build_error_message = format!("Missing required field {}", field_name);
if field.builder_attr.setter.extend.is_some() {
write!(&mut early_build_error_message, " (single item setter: {})", field.item_name()).unwrap();
}
Comment on lines +619 to +622
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There probably should be a special message in case neither of these are available as initialisers.
I'll stop for today, but I've added this point to my to-do list.

(As an aside, I've just been able to confirm this feature will work for my use-case 🥳
I've queued that feature up just so it's easier to keep track of, but that won't change how I work on this one.)


Ok(quote! {
#[doc(hidden)]
Expand Down