Skip to content

Commit 719e801

Browse files
committed
Add a name optional argument to #[export]
This allows exporting methods to godot under a different name. Implements #732
1 parent 8d0e584 commit 719e801

File tree

1 file changed

+47
-7
lines changed

1 file changed

+47
-7
lines changed

gdnative-derive/src/methods.rs

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ pub(crate) struct ExportMethod {
6565
pub(crate) struct ExportArgs {
6666
pub(crate) optional_args: Option<usize>,
6767
pub(crate) rpc_mode: RpcMode,
68+
pub(crate) name_override: Option<String>,
6869
}
6970

7071
pub(crate) fn derive_methods(item_impl: ItemImpl) -> TokenStream2 {
@@ -82,7 +83,10 @@ pub(crate) fn derive_methods(item_impl: ItemImpl) -> TokenStream2 {
8283
let sig_span = sig.ident.span();
8384

8485
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+
};
8690
let ret_span = sig.output.span();
8791
let ret_ty = match sig.output {
8892
syn::ReturnType::Default => quote_spanned!(ret_span => ()),
@@ -181,6 +185,7 @@ fn impl_gdnative_expose(ast: ItemImpl) -> (ItemImpl, ClassMethodExport) {
181185
ImplItem::Method(mut method) => {
182186
let mut export_args = None;
183187
let mut rpc = None;
188+
let mut name_override = None;
184189

185190
let mut errors = vec![];
186191

@@ -253,8 +258,9 @@ fn impl_gdnative_expose(ast: ItemImpl) -> (ItemImpl, ClassMethodExport) {
253258
};
254259
let path = last.ident.to_string();
255260

256-
// Match rpc mode
261+
// Match optional export arguments
257262
match path.as_str() {
263+
// rpc mode
258264
"rpc" => {
259265
let value = if let syn::Lit::Str(lit_str) = lit {
260266
lit_str.value()
@@ -281,17 +287,50 @@ fn impl_gdnative_expose(ast: ItemImpl) -> (ItemImpl, ClassMethodExport) {
281287
));
282288
return false;
283289
}
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+
};
284302

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));
285329
return false;
286330
}
287-
_ => (),
288331
}
289-
290-
let msg = format!("unknown option for export: `{}`", path);
291-
errors.push(syn::Error::new(last.span(), msg));
292332
}
293333
}
294-
295334
return false;
296335
}
297336
}
@@ -340,6 +379,7 @@ fn impl_gdnative_expose(ast: ItemImpl) -> (ItemImpl, ClassMethodExport) {
340379

341380
export_args.optional_args = optional_args;
342381
export_args.rpc_mode = rpc.unwrap_or(RpcMode::Disabled);
382+
export_args.name_override = name_override;
343383

344384
methods_to_export.push(ExportMethod {
345385
sig: method.sig.clone(),

0 commit comments

Comments
 (0)