@@ -398,6 +398,7 @@ fn transform_trait_impl(original_impl: Impl) -> Result<TokenStream, Error> {
398398 let mut on_notification_fn = quote ! { None } ;
399399
400400 let mut virtual_methods = vec ! [ ] ;
401+ let mut virtual_method_cfg_attrs = vec ! [ ] ;
401402 let mut virtual_method_names = vec ! [ ] ;
402403
403404 let prv = quote ! { :: godot:: private } ;
@@ -409,52 +410,85 @@ fn transform_trait_impl(original_impl: Impl) -> Result<TokenStream, Error> {
409410 continue ;
410411 } ;
411412
413+ // Transport #[cfg] attributes to the virtual method's FFI glue, to ensure it won't be
414+ // registered in Godot if conditionally removed from compilation.
415+ let cfg_attrs = util:: extract_cfg_attrs ( & method. attributes )
416+ . into_iter ( )
417+ . collect :: < Vec < _ > > ( ) ;
412418 let method_name = method. name . to_string ( ) ;
413419 match method_name. as_str ( ) {
414420 "register_class" => {
415421 register_class_impl = quote ! {
422+ #( #cfg_attrs) *
416423 impl :: godot:: obj:: cap:: GodotRegisterClass for #class_name {
417424 fn __godot_register_class( builder: & mut :: godot:: builder:: GodotBuilder <Self >) {
418425 <Self as #trait_name>:: register_class( builder)
419426 }
420427 }
421428 } ;
422429
430+ // Use 'match' as a way to only return 'Some(...)' if the given cfg attrs allow.
431+ // Needs '#[allow(unreachable_patterns)]' to avoid warnings about the last arm.
423432 register_fn = quote ! {
424- Some ( #prv:: ErasedRegisterFn {
425- raw: #prv:: callbacks:: register_class_by_builder:: <#class_name>
426- } )
433+ match ( ) {
434+ #( #cfg_attrs) *
435+ ( ) => Some ( #prv:: ErasedRegisterFn {
436+ raw: #prv:: callbacks:: register_class_by_builder:: <#class_name>
437+ } ) ,
438+ _ => None ,
439+ }
427440 } ;
428441 }
429442
430443 "init" => {
431444 godot_init_impl = quote ! {
445+ #( #cfg_attrs) *
432446 impl :: godot:: obj:: cap:: GodotInit for #class_name {
433447 fn __godot_init( base: :: godot:: obj:: Base <Self :: Base >) -> Self {
434448 <Self as #trait_name>:: init( base)
435449 }
436450 }
437451 } ;
438- create_fn = quote ! { Some ( #prv:: callbacks:: create:: <#class_name>) } ;
452+ create_fn = quote ! {
453+ match ( ) {
454+ #( #cfg_attrs) *
455+ ( ) => Some ( #prv:: callbacks:: create:: <#class_name>) ,
456+ _ => None ,
457+ }
458+ } ;
439459 if cfg ! ( since_api = "4.2" ) {
440- recreate_fn = quote ! { Some ( #prv:: callbacks:: recreate:: <#class_name>) } ;
460+ recreate_fn = quote ! {
461+ match ( ) {
462+ #( #cfg_attrs) *
463+ ( ) => Some ( #prv:: callbacks:: recreate:: <#class_name>) ,
464+ _ => None ,
465+ }
466+ } ;
441467 }
442468 }
443469
444470 "to_string" => {
445471 to_string_impl = quote ! {
472+ #( #cfg_attrs) *
446473 impl :: godot:: obj:: cap:: GodotToString for #class_name {
447474 fn __godot_to_string( & self ) -> :: godot:: builtin:: GodotString {
448475 <Self as #trait_name>:: to_string( self )
449476 }
450477 }
451478 } ;
452479
453- to_string_fn = quote ! { Some ( #prv:: callbacks:: to_string:: <#class_name>) } ;
480+ to_string_fn = quote ! {
481+ match ( ) {
482+ #( #cfg_attrs) *
483+ ( ) => Some ( #prv:: callbacks:: to_string:: <#class_name>) ,
484+ _ => None ,
485+ }
486+ } ;
454487 }
455488
456489 "on_notification" => {
457490 on_notification_impl = quote ! {
491+ #( #cfg_attrs) *
458492 impl :: godot:: obj:: cap:: GodotNotification for #class_name {
459493 fn __godot_notification( & mut self , what: i32 ) {
460494 if :: godot:: private:: is_class_inactive( Self :: __config( ) . is_tool) {
@@ -467,7 +501,11 @@ fn transform_trait_impl(original_impl: Impl) -> Result<TokenStream, Error> {
467501 } ;
468502
469503 on_notification_fn = quote ! {
470- Some ( #prv:: callbacks:: on_notification:: <#class_name>)
504+ match ( ) {
505+ #( #cfg_attrs) *
506+ ( ) => Some ( #prv:: callbacks:: on_notification:: <#class_name>) ,
507+ _ => None ,
508+ }
471509 } ;
472510 }
473511
@@ -487,6 +525,7 @@ fn transform_trait_impl(original_impl: Impl) -> Result<TokenStream, Error> {
487525 } else {
488526 format ! ( "_{method_name}" )
489527 } ;
528+ virtual_method_cfg_attrs. push ( cfg_attrs) ;
490529 virtual_method_names. push ( virtual_method_name) ;
491530 virtual_methods. push ( method) ;
492531 }
@@ -517,6 +556,7 @@ fn transform_trait_impl(original_impl: Impl) -> Result<TokenStream, Error> {
517556
518557 match name {
519558 #(
559+ #( #virtual_method_cfg_attrs) *
520560 #virtual_method_names => #virtual_method_callbacks,
521561 ) *
522562 _ => None ,
@@ -526,6 +566,8 @@ fn transform_trait_impl(original_impl: Impl) -> Result<TokenStream, Error> {
526566
527567 :: godot:: sys:: plugin_add!( __GODOT_PLUGIN_REGISTRY in #prv; #prv:: ClassPlugin {
528568 class_name: #class_name_obj,
569+ #[ allow( unreachable_patterns) ] // due to the cfg-based match statements
570+ #[ allow( clippy:: match_single_binding) ] // avoid warning on single-arm matches
529571 component: #prv:: PluginComponent :: UserVirtuals {
530572 user_register_fn: #register_fn,
531573 user_create_fn: #create_fn,
0 commit comments