@@ -148,8 +148,8 @@ fn parse_enum(
148148// )]
149149struct VariableSpecs {
150150 no_config : bool ,
151- setter : Option < syn:: Ident > ,
152- foreach : Option < syn:: Ident > ,
151+ setter : Option < syn:: Expr > ,
152+ foreach : Option < syn:: Expr > ,
153153 callback : Option < bool > ,
154154 config_name : Option < String > ,
155155 default : Option < syn:: Expr > ,
@@ -319,33 +319,7 @@ impl Variable {
319319 Consumer :: Noop
320320 } else {
321321 let inferred_type = looks_inferred ( & field. ty ) ;
322- match ( specs. setter , specs. foreach , specs. callback , inferred_type) {
323- ( None , None , None | Some ( false ) , false ) | ( None , None , Some ( false ) , true ) => {
324- // Default case: use a setter based on the ident.
325- let setter = format ! ( "set_{parameter_name}" ) ;
326- Consumer :: Setter ( Setter {
327- method : syn:: Ident :: new ( & setter, Span :: call_site ( ) ) ,
328- } )
329- }
330- ( Some ( setter) , None , None | Some ( false ) , _) => {
331- // Explicit setter function
332- Consumer :: Setter ( Setter { method : setter } )
333- }
334- ( None , Some ( foreach) , None | Some ( false ) , _) => {
335- // Foreach function (like `add_item`)
336- Consumer :: ForEach ( Box :: new ( Consumer :: Setter ( Setter { method : foreach } ) ) )
337- }
338- ( None , None , Some ( true ) , _) | ( None , None , _, true ) => {
339- // TODO: Check that the type is iterable? A Vec?
340-
341- // Callback flag means we use the callback_helper-generated `_cb` setter.
342- let setter = format ! ( "set_{parameter_name}_cb" ) ;
343- Consumer :: Setter ( Setter {
344- method : syn:: Ident :: new ( & setter, Span :: call_site ( ) ) ,
345- } )
346- }
347- _ => panic ! ( "unsupported configuration" ) ,
348- }
322+ Consumer :: parse ( & specs, inferred_type, & parameter_name)
349323 } ;
350324
351325 // Some types have special handling
@@ -372,8 +346,11 @@ impl Variable {
372346 }
373347}
374348
375- struct Setter {
376- method : syn:: Ident ,
349+ enum Setter {
350+ /// A method call, implicitly applied to the target object.
351+ Call ( syn:: ExprCall ) ,
352+ /// An ident, the name of the method to call, with a single arg.
353+ Ident ( syn:: Ident ) ,
377354}
378355
379356impl Setter {
@@ -382,9 +359,30 @@ impl Setter {
382359 base_ident : & syn:: Ident ,
383360 field_ident : & syn:: Ident ,
384361 ) -> proc_macro2:: TokenStream {
385- let function = & self . method ;
386- quote ! {
387- #base_ident. #function( #field_ident) ;
362+ match self {
363+ Self :: Call ( call) => {
364+ // Here we don't care about the field ident.
365+ quote ! {
366+ #base_ident. #call;
367+ }
368+ }
369+ Self :: Ident ( function) => {
370+ quote ! {
371+ #base_ident. #function( #field_ident) ;
372+ }
373+ }
374+ }
375+ }
376+
377+ fn parse ( expr : & syn:: Expr ) -> Self {
378+ match expr {
379+ syn:: Expr :: Path ( path) => {
380+ let ident = path. path . get_ident ( ) . unwrap ( ) ;
381+ Self :: Ident ( ident. clone ( ) )
382+ }
383+ syn:: Expr :: Call ( call) => Self :: Call ( call. clone ( ) ) ,
384+
385+ _ => panic ! ( "Unsupported setter expression ({expr:?})" ) ,
388386 }
389387 }
390388}
@@ -401,6 +399,7 @@ enum Consumer {
401399 // The value is a Vec<T> and we need to call something on each item.
402400 ForEach ( Box < Consumer > ) ,
403401
402+ // Optional consumer - unwraps an option and calls the inner consumer.
404403 Opt ( Box < Consumer > ) ,
405404
406405 // We need to call this method to "set" the value.
@@ -436,6 +435,37 @@ impl Consumer {
436435 }
437436 }
438437 }
438+
439+ fn parse ( specs : & VariableSpecs , inferred_type : bool , parameter_name : & str ) -> Self {
440+ match (
441+ & specs. setter ,
442+ & specs. foreach ,
443+ & specs. callback ,
444+ inferred_type,
445+ ) {
446+ ( None , None , None | Some ( false ) , false ) | ( None , None , Some ( false ) , true ) => {
447+ // Default case: use a setter based on the ident.
448+ let setter = format ! ( "set_{parameter_name}" ) ;
449+ Consumer :: Setter ( Setter :: Ident ( syn:: Ident :: new ( & setter, Span :: call_site ( ) ) ) )
450+ }
451+ ( Some ( setter) , None , None | Some ( false ) , _) => {
452+ // Explicit setter function
453+ Consumer :: Setter ( Setter :: parse ( setter) )
454+ }
455+ ( None , Some ( foreach) , None | Some ( false ) , _) => {
456+ // Foreach function (like `add_item`)
457+ Consumer :: ForEach ( Box :: new ( Consumer :: Setter ( Setter :: parse ( foreach) ) ) )
458+ }
459+ ( None , None , Some ( true ) , _) | ( None , None , _, true ) => {
460+ // TODO: Check that the type is iterable? A Vec?
461+
462+ // Callback flag means we use the callback_helper-generated `_cb` setter.
463+ let setter = format ! ( "set_{parameter_name}_cb" ) ;
464+ Consumer :: Setter ( Setter :: Ident ( syn:: Ident :: new ( & setter, Span :: call_site ( ) ) ) )
465+ }
466+ _ => panic ! ( "unsupported configuration" ) ,
467+ }
468+ }
439469}
440470
441471// Returns the quote!d code to build the object using this struct.
0 commit comments