@@ -42,7 +42,12 @@ impl Parse for PropsMacroInput {
42
42
. attrs
43
43
. iter ( )
44
44
. find ( |x| x. path . is_ident ( "properties" ) )
45
- . expect ( "missing #[properties(wrapper_type = ...)]" ) ;
45
+ . ok_or_else ( || {
46
+ syn:: Error :: new (
47
+ derive_input. span ( ) ,
48
+ "missing #[properties(wrapper_type = ...)]" ,
49
+ )
50
+ } ) ?;
46
51
let wrapper_ty: PropertiesAttr = wrapper_ty. parse_args ( ) ?;
47
52
let props: Vec < _ > = match derive_input. data {
48
53
syn:: Data :: Struct ( struct_data) => parse_fields ( struct_data. fields ) ?,
@@ -85,7 +90,7 @@ enum PropAttr {
85
90
Get ( Option < syn:: Expr > ) ,
86
91
Set ( Option < syn:: Expr > ) ,
87
92
88
- // ident [ = expr]
93
+ // ident = expr
89
94
OverrideClass ( syn:: Type ) ,
90
95
OverrideInterface ( syn:: Type ) ,
91
96
@@ -177,33 +182,19 @@ struct ReceivedAttrs {
177
182
builder_fields : HashMap < syn:: Ident , Option < syn:: Expr > > ,
178
183
}
179
184
180
- impl ReceivedAttrs {
181
- fn new (
182
- attrs_span : & proc_macro2:: Span ,
183
- attrs : impl IntoIterator < Item = PropAttr > ,
184
- ) -> syn:: Result < Self > {
185
+ impl Parse for ReceivedAttrs {
186
+ fn parse ( input : syn:: parse:: ParseStream ) -> syn:: Result < Self > {
187
+ let attrs = syn:: punctuated:: Punctuated :: < PropAttr , Token ! [ , ] > :: parse_terminated ( input) ?;
185
188
let this = attrs. into_iter ( ) . fold ( Self :: default ( ) , |mut this, attr| {
186
189
this. set_from_attr ( attr) ;
187
190
this
188
191
} ) ;
189
192
190
- if this. get . is_none ( ) && this. set . is_none ( ) {
191
- return Err ( syn:: Error :: new (
192
- * attrs_span,
193
- "No `get` or `set` specified: at least one is required." . to_string ( ) ,
194
- ) ) ;
195
- }
196
-
197
- if this. override_class . is_some ( ) && this. override_interface . is_some ( ) {
198
- return Err ( syn:: Error :: new (
199
- * attrs_span,
200
- "Both `override_class` and `override_interface` specified." . to_string ( ) ,
201
- ) ) ;
202
- }
203
-
204
193
Ok ( this)
205
194
}
195
+ }
206
196
197
+ impl ReceivedAttrs {
207
198
fn set_from_attr ( & mut self , attr : PropAttr ) {
208
199
match attr {
209
200
PropAttr :: Get ( some_fn) => self . get = Some ( some_fn. into ( ) ) ,
@@ -258,6 +249,20 @@ impl PropDesc {
258
249
builder_fields,
259
250
} = attrs;
260
251
252
+ if get. is_none ( ) && set. is_none ( ) {
253
+ return Err ( syn:: Error :: new (
254
+ attrs_span,
255
+ "No `get` or `set` specified: at least one is required." . to_string ( ) ,
256
+ ) ) ;
257
+ }
258
+
259
+ if override_class. is_some ( ) && override_interface. is_some ( ) {
260
+ return Err ( syn:: Error :: new (
261
+ attrs_span,
262
+ "Both `override_class` and `override_interface` specified." . to_string ( ) ,
263
+ ) ) ;
264
+ }
265
+
261
266
// Fill needed, but missing, attributes with calculated default values
262
267
let name = name. unwrap_or_else ( || {
263
268
syn:: LitStr :: new (
@@ -284,65 +289,66 @@ impl PropDesc {
284
289
}
285
290
}
286
291
287
- fn expand_properties_fn ( props : & [ PropDesc ] ) -> TokenStream2 {
288
- let n_props = props. len ( ) ;
292
+ fn expand_param_spec ( prop : & PropDesc ) -> TokenStream2 {
289
293
let crate_ident = crate_ident_new ( ) ;
290
- let properties_build_phase = props. iter ( ) . map ( |prop| {
291
- let PropDesc {
292
- ty, name, builder, ..
293
- } = prop;
294
-
295
- let rw_flags = match ( & prop. get , & prop. set ) {
296
- ( Some ( _) , Some ( _) ) => quote ! ( . readwrite( ) ) ,
297
- ( Some ( _) , None ) => quote ! ( . read_only( ) ) ,
298
- ( None , Some ( _) ) => quote ! ( . write_only( ) ) ,
299
- ( None , None ) => unreachable ! ( "No `get` or `set` specified" ) ,
300
- } ;
294
+ let PropDesc {
295
+ ty, name, builder, ..
296
+ } = prop;
297
+
298
+ match ( & prop. override_class , & prop. override_interface ) {
299
+ ( Some ( c) , None ) => return quote ! ( #crate_ident:: ParamSpecOverride :: for_class:: <#c>( #name) ) ,
300
+ ( None , Some ( i) ) => {
301
+ return quote ! ( #crate_ident:: ParamSpecOverride :: for_interface:: <#i>( #name) )
302
+ }
303
+ ( Some ( _) , Some ( _) ) => {
304
+ unreachable ! ( "Both `override_class` and `override_interface` specified" )
305
+ }
306
+ ( None , None ) => ( ) ,
307
+ } ;
301
308
302
- match ( & prop. override_class , & prop. override_interface ) {
303
- ( Some ( c) , None ) => {
304
- return quote ! ( #crate_ident:: ParamSpecOverride :: for_class:: <#c>( #name) )
305
- }
306
- ( None , Some ( i) ) => {
307
- return quote ! ( #crate_ident:: ParamSpecOverride :: for_interface:: <#i>( #name) )
308
- }
309
- ( Some ( _) , Some ( _) ) => {
310
- unreachable ! ( "Both `override_class` and `override_interface` specified" )
311
- }
312
- ( None , None ) => ( ) ,
313
- } ;
309
+ let rw_flags = match ( & prop. get , & prop. set ) {
310
+ ( Some ( _) , Some ( _) ) => quote ! ( . readwrite( ) ) ,
311
+ ( Some ( _) , None ) => quote ! ( . read_only( ) ) ,
312
+ ( None , Some ( _) ) => quote ! ( . write_only( ) ) ,
313
+ ( None , None ) => unreachable ! ( "No `get` or `set` specified" ) ,
314
+ } ;
314
315
315
- let builder_call = builder
316
- . as_ref ( )
317
- . cloned ( )
318
- . map ( |( mut required_params, chained_methods) | {
319
- let name_expr = syn:: ExprLit {
320
- attrs : vec ! [ ] ,
321
- lit : syn:: Lit :: Str ( name. to_owned ( ) ) ,
322
- } ;
323
- required_params. insert ( 0 , name_expr. into ( ) ) ;
324
- let required_params = required_params. iter ( ) ;
325
-
326
- quote ! ( ( #( #required_params, ) * ) #chained_methods)
327
- } )
328
- . unwrap_or ( quote ! ( ( #name) ) ) ;
316
+ let builder_call = builder
317
+ . as_ref ( )
318
+ . cloned ( )
319
+ . map ( |( mut required_params, chained_methods) | {
320
+ let name_expr = syn:: ExprLit {
321
+ attrs : vec ! [ ] ,
322
+ lit : syn:: Lit :: Str ( name. to_owned ( ) ) ,
323
+ } ;
324
+ required_params. insert ( 0 , name_expr. into ( ) ) ;
325
+ let required_params = required_params. iter ( ) ;
329
326
330
- let builder_fields = prop. builder_fields . iter ( ) . map ( |( k, v) | quote ! ( . #k( #v) ) ) ;
327
+ quote ! ( ( #( #required_params, ) * ) #chained_methods)
328
+ } )
329
+ . unwrap_or ( quote ! ( ( #name) ) ) ;
331
330
332
- let span = prop. attrs_span ;
333
- quote_spanned ! { span=>
334
- <<#ty as #crate_ident:: Property >:: Value as #crate_ident:: HasParamSpec >
335
- :: param_spec_builder( ) #builder_call
336
- #rw_flags
337
- #( #builder_fields) *
338
- . build( )
339
- }
340
- } ) ;
331
+ let builder_fields = prop. builder_fields . iter ( ) . map ( |( k, v) | quote ! ( . #k( #v) ) ) ;
332
+
333
+ let span = prop. attrs_span ;
334
+ quote_spanned ! { span=>
335
+ <<#ty as #crate_ident:: Property >:: Value as #crate_ident:: HasParamSpec >
336
+ :: param_spec_builder( ) #builder_call
337
+ #rw_flags
338
+ #( #builder_fields) *
339
+ . build( )
340
+ }
341
+ }
342
+
343
+ fn expand_properties_fn ( props : & [ PropDesc ] ) -> TokenStream2 {
344
+ let n_props = props. len ( ) ;
345
+ let crate_ident = crate_ident_new ( ) ;
346
+ let param_specs = props. iter ( ) . map ( expand_param_spec) ;
341
347
quote ! (
342
348
fn derived_properties( ) -> & ' static [ #crate_ident:: ParamSpec ] {
343
349
use #crate_ident:: once_cell:: sync:: Lazy ;
344
350
static PROPERTIES : Lazy <[ #crate_ident:: ParamSpec ; #n_props] > = Lazy :: new( || [
345
- #( #properties_build_phase , ) *
351
+ #( #param_specs , ) *
346
352
] ) ;
347
353
PROPERTIES . as_ref( )
348
354
}
@@ -392,10 +398,10 @@ fn expand_property_fn(props: &[PropDesc]) -> TokenStream2 {
392
398
pspec: & #crate_ident:: ParamSpec
393
399
) -> #crate_ident:: Value {
394
400
let prop = DerivedPropertiesEnum :: try_from( id-1 )
395
- . unwrap_or_else( |_| panic!( "missing handler for property {}" , pspec. name( ) ) ) ;
401
+ . unwrap_or_else( |_| panic!( "property not defined {}" , pspec. name( ) ) ) ;
396
402
match prop {
397
403
#( #match_branch_get, ) *
398
- _ => unreachable! ( ) ,
404
+ _ => panic! ( "missing getter for property {}" , pspec . name ( ) ) ,
399
405
}
400
406
}
401
407
)
@@ -450,10 +456,10 @@ fn expand_set_property_fn(props: &[PropDesc]) -> TokenStream2 {
450
456
pspec: & #crate_ident:: ParamSpec
451
457
) {
452
458
let prop = DerivedPropertiesEnum :: try_from( id-1 )
453
- . unwrap_or_else( |_| panic!( "missing handler for property {}" , pspec. name( ) ) ) ; ;
459
+ . unwrap_or_else( |_| panic!( "property not defined {}" , pspec. name( ) ) ) ;
454
460
match prop {
455
461
#( #match_branch_set, ) *
456
- _ => unreachable! ( ) ,
462
+ _ => panic! ( "missing setter for property {}" , pspec . name ( ) ) ,
457
463
}
458
464
}
459
465
)
@@ -469,16 +475,13 @@ fn parse_fields(fields: syn::Fields) -> syn::Result<Vec<PropDesc>> {
469
475
attrs
470
476
. into_iter ( )
471
477
. filter ( |a| a. path . is_ident ( "property" ) )
472
- . map ( move |attrs| {
473
- let span = attrs. span ( ) ;
474
- let attrs = attrs. parse_args_with (
475
- syn:: punctuated:: Punctuated :: < PropAttr , Token ! [ , ] > :: parse_terminated,
476
- ) ?;
478
+ . map ( move |prop_attrs| {
479
+ let span = prop_attrs. span ( ) ;
477
480
PropDesc :: new (
478
481
span,
479
482
ident. as_ref ( ) . unwrap ( ) . clone ( ) ,
480
483
ty. clone ( ) ,
481
- ReceivedAttrs :: new ( & span , attrs ) ?,
484
+ prop_attrs . parse_args ( ) ?,
482
485
)
483
486
} )
484
487
} )
@@ -490,7 +493,7 @@ fn name_to_ident(name: &syn::LitStr) -> syn::Ident {
490
493
format_ident ! ( "{}" , name. value( ) . replace( '-' , "_" ) )
491
494
}
492
495
493
- fn expand_getset_properties_impl ( props : & [ PropDesc ] ) -> TokenStream2 {
496
+ fn expand_wrapper_getset_properties ( props : & [ PropDesc ] ) -> TokenStream2 {
494
497
let crate_ident = crate_ident_new ( ) ;
495
498
let defs = props. iter ( ) . map ( |p| {
496
499
let name = & p. name ;
@@ -518,7 +521,7 @@ fn expand_getset_properties_impl(props: &[PropDesc]) -> TokenStream2 {
518
521
quote ! ( #( #defs) * )
519
522
}
520
523
521
- fn expand_connect_prop_notify_impl ( props : & [ PropDesc ] ) -> TokenStream2 {
524
+ fn expand_wrapper_connect_prop_notify ( props : & [ PropDesc ] ) -> TokenStream2 {
522
525
let crate_ident = crate_ident_new ( ) ;
523
526
let connection_fns = props. iter ( ) . map ( |p| {
524
527
let name = & p. name ;
@@ -533,7 +536,7 @@ fn expand_connect_prop_notify_impl(props: &[PropDesc]) -> TokenStream2 {
533
536
quote ! ( #( #connection_fns) * )
534
537
}
535
538
536
- fn expand_notify_impl ( props : & [ PropDesc ] ) -> TokenStream2 {
539
+ fn expand_wrapper_notify_prop ( props : & [ PropDesc ] ) -> TokenStream2 {
537
540
let crate_ident = crate_ident_new ( ) ;
538
541
let emit_fns = props. iter ( ) . map ( |p| {
539
542
let name = & p. name ;
@@ -603,9 +606,9 @@ pub fn impl_derive_props(input: PropsMacroInput) -> TokenStream {
603
606
let fn_properties = expand_properties_fn ( & input. props ) ;
604
607
let fn_property = expand_property_fn ( & input. props ) ;
605
608
let fn_set_property = expand_set_property_fn ( & input. props ) ;
606
- let getset_properties_impl = expand_getset_properties_impl ( & input. props ) ;
607
- let connect_prop_notify_impl = expand_connect_prop_notify_impl ( & input. props ) ;
608
- let notify_impl = expand_notify_impl ( & input. props ) ;
609
+ let getset_properties = expand_wrapper_getset_properties ( & input. props ) ;
610
+ let connect_prop_notify = expand_wrapper_connect_prop_notify ( & input. props ) ;
611
+ let notify_prop = expand_wrapper_notify_prop ( & input. props ) ;
609
612
let properties_enum = expand_properties_enum ( & input. props ) ;
610
613
611
614
let expanded = quote ! {
@@ -620,9 +623,9 @@ pub fn impl_derive_props(input: PropsMacroInput) -> TokenStream {
620
623
}
621
624
622
625
impl #wrapper_type {
623
- #getset_properties_impl
624
- #connect_prop_notify_impl
625
- #notify_impl
626
+ #getset_properties
627
+ #connect_prop_notify
628
+ #notify_prop
626
629
}
627
630
628
631
} ;
0 commit comments