Skip to content

Commit 7c942cf

Browse files
committed
merge main
1 parent 7fab13c commit 7c942cf

File tree

1 file changed

+37
-15
lines changed
  • crates/bevy_ecs/macros/src

1 file changed

+37
-15
lines changed

crates/bevy_ecs/macros/src/lib.rs

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -266,19 +266,26 @@ pub fn derive_map_entities(input: TokenStream) -> TokenStream {
266266
}
267267
})
268268
}
269-
270269
/// Implement `SystemParam` to use a struct as a parameter in a system
271270
#[proc_macro_derive(SystemParam, attributes(system_param))]
272271
pub fn derive_system_param(input: TokenStream) -> TokenStream {
273272
let token_stream = input.clone();
274273
let ast = parse_macro_input!(input as DeriveInput);
274+
match derive_system_param_impl(token_stream, ast) {
275+
Ok(t) => t,
276+
Err(e) => e.into_compile_error().into(),
277+
}
278+
}
279+
280+
fn derive_system_param_impl(
281+
token_stream: TokenStream,
282+
ast: DeriveInput,
283+
) -> syn::Result<TokenStream> {
275284
let Data::Struct(DataStruct { fields, .. }) = ast.data else {
276-
return syn::Error::new(
285+
return Err(syn::Error::new(
277286
ast.span(),
278287
"Invalid `SystemParam` type: expected a `struct`",
279-
)
280-
.into_compile_error()
281-
.into();
288+
));
282289
};
283290
let path = bevy_ecs_path();
284291

@@ -289,6 +296,25 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
289296
let field_members = fields.members().collect::<Vec<_>>();
290297
let field_types = fields.iter().map(|f| &f.ty).collect::<Vec<_>>();
291298

299+
let field_names = fields.members().map(|m| format_ident!("::{}", m));
300+
301+
let mut field_messages = Vec::new();
302+
for attr in fields
303+
.iter()
304+
.filter_map(|f| f.attrs.iter().find(|a| a.path().is_ident("system_param")))
305+
{
306+
let mut field_message = None;
307+
attr.parse_nested_meta(|nested| {
308+
if nested.path.is_ident("validation_message") {
309+
field_message = Some(nested.value()?.parse()?);
310+
Ok(())
311+
} else {
312+
Err(nested.error("Unsupported attribute"))
313+
}
314+
})?;
315+
field_messages.push(field_message.unwrap_or_else(|| quote! { err.message }));
316+
}
317+
292318
let generics = ast.generics;
293319

294320
// Emit an error if there's any unrecognized lifetime names.
@@ -297,14 +323,12 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
297323
let w = format_ident!("w");
298324
let s = format_ident!("s");
299325
if ident != &w && ident != &s {
300-
return syn::Error::new_spanned(
326+
return Err(syn::Error::new_spanned(
301327
lt,
302328
r#"invalid lifetime name: expected `'w` or `'s`
303329
'w -- refers to data stored in the World.
304330
's -- refers to data stored in the SystemParam's state.'"#,
305-
)
306-
.into_compile_error()
307-
.into();
331+
));
308332
}
309333
}
310334

@@ -386,16 +410,14 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
386410
.iter()
387411
.filter(|a| a.path().is_ident("system_param"))
388412
{
389-
if let Err(e) = meta.parse_nested_meta(|nested| {
413+
meta.parse_nested_meta(|nested| {
390414
if nested.path.is_ident("builder") {
391415
builder_name = Some(format_ident!("{struct_name}Builder"));
392416
Ok(())
393417
} else {
394418
Err(nested.error("Unsupported attribute"))
395419
}
396-
}) {
397-
return e.into_compile_error().into();
398-
}
420+
})?;
399421
}
400422

401423
let builder = builder_name.map(|builder_name| {
@@ -430,7 +452,7 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
430452
});
431453
let (builder_struct, builder_impl) = builder.unzip();
432454

433-
TokenStream::from(quote! {
455+
Ok(TokenStream::from(quote! {
434456
// We define the FetchState struct in an anonymous scope to avoid polluting the user namespace.
435457
// The struct can still be accessed via SystemParam::State, e.g. MessageReaderState can be accessed via
436458
// <MessageReader<'static, 'static, T> as SystemParam>::State
@@ -505,7 +527,7 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
505527
};
506528

507529
#builder_struct
508-
})
530+
}))
509531
}
510532

511533
/// Implement `QueryData` to use a struct as a data parameter in a query

0 commit comments

Comments
 (0)