Skip to content

Commit 9635465

Browse files
committed
Add attribute macro to enable the warning for missed events
1 parent b8010d7 commit 9635465

File tree

3 files changed

+110
-20
lines changed

3 files changed

+110
-20
lines changed

crates/bevy_ecs/macros/src/component.rs

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,6 @@ use proc_macro2::{Span, TokenStream as TokenStream2};
44
use quote::{quote, ToTokens};
55
use syn::{parse_macro_input, parse_quote, DeriveInput, Error, Ident, Path, Result};
66

7-
pub fn derive_event(input: TokenStream) -> TokenStream {
8-
let mut ast = parse_macro_input!(input as DeriveInput);
9-
let bevy_ecs_path: Path = crate::bevy_ecs_path();
10-
11-
ast.generics
12-
.make_where_clause()
13-
.predicates
14-
.push(parse_quote! { Self: Send + Sync + 'static });
15-
16-
let struct_name = &ast.ident;
17-
let (impl_generics, type_generics, where_clause) = &ast.generics.split_for_impl();
18-
19-
TokenStream::from(quote! {
20-
impl #impl_generics #bevy_ecs_path::event::Event for #struct_name #type_generics #where_clause {
21-
}
22-
})
23-
}
24-
257
pub fn derive_resource(input: TokenStream) -> TokenStream {
268
let mut ast = parse_macro_input!(input as DeriveInput);
279
let bevy_ecs_path: Path = crate::bevy_ecs_path();

crates/bevy_ecs/macros/src/event.rs

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
use bevy_macro_utils::{get_lit_str, Symbol};
2+
use proc_macro::TokenStream;
3+
use quote::{quote, ToTokens};
4+
use syn::{parse_macro_input, parse_quote, DeriveInput, Error, Path, Result};
5+
6+
pub fn derive_event(input: TokenStream) -> TokenStream {
7+
let mut ast = parse_macro_input!(input as DeriveInput);
8+
let bevy_ecs_path: Path = crate::bevy_ecs_path();
9+
10+
ast.generics
11+
.make_where_clause()
12+
.predicates
13+
.push(parse_quote! { Self: Send + Sync + 'static });
14+
15+
let attrs = match parse_event_attr(&ast) {
16+
Ok(attrs) => attrs,
17+
Err(e) => return e.into_compile_error().into(),
18+
};
19+
20+
let missed = attrs.missed;
21+
22+
let warn_missed = match missed {
23+
Missed::Ignore => quote! { const WARN_MISSED: bool = false; },
24+
Missed::DebugWarn => quote! {
25+
#[cfg(debug_assertions)]
26+
const WARN_MISSED: bool = true;
27+
#[cfg(not(debug_assertions))]
28+
const WARN_MISSED: bool = false;
29+
},
30+
Missed::Warn => quote! { const WARN_MISSED:bool = true; },
31+
};
32+
33+
let struct_name = &ast.ident;
34+
let (impl_generics, type_generics, where_clause) = &ast.generics.split_for_impl();
35+
36+
TokenStream::from(quote! {
37+
impl #impl_generics #bevy_ecs_path::event::Event for #struct_name #type_generics #where_clause {
38+
#warn_missed
39+
}
40+
})
41+
}
42+
43+
struct Attrs {
44+
missed: Missed,
45+
}
46+
47+
enum Missed {
48+
Ignore,
49+
DebugWarn,
50+
Warn,
51+
}
52+
53+
pub const EVENT: Symbol = Symbol("event");
54+
pub const MISSED: Symbol = Symbol("missed");
55+
56+
const IGNORE: &str = "ignore";
57+
const DEBUG_WARN: &str = "debug_warn";
58+
const WARN: &str = "warn";
59+
60+
fn parse_event_attr(ast: &DeriveInput) -> Result<Attrs> {
61+
let meta_items = bevy_macro_utils::parse_attrs(ast, EVENT)?;
62+
63+
let mut attrs = Attrs {
64+
missed: Missed::DebugWarn,
65+
};
66+
67+
for meta in meta_items {
68+
use syn::{
69+
Meta::NameValue,
70+
NestedMeta::{Lit, Meta},
71+
};
72+
match meta {
73+
Meta(NameValue(m)) if m.path == MISSED => {
74+
attrs.missed = match get_lit_str(MISSED, &m.lit)?.value().as_str() {
75+
IGNORE => Missed::Ignore,
76+
DEBUG_WARN => Missed::DebugWarn,
77+
WARN => Missed::Warn,
78+
e => {
79+
return Err(Error::new_spanned(
80+
m.lit,
81+
format!(
82+
"Invalid missed event behaviour `{e}`, expected '{IGNORE}', '{DEBUG_WARN}', or '{WARN}'.",
83+
),
84+
))
85+
}
86+
}
87+
}
88+
Meta(meta_item) => {
89+
return Err(Error::new_spanned(
90+
meta_item.path(),
91+
format!(
92+
"unknown event attribute `{}`",
93+
meta_item.path().into_token_stream()
94+
),
95+
));
96+
}
97+
Lit(lit) => {
98+
return Err(Error::new_spanned(
99+
lit,
100+
"unexpected literal in event attribute",
101+
))
102+
}
103+
}
104+
}
105+
106+
Ok(attrs)
107+
}

crates/bevy_ecs/macros/src/lib.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
extern crate proc_macro;
22

33
mod component;
4+
mod event;
45
mod fetch;
56
mod set;
67
mod states;
@@ -482,9 +483,9 @@ pub(crate) fn bevy_ecs_path() -> syn::Path {
482483
BevyManifest::default().get_path("bevy_ecs")
483484
}
484485

485-
#[proc_macro_derive(Event)]
486+
#[proc_macro_derive(Event, attributes(event))]
486487
pub fn derive_event(input: TokenStream) -> TokenStream {
487-
component::derive_event(input)
488+
event::derive_event(input)
488489
}
489490

490491
#[proc_macro_derive(Resource)]

0 commit comments

Comments
 (0)