 f9c52f98b9
			
		
	
	
		f9c52f98b9
		
	
	
	
	
		
			
			# Objective - Fixes #3004 ## Solution - Replaced all the types with their fully quallified names - Replaced all trait methods and inherent methods on dyn traits with their fully qualified names - Made a new file `fq_std.rs` that contains structs corresponding to commonly used Structs and Traits from `std`. These structs are replaced by their respective fully qualified names when used inside `quote!`
		
			
				
	
	
		
			188 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			188 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
| //! This crate contains macros used by Bevy's `Reflect` API.
 | |
| //!
 | |
| //! The main export of this crate is the derive macro for [`Reflect`]. This allows
 | |
| //! types to easily implement `Reflect` along with other `bevy_reflect` traits,
 | |
| //! such as `Struct`, `GetTypeRegistration`, and more— all with a single derive!
 | |
| //!
 | |
| //! Some other noteworthy exports include the derive macros for [`FromReflect`] and
 | |
| //! [`TypeUuid`], as well as the [`reflect_trait`] attribute macro.
 | |
| //!
 | |
| //! [`Reflect`]: crate::derive_reflect
 | |
| //! [`FromReflect`]: crate::derive_from_reflect
 | |
| //! [`TypeUuid`]: crate::derive_type_uuid
 | |
| //! [`reflect_trait`]: macro@reflect_trait
 | |
| 
 | |
| extern crate proc_macro;
 | |
| 
 | |
| mod container_attributes;
 | |
| mod derive_data;
 | |
| #[cfg(feature = "documentation")]
 | |
| mod documentation;
 | |
| mod enum_utility;
 | |
| mod field_attributes;
 | |
| mod fq_std;
 | |
| mod from_reflect;
 | |
| mod impls;
 | |
| mod reflect_value;
 | |
| mod registration;
 | |
| mod trait_reflection;
 | |
| mod type_uuid;
 | |
| mod utility;
 | |
| 
 | |
| use crate::derive_data::{ReflectDerive, ReflectMeta, ReflectStruct};
 | |
| use proc_macro::TokenStream;
 | |
| use quote::quote;
 | |
| use reflect_value::ReflectValueDef;
 | |
| use syn::spanned::Spanned;
 | |
| use syn::{parse_macro_input, DeriveInput};
 | |
| 
 | |
| pub(crate) static REFLECT_ATTRIBUTE_NAME: &str = "reflect";
 | |
| pub(crate) static REFLECT_VALUE_ATTRIBUTE_NAME: &str = "reflect_value";
 | |
| 
 | |
| #[proc_macro_derive(Reflect, attributes(reflect, reflect_value, module))]
 | |
| pub fn derive_reflect(input: TokenStream) -> TokenStream {
 | |
|     let ast = parse_macro_input!(input as DeriveInput);
 | |
| 
 | |
|     let derive_data = match ReflectDerive::from_input(&ast) {
 | |
|         Ok(data) => data,
 | |
|         Err(err) => return err.into_compile_error().into(),
 | |
|     };
 | |
| 
 | |
|     match derive_data {
 | |
|         ReflectDerive::Struct(struct_data) | ReflectDerive::UnitStruct(struct_data) => {
 | |
|             impls::impl_struct(&struct_data)
 | |
|         }
 | |
|         ReflectDerive::TupleStruct(struct_data) => impls::impl_tuple_struct(&struct_data),
 | |
|         ReflectDerive::Enum(meta) => impls::impl_enum(&meta),
 | |
|         ReflectDerive::Value(meta) => impls::impl_value(&meta),
 | |
|     }
 | |
| }
 | |
| 
 | |
| /// Derives the `FromReflect` trait.
 | |
| ///
 | |
| /// This macro supports the following field attributes:
 | |
| /// * `#[reflect(ignore)]`: Ignores the field. This requires the field to implement [`Default`].
 | |
| /// * `#[reflect(default)]`: If the field's value cannot be read, uses its [`Default`] implementation.
 | |
| /// * `#[reflect(default = "some_func")]`: If the field's value cannot be read, uses the function with the given name.
 | |
| ///
 | |
| #[proc_macro_derive(FromReflect, attributes(reflect))]
 | |
| pub fn derive_from_reflect(input: TokenStream) -> TokenStream {
 | |
|     let ast = parse_macro_input!(input as DeriveInput);
 | |
| 
 | |
|     let derive_data = match ReflectDerive::from_input(&ast) {
 | |
|         Ok(data) => data,
 | |
|         Err(err) => return err.into_compile_error().into(),
 | |
|     };
 | |
| 
 | |
|     match derive_data {
 | |
|         ReflectDerive::Struct(struct_data) | ReflectDerive::UnitStruct(struct_data) => {
 | |
|             from_reflect::impl_struct(&struct_data)
 | |
|         }
 | |
|         ReflectDerive::TupleStruct(struct_data) => from_reflect::impl_tuple_struct(&struct_data),
 | |
|         ReflectDerive::Enum(meta) => from_reflect::impl_enum(&meta),
 | |
|         ReflectDerive::Value(meta) => from_reflect::impl_value(&meta),
 | |
|     }
 | |
| }
 | |
