77
88use  crate :: class:: RpcAttr ; 
99use  crate :: util:: { bail_fn,  ident,  safe_ident} ; 
10- use  crate :: { util,  ParseResult } ; 
10+ use  crate :: { bail ,   util,   KvParser ,  ParseResult } ; 
1111use  proc_macro2:: { Group ,  Ident ,  TokenStream ,  TokenTree } ; 
1212use  quote:: { format_ident,  quote} ; 
1313
@@ -126,6 +126,7 @@ pub fn make_method_registration(
126126        . iter ( ) 
127127        . map ( |ident| ident. to_string ( ) ) ; 
128128
129+     let  default_parameters = extract_default_parameters ( & func_definition. signature_info ) ?; 
129130    // Transport #[cfg] attrs to the FFI glue to ensure functions which were conditionally 
130131    // removed from compilation don't cause errors. 
131132    let  cfg_attrs = util:: extract_cfg_attrs ( & func_definition. external_attributes ) 
@@ -158,6 +159,9 @@ pub fn make_method_registration(
158159                    & [ 
159160                        #(  #param_ident_strs ) , * 
160161                    ] , 
162+                     vec![ 
163+                        #(  <#default_parameters as  :: godot:: meta:: AsArg >. to_variant( )  ) , * 
164+                     ] 
161165                ) 
162166            } ; 
163167
@@ -175,6 +179,30 @@ pub fn make_method_registration(
175179    Ok ( registration) 
176180} 
177181
182+ fn  extract_default_parameters ( sig_info :  & SignatureInfo )  -> ParseResult < Vec < TokenStream > >  { 
183+     let  mut  res = vec ! [ ] ; 
184+     let  mut  allowed = true ; 
185+     for  pd in  sig_info. param_defaults . iter ( ) . rev ( )  { 
186+         match  pd { 
187+             Some ( tk)  if  allowed => { 
188+                 res. push ( tk. clone ( ) ) ;  // toreview: if we really care about it, we can use &mut sig_info and mem::take() as we don't use this later 
189+             } 
190+             None  if  allowed => { 
191+                 allowed = false ; 
192+             } 
193+             Some ( tk)  if  !allowed => { 
194+                 return  bail ! ( 
195+                     tk, 
196+                     "opt arguments are only allowed at the end of the argument list." 
197+                 ) ; 
198+             } 
199+             _ => ( ) , 
200+         } 
201+     } 
202+     res. reverse ( ) ; 
203+     Ok ( res) 
204+ } 
205+ 
178206// ---------------------------------------------------------------------------------------------------------------------------------------------- 
179207// Implementation 
180208
@@ -199,6 +227,8 @@ pub struct SignatureInfo {
199227/// 
200228/// Index points into original venial tokens (i.e. takes into account potential receiver params). 
201229pub  modified_param_types :  Vec < ( usize ,  venial:: TypeExpr ) > , 
230+     /// Contains expressions of the default values of parameters. 
231+ pub  param_defaults :  Vec < Option < TokenStream > > , 
202232} 
203233
204234impl  SignatureInfo  { 
@@ -210,6 +240,7 @@ impl SignatureInfo {
210240            param_types :  vec ! [ ] , 
211241            return_type :  quote !  {  ( )  } , 
212242            modified_param_types :  vec ! [ ] , 
243+             param_defaults :  vec ! [ ] , 
213244        } 
214245    } 
215246
@@ -350,7 +381,7 @@ pub(crate) fn into_signature_info(
350381    signature :  venial:: Function , 
351382    class_name :  & Ident , 
352383    has_gd_self :  bool , 
353- )  -> SignatureInfo  { 
384+ )  -> ParseResult < SignatureInfo >  { 
354385    let  method_name = signature. name . clone ( ) ; 
355386    let  mut  receiver_type = if  has_gd_self { 
356387        ReceiverType :: GdSelf 
@@ -361,6 +392,8 @@ pub(crate) fn into_signature_info(
361392    let  num_params = signature. params . inner . len ( ) ; 
362393    let  mut  param_idents = Vec :: with_capacity ( num_params) ; 
363394    let  mut  param_types = Vec :: with_capacity ( num_params) ; 
395+     let  mut  param_defaults = Vec :: with_capacity ( num_params) ; 
396+ 
364397    let  ret_type = match  signature. return_ty  { 
365398        None  => quote !  {  ( )  } , 
366399        Some ( ty)  => map_self_to_class_name ( ty. tokens ,  class_name) , 
@@ -398,21 +431,27 @@ pub(crate) fn into_signature_info(
398431                        tokens :  map_self_to_class_name ( ty. tokens ,  class_name) , 
399432                    } , 
400433                } ; 
434+                 let  default = match  crate :: KvParser :: parse ( & arg. attributes ,  "opt" ) ? { 
435+                     None  => None , 
436+                     Some ( mut  parser)  => Some ( parser. handle_expr_required ( "default" ) ?) , 
437+                 } ; 
401438
402439                param_types. push ( ty) ; 
403440                param_idents. push ( ident) ; 
441+                 param_defaults. push ( default) ; 
404442            } 
405443        } 
406444    } 
407445
408-     SignatureInfo  { 
446+     Ok ( SignatureInfo  { 
409447        method_name, 
410448        receiver_type, 
411449        param_idents, 
412450        param_types, 
413451        return_type :  ret_type, 
414452        modified_param_types, 
415-     } 
453+         param_defaults, 
454+     } ) 
416455} 
417456
418457/// If `f32` is used for a delta parameter in a virtual process function, transparently use `f64` behind the scenes. 
0 commit comments