Skip to content

Commit fdc27df

Browse files
committed
Factor out more validation/extraction functions
1 parent 2b04214 commit fdc27df

File tree

1 file changed

+49
-35
lines changed

1 file changed

+49
-35
lines changed

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

Lines changed: 49 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,6 @@ struct ItemAttr {
3232
ty: ItemAttrType,
3333
}
3434

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-
4135
enum AttrParseResult {
4236
Func(FuncAttr),
4337
Rpc(RpcAttr),
@@ -230,6 +224,30 @@ fn extract_hint_attribute(impl_block: &mut venial:: Impl) -> ParseResult<GodotAp
230224
}
231225
*/
232226

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+
233251
fn process_godot_fns(
234252
class_name: &Ident,
235253
impl_block: &mut venial::Impl,
@@ -256,40 +274,31 @@ fn process_godot_fns(
256274
|| function.qualifiers.tk_extern.is_some()
257275
|| function.qualifiers.extern_abi.is_some()
258276
{
259-
return attr.bail("fn qualifiers are not allowed", function);
277+
return bail!(
278+
&function.qualifiers,
279+
"#[func]: fn qualifiers are not allowed"
280+
);
260281
}
261282

262283
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+
);
264288
}
265289

266290
match attr.ty {
267291
ItemAttrType::Func(func, rpc_info) => {
268292
let external_attributes = function.attributes.clone();
269293

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
271297
let mut signature = util::reduce_to_signature(function);
272298
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)
293302
} else {
294303
None
295304
};
@@ -326,9 +335,9 @@ fn process_godot_fns(
326335

327336
ItemAttrType::Signal(ref signal, ref _attr_val) => {
328337
if is_secondary_impl {
329-
return attr.bail(
330-
"#[signal] is currently not supported in secondary impl blocks",
338+
return bail!(
331339
function,
340+
"#[signal] is currently not supported in secondary impl blocks",
332341
);
333342
}
334343
if function.return_ty.is_some() {
@@ -359,9 +368,9 @@ fn process_godot_fns(
359368
}
360369

361370
ItemAttrType::Const(_) => {
362-
return attr.bail(
363-
"#[constant] can only be used on associated constant",
371+
return bail!(
364372
function,
373+
"#[constant] can only be used on associated constant",
365374
)
366375
}
367376
}
@@ -416,6 +425,11 @@ fn process_godot_constants(decl: &mut venial::Impl) -> ParseResult<Vec<ConstDefi
416425
Ok(constant_signatures)
417426
}
418427

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 = ...)]`).
419433
fn add_virtual_script_call(
420434
virtual_functions: &mut Vec<venial::Function>,
421435
function: &mut venial::Function,
@@ -674,8 +688,8 @@ fn parse_constant_attr(
674688
Ok(AttrParseResult::Constant(attr.value.clone()))
675689
}
676690

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}")
679693
}
680694

681695
// ----------------------------------------------------------------------------------------------------------------------------------------------

0 commit comments

Comments
 (0)