@@ -33,7 +33,7 @@ pub fn make_function_definition_with_defaults(
3333 let default_parameter_usage = format ! ( "To set the default parameters, use [`Self::{extended_fn_name}`] and its builder methods. See [the book](https://godot-rust.github.io/book/godot-api/functions.html#default-parameters) for detailed usage instructions." ) ;
3434 let vis = functions_common:: make_vis ( sig. is_private ( ) ) ;
3535
36- let ( builder_doc, surround_class_prefix ) = make_extender_doc ( sig, & extended_fn_name) ;
36+ let ( builder_doc, surround_class_path ) = make_extender_doc ( sig, & extended_fn_name) ;
3737
3838 let ExtenderReceiver {
3939 object_fn_param,
@@ -62,26 +62,26 @@ pub fn make_function_definition_with_defaults(
6262 let return_decl = & sig. return_value ( ) . decl ;
6363
6464 // If either the builder has a lifetime (non-static/global method), or one of its parameters is a reference,
65- // then we need to annotate the _ex() function with an explicit lifetime. Also adjust &self -> &'a self.
65+ // then we need to annotate the _ex() function with an explicit lifetime. Also adjust &self -> &'ex self.
6666 let receiver_self = & code. receiver . self_prefix ;
6767 let simple_receiver_param = & code. receiver . param ;
68- let extended_receiver_param = & code. receiver . param_lifetime_a ;
68+ let extended_receiver_param = & code. receiver . param_lifetime_ex ;
6969
7070 let builders = quote ! {
7171 #[ doc = #builder_doc]
7272 #[ must_use]
7373 #cfg_attributes
74- #vis struct #builder_ty<' a > {
75- _phantom: std:: marker:: PhantomData <& ' a ( ) >,
74+ #vis struct #builder_ty<' ex > {
75+ _phantom: std:: marker:: PhantomData <& ' ex ( ) >,
7676 #( #builder_field_decls, ) *
7777 }
7878
7979 // #[allow] exceptions:
8080 // - wrong_self_convention: to_*() and from_*() are taken from Godot
8181 // - redundant_field_names: 'value: value' is a possible initialization pattern
82- // - needless-update : Remainder expression '..self' has nothing left to change
82+ // - needless_update : Remainder expression '..self' has nothing left to change
8383 #[ allow( clippy:: wrong_self_convention, clippy:: redundant_field_names, clippy:: needless_update) ]
84- impl <' a > #builder_ty<' a > {
84+ impl <' ex > #builder_ty<' ex > {
8585 fn new(
8686 //#object_param
8787 #( #builder_ctor_params, ) *
@@ -98,7 +98,7 @@ pub fn make_function_definition_with_defaults(
9898 #[ inline]
9999 pub fn done( self ) #return_decl {
100100 let Self { _phantom, #( #builder_field_names, ) * } = self ;
101- #surround_class_prefix #full_fn_name(
101+ #surround_class_path :: #full_fn_name(
102102 #( #full_fn_args, ) * // includes `surround_object` if present
103103 )
104104 }
@@ -122,10 +122,10 @@ pub fn make_function_definition_with_defaults(
122122 // _ex() function:
123123 // Lifetime is set if any parameter is a reference OR if the method is not static/global (and thus can refer to self).
124124 #[ inline]
125- #vis fn #extended_fn_name<' a > (
125+ #vis fn #extended_fn_name<' ex > (
126126 #extended_receiver_param
127127 #( #class_method_required_params_lifetimed, ) *
128- ) -> #builder_ty<' a > {
128+ ) -> #builder_ty<' ex > {
129129 #builder_ty:: new(
130130 #object_arg
131131 #( #class_method_required_args, ) *
@@ -137,11 +137,30 @@ pub fn make_function_definition_with_defaults(
137137}
138138
139139pub fn function_uses_default_params ( sig : & dyn Function ) -> bool {
140- sig. params ( ) . iter ( ) . any ( |arg| arg. default_value . is_some ( ) )
140+ // For builtin types, strip "Inner" prefix, while avoiding collision with classes that might start with "Inner".
141+ let class_or_builtin = sig. surrounding_class ( ) . map ( |ty| {
142+ let rust_name = ty. rust_ty . to_string ( ) ;
143+
144+ // If it’s builtin and starts with "Inner", drop that prefix; otherwise keep original string.
145+ match ( sig. is_builtin ( ) , rust_name. strip_prefix ( "Inner" ) ) {
146+ ( true , Some ( rest) ) => rest. to_string ( ) ,
147+ _ => rust_name,
148+ }
149+ } ) ;
150+
151+ let fn_declares_default_params = sig. params ( ) . iter ( ) . any ( |arg| arg. default_value . is_some ( ) )
141152 && !special_cases:: is_method_excluded_from_default_params (
142- sig . surrounding_class ( ) ,
153+ class_or_builtin . as_deref ( ) ,
143154 sig. name ( ) ,
144- )
155+ ) ;
156+
157+ // For builtins, only generate `Ex*` builders if the method is exposed on the outer type.
158+ // This saves on code generation and compile time for `Inner*` methods.
159+ if fn_declares_default_params && sig. is_builtin ( ) {
160+ return sig. is_exposed_outer_builtin ( ) ;
161+ }
162+
163+ fn_declares_default_params
145164}
146165
147166// ----------------------------------------------------------------------------------------------------------------------------------------------
@@ -179,11 +198,17 @@ fn make_extender_doc(sig: &dyn Function, extended_fn_name: &Ident) -> (String, T
179198 #[ allow( clippy:: uninlined_format_args) ]
180199 match sig. surrounding_class ( ) {
181200 Some ( TyName { rust_ty, .. } ) => {
182- surround_class_prefix = quote ! { re_export:: #rust_ty:: } ;
201+ surround_class_prefix = make_qualified_type ( sig, rust_ty, true ) ;
202+ let path = if sig. is_builtin ( ) {
203+ format ! ( "crate::builtin::{rust_ty}" )
204+ } else {
205+ format ! ( "super::{rust_ty}" )
206+ } ;
183207 builder_doc = format ! (
184- "Default-param extender for [`{class}::{method}`][super::{class }::{method}]." ,
208+ "Default-param extender for [`{class}::{method}`][{path }::{method}]." ,
185209 class = rust_ty,
186210 method = extended_fn_name,
211+ path = path,
187212 ) ;
188213 }
189214 None => {
@@ -213,13 +238,13 @@ fn make_extender_receiver(sig: &dyn Function) -> ExtenderReceiver {
213238 // Only add it if the method is not global or static.
214239 match sig. surrounding_class ( ) {
215240 Some ( surrounding_class) if !sig. qualifier ( ) . is_static_or_global ( ) => {
216- let class = & surrounding_class. rust_ty ;
241+ let ty = make_qualified_type ( sig , & surrounding_class. rust_ty , false ) ;
217242
218243 ExtenderReceiver {
219244 object_fn_param : Some ( FnParam {
220245 name : ident ( "surround_object" ) ,
221246 type_ : RustTy :: ExtenderReceiver {
222- tokens : quote ! { & ' a #builder_mut re_export :: #class } ,
247+ tokens : quote ! { & ' ex #builder_mut #ty } ,
223248 } ,
224249 default_value : None ,
225250 } ) ,
@@ -331,3 +356,23 @@ fn make_extender(
331356 class_method_required_args,
332357 }
333358}
359+
360+ /// Returns a qualified type path for builtin or class.
361+ ///
362+ /// Type categories:
363+ /// - Exposed outer builtins (like `GString`): direct type reference without `re_export::`.
364+ /// - `Inner\*` types (like `InnerString`): `re_export::Type<'ex>`, with lifetime if `with_inner_lifetime` is true.
365+ /// - Classes (like `Node`): `re_export::Type` without lifetime.
366+ fn make_qualified_type (
367+ sig : & dyn Function ,
368+ class_or_builtin : & Ident ,
369+ with_inner_lifetime : bool ,
370+ ) -> TokenStream {
371+ if sig. is_exposed_outer_builtin ( ) {
372+ quote ! { #class_or_builtin }
373+ } else if with_inner_lifetime && sig. is_builtin ( ) {
374+ quote ! { re_export:: #class_or_builtin<' ex> }
375+ } else {
376+ quote ! { re_export:: #class_or_builtin }
377+ }
378+ }
0 commit comments