Skip to content

Commit 7ad321f

Browse files
authored
Merge pull request #1096 from ranfdev/syn2
Update syn: v2.0
2 parents c85cd50 + 8b97e5e commit 7ad321f

12 files changed

+389
-238
lines changed

glib-macros/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ heck = "0.4"
1717
proc-macro-error = "1.0"
1818
proc-macro2 = "1.0"
1919
quote = "1.0"
20-
syn = { version = "1.0", features = ["full"] }
20+
syn = { version = "2.0", features = ["full"] }
2121
proc-macro-crate = "1.0"
2222

2323
[lib]

glib-macros/src/boxed_derive.rs

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use proc_macro2::{Ident, TokenStream};
44
use proc_macro_error::abort_call_site;
55
use quote::quote;
66

7-
use crate::utils::{crate_ident_new, find_attribute_meta, find_nested_meta, parse_name};
7+
use crate::utils::{crate_ident_new, parse_nested_meta_items, NestedMetaItem};
88

99
fn gen_option_to_ptr() -> TokenStream {
1010
quote! {
@@ -94,18 +94,29 @@ fn gen_impl_to_value_optional(name: &Ident, crate_ident: &TokenStream) -> TokenS
9494
pub fn impl_boxed(input: &syn::DeriveInput) -> TokenStream {
9595
let name = &input.ident;
9696

97-
let gtype_name = match parse_name(input, "boxed_type") {
98-
Ok(name) => name,
99-
Err(e) => abort_call_site!(
100-
"{}: #[derive(glib::Boxed)] requires #[boxed_type(name = \"BoxedTypeName\")]",
101-
e
102-
),
97+
let mut gtype_name = NestedMetaItem::<syn::LitStr>::new("name")
98+
.required()
99+
.value_required();
100+
let mut nullable = NestedMetaItem::<syn::LitBool>::new("nullable").value_optional();
101+
102+
let found = parse_nested_meta_items(
103+
&input.attrs,
104+
"boxed_type",
105+
&mut [&mut gtype_name, &mut nullable],
106+
);
107+
108+
match found {
109+
Ok(None) => {
110+
abort_call_site!(
111+
"#[derive(glib::Boxed)] requires #[boxed_type(name = \"BoxedTypeName\")]"
112+
)
113+
}
114+
Err(e) => return e.to_compile_error(),
115+
Ok(_) => {}
103116
};
104117

105-
let meta = find_attribute_meta(&input.attrs, "boxed_type")
106-
.unwrap()
107-
.unwrap();
108-
let nullable = find_nested_meta(&meta, "nullable").is_some();
118+
let gtype_name = gtype_name.value.unwrap();
119+
let nullable = nullable.found || nullable.value.map(|b| b.value()).unwrap_or(false);
109120

110121
let crate_ident = crate_ident_new();
111122

glib-macros/src/enum_derive.rs

Lines changed: 24 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@ use proc_macro_error::abort_call_site;
66
use quote::{quote, quote_spanned};
77
use syn::{punctuated::Punctuated, spanned::Spanned, token::Comma, Data, Ident, Variant};
88

9-
use crate::utils::{
10-
crate_ident_new, gen_enum_from_glib, parse_item_attributes, parse_name, ItemAttribute,
11-
};
9+
use crate::utils::{crate_ident_new, gen_enum_from_glib, parse_nested_meta_items, NestedMetaItem};
1210

1311
// Generate glib::gobject_ffi::GEnumValue structs mapping the enum such as:
1412
// glib::gobject_ffi::GEnumValue {
@@ -29,21 +27,17 @@ fn gen_enum_values(
2927
let mut value_name = name.to_string().to_upper_camel_case();
3028
let mut value_nick = name.to_string().to_kebab_case();
3129

32-
let attrs = parse_item_attributes("enum_value", &v.attrs);
33-
let attrs = match attrs {
34-
Ok(attrs) => attrs,
35-
Err(e) => abort_call_site!(
36-
"{}: derive(glib::Enum) enum supports only the following optional attributes: #[enum_value(name = \"The Cat\", nick = \"chat\")]",
37-
e
38-
),
39-
};
40-
41-
attrs.into_iter().for_each(|attr|
42-
match attr {
43-
ItemAttribute::Name(n) => value_name = n,
44-
ItemAttribute::Nick(n) => value_nick = n,
45-
}
46-
);
30+
let mut name_attr = NestedMetaItem::<syn::LitStr>::new("name").value_required();
31+
let mut nick = NestedMetaItem::<syn::LitStr>::new("nick").value_required();
32+
33+
let found =
34+
parse_nested_meta_items(&v.attrs, "enum_value", &mut [&mut name_attr, &mut nick]);
35+
if let Err(e) = found {
36+
return e.to_compile_error();
37+
}
38+
39+
value_name = name_attr.value.map(|s| s.value()).unwrap_or(value_name);
40+
value_nick = nick.value.map(|s| s.value()).unwrap_or(value_nick);
4741

4842
let value_name = format!("{value_name}\0");
4943
let value_nick = format!("{value_nick}\0");
@@ -73,14 +67,19 @@ pub fn impl_enum(input: &syn::DeriveInput) -> TokenStream {
7367
_ => abort_call_site!("#[derive(glib::Enum)] only supports enums"),
7468
};
7569

76-
let gtype_name = match parse_name(input, "enum_type") {
77-
Ok(name) => name,
78-
Err(e) => abort_call_site!(
79-
"{}: #[derive(glib::Enum)] requires #[enum_type(name = \"EnumTypeName\")]",
80-
e
81-
),
82-
};
70+
let mut gtype_name = NestedMetaItem::<syn::LitStr>::new("name")
71+
.required()
72+
.value_required();
73+
let found = parse_nested_meta_items(&input.attrs, "enum_type", &mut [&mut gtype_name]);
8374

75+
match found {
76+
Ok(None) => {
77+
abort_call_site!("#[derive(glib::Enum)] requires #[enum_type(name = \"EnumTypeName\")]")
78+
}
79+
Err(e) => return e.to_compile_error(),
80+
Ok(attr) => attr,
81+
};
82+
let gtype_name = gtype_name.value.unwrap();
8483
let from_glib = gen_enum_from_glib(name, enum_variants);
8584
let (enum_values, nb_enum_values) = gen_enum_values(name, enum_variants);
8685

glib-macros/src/error_domain_derive.rs

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use proc_macro_error::abort_call_site;
55
use quote::quote;
66
use syn::Data;
77

8-
use crate::utils::{crate_ident_new, gen_enum_from_glib, parse_name};
8+
use crate::utils::{crate_ident_new, gen_enum_from_glib, parse_nested_meta_items, NestedMetaItem};
99

1010
pub fn impl_error_domain(input: &syn::DeriveInput) -> TokenStream {
1111
let name = &input.ident;
@@ -15,14 +15,21 @@ pub fn impl_error_domain(input: &syn::DeriveInput) -> TokenStream {
1515
_ => abort_call_site!("#[derive(glib::ErrorDomain)] only supports enums"),
1616
};
1717

18-
let domain_name = match parse_name(input, "error_domain") {
19-
Ok(name) => name,
20-
Err(e) => abort_call_site!(
21-
"{}: #[derive(glib::ErrorDomain)] requires #[error_domain(name = \"domain-name\")]",
22-
e
23-
),
24-
};
18+
let mut domain_name = NestedMetaItem::<syn::LitStr>::new("name")
19+
.required()
20+
.value_required();
21+
let found = parse_nested_meta_items(&input.attrs, "error_domain", &mut [&mut domain_name]);
2522

23+
match found {
24+
Ok(None) => {
25+
abort_call_site!(
26+
"#[derive(glib::ErrorDomain)] requires #[error_domain(name = \"domain-name\")]"
27+
)
28+
}
29+
Err(e) => return e.to_compile_error(),
30+
Ok(_) => (),
31+
};
32+
let domain_name = domain_name.value.unwrap();
2633
let crate_ident = crate_ident_new();
2734

2835
let from_glib = gen_enum_from_glib(name, enum_variants);

glib-macros/src/flags_attribute.rs

Lines changed: 53 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,34 @@ use proc_macro_error::abort_call_site;
66
use quote::{quote, quote_spanned};
77
use syn::{
88
punctuated::Punctuated, spanned::Spanned, token::Comma, Attribute, Data, DeriveInput, Ident,
9-
NestedMeta, Variant, Visibility,
9+
Variant, Visibility,
1010
};
1111

12-
use crate::utils::{
13-
crate_ident_new, find_attribute_meta, find_nested_meta, parse_item_attributes,
14-
parse_name_attribute, ItemAttribute,
15-
};
16-
17-
// Flag is not registered if it has the #[flags_value(skip)] meta
18-
fn attribute_has_skip(attrs: &[Attribute]) -> bool {
19-
let meta = find_attribute_meta(attrs, "flags_value").unwrap();
12+
use crate::utils::{crate_ident_new, parse_nested_meta_items, NestedMetaItem};
2013

21-
match meta {
22-
None => false,
23-
Some(meta) => find_nested_meta(&meta, "skip").is_some(),
14+
pub struct AttrInput {
15+
pub enum_name: syn::LitStr,
16+
}
17+
struct FlagsDesc {
18+
variant: Variant,
19+
name: Option<String>,
20+
nick: Option<String>,
21+
skip: bool,
22+
}
23+
impl FlagsDesc {
24+
fn from_attrs(variant: Variant, attrs: &[Attribute]) -> syn::Result<Self> {
25+
let mut name = NestedMetaItem::<syn::LitStr>::new("name").value_required();
26+
let mut nick = NestedMetaItem::<syn::LitStr>::new("nick").value_required();
27+
let mut skip = NestedMetaItem::<syn::LitBool>::new("skip").value_optional();
28+
29+
parse_nested_meta_items(attrs, "flags_value", &mut [&mut name, &mut nick, &mut skip])?;
30+
31+
Ok(Self {
32+
variant,
33+
name: name.value.map(|s| s.value()),
34+
nick: nick.value.map(|s| s.value()),
35+
skip: skip.found || skip.value.map(|b| b.value()).unwrap_or(false),
36+
})
2437
}
2538
}
2639

@@ -38,39 +51,35 @@ fn gen_flags_values(
3851

3952
// start at one as GFlagsValue array is null-terminated
4053
let mut n = 1;
41-
let recurse = enum_variants.iter().filter(|v| { !attribute_has_skip(&v.attrs) } ).map(|v| {
42-
let name = &v.ident;
43-
let mut value_name = name.to_string().to_upper_camel_case();
44-
let mut value_nick = name.to_string().to_kebab_case();
45-
46-
let attrs = parse_item_attributes("flags_value", &v.attrs);
47-
let attrs = match attrs {
48-
Ok(attrs) => attrs,
49-
Err(e) => abort_call_site!(
50-
"{}: #[glib::flags] supports only the following optional attributes: #[flags_value(name = \"The Name\", nick = \"the-nick\")] or #[flags_value(skip)]",
51-
e
52-
),
53-
};
54-
55-
attrs.into_iter().for_each(|attr|
56-
match attr {
57-
ItemAttribute::Name(n) => value_name = n,
58-
ItemAttribute::Nick(n) => value_nick = n,
54+
let recurse = enum_variants
55+
.iter()
56+
.map(|v| FlagsDesc::from_attrs(v.clone(), &v.attrs).unwrap())
57+
.filter(|desc| !desc.skip)
58+
.map(|desc| {
59+
let v = desc.variant;
60+
let name = &v.ident;
61+
let mut value_name = name.to_string().to_upper_camel_case();
62+
let mut value_nick = name.to_string().to_kebab_case();
63+
64+
if let Some(n) = desc.name {
65+
value_name = n;
66+
}
67+
if let Some(n) = desc.nick {
68+
value_nick = n;
5969
}
60-
);
6170

62-
let value_name = format!("{value_name}\0");
63-
let value_nick = format!("{value_nick}\0");
71+
let value_name = format!("{value_name}\0");
72+
let value_nick = format!("{value_nick}\0");
6473

65-
n += 1;
66-
quote_spanned! {v.span()=>
67-
#crate_ident::gobject_ffi::GFlagsValue {
68-
value: #enum_name::#name.bits(),
69-
value_name: #value_name as *const _ as *const _,
70-
value_nick: #value_nick as *const _ as *const _,
71-
},
72-
}
73-
});
74+
n += 1;
75+
quote_spanned! {v.span()=>
76+
#crate_ident::gobject_ffi::GFlagsValue {
77+
value: #enum_name::#name.bits(),
78+
value_name: #value_name as *const _ as *const _,
79+
value_nick: #value_nick as *const _ as *const _,
80+
},
81+
}
82+
});
7483
(
7584
quote! {
7685
#(#recurse)*
@@ -104,15 +113,8 @@ fn gen_bitflags(
104113
}
105114
}
106115

107-
pub fn impl_flags(attrs: &NestedMeta, input: &DeriveInput) -> TokenStream {
108-
let gtype_name = match parse_name_attribute(attrs) {
109-
Ok(name) => name,
110-
Err(e) => abort_call_site!(
111-
"{}: [glib::flags] requires #[glib::flags(name = \"FlagsTypeName\")]",
112-
e
113-
),
114-
};
115-
116+
pub fn impl_flags(attrs: AttrInput, input: &DeriveInput) -> TokenStream {
117+
let gtype_name = attrs.enum_name.value();
116118
let name = &input.ident;
117119
let visibility = &input.vis;
118120

glib-macros/src/lib.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@ mod variant_derive;
1616

1717
mod utils;
1818

19+
use flags_attribute::AttrInput;
1920
use proc_macro::TokenStream;
2021
use proc_macro_error::proc_macro_error;
21-
use syn::{parse_macro_input, DeriveInput, NestedMeta};
22+
use syn::{parse_macro_input, DeriveInput};
23+
use utils::{parse_nested_meta_items_from_stream, NestedMetaItem};
2224

2325
/// Macro for passing variables as strong or weak references into a closure.
2426
///
@@ -498,9 +500,19 @@ pub fn enum_derive(input: TokenStream) -> TokenStream {
498500
#[proc_macro_attribute]
499501
#[proc_macro_error]
500502
pub fn flags(attr: TokenStream, item: TokenStream) -> TokenStream {
501-
let attr_meta = parse_macro_input!(attr as NestedMeta);
503+
let mut name = NestedMetaItem::<syn::LitStr>::new("name")
504+
.required()
505+
.value_required();
506+
507+
if let Err(e) = parse_nested_meta_items_from_stream(attr.into(), &mut [&mut name]) {
508+
return e.to_compile_error().into();
509+
}
510+
511+
let attr_meta = AttrInput {
512+
enum_name: name.value.unwrap(),
513+
};
502514
let input = parse_macro_input!(item as DeriveInput);
503-
let gen = flags_attribute::impl_flags(&attr_meta, &input);
515+
let gen = flags_attribute::impl_flags(attr_meta, &input);
504516
gen.into()
505517
}
506518

glib-macros/src/object_subclass_attribute.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ pub fn impl_object_subclass(input: &syn::ItemImpl) -> TokenStream {
1515
let mut has_class = false;
1616
for item in &input.items {
1717
match item {
18-
syn::ImplItem::Method(method) => {
18+
syn::ImplItem::Fn(method) => {
1919
let name = &method.sig.ident;
2020
if name == "new" || name == "with_class" {
2121
has_new = true;

glib-macros/src/properties.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ impl Parse for PropsMacroInput {
4242
let wrapper_ty = derive_input
4343
.attrs
4444
.iter()
45-
.find(|x| x.path.is_ident("properties"))
45+
.find(|x| x.path().is_ident("properties"))
4646
.ok_or_else(|| {
4747
syn::Error::new(
4848
derive_input.span(),
@@ -141,7 +141,7 @@ impl Parse for PropAttr {
141141
"builder" => {
142142
let content;
143143
parenthesized!(content in input);
144-
let required = content.parse_terminated(syn::Expr::parse)?;
144+
let required = content.parse_terminated(syn::Expr::parse, Token![,])?;
145145
let rest: TokenStream2 = input.parse()?;
146146
PropAttr::Builder(required, rest)
147147
}
@@ -502,7 +502,7 @@ fn parse_fields(fields: syn::Fields) -> syn::Result<Vec<PropDesc>> {
502502
} = field;
503503
attrs
504504
.into_iter()
505-
.filter(|a| a.path.is_ident("property"))
505+
.filter(|a| a.path().is_ident("property"))
506506
.map(move |prop_attrs| {
507507
let span = prop_attrs.span();
508508
PropDesc::new(

0 commit comments

Comments
 (0)