@@ -17,9 +17,9 @@ use proc_macro2::{Ident, Literal, TokenStream};
17
17
use quote:: { format_ident, quote, ToTokens } ;
18
18
19
19
use crate :: context:: Context ;
20
+ use crate :: conv;
20
21
use crate :: models:: json:: { JsonMethodArg , JsonMethodReturn } ;
21
22
use crate :: util:: { ident, option_as_slice, safe_ident} ;
22
- use crate :: { conv, special_cases} ;
23
23
24
24
mod enums;
25
25
@@ -498,7 +498,6 @@ impl FnQualifier {
498
498
}
499
499
// ----------------------------------------------------------------------------------------------------------------------------------------------
500
500
501
- #[ derive( Clone ) ]
502
501
pub struct FnParam {
503
502
pub name : Ident ,
504
503
@@ -511,29 +510,29 @@ pub struct FnParam {
511
510
512
511
impl FnParam {
513
512
/// Creates a new parameter builder for constructing function parameters with configurable options.
514
- pub fn builder < ' a > ( ) -> FnParamBuilder < ' a > {
513
+ pub fn builder ( ) -> FnParamBuilder {
515
514
FnParamBuilder :: new ( )
516
515
}
517
516
}
518
517
519
518
/// Builder for constructing `FnParam` instances with configurable enum replacements and default value handling.
520
- pub struct FnParamBuilder < ' a > {
521
- surrounding_class_method : Option < ( & ' a TyName , & ' a str ) > ,
519
+ pub struct FnParamBuilder {
520
+ replacements : EnumReplacements ,
522
521
no_defaults : bool ,
523
522
}
524
523
525
- impl < ' a > FnParamBuilder < ' a > {
526
- /// Creates a new parameter builder with default settings (replacements disabled , defaults enabled).
524
+ impl FnParamBuilder {
525
+ /// Creates a new parameter builder with default settings (no replacements , defaults enabled).
527
526
pub fn new ( ) -> Self {
528
527
Self {
529
- surrounding_class_method : None ,
528
+ replacements : & [ ] ,
530
529
no_defaults : false ,
531
530
}
532
531
}
533
532
534
- /// Configures the builder to apply enum replacements for the specified class and method context .
535
- pub fn with_replacements ( mut self , class_name : & ' a TyName , method_name : & ' a str ) -> Self {
536
- self . surrounding_class_method = Some ( ( class_name , method_name ) ) ;
533
+ /// Configures the builder to use specific enum replacements.
534
+ pub fn enum_replacements ( mut self , replacements : EnumReplacements ) -> Self {
535
+ self . replacements = replacements ;
537
536
self
538
537
}
539
538
@@ -543,12 +542,44 @@ impl<'a> FnParamBuilder<'a> {
543
542
self
544
543
}
545
544
545
+ /// Builds a single function parameter from the provided JSON method argument.
546
+ pub fn build_single ( self , method_arg : & JsonMethodArg , ctx : & mut Context ) -> FnParam {
547
+ self . build_single_impl ( method_arg, ctx)
548
+ }
549
+
550
+ /// Builds a vector of function parameters from the provided JSON method arguments.
551
+ pub fn build_many (
552
+ self ,
553
+ method_args : & Option < Vec < JsonMethodArg > > ,
554
+ ctx : & mut Context ,
555
+ ) -> Vec < FnParam > {
556
+ option_as_slice ( method_args)
557
+ . iter ( )
558
+ . map ( |arg| self . build_single_impl ( arg, ctx) )
559
+ . collect ( )
560
+ }
561
+
546
562
/// Core implementation for processing a single JSON method argument into a `FnParam`.
547
563
fn build_single_impl ( & self , method_arg : & JsonMethodArg , ctx : & mut Context ) -> FnParam {
548
564
let name = safe_ident ( & method_arg. name ) ;
549
565
let type_ = conv:: to_rust_type ( & method_arg. type_ , method_arg. meta . as_ref ( ) , ctx) ;
550
- let type_ =
551
- apply_enum_replacement ( Some ( & method_arg. name ) , type_, self . surrounding_class_method ) ;
566
+
567
+ // Apply enum replacement if one exists for this parameter
568
+ let matching_replacement = self
569
+ . replacements
570
+ . iter ( )
571
+ . find ( |( p, ..) | * p == method_arg. name ) ;
572
+ let type_ = if let Some ( ( _, enum_name, is_bitfield) ) = matching_replacement {
573
+ if !type_. is_integer ( ) {
574
+ panic ! (
575
+ "Parameter `{}` is of type {}, but can only replace int with enum" ,
576
+ method_arg. name, type_
577
+ ) ;
578
+ }
579
+ conv:: to_enum_type_uncached ( enum_name, * is_bitfield)
580
+ } else {
581
+ type_
582
+ } ;
552
583
553
584
let default_value = if self . no_defaults {
554
585
None
@@ -565,23 +596,6 @@ impl<'a> FnParamBuilder<'a> {
565
596
default_value,
566
597
}
567
598
}
568
-
569
- /// Builds a single function parameter from the provided JSON method argument.
570
- pub fn build_single ( self , method_arg : & JsonMethodArg , ctx : & mut Context ) -> FnParam {
571
- self . build_single_impl ( method_arg, ctx)
572
- }
573
-
574
- /// Builds a vector of function parameters from the provided JSON method arguments.
575
- pub fn build_many (
576
- self ,
577
- method_args : & Option < Vec < JsonMethodArg > > ,
578
- ctx : & mut Context ,
579
- ) -> Vec < FnParam > {
580
- option_as_slice ( method_args)
581
- . iter ( )
582
- . map ( |arg| self . build_single_impl ( arg, ctx) )
583
- . collect ( )
584
- }
585
599
}
586
600
587
601
impl fmt:: Debug for FnParam {
@@ -604,17 +618,30 @@ pub struct FnReturn {
604
618
605
619
impl FnReturn {
606
620
pub fn new ( return_value : & Option < JsonMethodReturn > , ctx : & mut Context ) -> Self {
607
- Self :: new_with_replacements ( return_value, None , ctx)
621
+ Self :: with_enum_replacements ( return_value, & [ ] , ctx)
608
622
}
609
623
610
- pub fn new_with_replacements (
624
+ pub fn with_enum_replacements (
611
625
return_value : & Option < JsonMethodReturn > ,
612
- surrounding_class_method : Option < ( & TyName , & str ) > ,
626
+ replacements : EnumReplacements ,
613
627
ctx : & mut Context ,
614
628
) -> Self {
615
629
if let Some ( ret) = return_value {
616
630
let ty = conv:: to_rust_type ( & ret. type_ , ret. meta . as_ref ( ) , ctx) ;
617
- let ty = apply_enum_replacement ( None , ty, surrounding_class_method) ;
631
+
632
+ // Apply enum replacement if one exists for return type (indicated by empty string)
633
+ let matching_replacement = replacements. iter ( ) . find ( |( p, ..) | p. is_empty ( ) ) ;
634
+ let ty = if let Some ( ( _, enum_name, is_bitfield) ) = matching_replacement {
635
+ if !ty. is_integer ( ) {
636
+ panic ! (
637
+ "Return type is of type {}, but can only replace int with enum" ,
638
+ ty
639
+ ) ;
640
+ }
641
+ conv:: to_enum_type_uncached ( enum_name, * is_bitfield)
642
+ } else {
643
+ ty
644
+ } ;
618
645
619
646
Self {
620
647
decl : ty. return_decl ( ) ,
@@ -649,56 +676,12 @@ impl FnReturn {
649
676
}
650
677
651
678
// ----------------------------------------------------------------------------------------------------------------------------------------------
679
+ // Int->enum replacements
652
680
653
- /// Replaces int parameters/return types with enums, if applicable.
654
- fn apply_enum_replacement (
655
- param_or_return : Option < & str > , // None for return type, Some(name) for parameter
656
- type_ : RustTy ,
657
- surrounding : Option < ( & TyName , & str ) > ,
658
- ) -> RustTy {
659
- // No surrounding class/method info -> caller doesn't need replacements.
660
- let Some ( ( class_name, method_name) ) = surrounding else {
661
- return type_;
662
- } ;
663
-
664
- let replacements =
665
- special_cases:: get_class_method_param_enum_replacement ( class_name, method_name) ;
666
-
667
- let matching_replacement = match param_or_return {
668
- // Look for a specific parameter name.
669
- Some ( param_name) => replacements. iter ( ) . find ( |( p, ..) | * p == param_name) ,
670
-
671
- // Look for return type (empty string).
672
- None => replacements. iter ( ) . find ( |( p, ..) | p. is_empty ( ) ) ,
673
- } ;
674
-
675
- if let Some ( ( _, enum_name, is_bitfield) ) = matching_replacement {
676
- if !type_. is_integer ( ) {
677
- let what = format_param_or_return ( class_name, method_name, param_or_return) ;
678
- panic ! ( "{what} is of type {type_}, but can only replace int with enum" ) ;
679
- }
680
-
681
- conv:: to_enum_type_uncached ( enum_name, * is_bitfield)
682
- } else {
683
- // No replacement.
684
- type_
685
- }
686
- }
687
-
688
- fn format_param_or_return (
689
- class_name : & TyName ,
690
- method_name : & str ,
691
- param_or_return : Option < & str > ,
692
- ) -> String {
693
- let what = if let Some ( param_name) = param_or_return {
694
- format ! ( "parameter `{param_name}`" )
695
- } else {
696
- "return type" . to_string ( )
697
- } ;
698
-
699
- let class_name = & class_name. godot_ty ;
700
- format ! ( "{class_name}::{method_name} {what}" )
701
- }
681
+ /// Replacement of int->enum in engine APIs; each tuple being `(param_name, enum_type, is_bitfield)`.
682
+ ///
683
+ /// Empty string `""` is used as `param_name` to denote return type replacements.
684
+ pub type EnumReplacements = & ' static [ ( & ' static str , & ' static str , bool ) ] ;
702
685
703
686
// ----------------------------------------------------------------------------------------------------------------------------------------------
704
687
// Godot type
0 commit comments