Skip to content

Commit 6695a62

Browse files
committed
#[var(get=f, set=f)]: properly handle #[func]s that have been renamed with (rename=godot_name)
1 parent 40186f3 commit 6695a62

File tree

5 files changed

+102
-8
lines changed

5 files changed

+102
-8
lines changed

Diff for: godot-macros/src/class/data_models/field_var.rs

+5
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use crate::class::{
1212
into_signature_info, make_existence_check, make_method_registration, Field, FieldHint,
1313
FuncDefinition,
1414
};
15+
use crate::util::make_function_registered_name_constant;
1516
use crate::util::KvParser;
1617
use crate::{util, ParseResult};
1718

@@ -200,10 +201,14 @@ impl GetterSetterImpl {
200201
}
201202
}
202203

204+
let constant_declaration =
205+
make_function_registered_name_constant(class_name, &function_name, &None, &vec![]);
206+
203207
let function_impl = quote! {
204208
pub #signature {
205209
#function_body
206210
}
211+
#constant_declaration
207212
};
208213

209214
let signature = util::parse_signature(signature);

Diff for: godot-macros/src/class/data_models/inherent_impl.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ use crate::class::{
1010
make_signal_registrations, ConstDefinition, FuncDefinition, RpcAttr, RpcMode, SignalDefinition,
1111
SignatureInfo, TransferMode,
1212
};
13-
use crate::util::{bail, c_str, ident, require_api_version, KvParser};
13+
use crate::util::{
14+
bail, c_str, ident, make_function_registered_name_constants, require_api_version, KvParser,
15+
};
1416
use crate::{handle_mutually_exclusive_keys, util, ParseResult};
1517

1618
use proc_macro2::{Delimiter, Group, Ident, TokenStream};
@@ -84,6 +86,8 @@ pub fn transform_inherent_impl(
8486
let (funcs, signals) = process_godot_fns(&class_name, &mut impl_block, meta.secondary)?;
8587
let consts = process_godot_constants(&mut impl_block)?;
8688

89+
let func_export_name_constants = make_function_registered_name_constants(&funcs, &class_name);
90+
8791
#[cfg(all(feature = "register-docs", since_api = "4.3"))]
8892
let docs = crate::docs::make_inherent_impl_docs(&funcs, &consts, &signals);
8993
#[cfg(not(all(feature = "register-docs", since_api = "4.3")))]
@@ -174,6 +178,9 @@ pub fn transform_inherent_impl(
174178
#trait_impl
175179
#fill_storage
176180
#class_registration
181+
impl #class_name{
182+
#( #func_export_name_constants )*
183+
}
177184
};
178185

179186
Ok(result)
@@ -184,6 +191,9 @@ pub fn transform_inherent_impl(
184191
let result = quote! {
185192
#impl_block
186193
#fill_storage
194+
impl #class_name{
195+
#( #func_export_name_constants )*
196+
}
187197
};
188198

189199
Ok(result)

Diff for: godot-macros/src/class/data_models/property.rs

+15-7
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
//! Parsing the `var` and `export` attributes on fields.
99
1010
use crate::class::{Field, FieldVar, Fields, GetSet, GetterSetterImpl, UsageFlags};
11+
use crate::util::{format_function_registered_name_constant, ident};
1112
use proc_macro2::{Ident, TokenStream};
1213
use quote::quote;
1314

@@ -134,22 +135,24 @@ pub fn make_property_impl(class_name: &Ident, fields: &Fields) -> TokenStream {
134135
},
135136
};
136137