| 
 | |
| // From https://github.com/randomPoison/type-uuid
 | |
| #[proc_macro_derive(TypeUuid, attributes(uuid))]
 | |
| pub fn derive_type_uuid(input: TokenStream) -> TokenStream {
 | |
|     type_uuid::type_uuid_derive(input)
 | |
| }
 | |
| 
 | |
| #[proc_macro_attribute]
 | |
| pub fn reflect_trait(args: TokenStream, input: TokenStream) -> TokenStream {
 | |
|     trait_reflection::reflect_trait(&args, input)
 | |
| }
 | |
| 
 | |
| #[proc_macro]
 | |
| pub fn impl_reflect_value(input: TokenStream) -> TokenStream {
 | |
|     let def = parse_macro_input!(input as ReflectValueDef);
 | |
|     let meta = ReflectMeta::new(
 | |
|         &def.type_name,
 | |
|         &def.generics,
 | |
|         def.traits.unwrap_or_default(),
 | |
|     );
 | |
| 
 | |
|     #[cfg(feature = "documentation")]
 | |
|     let meta = meta.with_docs(documentation::Documentation::from_attributes(&def.attrs));
 | |
| 
 | |
|     impls::impl_value(&meta)
 | |
| }
 | |
| 
 | |
| /// A replacement for `#[derive(Reflect)]` to be used with foreign types which
 | |
| /// the definitions of cannot be altered.
 | |
| ///
 | |
| /// This macro is an alternative to [`impl_reflect_value!`] and [`impl_from_reflect_value!`]
 | |
| /// which implement foreign types as Value types. Note that there is no `impl_from_reflect_struct`,
 | |
| /// as this macro will do the job of both. This macro implements them as `Struct` types,
 | |
| /// which have greater functionality. The type being reflected must be in scope, as you cannot
 | |
| /// qualify it in the macro as e.g. `bevy::prelude::Vec3`.
 | |
| ///
 | |
| /// It may be necessary to add `#[reflect(Default)]` for some types, specifically non-constructible
 | |
| /// foreign types. Without `Default` reflected for such types, you will usually get an arcane
 | |
| /// error message and fail to compile. If the type does not implement `Default`, it may not
 | |
| /// be possible to reflect without extending the macro.
 | |
| ///
 | |
| /// # Example
 | |
| /// Implementing `Reflect` for `bevy::prelude::Vec3` as a struct type:
 | |
| /// ```ignore
 | |
| /// use bevy::prelude::Vec3;
 | |
| ///
 | |
| /// impl_reflect_struct!(
 | |
| ///    #[reflect(PartialEq, Serialize, Deserialize, Default)]
 | |
| ///    struct Vec3 {
 | |
| ///        x: f32,
 | |
| ///        y: f32,
 | |
| ///        z: f32
 | |
| ///    }
 | |
| /// );
 | |
| /// ```
 | |
| #[proc_macro]
 | |
| pub fn impl_reflect_struct(input: TokenStream) -> TokenStream {
 | |
|     let ast = parse_macro_input!(input as DeriveInput);
 | |
|     let derive_data = match ReflectDerive::from_input(&ast) {
 | |
|         Ok(data) => data,
 | |
|         Err(err) => return err.into_compile_error().into(),
 | |
|     };
 | |
| 
 | |
|     match derive_data {
 | |
|         ReflectDerive::Struct(struct_data) => {
 | |
|             let impl_struct: proc_macro2::TokenStream = impls::impl_struct(&struct_data).into();
 | |
|             let impl_from_struct: proc_macro2::TokenStream =
 | |
|                 from_reflect::impl_struct(&struct_data).into();
 | |
| 
 | |
|             TokenStream::from(quote! {
 | |
|                 #impl_struct
 | |
| 
 | |
|                 #impl_from_struct
 | |
|             })
 | |
|         }
 | |
|         ReflectDerive::TupleStruct(..) => syn::Error::new(
 | |
|             ast.span(),
 | |
|             "impl_reflect_struct does not support tuple structs",
 | |
|         )
 | |
|         .into_compile_error()
 | |
|         .into(),
 | |
|         ReflectDerive::UnitStruct(..) => syn::Error::new(
 | |
|             ast.span(),
 | |
|             "impl_reflect_struct does not support unit structs",
 | |
|         )
 | |
|         .into_compile_error()
 | |
|         .into(),
 | |
|         _ => syn::Error::new(ast.span(), "impl_reflect_struct only supports structs")
 | |
|             .into_compile_error()
 | |
|             .into(),
 | |
|     }
 | |
| }
 | |
| 
 | |
| #[proc_macro]
 | |
| pub fn impl_from_reflect_value(input: TokenStream) -> TokenStream {
 | |
|     let def = parse_macro_input!(input as ReflectValueDef);
 | |
|     from_reflect::impl_value(&ReflectMeta::new(
 | |
|         &def.type_name,
 | |
|         &def.generics,
 | |
|         def.traits.unwrap_or_default(),
 | |
|     ))
 | |
| }
 |