Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_reflect/derive/src/generics.rs
6599 views
1
use crate::derive_data::ReflectMeta;
2
use proc_macro2::TokenStream;
3
use quote::quote;
4
use syn::punctuated::Punctuated;
5
use syn::{GenericParam, Token};
6
7
/// Creates a `TokenStream` for generating an expression that creates a `Generics` instance.
8
///
9
/// Returns `None` if `Generics` cannot or should not be generated.
10
pub(crate) fn generate_generics(meta: &ReflectMeta) -> Option<TokenStream> {
11
if !meta.attrs().type_path_attrs().should_auto_derive() {
12
// Cannot verify that all generic parameters implement `TypePath`
13
return None;
14
}
15
16
let bevy_reflect_path = meta.bevy_reflect_path();
17
18
let generics = meta
19
.type_path()
20
.generics()
21
.params
22
.iter()
23
.filter_map(|param| match param {
24
GenericParam::Type(ty_param) => {
25
let ident = &ty_param.ident;
26
let name = ident.to_string();
27
let with_default = ty_param
28
.default
29
.as_ref()
30
.map(|default_ty| quote!(.with_default::<#default_ty>()));
31
32
Some(quote! {
33
#bevy_reflect_path::GenericInfo::Type(
34
#bevy_reflect_path::TypeParamInfo::new::<#ident>(
35
#bevy_reflect_path::__macro_exports::alloc_utils::Cow::Borrowed(#name),
36
)
37
#with_default
38
)
39
})
40
}
41
GenericParam::Const(const_param) => {
42
let ty = &const_param.ty;
43
let name = const_param.ident.to_string();
44
let with_default = const_param.default.as_ref().map(|default| {
45
// We add the `as #ty` to ensure that the correct type is inferred.
46
quote!(.with_default(#default as #ty))
47
});
48
49
Some(quote! {
50
#[allow(
51
clippy::unnecessary_cast,
52
reason = "reflection requires an explicit type hint for const generics"
53
)]
54
#bevy_reflect_path::GenericInfo::Const(
55
#bevy_reflect_path::ConstParamInfo::new::<#ty>(
56
#bevy_reflect_path::__macro_exports::alloc_utils::Cow::Borrowed(#name),
57
)
58
#with_default
59
)
60
})
61
}
62
GenericParam::Lifetime(_) => None,
63
})
64
.collect::<Punctuated<_, Token![,]>>();
65
66
if generics.is_empty() {
67
// No generics to generate
68
return None;
69
}
70
71
Some(quote!(#bevy_reflect_path::Generics::from_iter([ #generics ])))
72
}
73
74