Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_reflect/derive/src/lib.rs
9367 views
1
#![cfg_attr(docsrs, feature(doc_cfg))]
2
3
//! This crate contains macros used by Bevy's `Reflect` API.
4
//!
5
//! The main export of this crate is the derive macro for [`Reflect`]. This allows
6
//! types to easily implement `Reflect` along with other `bevy_reflect` traits,
7
//! such as `Struct`, `GetTypeRegistration`, and more— all with a single derive!
8
//!
9
//! Some other noteworthy exports include the derive macros for [`FromReflect`] and
10
//! [`TypePath`], as well as the [`reflect_trait`] attribute macro.
11
//!
12
//! [`Reflect`]: crate::derive_reflect
13
//! [`FromReflect`]: crate::derive_from_reflect
14
//! [`TypePath`]: crate::derive_type_path
15
//! [`reflect_trait`]: macro@reflect_trait
16
17
extern crate proc_macro;
18
19
mod container_attributes;
20
mod custom_attributes;
21
mod derive_data;
22
#[cfg(feature = "reflect_documentation")]
23
mod documentation;
24
mod enum_utility;
25
mod field_attributes;
26
mod from_reflect;
27
mod generics;
28
mod ident;
29
mod impls;
30
mod meta;
31
mod reflect_opaque;
32
mod registration;
33
mod remote;
34
mod serialization;
35
mod string_expr;
36
mod struct_utility;
37
mod trait_reflection;
38
mod type_path;
39
mod where_clause_options;
40
41
use std::{fs, io::Read, path::PathBuf};
42
43
use crate::derive_data::{ReflectDerive, ReflectMeta, ReflectStruct};
44
use container_attributes::ContainerAttributes;
45
use derive_data::{ReflectImplSource, ReflectProvenance, ReflectTraitToImpl, ReflectTypePath};
46
use proc_macro::TokenStream;
47
use quote::quote;
48
use reflect_opaque::ReflectOpaqueDef;
49
use syn::{parse_macro_input, DeriveInput};
50
use type_path::NamedTypePathDef;
51
52
pub(crate) static REFLECT_ATTRIBUTE_NAME: &str = "reflect";
53
pub(crate) static TYPE_PATH_ATTRIBUTE_NAME: &str = "type_path";
54
pub(crate) static TYPE_NAME_ATTRIBUTE_NAME: &str = "type_name";
55
56
/// Used both for [`impl_reflect`] and [`derive_reflect`].
57
///
58
/// [`impl_reflect`]: macro@impl_reflect
59
/// [`derive_reflect`]: derive_reflect()
60
fn match_reflect_impls(ast: DeriveInput, source: ReflectImplSource) -> TokenStream {
61
let derive_data = match ReflectDerive::from_input(
62
&ast,
63
ReflectProvenance {
64
source,
65
trait_: ReflectTraitToImpl::Reflect,
66
},
67
) {
68
Ok(data) => data,
69
Err(err) => return err.into_compile_error().into(),
70
};
71
72
let assertions = impls::impl_assertions(&derive_data);
73
74
let (reflect_impls, from_reflect_impl) = match derive_data {
75
ReflectDerive::Struct(struct_data) | ReflectDerive::UnitStruct(struct_data) => (
76
impls::impl_struct(&struct_data),
77
if struct_data.meta().from_reflect().should_auto_derive() {
78
Some(from_reflect::impl_struct(&struct_data))
79
} else {
80
None
81
},
82
),
83
ReflectDerive::TupleStruct(struct_data) => (
84
impls::impl_tuple_struct(&struct_data),
85
if struct_data.meta().from_reflect().should_auto_derive() {
86
Some(from_reflect::impl_tuple_struct(&struct_data))
87
} else {
88
None
89
},
90
),
91
ReflectDerive::Enum(enum_data) => (
92
impls::impl_enum(&enum_data),
93
if enum_data.meta().from_reflect().should_auto_derive() {
94
Some(from_reflect::impl_enum(&enum_data))
95
} else {
96
None
97
},
98
),
99
ReflectDerive::Opaque(meta) => (
100
impls::impl_opaque(&meta),
101
if meta.from_reflect().should_auto_derive() {
102
Some(from_reflect::impl_opaque(&meta))
103
} else {
104
None
105
},
106
),
107
};
108
109
TokenStream::from(quote! {
110
const _: () = {
111
#reflect_impls
112
113
#from_reflect_impl
114
115
#assertions
116
};
117
})
118
}
119
120
/// The main derive macro used by `bevy_reflect` for deriving its `Reflect` trait.
121
///
122
/// This macro can be used on all structs and enums (unions are not supported).
123
/// It will automatically generate implementations for `Reflect`, `Typed`, `GetTypeRegistration`, and `FromReflect`.
124
/// And, depending on the item's structure, will either implement `Struct`, `TupleStruct`, or `Enum`.
125
///
126
/// See the [`FromReflect`] derive macro for more information on how to customize the `FromReflect` implementation.
127
///
128
/// # Container Attributes
129
///
130
/// This macro comes with some helper attributes that can be added to the container item
131
/// in order to provide additional functionality or alter the generated implementations.
132
///
133
/// In addition to those listed, this macro can also use the attributes for [`TypePath`] derives.
134
///
135
/// ## `#[reflect(Ident)]`
136
///
137
/// The `#[reflect(Ident)]` attribute is used to add type data registrations to the `GetTypeRegistration`
138
/// implementation corresponding to the given identifier, prepended by `Reflect`.
139
///
140
/// For example, `#[reflect(Foo, Bar)]` would add two registrations:
141
/// one for `ReflectFoo` and another for `ReflectBar`.
142
/// This assumes these types are indeed in-scope wherever this macro is called.
143
///
144
/// This is often used with traits that have been marked by the [`#[reflect_trait]`](macro@reflect_trait)
145
/// macro in order to register the type's implementation of that trait.
146
///
147
/// ### Default Registrations
148
///
149
/// The following types are automatically registered when deriving `Reflect`:
150
///
151
/// * `ReflectFromReflect` (unless opting out of `FromReflect`)
152
/// * `SerializationData`
153
/// * `ReflectFromPtr`
154
///
155
/// ### Special Identifiers
156
///
157
/// There are a few "special" identifiers that work a bit differently:
158
///
159
/// * `#[reflect(Clone)]` will force the implementation of `Reflect::reflect_clone` to rely on
160
/// the type's [`Clone`] implementation.
161
/// A custom implementation may be provided using `#[reflect(Clone(my_clone_func))]` where
162
/// `my_clone_func` is the path to a function matching the signature:
163
/// `(&Self) -> Self`.
164
/// * `#[reflect(Debug)]` will force the implementation of `Reflect::debug` to rely on
165
/// the type's [`Debug`] implementation.
166
/// A custom implementation may be provided using `#[reflect(Debug(my_debug_func))]` where
167
/// `my_debug_func` is the path to a function matching the signature:
168
/// `(&Self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result`.
169
/// * `#[reflect(PartialEq)]` will force the implementation of `Reflect::reflect_partial_eq` to rely on
170
/// the type's [`PartialEq`] implementation.
171
/// A custom implementation may be provided using `#[reflect(PartialEq(my_partial_eq_func))]` where
172
/// `my_partial_eq_func` is the path to a function matching the signature:
173
/// `(&Self, value: &dyn #bevy_reflect_path::Reflect) -> bool`.
174
/// * `#[reflect(PartialOrd)]` will force the implementation of `PartialReflect::reflect_partial_cmp`
175
/// to rely on the type's [`PartialOrd`] implementation.
176
/// A custom implementation may be provided using `#[reflect(PartialOrd(my_partial_cmp_fn))]` where
177
/// `my_partial_cmp_fn` is the path to a function matching the signature:
178
/// `(&Self, value: &dyn #bevy_reflect_path::PartialReflect) -> Option<::core::cmp::Ordering>`.
179
/// * `#[reflect(Hash)]` will force the implementation of `Reflect::reflect_hash` to rely on
180
/// the type's [`Hash`] implementation.
181
/// A custom implementation may be provided using `#[reflect(Hash(my_hash_func))]` where
182
/// `my_hash_func` is the path to a function matching the signature: `(&Self) -> u64`.
183
/// * `#[reflect(Default)]` will register the `ReflectDefault` type data as normal.
184
/// However, it will also affect how certain other operations are performed in order
185
/// to improve performance and/or robustness.
186
/// An example of where this is used is in the [`FromReflect`] derive macro,
187
/// where adding this attribute will cause the `FromReflect` implementation to create
188
/// a base value using its [`Default`] implementation avoiding issues with ignored fields
189
/// (for structs and tuple structs only).
190
///
191
/// ## `#[reflect(opaque)]`
192
///
193
/// The `#[reflect(opaque)]` attribute denotes that the item should implement `Reflect` as an opaque type,
194
/// hiding its structure and fields from the reflection API.
195
/// This means that it will forgo implementing `Struct`, `TupleStruct`, or `Enum`.
196
///
197
/// Furthermore, it requires that the type implements [`Clone`].
198
/// If planning to serialize this type using the reflection serializers,
199
/// then the `Serialize` and `Deserialize` traits will need to be implemented and registered as well.
200
///
201
/// ## `#[reflect(from_reflect = false)]`
202
///
203
/// This attribute will opt-out of the default `FromReflect` implementation.
204
///
205
/// This is useful for when a type can't or shouldn't implement `FromReflect`,
206
/// or if a manual implementation is desired.
207
///
208
/// Note that in the latter case, `ReflectFromReflect` will no longer be automatically registered.
209
///
210
/// ## `#[reflect(type_path = false)]`
211
///
212
/// This attribute will opt-out of the default `TypePath` implementation.
213
///
214
/// This is useful for when a type can't or shouldn't implement `TypePath`,
215
/// or if a manual implementation is desired.
216
///
217
/// ## `#[reflect(no_field_bounds)]`
218
///
219
/// This attribute will opt-out of the default trait bounds added to all field types
220
/// for the generated reflection trait impls.
221
///
222
/// Normally, all fields will have the bounds `TypePath`, and either `FromReflect` or `Reflect`
223
/// depending on if `#[reflect(from_reflect = false)]` is used.
224
/// However, this might not always be desirable, and so this attribute may be used to remove those bounds.
225
///
226
/// ### Example
227
///
228
/// If a type is recursive the default bounds will cause an overflow error when building:
229
///
230
/// ```ignore (bevy_reflect is not accessible from this crate)
231
/// #[derive(Reflect)] // ERROR: overflow evaluating the requirement `Foo: FromReflect`
232
/// struct Foo {
233
/// foo: Vec<Foo>,
234
/// }
235
///
236
/// // Generates a where clause like:
237
/// // impl bevy_reflect::Reflect for Foo
238
/// // where
239
/// // Foo: Any + Send + Sync,
240
/// // Vec<Foo>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
241
/// ```
242
///
243
/// In this case, `Foo` is given the bounds `Vec<Foo>: FromReflect + ...`,
244
/// which requires that `Foo` implements `FromReflect`,
245
/// which requires that `Vec<Foo>` implements `FromReflect`,
246
/// and so on, resulting in the error.
247
///
248
/// To fix this, we can add `#[reflect(no_field_bounds)]` to `Foo` to remove the bounds on `Vec<Foo>`:
249
///
250
/// ```ignore (bevy_reflect is not accessible from this crate)
251
/// #[derive(Reflect)]
252
/// #[reflect(no_field_bounds)]
253
/// struct Foo {
254
/// foo: Vec<Foo>,
255
/// }
256
///
257
/// // Generates a where clause like:
258
/// // impl bevy_reflect::Reflect for Foo
259
/// // where
260
/// // Self: Any + Send + Sync,
261
/// ```
262
///
263
/// ## `#[reflect(where T: Trait, U::Assoc: Trait, ...)]`
264
///
265
/// This attribute can be used to add additional bounds to the generated reflection trait impls.
266
///
267
/// This is useful for when a type needs certain bounds only applied to the reflection impls
268
/// that are not otherwise automatically added by the derive macro.
269
///
270
/// ### Example
271
///
272
/// In the example below, we want to enforce that `T::Assoc: List` is required in order for
273
/// `Foo<T>` to be reflectable, but we don't want it to prevent `Foo<T>` from being used
274
/// in places where `T::Assoc: List` is not required.
275
///
276
/// ```ignore
277
/// trait Trait {
278
/// type Assoc;
279
/// }
280
///
281
/// #[derive(Reflect)]
282
/// #[reflect(where T::Assoc: List)]
283
/// struct Foo<T: Trait> where T::Assoc: Default {
284
/// value: T::Assoc,
285
/// }
286
///
287
/// // Generates a where clause like:
288
/// //
289
/// // impl<T: Trait> bevy_reflect::Reflect for Foo<T>
290
/// // where
291
/// // Foo<T>: Any + Send + Sync,
292
/// // T::Assoc: Default,
293
/// // T: TypePath,
294
/// // T::Assoc: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
295
/// // T::Assoc: List,
296
/// // {/* ... */}
297
/// ```
298
///
299
/// ## `#[reflect(@...)]`
300
///
301
/// This attribute can be used to register custom attributes to the type's `TypeInfo`.
302
///
303
/// It accepts any expression after the `@` symbol that resolves to a value which implements `Reflect`.
304
///
305
/// Any number of custom attributes may be registered, however, each the type of each attribute must be unique.
306
/// If two attributes of the same type are registered, the last one will overwrite the first.
307
///
308
/// ### Example
309
///
310
/// ```ignore
311
/// #[derive(Reflect)]
312
/// struct Required;
313
///
314
/// #[derive(Reflect)]
315
/// struct EditorTooltip(String);
316
///
317
/// impl EditorTooltip {
318
/// fn new(text: &str) -> Self {
319
/// Self(text.to_string())
320
/// }
321
/// }
322
///
323
/// #[derive(Reflect)]
324
/// // Specify a "required" status and tooltip:
325
/// #[reflect(@Required, @EditorTooltip::new("An ID is required!"))]
326
/// struct Id(u8);
327
/// ```
328
/// ## `#[reflect(no_auto_register)]`
329
///
330
/// This attribute will opt-out of the automatic reflect type registration.
331
///
332
/// All non-generic types annotated with `#[derive(Reflect)]` are usually automatically registered on app startup.
333
/// If this behavior is not desired, this attribute may be used to disable it for the annotated type.
334
///
335
/// # Field Attributes
336
///
337
/// Along with the container attributes, this macro comes with some attributes that may be applied
338
/// to the contained fields themselves.
339
///
340
/// ## `#[reflect(ignore)]`
341
///
342
/// This attribute simply marks a field to be ignored by the reflection API.
343
///
344
/// This allows fields to completely opt-out of reflection,
345
/// which may be useful for maintaining invariants, keeping certain data private,
346
/// or allowing the use of types that do not implement `Reflect` within the container.
347
///
348
/// ## `#[reflect(skip_serializing)]`
349
///
350
/// This works similar to `#[reflect(ignore)]`, but rather than opting out of _all_ of reflection,
351
/// it simply opts the field out of both serialization and deserialization.
352
/// This can be useful when a field should be accessible via reflection, but may not make
353
/// sense in a serialized form, such as computed data.
354
///
355
/// What this does is register the `SerializationData` type within the `GetTypeRegistration` implementation,
356
/// which will be used by the reflection serializers to determine whether or not the field is serializable.
357
///
358
/// ## `#[reflect(clone)]`
359
///
360
/// This attribute affects the `Reflect::reflect_clone` implementation.
361
///
362
/// Without this attribute, the implementation will rely on the field's own `Reflect::reflect_clone` implementation.
363
/// When this attribute is present, the implementation will instead use the field's `Clone` implementation directly.
364
///
365
/// The attribute may also take the path to a custom function like `#[reflect(clone = "path::to::my_clone_func")]`,
366
/// where `my_clone_func` matches the signature `(&Self) -> Self`.
367
///
368
/// This attribute does nothing if the containing struct/enum has the `#[reflect(Clone)]` attribute.
369
///
370
/// ## `#[reflect(@...)]`
371
///
372
/// This attribute can be used to register custom attributes to the field's `TypeInfo`.
373
///
374
/// It accepts any expression after the `@` symbol that resolves to a value which implements `Reflect`.
375
///
376
/// Any number of custom attributes may be registered, however, each the type of each attribute must be unique.
377
/// If two attributes of the same type are registered, the last one will overwrite the first.
378
///
379
/// ### Example
380
///
381
/// ```ignore
382
/// #[derive(Reflect)]
383
/// struct EditorTooltip(String);
384
///
385
/// impl EditorTooltip {
386
/// fn new(text: &str) -> Self {
387
/// Self(text.to_string())
388
/// }
389
/// }
390
///
391
/// #[derive(Reflect)]
392
/// struct Slider {
393
/// // Specify a custom range and tooltip:
394
/// #[reflect(@0.0..=1.0, @EditorTooltip::new("Must be between 0 and 1"))]
395
/// value: f32,
396
/// }
397
/// ```
398
///
399
/// [`reflect_trait`]: macro@reflect_trait
400
#[proc_macro_derive(Reflect, attributes(reflect, type_path, type_name))]
401
pub fn derive_reflect(input: TokenStream) -> TokenStream {
402
let ast = parse_macro_input!(input as DeriveInput);
403
match_reflect_impls(ast, ReflectImplSource::DeriveLocalType)
404
}
405
406
/// Derives the `FromReflect` trait.
407
///
408
/// # Field Attributes
409
///
410
/// ## `#[reflect(ignore)]`
411
///
412
/// The `#[reflect(ignore)]` attribute is shared with the [`#[derive(Reflect)]`](Reflect) macro and has much of the same
413
/// functionality in that it denotes that a field will be ignored by the reflection API.
414
///
415
/// The only major difference is that using it with this derive requires that the field implements [`Default`].
416
/// Without this requirement, there would be no way for `FromReflect` to automatically construct missing fields
417
/// that have been ignored.
418
///
419
/// ## `#[reflect(default)]`
420
///
421
/// If a field cannot be read, this attribute specifies a default value to be used in its place.
422
///
423
/// By default, this attribute denotes that the field's type implements [`Default`].
424
/// However, it can also take in a path string to a user-defined function that will return the default value.
425
/// This takes the form: `#[reflect(default = "path::to::my_function")]` where `my_function` is a parameterless
426
/// function that must return some default value for the type.
427
///
428
/// Specifying a custom default can be used to give different fields their own specialized defaults,
429
/// or to remove the `Default` requirement on fields marked with `#[reflect(ignore)]`.
430
/// Additionally, either form of this attribute can be used to fill in fields that are simply missing,
431
/// such as when converting a partially-constructed dynamic type to a concrete one.
432
#[proc_macro_derive(FromReflect, attributes(reflect))]
433
pub fn derive_from_reflect(input: TokenStream) -> TokenStream {
434
let ast = parse_macro_input!(input as DeriveInput);
435
436
let derive_data = match ReflectDerive::from_input(
437
&ast,
438
ReflectProvenance {
439
source: ReflectImplSource::DeriveLocalType,
440
trait_: ReflectTraitToImpl::FromReflect,
441
},
442
) {
443
Ok(data) => data,
444
Err(err) => return err.into_compile_error().into(),
445
};
446
447
let from_reflect_impl = match derive_data {
448
ReflectDerive::Struct(struct_data) | ReflectDerive::UnitStruct(struct_data) => {
449
from_reflect::impl_struct(&struct_data)
450
}
451
ReflectDerive::TupleStruct(struct_data) => from_reflect::impl_tuple_struct(&struct_data),
452
ReflectDerive::Enum(meta) => from_reflect::impl_enum(&meta),
453
ReflectDerive::Opaque(meta) => from_reflect::impl_opaque(&meta),
454
};
455
456
TokenStream::from(quote! {
457
const _: () = {
458
#from_reflect_impl
459
};
460
})
461
}
462
463
/// Derives the `TypePath` trait, providing a stable alternative to [`std::any::type_name`].
464
///
465
/// # Container Attributes
466
///
467
/// ## `#[type_path = "my_crate::foo"]`
468
///
469
/// Optionally specifies a custom module path to use instead of [`module_path`].
470
///
471
/// This path does not include the final identifier.
472
///
473
/// ## `#[type_name = "RenamedType"]`
474
///
475
/// Optionally specifies a new terminating identifier for `TypePath`.
476
///
477
/// To use this attribute, `#[type_path = "..."]` must also be specified.
478
#[proc_macro_derive(TypePath, attributes(type_path, type_name))]
479
pub fn derive_type_path(input: TokenStream) -> TokenStream {
480
let ast = parse_macro_input!(input as DeriveInput);
481
let derive_data = match ReflectDerive::from_input(
482
&ast,
483
ReflectProvenance {
484
source: ReflectImplSource::DeriveLocalType,
485
trait_: ReflectTraitToImpl::TypePath,
486
},
487
) {
488
Ok(data) => data,
489
Err(err) => return err.into_compile_error().into(),
490
};
491
492
let type_path_impl = impls::impl_type_path(derive_data.meta());
493
494
TokenStream::from(quote! {
495
const _: () = {
496
#type_path_impl
497
};
498
})
499
}
500
501
/// A macro that automatically generates type data for traits, which their implementors can then register.
502
///
503
/// The output of this macro is a struct that takes reflected instances of the implementor's type
504
/// and returns the value as a trait object.
505
/// Because of this, **it can only be used on [object-safe] traits.**
506
///
507
/// For a trait named `MyTrait`, this will generate the struct `ReflectMyTrait`.
508
/// The generated struct can be created using `FromType` with any type that implements the trait.
509
/// The creation and registration of this generated struct as type data can be automatically handled
510
/// by [`#[derive(Reflect)]`](Reflect).
511
///
512
/// # Example
513
///
514
/// ```ignore (bevy_reflect is not accessible from this crate)
515
/// # use std::any::TypeId;
516
/// # use bevy_reflect_derive::{Reflect, reflect_trait};
517
/// #[reflect_trait] // Generates `ReflectMyTrait`
518
/// trait MyTrait {
519
/// fn print(&self) -> &str;
520
/// }
521
///
522
/// #[derive(Reflect)]
523
/// #[reflect(MyTrait)] // Automatically registers `ReflectMyTrait`
524
/// struct SomeStruct;
525
///
526
/// impl MyTrait for SomeStruct {
527
/// fn print(&self) -> &str {
528
/// "Hello, World!"
529
/// }
530
/// }
531
///
532
/// // We can create the type data manually if we wanted:
533
/// let my_trait: ReflectMyTrait = FromType::<SomeStruct>::from_type();
534
///
535
/// // Or we can simply get it from the registry:
536
/// let mut registry = TypeRegistry::default();
537
/// registry.register::<SomeStruct>();
538
/// let my_trait = registry
539
/// .get_type_data::<ReflectMyTrait>(TypeId::of::<SomeStruct>())
540
/// .unwrap();
541
///
542
/// // Then use it on reflected data
543
/// let reflected: Box<dyn Reflect> = Box::new(SomeStruct);
544
/// let reflected_my_trait: &dyn MyTrait = my_trait.get(&*reflected).unwrap();
545
/// assert_eq!("Hello, World!", reflected_my_trait.print());
546
/// ```
547
///
548
/// [object-safe]: https://doc.rust-lang.org/reference/items/traits.html#object-safety
549
#[proc_macro_attribute]
550
pub fn reflect_trait(args: TokenStream, input: TokenStream) -> TokenStream {
551
trait_reflection::reflect_trait(&args, input)
552
}
553
554
/// Generates a wrapper type that can be used to "derive `Reflect`" for remote types.
555
///
556
/// This works by wrapping the remote type in a generated wrapper that has the `#[repr(transparent)]` attribute.
557
/// This allows the two types to be safely [transmuted] back-and-forth.
558
///
559
/// # Defining the Wrapper
560
///
561
/// Before defining the wrapper type, please note that it is _required_ that all fields of the remote type are public.
562
/// The generated code will, at times, need to access or mutate them,
563
/// and we do not currently have a way to assign getters/setters to each field
564
/// (but this may change in the future).
565
///
566
/// The wrapper definition should match the remote type 1-to-1.
567
/// This includes the naming and ordering of the fields and variants.
568
///
569
/// Generics and lifetimes do _not_ need to have the same names, however, they _do_ need to follow the same order.
570
/// Additionally, whether generics are inlined or placed in a where clause should not matter.
571
///
572
/// Lastly, all macros and doc-comments should be placed __below__ this attribute.
573
/// If they are placed above, they will not be properly passed to the generated wrapper type.
574
///
575
/// # Example
576
///
577
/// Given a remote type, `RemoteType`:
578
///
579
/// ```
580
/// #[derive(Default)]
581
/// struct RemoteType<T>
582
/// where
583
/// T: Default + Clone,
584
/// {
585
/// pub foo: T,
586
/// pub bar: usize
587
/// }
588
/// ```
589
///
590
/// We would define our wrapper type as such:
591
///
592
/// ```ignore
593
/// use external_crate::RemoteType;
594
///
595
/// #[reflect_remote(RemoteType<T>)]
596
/// #[derive(Default)]
597
/// pub struct WrapperType<T: Default + Clone> {
598
/// pub foo: T,
599
/// pub bar: usize
600
/// }
601
/// ```
602
///
603
/// Apart from all the reflection trait implementations, this generates something like the following:
604
///
605
/// ```ignore
606
/// use external_crate::RemoteType;
607
///
608
/// #[derive(Default)]
609
/// #[repr(transparent)]
610
/// pub struct Wrapper<T: Default + Clone>(RemoteType<T>);
611
/// ```
612
///
613
/// # Usage as a Field
614
///
615
/// You can tell `Reflect` to use a remote type's wrapper internally on fields of a struct or enum.
616
/// This allows the real type to be used as usual while `Reflect` handles everything internally.
617
/// To do this, add the `#[reflect(remote = path::to::MyType)]` attribute to your field:
618
///
619
/// ```ignore
620
/// #[derive(Reflect)]
621
/// struct SomeStruct {
622
/// #[reflect(remote = RemoteTypeWrapper)]
623
/// data: RemoteType
624
/// }
625
/// ```
626
///
627
/// ## Safety
628
///
629
/// When using the `#[reflect(remote = path::to::MyType)]` field attribute, be sure you are defining the correct wrapper type.
630
/// Internally, this field will be unsafely [transmuted], and is only sound if using a wrapper generated for the remote type.
631
/// This also means keeping your wrapper definitions up-to-date with the remote types.
632
///
633
/// [transmuted]: std::mem::transmute
634
#[proc_macro_attribute]
635
pub fn reflect_remote(args: TokenStream, input: TokenStream) -> TokenStream {
636
remote::reflect_remote(args, input)
637
}
638
639
/// A macro used to generate reflection trait implementations for the given type.
640
///
641
/// This is functionally the same as [deriving `Reflect`] using the `#[reflect(opaque)]` container attribute.
642
///
643
/// The only reason for this macro's existence is so that `bevy_reflect` can easily implement the reflection traits
644
/// on primitives and other opaque types internally.
645
///
646
/// Since this macro also implements `TypePath`, the type path must be explicit.
647
/// See [`impl_type_path!`] for the exact syntax.
648
///
649
/// # Examples
650
///
651
/// Types can be passed with or without registering type data:
652
///
653
/// ```ignore (bevy_reflect is not accessible from this crate)
654
/// impl_reflect_opaque!(my_crate::Foo);
655
/// impl_reflect_opaque!(my_crate::Bar(Debug, Default, Serialize, Deserialize));
656
/// ```
657
///
658
/// Generic types can also specify their parameters and bounds:
659
///
660
/// ```ignore (bevy_reflect is not accessible from this crate)
661
/// impl_reflect_opaque!(my_crate::Foo<T1, T2: Baz> where T1: Bar (Default, Serialize, Deserialize));
662
/// ```
663
///
664
/// Custom type paths can be specified:
665
///
666
/// ```ignore (bevy_reflect is not accessible from this crate)
667
/// impl_reflect_opaque!((in not_my_crate as NotFoo) Foo(Debug, Default));
668
/// ```
669
///
670
/// [deriving `Reflect`]: Reflect
671
#[proc_macro]
672
pub fn impl_reflect_opaque(input: TokenStream) -> TokenStream {
673
let def = parse_macro_input!(input with ReflectOpaqueDef::parse_reflect);
674
675
let default_name = &def.type_path.segments.last().unwrap().ident;
676
let type_path = if def.type_path.leading_colon.is_none() && def.custom_path.is_none() {
677
ReflectTypePath::Primitive(default_name)
678
} else {
679
ReflectTypePath::External {
680
path: &def.type_path,
681
custom_path: def.custom_path.map(|path| path.into_path(default_name)),
682
generics: &def.generics,
683
}
684
};
685
686
let meta = ReflectMeta::new(type_path, def.traits.unwrap_or_default());
687
688
#[cfg(feature = "reflect_documentation")]
689
let meta = meta.with_docs(documentation::Documentation::from_attributes(&def.attrs));
690
691
let reflect_impls = impls::impl_opaque(&meta);
692
let from_reflect_impl = from_reflect::impl_opaque(&meta);
693
694
TokenStream::from(quote! {
695
const _: () = {
696
#reflect_impls
697
#from_reflect_impl
698
};
699
})
700
}
701
702
/// A replacement for `#[derive(Reflect)]` to be used with foreign types which
703
/// the definitions of cannot be altered.
704
///
705
/// This macro is an alternative to [`impl_reflect_opaque!`] and [`impl_from_reflect_opaque!`]
706
/// which implement foreign types as Opaque types. Note that there is no `impl_from_reflect`,
707
/// as this macro will do the job of both. This macro implements them using one of the reflect
708
/// variant traits (`bevy_reflect::{Struct, TupleStruct, Enum}`, etc.),
709
/// which have greater functionality. The type being reflected must be in scope, as you cannot
710
/// qualify it in the macro as e.g. `bevy::prelude::Vec3`.
711
///
712
/// It is necessary to add a `#[type_path = "my_crate::foo"]` attribute to all types.
713
///
714
/// It may be necessary to add `#[reflect(Default)]` for some types, specifically non-constructible
715
/// foreign types. Without `Default` reflected for such types, you will usually get an arcane
716
/// error message and fail to compile. If the type does not implement `Default`, it may not
717
/// be possible to reflect without extending the macro.
718
///
719
///
720
/// # Example
721
/// Implementing `Reflect` for `bevy::prelude::Vec3` as a struct type:
722
/// ```ignore (bevy_reflect is not accessible from this crate)
723
/// use bevy::prelude::Vec3;
724
///
725
/// impl_reflect!(
726
/// #[reflect(PartialEq, Serialize, Deserialize, Default)]
727
/// #[type_path = "bevy::prelude"]
728
/// struct Vec3 {
729
/// x: f32,
730
/// y: f32,
731
/// z: f32
732
/// }
733
/// );
734
/// ```
735
#[proc_macro]
736
pub fn impl_reflect(input: TokenStream) -> TokenStream {
737
let ast = parse_macro_input!(input as DeriveInput);
738
match_reflect_impls(ast, ReflectImplSource::ImplRemoteType)
739
}
740
741
/// A macro used to generate a `FromReflect` trait implementation for the given type.
742
///
743
/// This is functionally the same as [deriving `FromReflect`] on a type that [derives `Reflect`] using
744
/// the `#[reflect(opaque)]` container attribute.
745
///
746
/// The only reason this macro exists is so that `bevy_reflect` can easily implement `FromReflect` on
747
/// primitives and other opaque types internally.
748
///
749
/// Please note that this macro will not work with any type that [derives `Reflect`] normally
750
/// or makes use of the [`impl_reflect_opaque!`] macro, as those macros also implement `FromReflect`
751
/// by default.
752
///
753
/// # Examples
754
///
755
/// ```ignore (bevy_reflect is not accessible from this crate)
756
/// impl_from_reflect_opaque!(foo<T1, T2: Baz> where T1: Bar);
757
/// ```
758
///
759
/// [deriving `FromReflect`]: FromReflect
760
/// [derives `Reflect`]: Reflect
761
#[proc_macro]
762
pub fn impl_from_reflect_opaque(input: TokenStream) -> TokenStream {
763
let def = parse_macro_input!(input with ReflectOpaqueDef::parse_from_reflect);
764
765
let default_name = &def.type_path.segments.last().unwrap().ident;
766
let type_path = if def.type_path.leading_colon.is_none()
767
&& def.custom_path.is_none()
768
&& def.generics.params.is_empty()
769
{
770
ReflectTypePath::Primitive(default_name)
771
} else {
772
ReflectTypePath::External {
773
path: &def.type_path,
774
custom_path: def.custom_path.map(|alias| alias.into_path(default_name)),
775
generics: &def.generics,
776
}
777
};
778
779
let from_reflect_impl =
780
from_reflect::impl_opaque(&ReflectMeta::new(type_path, def.traits.unwrap_or_default()));
781
782
TokenStream::from(quote! {
783
const _: () = {
784
#from_reflect_impl
785
};
786
})
787
}
788
789
/// A replacement for [deriving `TypePath`] for use on foreign types.
790
///
791
/// Since (unlike the derive) this macro may be invoked in a different module to where the type is defined,
792
/// it requires an 'absolute' path definition.
793
///
794
/// Specifically, a leading `::` denoting a global path must be specified
795
/// or a preceding `(in my_crate::foo)` to specify the custom path must be used.
796
///
797
/// # Examples
798
///
799
/// Implementing `TypePath` on a foreign type:
800
/// ```ignore (bevy_reflect is not accessible from this crate)
801
/// impl_type_path!(::foreign_crate::foo::bar::Baz);
802
/// ```
803
///
804
/// On a generic type (this can also accept trait bounds):
805
/// ```ignore (bevy_reflect is not accessible from this crate)
806
/// impl_type_path!(::foreign_crate::Foo<T>);
807
/// impl_type_path!(::foreign_crate::Goo<T: ?Sized>);
808
/// ```
809
///
810
/// On a primitive (note this will not compile for a non-primitive type):
811
/// ```ignore (bevy_reflect is not accessible from this crate)
812
/// impl_type_path!(bool);
813
/// ```
814
///
815
/// With a custom type path:
816
/// ```ignore (bevy_reflect is not accessible from this crate)
817
/// impl_type_path!((in other_crate::foo::bar) Baz);
818
/// ```
819
///
820
/// With a custom type path and a custom type name:
821
/// ```ignore (bevy_reflect is not accessible from this crate)
822
/// impl_type_path!((in other_crate::foo as Baz) Bar);
823
/// ```
824
///
825
/// [deriving `TypePath`]: TypePath
826
#[proc_macro]
827
pub fn impl_type_path(input: TokenStream) -> TokenStream {
828
let def = parse_macro_input!(input as NamedTypePathDef);
829
830
let type_path = match def {
831
NamedTypePathDef::External {
832
ref path,
833
custom_path,
834
ref generics,
835
} => {
836
let default_name = &path.segments.last().unwrap().ident;
837
838
ReflectTypePath::External {
839
path,
840
custom_path: custom_path.map(|path| path.into_path(default_name)),
841
generics,
842
}
843
}
844
NamedTypePathDef::Primitive(ref ident) => ReflectTypePath::Primitive(ident),
845
};
846
847
let meta = ReflectMeta::new(type_path, ContainerAttributes::default());
848
849
let type_path_impl = impls::impl_type_path(&meta);
850
851
TokenStream::from(quote! {
852
const _: () = {
853
#type_path_impl
854
};
855
})
856
}
857
858
/// Collects and loads type registrations when using `auto_register_static` feature.
859
///
860
/// Correctly using this macro requires following:
861
/// 1. This macro must be called **last** during compilation. This can be achieved by putting your main function
862
/// in a separate crate or restructuring your project to be separated into `bin` and `lib`, and putting this macro in `bin`.
863
/// Any automatic type registrations using `#[derive(Reflect)]` within the same crate as this macro are not guaranteed to run.
864
/// 2. Your project must be compiled with `auto_register_static` feature **and** `BEVY_REFLECT_AUTO_REGISTER_STATIC=1` env variable.
865
/// Enabling the feature generates registration functions while setting the variable enables export and
866
/// caching of registration function names.
867
/// 3. Must be called before creating `App` or using `TypeRegistry::register_derived_types`.
868
///
869
/// If you're experiencing linking issues try running `cargo clean` before rebuilding.
870
#[proc_macro]
871
pub fn load_type_registrations(_input: TokenStream) -> TokenStream {
872
if !cfg!(feature = "auto_register_static") {
873
return TokenStream::new();
874
}
875
876
let Ok(dir) = fs::read_dir(PathBuf::from("target").join("bevy_reflect_type_registrations"))
877
else {
878
return TokenStream::new();
879
};
880
let mut str_buf = String::new();
881
let mut registration_fns = Vec::new();
882
for file_path in dir {
883
let mut file = fs::OpenOptions::new()
884
.read(true)
885
.open(file_path.unwrap().path())
886
.unwrap();
887
file.read_to_string(&mut str_buf).unwrap();
888
registration_fns.extend(str_buf.lines().filter(|s| !s.is_empty()).map(|s| {
889
s.parse::<proc_macro2::TokenStream>()
890
.expect("Unexpected function name")
891
}));
892
str_buf.clear();
893
}
894
let bevy_reflect_path = meta::get_bevy_reflect_path();
895
TokenStream::from(quote! {
896
{
897
fn _register_types(){
898
unsafe extern "Rust" {
899
#( safe fn #registration_fns(registry_ptr: &mut #bevy_reflect_path::TypeRegistry); )*
900
};
901
#( #bevy_reflect_path::__macro_exports::auto_register::push_registration_fn(#registration_fns); )*
902
}
903
_register_types();
904
}
905
})
906
}
907
908