bevy_derive/
lib.rs

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