Skip to content

Commit daa6bfa

Browse files
committed
Allow #[cfg] to be used with #[signal]
1 parent aca267a commit daa6bfa

File tree

2 files changed

+54
-20
lines changed

2 files changed

+54
-20
lines changed

godot-macros/src/class/godot_api.rs

+46-20
Original file line numberDiff line numberDiff line change
@@ -67,21 +67,35 @@ impl BoundAttr {
6767
}
6868
}
6969

70+
/// Holds information known from a signal's definition
71+
struct SignalDefinition {
72+
/// The signal's function signature.
73+
signature: Function,
74+
75+
/// The signal's non-gdext attributes (that is, excluding #[signal]).
76+
external_attributes: Vec<Attribute>,
77+
}
78+
7079
/// Codegen for `#[godot_api] impl MyType`
7180
fn transform_inherent_impl(mut decl: Impl) -> Result<TokenStream, Error> {
7281
let class_name = util::validate_impl(&decl, None, "godot_api")?;
7382
let class_name_obj = util::class_name_obj(&class_name);
7483
let (funcs, signals) = process_godot_fns(&mut decl)?;
7584

85+
let mut signal_cfg_attrs: Vec<Vec<&Attribute>> = Vec::new();
7686
let mut signal_name_strs: Vec<String> = Vec::new();
7787
let mut signal_parameters_count: Vec<usize> = Vec::new();
7888
let mut signal_parameters: Vec<TokenStream> = Vec::new();
7989

80-
for signature in signals {
90+
for signal in signals.iter() {
91+
let SignalDefinition {
92+
signature,
93+
external_attributes,
94+
} = signal;
8195
let mut param_types: Vec<TyExpr> = Vec::new();
8296
let mut param_names: Vec<String> = Vec::new();
8397

84-
for param in signature.params.inner {
98+
for param in signature.params.inner.iter() {
8599
match &param.0 {
86100
FnParam::Typed(param) => {
87101
param_types.push(param.ty.clone());
@@ -103,6 +117,9 @@ fn transform_inherent_impl(mut decl: Impl) -> Result<TokenStream, Error> {
103117
]
104118
};
105119

120+
// Transport #[cfg] attrs to the FFI glue to ensure signals which were conditionally
121+
// removed from compilation don't cause errors.
122+
signal_cfg_attrs.push(util::extract_cfg_attrs(external_attributes).into_iter().collect());
106123
signal_name_strs.push(signature.name.to_string());
107124
signal_parameters_count.push(param_names.len());
108125
signal_parameters.push(param_array_decl);
@@ -164,20 +181,23 @@ fn transform_inherent_impl(mut decl: Impl) -> Result<TokenStream, Error> {
164181
use ::godot::sys;
165182

166183
#(
167-
let parameters_info: [::godot::builtin::meta::PropertyInfo; #signal_parameters_count] = #signal_parameters;
168-
169-
let mut parameters_info_sys: [::godot::sys::GDExtensionPropertyInfo; #signal_parameters_count] =
170-
std::array::from_fn(|i| parameters_info[i].property_sys());
171-
172-
let signal_name = ::godot::builtin::StringName::from(#signal_name_strs);
173-
174-
sys::interface_fn!(classdb_register_extension_class_signal)(
175-
sys::get_library(),
176-
#class_name_obj.string_sys(),
177-
signal_name.string_sys(),
178-
parameters_info_sys.as_ptr(),
179-
sys::GDExtensionInt::from(#signal_parameters_count as i64),
180-
);
184+
#(#signal_cfg_attrs)*
185+
{
186+
let parameters_info: [::godot::builtin::meta::PropertyInfo; #signal_parameters_count] = #signal_parameters;
187+
188+
let mut parameters_info_sys: [::godot::sys::GDExtensionPropertyInfo; #signal_parameters_count] =
189+
std::array::from_fn(|i| parameters_info[i].property_sys());
190+
191+
let signal_name = ::godot::builtin::StringName::from(#signal_name_strs);
192+
193+
sys::interface_fn!(classdb_register_extension_class_signal)(
194+
sys::get_library(),
195+
#class_name_obj.string_sys(),
196+
signal_name.string_sys(),
197+
parameters_info_sys.as_ptr(),
198+
sys::GDExtensionInt::from(#signal_parameters_count as i64),
199+
);
200+
};
181201
)*
182202
}
183203
}
@@ -203,9 +223,11 @@ fn transform_inherent_impl(mut decl: Impl) -> Result<TokenStream, Error> {
203223
Ok(result)
204224
}
205225

206-
fn process_godot_fns(decl: &mut Impl) -> Result<(Vec<FuncDefinition>, Vec<Function>), Error> {
226+
fn process_godot_fns(
227+
decl: &mut Impl,
228+
) -> Result<(Vec<FuncDefinition>, Vec<SignalDefinition>), Error> {
207229
let mut func_definitions = vec![];
208-
let mut signal_signatures = vec![];
230+
let mut signal_definitions = vec![];
209231

210232
let mut removed_indexes = vec![];
211233
for (index, item) in decl.body_items.iter_mut().enumerate() {
@@ -259,9 +281,13 @@ fn process_godot_fns(decl: &mut Impl) -> Result<(Vec<FuncDefinition>, Vec<Functi
259281
if method.return_ty.is_some() {
260282
return attr.bail("return types are not supported", method);
261283
}
284+
let external_attributes = method.attributes.clone();
262285
let sig = util::reduce_to_signature(method);
263286

264-
signal_signatures.push(sig.clone());
287+
signal_definitions.push(SignalDefinition {
288+
signature: sig,
289+
external_attributes,
290+
});
265291
removed_indexes.push(index);
266292
}
267293
BoundAttrType::Const(_) => {
@@ -280,7 +306,7 @@ fn process_godot_fns(decl: &mut Impl) -> Result<(Vec<FuncDefinition>, Vec<Functi
280306
decl.body_items.remove(index);
281307
}
282308

283-
Ok((func_definitions, signal_signatures))
309+
Ok((func_definitions, signal_definitions))
284310
}
285311

286312
fn process_godot_constants(decl: &mut Impl) -> Result<Vec<Constant>, Error> {

itest/rust/src/register_tests/func_test.rs

+8
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,14 @@ impl GdSelfReference {
130130
#[cfg(all())]
131131
fn signal_recognized_with_simple_path_attribute_below_signal_attr();
132132

133+
#[cfg(any())]
134+
#[signal]
135+
fn cfg_removes_signal_ffi_glue();
136+
137+
#[signal]
138+
#[cfg(any())]
139+
fn cfg_removes_signal_ffi_glue();
140+
133141
#[func]
134142
fn fail_to_update_internal_value_due_to_conflicting_borrow(
135143
&mut self,

0 commit comments

Comments
 (0)