Skip to content

Commit 7116516

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

File tree

2 files changed

+58
-20
lines changed

2 files changed

+58
-20
lines changed

godot-macros/src/class/godot_api.rs

+50-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,13 @@ 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(
123+
util::extract_cfg_attrs(external_attributes)
124+
.into_iter()
125+
.collect(),
126+
);
106127
signal_name_strs.push(signature.name.to_string());
107128
signal_parameters_count.push(param_names.len());
108129
signal_parameters.push(param_array_decl);
@@ -164,20 +185,23 @@ fn transform_inherent_impl(mut decl: Impl) -> Result<TokenStream, Error> {
164185
use ::godot::sys;
165186

166187
#(
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-
);
188+
#(#signal_cfg_attrs)*
189+
{
190+
let parameters_info: [::godot::builtin::meta::PropertyInfo; #signal_parameters_count] = #signal_parameters;
191+
192+
let mut parameters_info_sys: [::godot::sys::GDExtensionPropertyInfo; #signal_parameters_count] =
193+
std::array::from_fn(|i| parameters_info[i].property_sys());
194+
195+
let signal_name = ::godot::builtin::StringName::from(#signal_name_strs);
196+
197+
sys::interface_fn!(classdb_register_extension_class_signal)(
198+
sys::get_library(),
199+
#class_name_obj.string_sys(),
200+
signal_name.string_sys(),
201+
parameters_info_sys.as_ptr(),
202+
sys::GDExtensionInt::from(#signal_parameters_count as i64),
203+
);
204+
};
181205
)*
182206
}
183207
}
@@ -203,9 +227,11 @@ fn transform_inherent_impl(mut decl: Impl) -> Result<TokenStream, Error> {
203227
Ok(result)
204228
}
205229

206-
fn process_godot_fns(decl: &mut Impl) -> Result<(Vec<FuncDefinition>, Vec<Function>), Error> {
230+
fn process_godot_fns(
231+
decl: &mut Impl,
232+
) -> Result<(Vec<FuncDefinition>, Vec<SignalDefinition>), Error> {
207233
let mut func_definitions = vec![];
208-
let mut signal_signatures = vec![];
234+
let mut signal_definitions = vec![];
209235

210236
let mut removed_indexes = vec![];
211237
for (index, item) in decl.body_items.iter_mut().enumerate() {
@@ -259,9 +285,13 @@ fn process_godot_fns(decl: &mut Impl) -> Result<(Vec<FuncDefinition>, Vec<Functi
259285
if method.return_ty.is_some() {
260286
return attr.bail("return types are not supported", method);
261287
}
288+
let external_attributes = method.attributes.clone();
262289
let sig = util::reduce_to_signature(method);
263290

264-
signal_signatures.push(sig.clone());
291+
signal_definitions.push(SignalDefinition {
292+
signature: sig,
293+
external_attributes,
294+
});
265295
removed_indexes.push(index);
266296
}
267297
BoundAttrType::Const(_) => {
@@ -280,7 +310,7 @@ fn process_godot_fns(decl: &mut Impl) -> Result<(Vec<FuncDefinition>, Vec<Functi
280310
decl.body_items.remove(index);
281311
}
282312

283-
Ok((func_definitions, signal_signatures))
313+
Ok((func_definitions, signal_definitions))
284314
}
285315

286316
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)