Skip to content

Commit 60c69fa

Browse files
committed
Refactor #[init(...)] shared code
1 parent 7096bac commit 60c69fa

File tree

2 files changed

+47
-49
lines changed

2 files changed

+47
-49
lines changed

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

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66
*/
77

88
use crate::class::{FieldExport, FieldVar};
9-
use crate::util::error;
9+
use crate::util::{error, KvParser};
1010
use proc_macro2::{Ident, Span, TokenStream};
11-
use quote::ToTokens;
11+
use quote::{quote, ToTokens};
1212

1313
pub struct Field {
1414
pub name: Ident,
@@ -39,10 +39,37 @@ impl Field {
3939
}
4040
}
4141

42-
#[must_use]
43-
pub fn ensure_preconditions(
42+
/// For a previously performed check, either pastes the generated code, or a syntactically valid fallback.
43+
///
44+
/// In case of incorrect proc-macro usage, it's nice if the resulting generated code is still syntactically valid, to not trip over
45+
/// IDEs and static analysis tools. So, in case of errors, a syntactically valid placeholder is generated.
46+
pub fn set_default_val_if(
47+
&mut self,
48+
default_expr: impl FnOnce() -> TokenStream,
49+
precondition: FieldCond,
50+
parser: &KvParser,
51+
errors: &mut Vec<venial::Error>,
52+
) {
53+
debug_assert!(
54+
self.default_val.is_none(),
55+
"default already set; check precondition"
56+
);
57+
58+
let span = parser.span();
59+
let is_well_formed = self.ensure_preconditions(precondition, span, errors);
60+
61+
let default_val = if is_well_formed {
62+
default_expr()
63+
} else {
64+
quote! { todo!() }
65+
};
66+
67+
self.default_val = Some(FieldDefault { default_val, span });
68+
}
69+
70+
fn ensure_preconditions(
4471
&self,
45-
cond: Option<FieldCond>,
72+
cond: FieldCond,
4673
span: Span,
4774
errors: &mut Vec<venial::Error>,
4875
) -> bool {
@@ -56,14 +83,14 @@ impl Field {
5683
}
5784

5885
match cond {
59-
Some(FieldCond::IsOnReady) if !self.is_onready => {
86+
FieldCond::IsOnReady if !self.is_onready => {
6087
errors.push(error!(
6188
span,
6289
"used #[init(…)] pattern requires field type `OnReady<T>`"
6390
));
6491
}
6592

66-
Some(FieldCond::IsOnEditor) if !self.is_oneditor => {
93+
FieldCond::IsOnEditor if !self.is_oneditor => {
6794
errors.push(error!(
6895
span,
6996
"used #[init(…)] pattern requires field type `OnEditor<T>`"
@@ -78,6 +105,7 @@ impl Field {
78105
}
79106

80107
pub enum FieldCond {
108+
// None, - enable once needed.
81109
IsOnReady,
82110
IsOnEditor,
83111
}

godot-macros/src/class/derive_godot_class.rs

Lines changed: 12 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -557,62 +557,32 @@ fn parse_fields(
557557

558558
// #[init(node = "PATH")]
559559
if let Some(node_path) = parser.handle_expr("node")? {
560-
let is_well_formed = field.ensure_preconditions(
561-
Some(FieldCond::IsOnReady),
562-
parser.span(),
560+
field.set_default_val_if(
561+
|| quote! { OnReady::from_node(#node_path) },
562+
FieldCond::IsOnReady,
563+
&parser,
563564
&mut errors,
564565
);
565-
566-
let default_val = if is_well_formed {
567-
quote! { OnReady::from_node(#node_path) }
568-
} else {
569-
quote! { todo!() }
570-
};
571-
572-
field.default_val = Some(FieldDefault {
573-
default_val,
574-
span: parser.span(),
575-
});
576566
}
577567

578568
// #[init(load = "PATH")]
579569
if let Some(resource_path) = parser.handle_expr("load")? {
580-
let is_well_formed = field.ensure_preconditions(
581-
Some(FieldCond::IsOnReady),
582-
parser.span(),
570+
field.set_default_val_if(
571+
|| quote! { OnReady::from_loaded(#resource_path) },
572+
FieldCond::IsOnReady,
573+
&parser,
583574
&mut errors,
584575
);
585-
586-
let default_val = if is_well_formed {
587-
quote! { OnReady::from_loaded(#resource_path) }
588-
} else {
589-
quote! { todo!() }
590-
};
591-
592-
field.default_val = Some(FieldDefault {
593-
default_val,
594-
span: parser.span(),
595-
});
596576
}
597577

598578
// #[init(sentinel = EXPR)]
599579
if let Some(sentinel_value) = parser.handle_expr("sentinel")? {
600-
let is_well_formed = field.ensure_preconditions(
601-
Some(FieldCond::IsOnEditor),
602-
parser.span(),
580+
field.set_default_val_if(
581+
|| quote! { OnEditor::from_sentinel(#sentinel_value) },
582+
FieldCond::IsOnEditor,
583+
&parser,
603584
&mut errors,
604585
);
605-
606-
let default_val = if is_well_formed {
607-
quote! { OnEditor::from_sentinel(#sentinel_value) }
608-
} else {
609-
quote! { todo!() }
610-
};
611-
612-
field.default_val = Some(FieldDefault {
613-
default_val,
614-
span: parser.span(),
615-
});
616586
}
617587

618588
parser.finish()?;

0 commit comments

Comments
 (0)