@@ -13,14 +13,14 @@ use crate::context::Context;
13
13
use crate :: models:: domain:: {
14
14
BuildConfiguration , BuiltinClass , BuiltinMethod , BuiltinSize , BuiltinVariant , Class ,
15
15
ClassCommons , ClassConstant , ClassConstantValue , ClassMethod , ClassSignal , Constructor , Enum ,
16
- Enumerator , EnumeratorValue , ExtensionApi , FnDirection , FnParam , FnQualifier , FnReturn ,
17
- FunctionCommon , GodotApiVersion , ModName , NativeStructure , Operator , RustTy , Singleton , TyName ,
18
- UtilityFunction ,
16
+ EnumReplacements , Enumerator , EnumeratorValue , ExtensionApi , FnDirection , FnParam , FnQualifier ,
17
+ FnReturn , FunctionCommon , GodotApiVersion , ModName , NativeStructure , Operator , RustTy ,
18
+ Singleton , TyName , UtilityFunction ,
19
19
} ;
20
20
use crate :: models:: json:: {
21
21
JsonBuiltinClass , JsonBuiltinMethod , JsonBuiltinSizes , JsonClass , JsonClassConstant ,
22
22
JsonClassMethod , JsonConstructor , JsonEnum , JsonEnumConstant , JsonExtensionApi , JsonHeader ,
23
- JsonMethodReturn , JsonNativeStructure , JsonOperator , JsonSignal , JsonSingleton ,
23
+ JsonMethodArg , JsonMethodReturn , JsonNativeStructure , JsonOperator , JsonSignal , JsonSingleton ,
24
24
JsonUtilityFunction ,
25
25
} ;
26
26
use crate :: util:: { get_api_level, ident, option_as_slice} ;
@@ -378,7 +378,9 @@ impl BuiltinMethod {
378
378
godot_name : method. name . clone ( ) ,
379
379
// Disable default parameters for builtin classes.
380
380
// They are not public-facing and need more involved implementation (lifetimes etc.). Also reduces number of symbols in API.
381
- parameters : FnParam :: new_range_no_defaults ( & method. arguments , ctx) ,
381
+ parameters : FnParam :: builder ( )
382
+ . no_defaults ( )
383
+ . build_many ( & method. arguments , ctx) ,
382
384
return_value : FnReturn :: new ( & return_value, ctx) ,
383
385
is_vararg : method. is_vararg ,
384
386
is_private : false , // See 'exposed' below. Could be special_cases::is_method_private(builtin_name, &method.name),
@@ -431,7 +433,7 @@ impl ClassMethod {
431
433
432
434
Self :: from_json_inner (
433
435
method,
434
- rust_method_name,
436
+ rust_method_name. as_ref ( ) ,
435
437
class_name,
436
438
FnDirection :: Outbound { hash } ,
437
439
ctx,
@@ -518,8 +520,22 @@ impl ClassMethod {
518
520
is_required_in_json
519
521
} ;
520
522
521
- let parameters = FnParam :: new_range ( & method. arguments , ctx) ;
522
- let return_value = FnReturn :: new ( & method. return_value , ctx) ;
523
+ // Ensure that parameters/return types listed in the replacement truly exist in the method.
524
+ // The validation function now returns the validated replacement slice for reuse.
525
+ let enum_replacements = validate_enum_replacements (
526
+ class_name,
527
+ & method. name ,
528
+ option_as_slice ( & method. arguments ) ,
529
+ method. return_value . is_some ( ) ,
530
+ ) ;
531
+
532
+ let parameters = FnParam :: builder ( )
533
+ . enum_replacements ( enum_replacements)
534
+ . build_many ( & method. arguments , ctx) ;
535
+
536
+ let return_value =
537
+ FnReturn :: with_enum_replacements ( & method. return_value , enum_replacements, ctx) ;
538
+
523
539
let is_unsafe = Self :: function_uses_pointers ( & parameters, & return_value) ;
524
540
525
541
// Future note: if further changes are made to the virtual method name, make sure to make it reversible so that #[godot_api]
@@ -586,7 +602,7 @@ impl ClassSignal {
586
602
587
603
Some ( Self {
588
604
name : json_signal. name . clone ( ) ,
589
- parameters : FnParam :: new_range ( & json_signal. arguments , ctx) ,
605
+ parameters : FnParam :: builder ( ) . build_many ( & json_signal. arguments , ctx) ,
590
606
surrounding_class : surrounding_class. clone ( ) ,
591
607
} )
592
608
}
@@ -605,7 +621,7 @@ impl UtilityFunction {
605
621
let parameters = if function. is_vararg && args. len ( ) == 1 && args[ 0 ] . name == "arg1" {
606
622
vec ! [ ]
607
623
} else {
608
- FnParam :: new_range ( & function. arguments , ctx)
624
+ FnParam :: builder ( ) . build_many ( & function. arguments , ctx)
609
625
} ;
610
626
611
627
let godot_method_name = function. name . clone ( ) ;
@@ -737,6 +753,44 @@ impl ClassConstant {
737
753
}
738
754
}
739
755
756
+ // ----------------------------------------------------------------------------------------------------------------------------------------------
757
+
758
+ /// Validates that all parameters and non-unit return types declared in an enum replacement slices actually exist in the method.
759
+ ///
760
+ /// This is a measure to prevent accidental typos or listing inexistent parameters, which would have no effect.
761
+ fn validate_enum_replacements (
762
+ class_ty : & TyName ,
763
+ godot_method_name : & str ,
764
+ method_arguments : & [ JsonMethodArg ] ,
765
+ has_return_type : bool ,
766
+ ) -> EnumReplacements {
767
+ let replacements =
768
+ special_cases:: get_class_method_param_enum_replacement ( class_ty, godot_method_name) ;
769
+
770
+ for ( param_name, enum_name, _) in replacements {
771
+ if param_name. is_empty ( ) {
772
+ assert ! ( has_return_type,
773
+ "Method `{class}.{godot_method_name}` has no return type, but replacement with `{enum_name}` is declared" ,
774
+ class = class_ty. godot_ty
775
+ ) ;
776
+ } else if !method_arguments. iter ( ) . any ( |arg| arg. name == * param_name) {
777
+ let available_params = method_arguments
778
+ . iter ( )
779
+ . map ( |arg| format ! ( " * {}: {}" , arg. name, arg. type_) )
780
+ . collect :: < Vec < _ > > ( )
781
+ . join ( "\n " ) ;
782
+
783
+ panic ! (
784
+ "Method `{class}.{godot_method_name}` has no parameter `{param_name}`, but a replacement with `{enum_name}` is declared\n \
785
+ \n {count} parameters available:\n {available_params}\n ",
786
+ class = class_ty. godot_ty, count = method_arguments. len( ) ,
787
+ ) ;
788
+ }
789
+ }
790
+
791
+ replacements
792
+ }
793
+
740
794
// ----------------------------------------------------------------------------------------------------------------------------------------------
741
795
// Native structures
742
796
0 commit comments