@@ -32,12 +32,6 @@ struct ItemAttr {
32
32
ty : ItemAttrType ,
33
33
}
34
34
35
- impl ItemAttr {
36
- fn bail < R > ( self , msg : & str , method : & venial:: Function ) -> ParseResult < R > {
37
- bail ! ( & method. name, "#[{}]: {}" , self . attr_name, msg)
38
- }
39
- }
40
-
41
35
enum AttrParseResult {
42
36
Func ( FuncAttr ) ,
43
37
Rpc ( RpcAttr ) ,
@@ -230,6 +224,30 @@ fn extract_hint_attribute(impl_block: &mut venial:: Impl) -> ParseResult<GodotAp
230
224
}
231
225
*/
232
226
227
+ fn extract_gd_self ( signature : & mut venial:: Function , attr_name : & Ident ) -> ParseResult < Ident > {
228
+ if signature. params . is_empty ( ) {
229
+ return bail_attr (
230
+ attr_name,
231
+ "with attribute key `gd_self`, the method must have a first parameter of type Gd<Self>" ,
232
+ & signature. name ,
233
+ ) ;
234
+ }
235
+
236
+ // Remove Gd<Self> receiver from signature for further processing.
237
+ let param = signature. params . inner . remove ( 0 ) ;
238
+
239
+ let venial:: FnParam :: Typed ( param) = param. 0 else {
240
+ return bail_attr (
241
+ attr_name,
242
+ "with attribute key `gd_self`, the first parameter must be Gd<Self> (not a `self` receiver)" ,
243
+ & signature. name
244
+ ) ;
245
+ } ;
246
+
247
+ // Note: parameter is explicitly NOT renamed (maybe_rename_parameter).
248
+ Ok ( param. name )
249
+ }
250
+
233
251
fn process_godot_fns (
234
252
class_name : & Ident ,
235
253
impl_block : & mut venial:: Impl ,
@@ -256,40 +274,31 @@ fn process_godot_fns(
256
274
|| function. qualifiers . tk_extern . is_some ( )
257
275
|| function. qualifiers . extern_abi . is_some ( )
258
276
{
259
- return attr. bail ( "fn qualifiers are not allowed" , function) ;
277
+ return bail ! (
278
+ & function. qualifiers,
279
+ "#[func]: fn qualifiers are not allowed"
280
+ ) ;
260
281
}
261
282
262
283
if function. generic_params . is_some ( ) {
263
- return attr. bail ( "generic fn parameters are not supported" , function) ;
284
+ return bail ! (
285
+ & function. generic_params,
286
+ "#[func]: generic fn parameters are not supported"
287
+ ) ;
264
288
}
265
289
266
290
match attr. ty {
267
291
ItemAttrType :: Func ( func, rpc_info) => {
268
292
let external_attributes = function. attributes . clone ( ) ;
269
293
270
- // Signatures are the same thing without body.
294
+ // Transforms the following.
295
+ // from function: #[attr] pub fn foo(&self, a: i32) -> i32 { ... }
296
+ // into signature: fn foo(&self, a: i32) -> i32
271
297
let mut signature = util:: reduce_to_signature ( function) ;
272
298
let gd_self_parameter = if func. has_gd_self {
273
- if signature. params . is_empty ( ) {
274
- return bail_attr (
275
- attr. attr_name ,
276
- "with attribute key `gd_self`, the method must have a first parameter of type Gd<Self>" ,
277
- function
278
- ) ;
279
- } else {
280
- let param = signature. params . inner . remove ( 0 ) ;
281
-
282
- let venial:: FnParam :: Typed ( param) = param. 0 else {
283
- return bail_attr (
284
- attr. attr_name ,
285
- "with attribute key `gd_self`, the first parameter must be Gd<Self> (not a `self` receiver)" ,
286
- function
287
- ) ;
288
- } ;
289
-
290
- // Note: parameter is explicitly NOT renamed (maybe_rename_parameter).
291
- Some ( param. name )
292
- }
299
+ // Removes Gd<Self> receiver from signature for further processing.
300
+ let param_name = extract_gd_self ( & mut signature, & attr. attr_name ) ?;
301
+ Some ( param_name)
293
302
} else {
294
303
None
295
304
} ;
@@ -326,9 +335,9 @@ fn process_godot_fns(
326
335
327
336
ItemAttrType :: Signal ( ref signal, ref _attr_val) => {
328
337
if is_secondary_impl {
329
- return attr. bail (
330
- "#[signal] is currently not supported in secondary impl blocks" ,
338
+ return bail ! (
331
339
function,
340
+ "#[signal] is currently not supported in secondary impl blocks" ,
332
341
) ;
333
342
}
334
343
if function. return_ty . is_some ( ) {
@@ -359,9 +368,9 @@ fn process_godot_fns(
359
368
}
360
369
361
370
ItemAttrType :: Const ( _) => {
362
- return attr. bail (
363
- "#[constant] can only be used on associated constant" ,
371
+ return bail ! (
364
372
function,
373
+ "#[constant] can only be used on associated constant" ,
365
374
)
366
375
}
367
376
}
@@ -416,6 +425,11 @@ fn process_godot_constants(decl: &mut venial::Impl) -> ParseResult<Vec<ConstDefi
416
425
Ok ( constant_signatures)
417
426
}
418
427
428
+ /// Replaces the body of `function` with custom code that performs virtual dispatch.
429
+ ///
430
+ /// Appends the virtual function to `virtual_functions`.
431
+ ///
432
+ /// Returns the Godot-registered name of the virtual function, usually `_<name>` (but overridable with `#[func(rename = ...)]`).
419
433
fn add_virtual_script_call (
420
434
virtual_functions : & mut Vec < venial:: Function > ,
421
435
function : & mut venial:: Function ,
@@ -674,8 +688,8 @@ fn parse_constant_attr(
674
688
Ok ( AttrParseResult :: Constant ( attr. value . clone ( ) ) )
675
689
}
676
690
677
- fn bail_attr < R > ( attr_name : Ident , msg : & str , method : & venial :: Function ) -> ParseResult < R > {
678
- bail ! ( & method . name , "#[{}]: {}" , attr_name , msg )
691
+ fn bail_attr < R > ( attr_name : & Ident , msg : & str , method_name : & Ident ) -> ParseResult < R > {
692
+ bail ! ( method_name , "#[{attr_name }]: {msg}" )
679
693
}
680
694
681
695
// ----------------------------------------------------------------------------------------------------------------------------------------------
0 commit comments