let mut builder = Vec::new();
for field in fields.iter_mut() {
for (i, attr) in field.attrs.iter_mut().enumerate() {
- if attr.path.is_ident("builder") {
+ if attr.path().is_ident("builder") {
let attr = attr.clone();
builder.push((field.clone(), attr, BuilderType::Field));
field.attrs.remove(i);
break;
- } else if attr.path.is_ident("builder_cb") {
+ } else if attr.path().is_ident("builder_cb") {
let attr = attr.clone();
builder.push((field.clone(), attr, BuilderType::Callback));
field.attrs.remove(i);
_ => {
let mut doc = String::new();
for attr in field.attrs {
- if attr.path.is_ident("doc") {
- if let Ok(syn::Meta::NameValue(meta)) = attr.parse_meta() {
- if let syn::Lit::Str(text) = meta.lit {
+ if attr.path().is_ident("doc") {
+ if let Ok(syn::Expr::Lit(literal)) =
+ attr.meta.require_name_value().map(|n| &n.value)
+ {
+ if let syn::Lit::Str(text) = &literal.lit {
doc.push_str(&text.value());
doc.push('\n');
}
}
};
- let mut parameter_tokens = attr.tokens.clone().into_iter();
- let (param_type, convert) = match parameter_tokens.next() {
- Some(parameters) => {
- let tokens = match parameters {
- proc_macro2::TokenTree::Group(group) => group.stream(),
- _ => panic!("invalid syntax"),
- };
-
- match builder_type {
- BuilderType::Field => {
- let options = syn::parse2::<FieldOptions>(tokens)?;
-
- let into_fn = options.into_fn;
- let into_trait = options.into_trait;
- if let Some(default) = options.default_value {
- (
- quote! {impl #into_trait<Option<#field_type>>},
- quote! {#field_ident.#into_fn().unwrap_or(#default)},
- )
- } else {
- (
- quote! {impl #into_trait<#field_type>},
- quote! {#field_ident.#into_fn()},
- )
- }
- }
- BuilderType::Callback => {
- let options = syn::parse2::<CallbackOptions>(tokens)?;
- let into_fn = options.into_fn;
- let into_trait = options.into_trait;
- let inner_type = options.inner_type;
+ let (param_type, convert) = if let Ok(list) = attr.meta.require_list() {
+ let tokens = list.tokens.clone();
+ match builder_type {
+ BuilderType::Field => {
+ let options = syn::parse2::<FieldOptions>(tokens)?;
+
+ let into_fn = options.into_fn;
+ let into_trait = options.into_trait;
+ if let Some(default) = options.default_value {
(
- quote! {impl #into_trait<#inner_type>},
+ quote! {impl #into_trait<Option<#field_type>>},
+ quote! {#field_ident.#into_fn().unwrap_or(#default)},
+ )
+ } else {
+ (
+ quote! {impl #into_trait<#field_type>},
quote! {#field_ident.#into_fn()},
)
}
}
+ BuilderType::Callback => {
+ let options = syn::parse2::<CallbackOptions>(tokens)?;
+ let into_fn = options.into_fn;
+ let into_trait = options.into_trait;
+ let inner_type = options.inner_type;
+ (
+ quote! {impl #into_trait<#inner_type>},
+ quote! {#field_ident.#into_fn()},
+ )
+ }
}
- None => (quote! { #field_type }, quote! { #field_ident}),
+ } else {
+ (quote! { #field_type }, quote! { #field_ident})
};
quotes.extend(quote! {
.into()
}
-fn has_property_derive(attrs: &Vec<Attribute>) -> bool {
+fn has_property_derive(attrs: &Vec<Attribute>) -> Result<bool> {
// SIGH!!
for attr in attrs {
if attr.style != syn::AttrStyle::Outer {
continue;
}
- if let Some(ident) = attr.path.get_ident() {
+ if let Some(ident) = attr.path().get_ident() {
if ident != "derive" {
continue;
}
- if let Ok(syn::Meta::List(list)) = attr.parse_meta() {
- for item in list.nested {
- if let syn::NestedMeta::Meta(meta) = item {
- if let syn::Meta::Path(ref path) = meta {
- if let Some(ident) = path.get_ident() {
- if ident == "Properties" {
- return true;
- }
- }
- }
- }
+ let mut has_properties = false;
+ attr.parse_nested_meta(|nested| {
+ if nested.path.is_ident("Properties") {
+ has_properties = true;
}
- }
+ Ok(())
+ })?;
+
+ return Ok(has_properties);
}
}
- false
+ Ok(false)
}
fn derive_widget(setup: &WidgetSetup, widget: DeriveInput) -> Result<proc_macro2::TokenStream> {
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
- let has_property_derive = has_property_derive(&attrs);
+ let has_property_derive = has_property_derive(&attrs)?;
let pwt: Ident = setup.pwt_crate_name.clone().unwrap_or(format_ident!("pwt"));