Skip to content

Commit 60de95f

Browse files
author
Astrale
committed
tmp commit: makes into sig_info faillible, makes sig_info contain info about default parameters, and misc
1 parent e1073bc commit 60de95f

File tree

3 files changed

+49
-7
lines changed

3 files changed

+49
-7
lines changed

godot-core/src/registry/method.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ impl ClassMethodInfo {
5959
ptrcall_func: sys::GDExtensionClassMethodPtrCall,
6060
method_flags: MethodFlags,
6161
param_names: &[&str],
62-
// default_arguments: Vec<Variant>, - not yet implemented
62+
default_arguments: Vec<Variant>,
6363
) -> Self {
6464
let return_value = Ret::Via::return_info();
6565
let arguments = Signature::<Params, Ret>::param_names(param_names);

godot-macros/src/class/data_models/func.rs

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
use crate::class::RpcAttr;
99
use crate::util::{bail_fn, ident, safe_ident};
10-
use crate::{util, ParseResult};
10+
use crate::{bail, util, KvParser, ParseResult};
1111
use proc_macro2::{Group, Ident, TokenStream, TokenTree};
1212
use quote::{format_ident, quote};
1313

@@ -126,6 +126,7 @@ pub fn make_method_registration(
126126
.iter()
127127
.map(|ident| ident.to_string());
128128

129+
let default_parameters = extract_default_parameters(&func_definition.signature_info)?;
129130
// Transport #[cfg] attrs to the FFI glue to ensure functions which were conditionally
130131
// removed from compilation don't cause errors.
131132
let cfg_attrs = util::extract_cfg_attrs(&func_definition.external_attributes)
@@ -158,6 +159,9 @@ pub fn make_method_registration(
158159
&[
159160
#( #param_ident_strs ),*
160161
],
162+
vec![
163+
#( <#default_parameters as ::godot::meta::AsArg>.to_variant() ),*
164+
]
161165
)
162166
};
163167

@@ -175,6 +179,30 @@ pub fn make_method_registration(
175179
Ok(registration)
176180
}
177181

182+
fn extract_default_parameters(sig_info: &SignatureInfo) -> ParseResult<Vec<TokenStream>> {
183+
let mut res = vec![];
184+
let mut allowed = true;
185+
for pd in sig_info.param_defaults.iter().rev() {
186+
match pd {
187+
Some(tk) if allowed => {
188+
res.push(tk.clone()); // toreview: if we really care about it, we can use &mut sig_info and mem::take() as we don't use this later
189+
}
190+
None if allowed => {
191+
allowed = false;
192+
}
193+
Some(tk) if !allowed => {
194+
return bail!(
195+
tk,
196+
"opt arguments are only allowed at the end of the argument list."
197+
);
198+
}
199+
_ => (),
200+
}
201+
}
202+
res.reverse();
203+
Ok(res)
204+
}
205+
178206
// ----------------------------------------------------------------------------------------------------------------------------------------------
179207
// Implementation
180208

@@ -199,6 +227,8 @@ pub struct SignatureInfo {
199227
///
200228
/// Index points into original venial tokens (i.e. takes into account potential receiver params).
201229
pub modified_param_types: Vec<(usize, venial::TypeExpr)>,
230+
/// Contains expressions of the default values of parameters.
231+
pub param_defaults: Vec<Option<TokenStream>>,
202232
}
203233

204234
impl SignatureInfo {
@@ -210,6 +240,7 @@ impl SignatureInfo {
210240
param_types: vec![],
211241
return_type: quote! { () },
212242
modified_param_types: vec![],
243+
param_defaults: vec![],
213244
}
214245
}
215246

@@ -350,7 +381,7 @@ pub(crate) fn into_signature_info(
350381
signature: venial::Function,
351382
class_name: &Ident,
352383
has_gd_self: bool,
353-
) -> SignatureInfo {
384+
) -> ParseResult<SignatureInfo> {
354385
let method_name = signature.name.clone();
355386
let mut receiver_type = if has_gd_self {
356387
ReceiverType::GdSelf
@@ -361,6 +392,8 @@ pub(crate) fn into_signature_info(
361392
let num_params = signature.params.inner.len();
362393
let mut param_idents = Vec::with_capacity(num_params);
363394
let mut param_types = Vec::with_capacity(num_params);
395+
let mut param_defaults = Vec::with_capacity(num_params);
396+
364397
let ret_type = match signature.return_ty {
365398
None => quote! { () },
366399
Some(ty) => map_self_to_class_name(ty.tokens, class_name),
@@ -398,21 +431,27 @@ pub(crate) fn into_signature_info(
398431
tokens: map_self_to_class_name(ty.tokens, class_name),
399432
},
400433
};
434+
let default = match crate::KvParser::parse(&arg.attributes, "opt")? {
435+
None => None,
436+
Some(mut parser) => Some(parser.handle_expr_required("default")?),
437+
};
401438

402439
param_types.push(ty);
403440
param_idents.push(ident);
441+
param_defaults.push(default);
404442
}
405443
}
406444
}
407445

408-
SignatureInfo {
446+
Ok(SignatureInfo {
409447
method_name,
410448
receiver_type,
411449
param_idents,
412450
param_types,
413451
return_type: ret_type,
414452
modified_param_types,
415-
}
453+
param_defaults,
454+
})
416455
}
417456

418457
/// If `f32` is used for a delta parameter in a virtual process function, transparently use `f64` behind the scenes.

godot-macros/src/class/data_models/inherent_impl.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -304,8 +304,11 @@ fn process_godot_fns(
304304
};
305305

306306
// Clone might not strictly be necessary, but the 2 other callers of into_signature_info() are better off with pass-by-value.
307-
let signature_info =
308-
into_signature_info(signature.clone(), class_name, gd_self_parameter.is_some());
307+
let signature_info = into_signature_info(
308+
signature.clone(),
309+
class_name,
310+
gd_self_parameter.is_some(),
311+
)?;
309312

310313
// For virtual methods, rename/mangle existing user method and create a new method with the original name,
311314
// which performs a dynamic dispatch.

0 commit comments

Comments
 (0)