Path: blob/main/crates/bevy_reflect/derive/src/generics.rs
6599 views
use crate::derive_data::ReflectMeta;1use proc_macro2::TokenStream;2use quote::quote;3use syn::punctuated::Punctuated;4use syn::{GenericParam, Token};56/// Creates a `TokenStream` for generating an expression that creates a `Generics` instance.7///8/// Returns `None` if `Generics` cannot or should not be generated.9pub(crate) fn generate_generics(meta: &ReflectMeta) -> Option<TokenStream> {10if !meta.attrs().type_path_attrs().should_auto_derive() {11// Cannot verify that all generic parameters implement `TypePath`12return None;13}1415let bevy_reflect_path = meta.bevy_reflect_path();1617let generics = meta18.type_path()19.generics()20.params21.iter()22.filter_map(|param| match param {23GenericParam::Type(ty_param) => {24let ident = &ty_param.ident;25let name = ident.to_string();26let with_default = ty_param27.default28.as_ref()29.map(|default_ty| quote!(.with_default::<#default_ty>()));3031Some(quote! {32#bevy_reflect_path::GenericInfo::Type(33#bevy_reflect_path::TypeParamInfo::new::<#ident>(34#bevy_reflect_path::__macro_exports::alloc_utils::Cow::Borrowed(#name),35)36#with_default37)38})39}40GenericParam::Const(const_param) => {41let ty = &const_param.ty;42let name = const_param.ident.to_string();43let with_default = const_param.default.as_ref().map(|default| {44// We add the `as #ty` to ensure that the correct type is inferred.45quote!(.with_default(#default as #ty))46});4748Some(quote! {49#[allow(50clippy::unnecessary_cast,51reason = "reflection requires an explicit type hint for const generics"52)]53#bevy_reflect_path::GenericInfo::Const(54#bevy_reflect_path::ConstParamInfo::new::<#ty>(55#bevy_reflect_path::__macro_exports::alloc_utils::Cow::Borrowed(#name),56)57#with_default58)59})60}61GenericParam::Lifetime(_) => None,62})63.collect::<Punctuated<_, Token![,]>>();6465if generics.is_empty() {66// No generics to generate67return None;68}6970Some(quote!(#bevy_reflect_path::Generics::from_iter([ #generics ])))71}727374