bevy_derive/lib.rs
1// FIXME(15321): solve CI failures, then replace with `#![expect()]`.
2#![allow(missing_docs, reason = "Not all docs are written yet, see #3492.")]
3#![forbid(unsafe_code)]
4#![cfg_attr(docsrs, feature(doc_auto_cfg))]
5#![doc(
6 html_logo_url = "https://bevyengine.org/assets/icon.png",
7 html_favicon_url = "https://bevyengine.org/assets/icon.png"
8)]
9
10extern crate proc_macro;
11
12mod bevy_main;
13mod derefs;
14mod enum_variant_meta;
15
16use bevy_macro_utils::{derive_label, BevyManifest};
17use proc_macro::TokenStream;
18use quote::format_ident;
19
20/// Implements [`Deref`] for structs. This is especially useful when utilizing the [newtype] pattern.
21///
22/// For single-field structs, the implementation automatically uses that field.
23/// For multi-field structs, you must specify which field to use with the `#[deref]` attribute.
24///
25/// If you need [`DerefMut`] as well, consider using the other [derive] macro alongside
26/// this one.
27///
28/// # Example
29///
30/// ## Tuple Structs
31///
32/// Using a single-field struct:
33///
34/// ```
35/// use bevy_derive::Deref;
36///
37/// #[derive(Deref)]
38/// struct MyNewtype(String);
39///
40/// let foo = MyNewtype(String::from("Hello"));
41/// assert_eq!("Hello", *foo);
42/// ```
43///
44/// Using a multi-field struct:
45///
46/// ```
47/// # use std::marker::PhantomData;
48/// use bevy_derive::Deref;
49///
50/// #[derive(Deref)]
51/// struct MyStruct<T>(#[deref] String, PhantomData<T>);
52///
53/// let foo = MyStruct(String::from("Hello"), PhantomData::<usize>);
54/// assert_eq!("Hello", *foo);
55/// ```
56///
57/// ## Named Structs
58///
59/// Using a single-field struct:
60///
61/// ```
62/// use bevy_derive::{Deref, DerefMut};
63///
64/// #[derive(Deref, DerefMut)]
65/// struct MyStruct {
66/// value: String,
67/// }
68///
69/// let foo = MyStruct {
70/// value: String::from("Hello")
71/// };
72/// assert_eq!("Hello", *foo);
73/// ```
74///
75/// Using a multi-field struct:
76///
77/// ```
78/// # use std::marker::PhantomData;
79/// use bevy_derive::{Deref, DerefMut};
80///
81/// #[derive(Deref, DerefMut)]
82/// struct MyStruct<T> {
83/// #[deref]
84/// value: String,
85/// _phantom: PhantomData<T>,
86/// }
87///
88/// let foo = MyStruct {
89/// value:String::from("Hello"),
90/// _phantom:PhantomData::<usize>
91/// };
92/// assert_eq!("Hello", *foo);
93/// ```
94///
95/// [`Deref`]: std::ops::Deref
96/// [newtype]: https://doc.rust-lang.org/rust-by-example/generics/new_types.html
97/// [`DerefMut`]: std::ops::DerefMut
98/// [derive]: crate::derive_deref_mut
99#[proc_macro_derive(Deref, attributes(deref))]
100pub fn derive_deref(input: TokenStream) -> TokenStream {
101 derefs::derive_deref(input)
102}
103
104/// Implements [`DerefMut`] for structs. This is especially useful when utilizing the [newtype] pattern.
105///
106/// For single-field structs, the implementation automatically uses that field.
107/// For multi-field structs, you must specify which field to use with the `#[deref]` attribute.
108///
109/// [`DerefMut`] requires a [`Deref`] implementation. You can implement it manually or use
110/// Bevy's [derive] macro for convenience.
111///
112/// # Example
113///
114/// ## Tuple Structs
115///
116/// Using a single-field struct:
117///
118/// ```
119/// use bevy_derive::{Deref, DerefMut};
120///
121/// #[derive(Deref, DerefMut)]
122/// struct MyNewtype(String);
123///
124/// let mut foo = MyNewtype(String::from("Hello"));
125/// foo.push_str(" World!");
126/// assert_eq!("Hello World!", *foo);
127/// ```
128///
129/// Using a multi-field struct:
130///
131/// ```
132/// # use std::marker::PhantomData;
133/// use bevy_derive::{Deref, DerefMut};
134///
135/// #[derive(Deref, DerefMut)]
136/// struct MyStruct<T>(#[deref] String, PhantomData<T>);
137///
138/// let mut foo = MyStruct(String::from("Hello"), PhantomData::<usize>);
139/// foo.push_str(" World!");
140/// assert_eq!("Hello World!", *foo);
141/// ```
142///
143/// ## Named Structs
144///
145/// Using a single-field struct:
146///
147/// ```
148/// use bevy_derive::{Deref, DerefMut};
149///
150/// #[derive(Deref, DerefMut)]
151/// struct MyStruct {
152/// value: String,
153/// }
154///
155/// let mut foo = MyStruct {
156/// value: String::from("Hello")
157/// };
158/// foo.push_str(" World!");
159/// assert_eq!("Hello World!", *foo);
160/// ```
161///
162/// Using a multi-field struct:
163///
164/// ```
165/// # use std::marker::PhantomData;
166/// use bevy_derive::{Deref, DerefMut};
167///
168/// #[derive(Deref, DerefMut)]
169/// struct MyStruct<T> {
170/// #[deref]
171/// value: String,
172/// _phantom: PhantomData<T>,
173/// }
174///
175/// let mut foo = MyStruct {
176/// value:String::from("Hello"),
177/// _phantom:PhantomData::<usize>
178/// };
179/// foo.push_str(" World!");
180/// assert_eq!("Hello World!", *foo);
181/// ```
182///
183/// [`DerefMut`]: std::ops::DerefMut
184/// [newtype]: https://doc.rust-lang.org/rust-by-example/generics/new_types.html
185/// [`Deref`]: std::ops::Deref
186/// [derive]: crate::derive_deref
187#[proc_macro_derive(DerefMut, attributes(deref))]
188pub fn derive_deref_mut(input: TokenStream) -> TokenStream {
189 derefs::derive_deref_mut(input)
190}
191
192#[proc_macro_attribute]
193pub fn bevy_main(attr: TokenStream, item: TokenStream) -> TokenStream {
194 bevy_main::bevy_main(attr, item)
195}
196
197#[proc_macro_derive(EnumVariantMeta)]
198pub fn derive_enum_variant_meta(input: TokenStream) -> TokenStream {
199 enum_variant_meta::derive_enum_variant_meta(input)
200}
201
202/// Generates an impl of the `AppLabel` trait.
203///
204/// This does not work for unions.
205#[proc_macro_derive(AppLabel)]
206pub fn derive_app_label(input: TokenStream) -> TokenStream {
207 let input = syn::parse_macro_input!(input as syn::DeriveInput);
208 let mut trait_path = BevyManifest::default().get_path("bevy_app");
209 let mut dyn_eq_path = trait_path.clone();
210 trait_path.segments.push(format_ident!("AppLabel").into());
211 dyn_eq_path.segments.push(format_ident!("DynEq").into());
212 derive_label(input, "AppLabel", &trait_path, &dyn_eq_path)
213}