@@ -67,21 +67,35 @@ impl BoundAttr {
67
67
}
68
68
}
69
69
70
+ /// Holds information known from a signal's definition
71
+ struct SignalDefinition {
72
+ /// The signal's function signature.
73
+ signature : Function ,
74
+
75
+ /// The signal's non-gdext attributes (all except #[signal]).
76
+ external_attributes : Vec < Attribute > ,
77
+ }
78
+
70
79
/// Codegen for `#[godot_api] impl MyType`
71
80
fn transform_inherent_impl ( mut decl : Impl ) -> Result < TokenStream , Error > {
72
81
let class_name = util:: validate_impl ( & decl, None , "godot_api" ) ?;
73
82
let class_name_obj = util:: class_name_obj ( & class_name) ;
74
83
let ( funcs, signals) = process_godot_fns ( & mut decl) ?;
75
84
85
+ let mut signal_cfg_attrs: Vec < Vec < & Attribute > > = Vec :: new ( ) ;
76
86
let mut signal_name_strs: Vec < String > = Vec :: new ( ) ;
77
87
let mut signal_parameters_count: Vec < usize > = Vec :: new ( ) ;
78
88
let mut signal_parameters: Vec < TokenStream > = Vec :: new ( ) ;
79
89
80
- for signature in signals {
90
+ for signal in signals. iter ( ) {
91
+ let SignalDefinition {
92
+ signature,
93
+ external_attributes,
94
+ } = signal;
81
95
let mut param_types: Vec < TyExpr > = Vec :: new ( ) ;
82
96
let mut param_names: Vec < String > = Vec :: new ( ) ;
83
97
84
- for param in signature. params . inner {
98
+ for param in signature. params . inner . iter ( ) {
85
99
match & param. 0 {
86
100
FnParam :: Typed ( param) => {
87
101
param_types. push ( param. ty . clone ( ) ) ;
@@ -103,6 +117,13 @@ fn transform_inherent_impl(mut decl: Impl) -> Result<TokenStream, Error> {
103
117
]
104
118
} ;
105
119
120
+ // Transport #[cfg] attrs to the FFI glue to ensure signals which were conditionally
121
+ // removed from compilation don't cause errors.
122
+ signal_cfg_attrs. push (
123
+ util:: extract_cfg_attrs ( external_attributes)
124
+ . into_iter ( )
125
+ . collect ( ) ,
126
+ ) ;
106
127
signal_name_strs. push ( signature. name . to_string ( ) ) ;
107
128
signal_parameters_count. push ( param_names. len ( ) ) ;
108
129
signal_parameters. push ( param_array_decl) ;
@@ -115,6 +136,7 @@ fn transform_inherent_impl(mut decl: Impl) -> Result<TokenStream, Error> {
115
136
. map ( |func_def| make_method_registration ( & class_name, func_def) ) ;
116
137
117
138
let consts = process_godot_constants ( & mut decl) ?;
139
+ let mut integer_constant_cfg_attrs = Vec :: new ( ) ;
118
140
let mut integer_constant_names = Vec :: new ( ) ;
119
141
let mut integer_constant_values = Vec :: new ( ) ;
120
142
@@ -125,6 +147,15 @@ fn transform_inherent_impl(mut decl: Impl) -> Result<TokenStream, Error> {
125
147
126
148
let name = & constant. name ;
127
149
150
+ // Unlike with #[func] and #[signal], we don't remove the attributes from Constant
151
+ // signatures within 'process_godot_constants'.
152
+ let cfg_attrs = util:: extract_cfg_attrs ( & constant. attributes )
153
+ . into_iter ( )
154
+ . collect :: < Vec < _ > > ( ) ;
155
+
156
+ // Transport #[cfg] attrs to the FFI glue to ensure constants which were conditionally
157
+ // removed from compilation don't cause errors.
158
+ integer_constant_cfg_attrs. push ( cfg_attrs) ;
128
159
integer_constant_names. push ( constant. name . to_string ( ) ) ;
129
160
integer_constant_values. push ( quote ! { #class_name:: #name } ) ;
130
161
}
@@ -136,6 +167,7 @@ fn transform_inherent_impl(mut decl: Impl) -> Result<TokenStream, Error> {
136
167
use :: godot:: builtin:: StringName ;
137
168
138
169
#(
170
+ #( #integer_constant_cfg_attrs) *
139
171
ExportConstant :: new(
140
172
#class_name_obj,
141
173
ConstantKind :: Integer (
@@ -164,20 +196,23 @@ fn transform_inherent_impl(mut decl: Impl) -> Result<TokenStream, Error> {
164
196
use :: godot:: sys;
165
197
166
198
#(
167
- let parameters_info: [ :: godot:: builtin:: meta:: PropertyInfo ; #signal_parameters_count] = #signal_parameters;
168
-
169
- let mut parameters_info_sys: [ :: godot:: sys:: GDExtensionPropertyInfo ; #signal_parameters_count] =
170
- std:: array:: from_fn( |i| parameters_info[ i] . property_sys( ) ) ;
171
-
172
- let signal_name = :: godot:: builtin:: StringName :: from( #signal_name_strs) ;
173
-
174
- sys:: interface_fn!( classdb_register_extension_class_signal) (
175
- sys:: get_library( ) ,
176
- #class_name_obj. string_sys( ) ,
177
- signal_name. string_sys( ) ,
178
- parameters_info_sys. as_ptr( ) ,
179
- sys:: GDExtensionInt :: from( #signal_parameters_count as i64 ) ,
180
- ) ;
199
+ #( #signal_cfg_attrs) *
200
+ {
201
+ let parameters_info: [ :: godot:: builtin:: meta:: PropertyInfo ; #signal_parameters_count] = #signal_parameters;
202
+
203
+ let mut parameters_info_sys: [ :: godot:: sys:: GDExtensionPropertyInfo ; #signal_parameters_count] =
204
+ std:: array:: from_fn( |i| parameters_info[ i] . property_sys( ) ) ;
205
+
206
+ let signal_name = :: godot:: builtin:: StringName :: from( #signal_name_strs) ;
207
+
208
+ sys:: interface_fn!( classdb_register_extension_class_signal) (
209
+ sys:: get_library( ) ,
210
+ #class_name_obj. string_sys( ) ,
211
+ signal_name. string_sys( ) ,
212
+ parameters_info_sys. as_ptr( ) ,
213
+ sys:: GDExtensionInt :: from( #signal_parameters_count as i64 ) ,
214
+ ) ;
215
+ } ;
181
216
) *
182
217
}
183
218
}
@@ -203,9 +238,11 @@ fn transform_inherent_impl(mut decl: Impl) -> Result<TokenStream, Error> {
203
238
Ok ( result)
204
239
}
205
240
206
- fn process_godot_fns ( decl : & mut Impl ) -> Result < ( Vec < FuncDefinition > , Vec < Function > ) , Error > {
241
+ fn process_godot_fns (
242
+ decl : & mut Impl ,
243
+ ) -> Result < ( Vec < FuncDefinition > , Vec < SignalDefinition > ) , Error > {
207
244
let mut func_definitions = vec ! [ ] ;
208
- let mut signal_signatures = vec ! [ ] ;
245
+ let mut signal_definitions = vec ! [ ] ;
209
246
210
247
let mut removed_indexes = vec ! [ ] ;
211
248
for ( index, item) in decl. body_items . iter_mut ( ) . enumerate ( ) {
@@ -238,6 +275,7 @@ fn process_godot_fns(decl: &mut Impl) -> Result<(Vec<FuncDefinition>, Vec<Functi
238
275
rename,
239
276
has_gd_self,
240
277
} => {
278
+ let external_attributes = method. attributes . clone ( ) ;
241
279
// Signatures are the same thing without body
242
280
let mut sig = util:: reduce_to_signature ( method) ;
243
281
if * has_gd_self {
@@ -249,6 +287,7 @@ fn process_godot_fns(decl: &mut Impl) -> Result<(Vec<FuncDefinition>, Vec<Functi
249
287
}
250
288
func_definitions. push ( FuncDefinition {
251
289
func : sig,
290
+ external_attributes,
252
291
rename : rename. clone ( ) ,
253
292
has_gd_self : * has_gd_self,
254
293
} ) ;
@@ -257,9 +296,13 @@ fn process_godot_fns(decl: &mut Impl) -> Result<(Vec<FuncDefinition>, Vec<Functi
257
296
if method. return_ty . is_some ( ) {
258
297
return attr. bail ( "return types are not supported" , method) ;
259
298
}
299
+ let external_attributes = method. attributes . clone ( ) ;
260
300
let sig = util:: reduce_to_signature ( method) ;
261
301
262
- signal_signatures. push ( sig. clone ( ) ) ;
302
+ signal_definitions. push ( SignalDefinition {
303
+ signature : sig,
304
+ external_attributes,
305
+ } ) ;
263
306
removed_indexes. push ( index) ;
264
307
}
265
308
BoundAttrType :: Const ( _) => {
@@ -278,7 +321,7 @@ fn process_godot_fns(decl: &mut Impl) -> Result<(Vec<FuncDefinition>, Vec<Functi
278
321
decl. body_items . remove ( index) ;
279
322
}
280
323
281
- Ok ( ( func_definitions, signal_signatures ) )
324
+ Ok ( ( func_definitions, signal_definitions ) )
282
325
}
283
326
284
327
fn process_godot_constants ( decl : & mut Impl ) -> Result < Vec < Constant > , Error > {
0 commit comments