137-
let getter_name = make_getter_setter(
138+
let getter_tokens = make_getter_setter(
138139
getter.to_impl(class_name, GetSet::Get, field),
139140
&mut getter_setter_impls,
140141
&mut export_tokens,
142+
&class_name,
141143
);
142-
let setter_name = make_getter_setter(
144+
let setter_tokens = make_getter_setter(
143145
setter.to_impl(class_name, GetSet::Set, field),
144146
&mut getter_setter_impls,
145147
&mut export_tokens,
148+
&class_name,
146149
);
147150

148151
export_tokens.push(quote! {
149152
::godot::register::private::#registration_fn::<#class_name, #field_type>(
150153
#field_name,
151-
#getter_name,
152-
#setter_name,
154+
#getter_tokens,
155+
#setter_tokens,
153156
#hint,
154157
#usage_flags,
155158
);
@@ -177,7 +180,8 @@ fn make_getter_setter(
177180
getter_setter_impl: Option<GetterSetterImpl>,
178181
getter_setter_impls: &mut Vec<TokenStream>,
179182
export_tokens: &mut Vec<TokenStream>,
180-
) -> String {
183+
class_name: &Ident,
184+
) -> TokenStream {
181185
if let Some(getter_impl) = getter_setter_impl {
182186
let GetterSetterImpl {
183187
function_name,
@@ -188,8 +192,12 @@ fn make_getter_setter(
188192
getter_setter_impls.push(function_impl);
189193
export_tokens.push(export_token);
190194

191-
function_name.to_string()
195+
let getter_setter_name = function_name.to_string();
196+
197+
let getter_setter_fn_const =
198+
format_function_registered_name_constant(class_name, &ident(&getter_setter_name));
199+
quote! { #class_name::#getter_setter_fn_const }
192200
} else {
193-
String::new()
201+
quote! { "" }
194202
}
195203
}

Diff for: godot-macros/src/util/mod.rs

+49
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@
77

88
// Note: some code duplication with godot-codegen crate.
99

10+
use crate::class::FuncDefinition;
1011
use crate::ParseResult;
1112
use proc_macro2::{Delimiter, Group, Ident, Literal, TokenStream, TokenTree};
1213
use quote::spanned::Spanned;
1314
use quote::{format_ident, quote, ToTokens, TokenStreamExt};
15+
use venial::Attribute;
1416

1517
mod kv_parser;
1618
mod list_parser;
@@ -303,3 +305,50 @@ pub fn venial_parse_meta(
303305

304306
venial::parse_item(input)
305307
}
308+
309+
// ----------------------------------------------------------------------------------------------------------------------------------------------
310+
311+
// util functions for handling #[func]s and #[var(get=f, set=f)]
312+
313+
pub fn make_function_registered_name_constants(
314+
funcs: &Vec<FuncDefinition>,
315+
class_name: &Ident,
316+
) -> Vec<TokenStream> {
317+
funcs
318+
.iter()
319+
.map(|func| {
320+
make_function_registered_name_constant(
321+
class_name,
322+
&func.signature_info.method_name,
323+
&func.registered_name,
324+
&func.external_attributes,
325+
)
326+
})
327+
.collect()
328+
}
329+
330+
/// funcs can be renamed with `#[func(rename=new_name) fn f();`.
331+
/// To be able to access the renamed function name at a later point, it is saved in a string constant.
332+
pub fn make_function_registered_name_constant(
333+
class_name: &Ident,
334+
func_name: &Ident,
335+
exported_name: &Option<String>,
336+
attributes: &Vec<Attribute>,
337+
) -> TokenStream {
338+
let const_name = format_function_registered_name_constant(class_name, func_name);
339+
let const_value = match &exported_name {
340+
Some(renamed) => renamed.to_string(),
341+
None => func_name.to_string(),
342+
};
343+
344+
quote! {
345+
#(#attributes)*
346+
#[doc(hidden)]
347+
#[allow(non_upper_case_globals)]
348+
pub const #const_name: &str = #const_value;
349+
}
350+
}
351+
352+
pub fn format_function_registered_name_constant(class_name: &Ident, func_name: &Ident) -> Ident {
353+
format_ident!("__gdext_func_{}_{}", class_name, func_name)
354+
}

Diff for: itest/rust/src/object_tests/property_test.rs

+22
Original file line numberDiff line numberDiff line change
@@ -482,3 +482,25 @@ fn override_export() {
482482
fn check_property(property: &Dictionary, key: &str, expected: impl ToGodot) {
483483
assert_eq!(property.get_or_nil(key), expected.to_variant());
484484
}
485+
486+
// ----------------------------------------------------------------------------------------------------------------------------------------------
487+
488+
#[derive(GodotClass)]
489+
#[class(base=Node, init)]
490+
struct RenamedFunc {
491+
#[var(get = get_int_val, set = set_int_val)]
492+
int_val: i32,
493+
}
494+
495+
#[godot_api]
496+
impl RenamedFunc {
497+
#[func(rename=f1)]
498+
pub fn get_int_val(&self) -> i32 {
499+
self.int_val
500+
}
501+
502+
#[func(rename=f2)]
503+
pub fn set_int_val(&mut self, val: i32) {
504+
self.int_val = val;
505+
}
506+
}

0 commit comments

Comments
 (0)