@@ -65,6 +65,7 @@ pub(crate) struct ExportMethod {
65
65
pub ( crate ) struct ExportArgs {
66
66
pub ( crate ) optional_args : Option < usize > ,
67
67
pub ( crate ) rpc_mode : RpcMode ,
68
+ pub ( crate ) name_override : Option < String > ,
68
69
}
69
70
70
71
pub ( crate ) fn derive_methods ( item_impl : ItemImpl ) -> TokenStream2 {
@@ -82,7 +83,10 @@ pub(crate) fn derive_methods(item_impl: ItemImpl) -> TokenStream2 {
82
83
let sig_span = sig. ident . span ( ) ;
83
84
84
85
let name = sig. ident ;
85
- let name_string = name. to_string ( ) ;
86
+ let name_string = match args. name_override {
87
+ Some ( name_override) => name_override,
88
+ None => name. to_string ( ) ,
89
+ } ;
86
90
let ret_span = sig. output . span ( ) ;
87
91
let ret_ty = match sig. output {
88
92
syn:: ReturnType :: Default => quote_spanned ! ( ret_span => ( ) ) ,
@@ -181,6 +185,7 @@ fn impl_gdnative_expose(ast: ItemImpl) -> (ItemImpl, ClassMethodExport) {
181
185
ImplItem :: Method ( mut method) => {
182
186
let mut export_args = None ;
183
187
let mut rpc = None ;
188
+ let mut name_override = None ;
184
189
185
190
let mut errors = vec ! [ ] ;
186
191
@@ -253,8 +258,9 @@ fn impl_gdnative_expose(ast: ItemImpl) -> (ItemImpl, ClassMethodExport) {
253
258
} ;
254
259
let path = last. ident . to_string ( ) ;
255
260
256
- // Match rpc mode
261
+ // Match optional export arguments
257
262
match path. as_str ( ) {
263
+ // rpc mode
258
264
"rpc" => {
259
265
let value = if let syn:: Lit :: Str ( lit_str) = lit {
260
266
lit_str. value ( )
@@ -281,17 +287,50 @@ fn impl_gdnative_expose(ast: ItemImpl) -> (ItemImpl, ClassMethodExport) {
281
287
) ) ;
282
288
return false ;
283
289
}
290
+ }
291
+ // name override
292
+ "name" => {
293
+ let value = if let syn:: Lit :: Str ( lit_str) = lit {
294
+ lit_str. value ( )
295
+ } else {
296
+ errors. push ( syn:: Error :: new (
297
+ last. span ( ) ,
298
+ "unexpected type for name value, expected Str" ,
299
+ ) ) ;
300
+ return false ;
301
+ } ;
284
302
303
+ // NOTE: We take advantage of rust identifiers following
304
+ // the same syntax rules as Godot method identifiers. See:
305
+ // https://docs.godotengine.org/en/stable/getting_started/scripting/gdscript/gdscript_basics.html#identifiers
306
+ match syn:: parse_str :: < syn:: Ident > ( value. as_ref ( ) ) {
307
+ Ok ( _) => {
308
+ if name_override. replace ( value) . is_some ( ) {
309
+ errors. push ( syn:: Error :: new (
310
+ last. span ( ) ,
311
+ "name was set more than once" ,
312
+ ) ) ;
313
+ return false ;
314
+ }
315
+ }
316
+ Err ( _) => {
317
+ errors. push ( syn:: Error :: new (
318
+ last. span ( ) ,
319
+ "name value must be a valid identifier" ,
320
+ ) ) ;
321
+ return false ;
322
+ }
323
+ }
324
+ }
325
+ _ => {
326
+ let msg =
327
+ format ! ( "unknown option for export: `{}`" , path) ;
328
+ errors. push ( syn:: Error :: new ( last. span ( ) , msg) ) ;
285
329
return false ;
286
330
}
287
- _ => ( ) ,
288
331
}
289
-
290
- let msg = format ! ( "unknown option for export: `{}`" , path) ;
291
- errors. push ( syn:: Error :: new ( last. span ( ) , msg) ) ;
292
332
}
293
333
}
294
-
295
334
return false ;
296
335
}
297
336
}
@@ -340,6 +379,7 @@ fn impl_gdnative_expose(ast: ItemImpl) -> (ItemImpl, ClassMethodExport) {
340
379
341
380
export_args. optional_args = optional_args;
342
381
export_args. rpc_mode = rpc. unwrap_or ( RpcMode :: Disabled ) ;
382
+ export_args. name_override = name_override;
343
383
344
384
methods_to_export. push ( ExportMethod {
345
385
sig : method. sig . clone ( ) ,
0 commit comments