From 7383302c339c88c6753121046d8368e3572f816e Mon Sep 17 00:00:00 2001 From: makspll Date: Sat, 15 Mar 2025 11:40:18 +0000 Subject: [PATCH 1/2] feat!: Re-design `GetTypeDependencies` & support more complex types as script arguments --- .../src/bindings/function/arg_meta.rs | 6 +- .../src/bindings/function/from.rs | 19 ++ .../src/bindings/function/into.rs | 25 +-- .../src/bindings/function/mod.rs | 40 ++-- .../bindings/function/type_dependencies.rs | 184 +++++++++++++----- .../src/private/mod.rs | 25 +-- .../src/derive/get_type_dependencies.rs | 162 +++++++++++++++ .../src/derive/mod.rs | 2 + crates/bevy_mod_scripting_derive/src/lib.rs | 19 ++ 9 files changed, 381 insertions(+), 101 deletions(-) create mode 100644 crates/bevy_mod_scripting_derive/src/derive/get_type_dependencies.rs diff --git a/crates/bevy_mod_scripting_core/src/bindings/function/arg_meta.rs b/crates/bevy_mod_scripting_core/src/bindings/function/arg_meta.rs index c5cab1da8c..165ee33f4f 100644 --- a/crates/bevy_mod_scripting_core/src/bindings/function/arg_meta.rs +++ b/crates/bevy_mod_scripting_core/src/bindings/function/arg_meta.rs @@ -3,8 +3,8 @@ use std::{ffi::OsString, path::PathBuf}; use crate::{ - bindings::{ScriptValue, ReflectReference}, - docgen::TypedThrough, + bindings::{ReflectReference, ScriptValue}, + docgen::TypedThrough, error::InteropError, }; use super::{ @@ -77,6 +77,8 @@ impl ArgMeta for Val {} impl ArgMeta for Ref<'_, T> {} impl ArgMeta for Mut<'_, T> {} +impl ArgMeta for Result {} + impl ArgMeta for Option { fn default_value() -> Option { Some(ScriptValue::Unit) diff --git a/crates/bevy_mod_scripting_core/src/bindings/function/from.rs b/crates/bevy_mod_scripting_core/src/bindings/function/from.rs index bc46ae2b66..98c9422020 100644 --- a/crates/bevy_mod_scripting_core/src/bindings/function/from.rs +++ b/crates/bevy_mod_scripting_core/src/bindings/function/from.rs @@ -469,6 +469,17 @@ where pub struct Union(Result); impl Union { + /// Create a new union with the left value. + pub fn new_left(value: T1) -> Self { + Union(Ok(value)) + } + + /// Create a new union with the right value. + pub fn new_right(value: T2) -> Self { + Union(Err(value)) + } + + /// Try interpret the union as the left type pub fn into_left(self) -> Result { match self.0 { @@ -484,6 +495,14 @@ impl Union { Ok(l) => Err(l), } } + + /// Map the union to another type + pub fn map_both U1, G: Fn(T2) -> U2>(self, f: F, g: G) -> Union { + match self.0 { + Ok(t) => Union(Ok(f(t))), + Err(t) => Union(Err(g(t))), + } + } } impl FromScript for Union diff --git a/crates/bevy_mod_scripting_core/src/bindings/function/into.rs b/crates/bevy_mod_scripting_core/src/bindings/function/into.rs index 210e847b42..a841ad714c 100644 --- a/crates/bevy_mod_scripting_core/src/bindings/function/into.rs +++ b/crates/bevy_mod_scripting_core/src/bindings/function/into.rs @@ -3,8 +3,8 @@ use std::{borrow::Cow, collections::HashMap, ffi::OsString, path::PathBuf}; use bevy::reflect::Reflect; -use crate::{bindings::{ReflectReference, ScriptValue, WorldGuard}, error::InteropError, private::self_type_dependency_only}; -use super::{DynamicScriptFunction, DynamicScriptFunctionMut, Val}; +use crate::{bindings::{ReflectReference, ScriptValue, WorldGuard}, error::InteropError}; +use super::{DynamicScriptFunction, DynamicScriptFunctionMut, Union, Val}; /// Converts a value into a [`ScriptValue`]. pub trait IntoScript { @@ -26,14 +26,13 @@ impl IntoScript for ScriptValue { } } -self_type_dependency_only!(ScriptValue); impl IntoScript for () { fn into_script(self, _world: WorldGuard) -> Result { Ok(ScriptValue::Unit) } } -self_type_dependency_only!(()); + impl IntoScript for DynamicScriptFunctionMut { fn into_script(self, _world: WorldGuard) -> Result { @@ -47,14 +46,12 @@ impl IntoScript for DynamicScriptFunction { } } -self_type_dependency_only!(DynamicScriptFunctionMut, DynamicScriptFunction); impl IntoScript for bool { fn into_script(self, _world: WorldGuard) -> Result { Ok(ScriptValue::Bool(self)) } } -self_type_dependency_only!(bool); macro_rules! impl_into_with_downcast { ($variant:tt as $cast:ty [$($ty:ty),*]) => { @@ -71,9 +68,7 @@ macro_rules! impl_into_with_downcast { impl_into_with_downcast!(Integer as i64 [i8, i16, i32, i64, i128, u8, u16, u32, u64, u128, usize, isize]); impl_into_with_downcast!(Float as f64 [f32, f64]); -self_type_dependency_only!( - i8, i16, i32, i64, i128, u8, u16, u32, u64, u128, usize, isize, f32, f64 -); + macro_rules! impl_into_stringlike { ($id:ident,[ $(($ty:ty => $conversion:expr)),*]) => { @@ -99,7 +94,6 @@ impl_into_stringlike!( ] ); -self_type_dependency_only!(String, char, PathBuf, OsString); impl IntoScript for &'static str { fn into_script(self, _world: WorldGuard) -> Result { @@ -107,7 +101,7 @@ impl IntoScript for &'static str { } } -self_type_dependency_only!(&'static str); + impl IntoScript for ReflectReference { fn into_script(self, _world: WorldGuard) -> Result { @@ -156,6 +150,15 @@ impl IntoScript for [T; N] { } } +impl IntoScript for Union { + fn into_script(self, world: WorldGuard) -> Result { + match self.into_left() { + Ok(left) => left.into_script(world), + Err(right) => right.into_script(world), + } + } +} + impl IntoScript for HashMap { fn into_script(self, world: WorldGuard) -> Result { let mut map = HashMap::new(); diff --git a/crates/bevy_mod_scripting_core/src/bindings/function/mod.rs b/crates/bevy_mod_scripting_core/src/bindings/function/mod.rs index 9a6d3c5ce8..e32f3145c4 100644 --- a/crates/bevy_mod_scripting_core/src/bindings/function/mod.rs +++ b/crates/bevy_mod_scripting_core/src/bindings/function/mod.rs @@ -17,17 +17,13 @@ mod test { use bevy::reflect::{FromReflect, GetTypeRegistration, Reflect, Typed}; use bevy_mod_scripting_derive::script_bindings; - use crate::{ - bindings::{ + use crate::bindings::{ function::{ from::{Ref, Union, Val}, namespace::IntoNamespace, script_function::AppScriptFunctionRegistry, - }, - script_value::ScriptValue, - }, - docgen::typed_through::TypedThrough, - }; + }, script_value::ScriptValue + }; use super::arg_meta::{ScriptArgument, ScriptReturn, TypedScriptArgument, TypedScriptReturn}; @@ -137,10 +133,20 @@ mod test { test_is_valid_arg::>(); } + fn test_union() + where + T: TypedScriptArgument + TypedScriptReturn, + T::Underlying: FromReflect + Typed + GetTypeRegistration, + for<'a> T::This<'a>: Into, + { + test_is_valid_arg_and_return::>(); + test_is_valid_arg_and_return::>>(); + } + fn test_array() where - T: ScriptArgument + ScriptReturn, - T: GetTypeRegistration + FromReflect + TypedThrough + Typed, + T: TypedScriptArgument + TypedScriptReturn + 'static, + T::Underlying: FromReflect + Typed + GetTypeRegistration, for<'a> T::This<'a>: Into, { test_is_valid_arg_and_return::<[T; N]>(); @@ -148,8 +154,8 @@ mod test { fn test_tuple() where - T: ScriptArgument + ScriptReturn, - T: GetTypeRegistration + FromReflect + TypedThrough + Typed, + T: TypedScriptArgument + TypedScriptReturn + 'static, + T::Underlying: FromReflect + Typed + GetTypeRegistration, for<'a> T::This<'a>: Into, { test_is_valid_arg_and_return::<()>(); @@ -160,8 +166,8 @@ mod test { fn test_option() where - T: ScriptArgument + ScriptReturn, - T: GetTypeRegistration + FromReflect + Typed + TypedThrough, + T: TypedScriptArgument + TypedScriptReturn, + T::Underlying: FromReflect + Typed + GetTypeRegistration, for<'a> T::This<'a>: Into, { test_is_valid_arg_and_return::>(); @@ -169,8 +175,8 @@ mod test { fn test_vec() where - T: ScriptArgument + ScriptReturn, - T: GetTypeRegistration + FromReflect + Typed + TypedThrough, + T: TypedScriptArgument + TypedScriptReturn + 'static, + T::Underlying: FromReflect + Typed + GetTypeRegistration, for<'a> T::This<'a>: Into, { test_is_valid_arg_and_return::>(); @@ -178,8 +184,8 @@ mod test { fn test_hashmap() where - V: ScriptArgument + ScriptReturn, - V: GetTypeRegistration + FromReflect + Typed + TypedThrough, + V: TypedScriptArgument + TypedScriptReturn + 'static, + V::Underlying: FromReflect + Typed + GetTypeRegistration + Eq, for<'a> V::This<'a>: Into, { test_is_valid_arg_and_return::>(); diff --git a/crates/bevy_mod_scripting_core/src/bindings/function/type_dependencies.rs b/crates/bevy_mod_scripting_core/src/bindings/function/type_dependencies.rs index 3d55f553cc..0bc1bf0a3f 100644 --- a/crates/bevy_mod_scripting_core/src/bindings/function/type_dependencies.rs +++ b/crates/bevy_mod_scripting_core/src/bindings/function/type_dependencies.rs @@ -2,73 +2,159 @@ use super::{ from::{Mut, Ref, Union, Val}, - script_function::FunctionCallContext, + script_function::FunctionCallContext, DynamicScriptFunction, DynamicScriptFunctionMut, }; use crate::{ - bindings::{ReflectReference, WorldGuard}, - error::InteropError, private::{no_type_dependencies, self_type_dependency_only}, -}; + bindings::{ReflectReference, ScriptValue}, error::InteropError} +; use bevy::reflect::{FromReflect, GetTypeRegistration, TypeRegistry, Typed}; -use std::collections::HashMap; -use std::hash::Hash; +use bevy_mod_scripting_derive::impl_get_type_dependencies; +use std::{collections::HashMap, ffi::OsString, hash::Hash, path::PathBuf}; + + + +macro_rules! impl_get_type_dependencies_primitives { + ($($ty:ty),*) => { + $( + impl_get_type_dependencies!( + #[derive(GetTypeDependencies)] + #[get_type_dependencies(bms_core_path="crate")] + struct $ty where {} + ); + )* + }; +} + +impl_get_type_dependencies_primitives!( + i8, i16, i32, i64, i128, u8, u16, u32, u64, u128, usize, isize, f32, f64, bool, + ScriptValue, DynamicScriptFunction, DynamicScriptFunctionMut, InteropError, + String, PathBuf, OsString, char +); + + +impl GetTypeDependencies for () { + type Underlying = (); + fn register_type_dependencies(registry: &mut TypeRegistry) { + registry.register::<()>(); + } +} + +impl GetTypeDependencies for &'static str { + type Underlying = &'static str; + fn register_type_dependencies(registry: &mut TypeRegistry) { + registry.register::<&'static str>(); + } +} /// Functionally identical to [`GetTypeRegistration`] but without the 'static bound pub trait GetTypeDependencies { + /// In the majority of the implementations, this will be `Self` + /// However some types might be `facades` for other types, in which case this will be the underlying type + type Underlying; + /// Registers the type dependencies of the implementing type with the given [`TypeRegistry`]. fn register_type_dependencies(registry: &mut TypeRegistry); } +impl_get_type_dependencies!( + #[derive(GetTypeDependencies)] + #[get_type_dependencies(bms_core_path="crate")] + struct HashMap where + K::Underlying: FromReflect + Eq + Hash + Typed, + V::Underlying: FromReflect + Typed {} +); -macro_rules! recursive_type_dependencies { - ($( ($path:ty where $($bound:ident : $($bound_val:path);*),* $(,,const $const:ident : $const_ty:ty)? $(=> with $self_:ident)?) ),* ) => { - $( - impl<$($bound : $($bound_val +)*),* , $(const $const : $const_ty )?> GetTypeDependencies for $path { - fn register_type_dependencies(registry: &mut TypeRegistry) { - $( - registry.register::<$bound>(); - )* - $( - registry.register::<$self_>(); - )? - } - } - )* - }; +impl_get_type_dependencies!( + #[derive(GetTypeDependencies)] + #[get_type_dependencies(bms_core_path="crate")] + struct Result where + T::Underlying: FromReflect + Typed, + E::Underlying: FromReflect + Typed {} +); + +impl_get_type_dependencies!( + #[derive(GetTypeDependencies)] + #[get_type_dependencies(bms_core_path="crate")] + struct Option where + T::Underlying: FromReflect + Typed {} +); + +impl_get_type_dependencies!( + #[derive(GetTypeDependencies)] + #[get_type_dependencies(bms_core_path="crate")] + struct Vec where + T::Underlying: FromReflect + Typed {} +); + + +impl_get_type_dependencies!( + #[derive(GetTypeDependencies)] + #[get_type_dependencies(bms_core_path="crate", underlying="Result")] + struct Union where + T1::Underlying: FromReflect + Typed, + T2::Underlying: FromReflect + Typed {} +); + +impl_get_type_dependencies!( + #[derive(GetTypeDependencies)] + #[get_type_dependencies(bms_core_path="crate", underlying="T", dont_recurse)] + struct Val {} +); + +impl_get_type_dependencies!( + #[derive(GetTypeDependencies)] + #[get_type_dependencies(bms_core_path="crate", underlying="T", dont_recurse)] + struct Ref<'a, T> {} +); + +impl_get_type_dependencies!( + #[derive(GetTypeDependencies)] + #[get_type_dependencies(bms_core_path="crate", underlying="T", dont_recurse)] + struct Mut<'a, T> {} +); + +impl_get_type_dependencies!( + #[derive(GetTypeDependencies)] + #[get_type_dependencies(bms_core_path="crate")] + struct ReflectReference where {} +); + +impl_get_type_dependencies!( + #[derive(GetTypeDependencies)] + #[get_type_dependencies(bms_core_path="crate")] + struct FunctionCallContext where {} +); + + +impl GetTypeDependencies for [T; N] where + T: GetTypeDependencies, + T::Underlying: FromReflect + Typed, +{ + type Underlying = [T::Underlying; N]; + fn register_type_dependencies(registry: &mut TypeRegistry) { + T::register_type_dependencies(registry); + } } macro_rules! register_tuple_dependencies { - ($($ty:ident),*) => { - impl<$($ty: GetTypeRegistration + Typed),*> GetTypeDependencies for ($($ty,)*) { + ($($param:ident),*) => { + impl <$($param),*> $crate::bindings::GetTypeDependencies for ($($param,)*) where + $( + $param: GetTypeDependencies, + <$param>::Underlying: FromReflect + Typed + GetTypeRegistration, + )* + { + type Underlying = ($(<$param as GetTypeDependencies>::Underlying,)*); fn register_type_dependencies(registry: &mut TypeRegistry) { $( - registry.register::<$ty>(); + registry.register::<<$param>::Underlying>(); + <$param>::register_type_dependencies(registry); )* } } }; } -no_type_dependencies!(InteropError); -no_type_dependencies!(WorldGuard<'static>); -self_type_dependency_only!(FunctionCallContext, ReflectReference); - -recursive_type_dependencies!( - (Val where T: GetTypeRegistration), - (Ref<'_, T> where T: GetTypeRegistration), - (Mut<'_, T> where T: GetTypeRegistration), - (Result where T: GetTypeRegistration), - ([T; N] where T: GetTypeRegistration;Typed,, const N: usize => with Self), - (Option where T: GetTypeRegistration;FromReflect;Typed => with Self), - (Vec where T: GetTypeRegistration;FromReflect;Typed => with Self), - (HashMap where K: GetTypeRegistration;FromReflect;Typed;Hash;Eq, V: GetTypeRegistration;FromReflect;Typed => with Self) -); - -impl GetTypeDependencies for Union { - fn register_type_dependencies(registry: &mut TypeRegistry) { - T1::register_type_dependencies(registry); - T2::register_type_dependencies(registry); - } -} bevy::utils::all_tuples!(register_tuple_dependencies, 1, 14, T); @@ -80,8 +166,12 @@ pub trait GetFunctionTypeDependencies { macro_rules! impl_script_function_type_dependencies{ ($( $param:ident ),* ) => { - impl GetFunctionTypeDependencies O> for F - where F: Fn( $( $param ),* ) -> O + impl GetFunctionTypeDependencies O> for F where + O: GetTypeDependencies, + F: Fn( $( $param ),* ) -> O, + $( + $param: GetTypeDependencies, + )* { fn register_type_dependencies(registry: &mut TypeRegistry) { $( diff --git a/crates/bevy_mod_scripting_core/src/private/mod.rs b/crates/bevy_mod_scripting_core/src/private/mod.rs index 12e2b78a90..7486edb66d 100644 --- a/crates/bevy_mod_scripting_core/src/private/mod.rs +++ b/crates/bevy_mod_scripting_core/src/private/mod.rs @@ -11,28 +11,5 @@ macro_rules! export_all_in_modules { }; } -/// A macro for implementing [`GetTypeDependencies`] for types with no type dependencies. -macro_rules! no_type_dependencies { - ($($path:path),*) => { - $( - impl $crate::bindings::function::type_dependencies::GetTypeDependencies for $path { - fn register_type_dependencies(_registry: &mut bevy::reflect::TypeRegistry) {} - } - )* - }; -} - -/// A macro for implementing [`GetTypeDependencies`] for types that only depend on themselves. -macro_rules! self_type_dependency_only { - ($($path:ty),*) => { - $( - impl $crate::bindings::function::type_dependencies::GetTypeDependencies for $path { - fn register_type_dependencies(registry: &mut bevy::reflect::TypeRegistry) { - registry.register::<$path>(); - } - } - )* - }; -} -pub(crate) use {export_all_in_modules, no_type_dependencies, self_type_dependency_only}; +pub(crate) use export_all_in_modules; diff --git a/crates/bevy_mod_scripting_derive/src/derive/get_type_dependencies.rs b/crates/bevy_mod_scripting_derive/src/derive/get_type_dependencies.rs new file mode 100644 index 0000000000..08d1d7cadb --- /dev/null +++ b/crates/bevy_mod_scripting_derive/src/derive/get_type_dependencies.rs @@ -0,0 +1,162 @@ +use proc_macro2::TokenStream; +use quote::{quote_spanned, ToTokens}; +use syn::{parse_quote, parse_quote_spanned, DeriveInput, WhereClause}; + + + + +/// Generate a GetTypeDependencies impl like below: +/// For type: +/// +/// ```rust,ignore +/// #[derive(GetTypeDependencies)] +/// #[get_type_dependencies(remote)] +/// struct TargetType{ +/// ... +/// } +/// ``` +/// +/// ```rust,ignore +/// impl GetTypeDependencies for TargetType +/// where +/// T1: GetTypeDependencies, +/// T2: GetTypeDependencies, +/// T1::Underlying: bevy::reflect::GetTypeRegistration + CustomBoundsT1, +/// T2::Underlying: bevy::reflect::GetTypeRegistration + CustomBoundsT2, +/// { +/// type Underlying = TargetType; +/// pub fn get_type_dependencies(registry: &mut bevy::reflect::TypeRegistry) { +/// T1::get_type_dependencies(registry); +/// T2::get_type_dependencies(registry); +/// +/// registry.register::>(); +/// } +/// } +/// ``` +fn get_type_dependencies_from_input(derive_input: DeriveInput) -> TokenStream { + let args = match Args::parse(&derive_input.attrs) { + Ok(args) => args, + Err(error) => return error.to_compile_error(), + }; + + let bms_core = &args.bms_core_path; + + + + let (impl_generics, type_generics, impl_where) = derive_input.generics.split_for_impl(); + + + let name = &derive_input.ident; + + + let generic_names = derive_input.generics.type_params().map(|param| ¶m.ident).collect::>(); + + let type_generics_underlying = if generic_names.is_empty() { + Default::default() + } else { + quote_spanned! {derive_input.ident.span()=> + <#( #generic_names::Underlying ),*> + } + }; + + let underlying = if let Some(underlying) = args.underlying { + underlying.to_token_stream() + } else { + quote_spanned! {derive_input.ident.span()=> + #name #type_generics_underlying + } + }; + + let mut impl_where: WhereClause = impl_where.cloned().unwrap_or_else(|| parse_quote!{where}); + let mut recursive_registrations = Vec::default(); + for param in derive_input.generics.type_params() { + let param_name = ¶m.ident; + if !args.dont_recurse { + impl_where.predicates.push( + parse_quote_spanned!(param.ident.span()=> #param_name: GetTypeDependencies), + ); + recursive_registrations.push( + quote_spanned! {param.ident.span()=> + <#param_name as GetTypeDependencies>::register_type_dependencies(registry); + } + ); + + impl_where.predicates.push( + parse_quote_spanned!(param.ident.span()=> #param_name::Underlying: bevy::reflect::GetTypeRegistration), + ); + } else { + impl_where.predicates.push( + parse_quote_spanned!(param.ident.span()=> #param_name: bevy::reflect::GetTypeRegistration), + ) + } + } + + + quote_spanned! {derive_input.ident.span()=> + #[automatically_derived] + #[allow(clippy::needless_lifetimes)] + impl #impl_generics #bms_core::bindings::GetTypeDependencies for #name #type_generics #impl_where + { + type Underlying = #underlying; + fn register_type_dependencies(registry: &mut bevy::reflect::TypeRegistry) { + #(#recursive_registrations)* + + registry.register::<#underlying>(); + } + } + } +} + +pub fn get_type_dependencies(input: TokenStream) -> TokenStream { + let derive_input: DeriveInput = match syn::parse2(input) { + Ok(input) => input, + Err(e) => return e.into_compile_error(), + }; + + get_type_dependencies_from_input(derive_input) +} + + + + +struct Args { + bms_core_path: syn::Path, + underlying: Option, + dont_recurse: bool, + // bounds: Vec, +} + +impl Args { + fn parse(attrs: &[syn::Attribute]) -> syn::Result { + let mut bms_core_path = parse_quote!(bevy_mod_scripting_core); + let mut underlying = None; + let mut dont_recurse = false; + + for attr in attrs { + // find attr with name `get_type_dependencies` + // then parse its meta + if attr.path().is_ident("get_type_dependencies") { + attr.parse_nested_meta(|meta| { + if meta.path.is_ident("bms_core_path") { + let value = meta.value()?; + let string: syn::LitStr = value.parse()?; + bms_core_path = string.parse()?; + Ok(()) + } else if meta.path.is_ident("underlying") { + let value = meta.value()?; + let string: syn::LitStr = value.parse()?; + underlying = Some(string.parse()?); + Ok(()) + } else if meta.path.is_ident("dont_recurse") { + dont_recurse = true; + Ok(()) + } else { + Err(syn::Error::new_spanned(meta.path, "unknown attribute, allowed: bms_core_path, underlying")) + } + })?; + } + } + + Ok(Self { bms_core_path, underlying, dont_recurse }) + } +} \ No newline at end of file diff --git a/crates/bevy_mod_scripting_derive/src/derive/mod.rs b/crates/bevy_mod_scripting_derive/src/derive/mod.rs index 9c55d9f3d2..9fcb9d7aa2 100644 --- a/crates/bevy_mod_scripting_derive/src/derive/mod.rs +++ b/crates/bevy_mod_scripting_derive/src/derive/mod.rs @@ -2,6 +2,7 @@ mod into_script; mod script_bindings; mod script_globals; mod typed_through; +mod get_type_dependencies; use proc_macro2::{Span, TokenStream}; use quote::{quote_spanned, ToTokens}; @@ -10,6 +11,7 @@ use syn::{Ident, ImplItemFn, ItemImpl}; pub use self::{ into_script::into_script, script_bindings::script_bindings, script_globals::script_globals, typed_through::typed_through, + get_type_dependencies::get_type_dependencies }; pub(crate) fn impl_fn_to_namespace_builder_registration(fun: &ImplItemFn) -> TokenStream { diff --git a/crates/bevy_mod_scripting_derive/src/lib.rs b/crates/bevy_mod_scripting_derive/src/lib.rs index c453a096f4..18753b3d91 100644 --- a/crates/bevy_mod_scripting_derive/src/lib.rs +++ b/crates/bevy_mod_scripting_derive/src/lib.rs @@ -2,6 +2,8 @@ mod derive; + + #[proc_macro_derive(TypedThrough)] /// Default implementation for the `TypedThrough` trait pub fn typed_through(input: proc_macro::TokenStream) -> proc_macro::TokenStream { @@ -49,3 +51,20 @@ pub fn script_globals( ) -> proc_macro::TokenStream { derive::script_globals(args, input) } + +/// Derive macro for generating `GetTypeDependencies` implementations. +#[proc_macro_derive(GetTypeDependencies, attributes(get_type_dependencies))] +pub fn get_type_dependencies( + input: proc_macro::TokenStream, +) -> proc_macro::TokenStream { + derive::get_type_dependencies(input.into()).into() +} + +/// Proc macro equivalent of `GetTypeDependencies` which does not generate a type, purely the impl. +/// Useful for generating implementations against remote types. +#[proc_macro] +pub fn impl_get_type_dependencies( + input: proc_macro::TokenStream, +) -> proc_macro::TokenStream { + derive::get_type_dependencies(input.into()).into() +} From 4d70e86b28d3fd59b9f8817409363e801d2272a0 Mon Sep 17 00:00:00 2001 From: makspll Date: Sat, 15 Mar 2025 12:01:59 +0000 Subject: [PATCH 2/2] format --- .../src/private/mod.rs | 1 - .../src/derive/get_type_dependencies.rs | 64 +++++++++---------- .../src/derive/mod.rs | 7 +- crates/bevy_mod_scripting_derive/src/lib.rs | 10 +-- 4 files changed, 36 insertions(+), 46 deletions(-) diff --git a/crates/bevy_mod_scripting_core/src/private/mod.rs b/crates/bevy_mod_scripting_core/src/private/mod.rs index 7486edb66d..0e66f3ef74 100644 --- a/crates/bevy_mod_scripting_core/src/private/mod.rs +++ b/crates/bevy_mod_scripting_core/src/private/mod.rs @@ -11,5 +11,4 @@ macro_rules! export_all_in_modules { }; } - pub(crate) use export_all_in_modules; diff --git a/crates/bevy_mod_scripting_derive/src/derive/get_type_dependencies.rs b/crates/bevy_mod_scripting_derive/src/derive/get_type_dependencies.rs index 08d1d7cadb..82755a1cc0 100644 --- a/crates/bevy_mod_scripting_derive/src/derive/get_type_dependencies.rs +++ b/crates/bevy_mod_scripting_derive/src/derive/get_type_dependencies.rs @@ -2,12 +2,9 @@ use proc_macro2::TokenStream; use quote::{quote_spanned, ToTokens}; use syn::{parse_quote, parse_quote_spanned, DeriveInput, WhereClause}; - - - /// Generate a GetTypeDependencies impl like below: /// For type: -/// +/// /// ```rust,ignore /// #[derive(GetTypeDependencies)] /// #[get_type_dependencies(remote)] @@ -15,9 +12,9 @@ use syn::{parse_quote, parse_quote_spanned, DeriveInput, WhereClause}; /// ... /// } /// ``` -/// +/// /// ```rust,ignore -/// impl GetTypeDependencies for TargetType +/// impl GetTypeDependencies for TargetType /// where /// T1: GetTypeDependencies, /// T2: GetTypeDependencies, @@ -28,7 +25,7 @@ use syn::{parse_quote, parse_quote_spanned, DeriveInput, WhereClause}; /// pub fn get_type_dependencies(registry: &mut bevy::reflect::TypeRegistry) { /// T1::get_type_dependencies(registry); /// T2::get_type_dependencies(registry); -/// +/// /// registry.register::>(); /// } /// } @@ -41,15 +38,15 @@ fn get_type_dependencies_from_input(derive_input: DeriveInput) -> TokenStream { let bms_core = &args.bms_core_path; - - let (impl_generics, type_generics, impl_where) = derive_input.generics.split_for_impl(); - let name = &derive_input.ident; - - - let generic_names = derive_input.generics.type_params().map(|param| ¶m.ident).collect::>(); + + let generic_names = derive_input + .generics + .type_params() + .map(|param| ¶m.ident) + .collect::>(); let type_generics_underlying = if generic_names.is_empty() { Default::default() @@ -67,20 +64,18 @@ fn get_type_dependencies_from_input(derive_input: DeriveInput) -> TokenStream { } }; - let mut impl_where: WhereClause = impl_where.cloned().unwrap_or_else(|| parse_quote!{where}); + let mut impl_where: WhereClause = impl_where.cloned().unwrap_or_else(|| parse_quote! {where}); let mut recursive_registrations = Vec::default(); for param in derive_input.generics.type_params() { let param_name = ¶m.ident; if !args.dont_recurse { - impl_where.predicates.push( - parse_quote_spanned!(param.ident.span()=> #param_name: GetTypeDependencies), - ); - recursive_registrations.push( - quote_spanned! {param.ident.span()=> - <#param_name as GetTypeDependencies>::register_type_dependencies(registry); - } - ); - + impl_where + .predicates + .push(parse_quote_spanned!(param.ident.span()=> #param_name: GetTypeDependencies)); + recursive_registrations.push(quote_spanned! {param.ident.span()=> + <#param_name as GetTypeDependencies>::register_type_dependencies(registry); + }); + impl_where.predicates.push( parse_quote_spanned!(param.ident.span()=> #param_name::Underlying: bevy::reflect::GetTypeRegistration), ); @@ -90,8 +85,7 @@ fn get_type_dependencies_from_input(derive_input: DeriveInput) -> TokenStream { ) } } - - + quote_spanned! {derive_input.ident.span()=> #[automatically_derived] #[allow(clippy::needless_lifetimes)] @@ -112,12 +106,9 @@ pub fn get_type_dependencies(input: TokenStream) -> TokenStream { Ok(input) => input, Err(e) => return e.into_compile_error(), }; - - get_type_dependencies_from_input(derive_input) -} - - + get_type_dependencies_from_input(derive_input) +} struct Args { bms_core_path: syn::Path, @@ -151,12 +142,19 @@ impl Args { dont_recurse = true; Ok(()) } else { - Err(syn::Error::new_spanned(meta.path, "unknown attribute, allowed: bms_core_path, underlying")) + Err(syn::Error::new_spanned( + meta.path, + "unknown attribute, allowed: bms_core_path, underlying", + )) } })?; } } - Ok(Self { bms_core_path, underlying, dont_recurse }) + Ok(Self { + bms_core_path, + underlying, + dont_recurse, + }) } -} \ No newline at end of file +} diff --git a/crates/bevy_mod_scripting_derive/src/derive/mod.rs b/crates/bevy_mod_scripting_derive/src/derive/mod.rs index 9fcb9d7aa2..b0363a2455 100644 --- a/crates/bevy_mod_scripting_derive/src/derive/mod.rs +++ b/crates/bevy_mod_scripting_derive/src/derive/mod.rs @@ -1,17 +1,16 @@ +mod get_type_dependencies; mod into_script; mod script_bindings; mod script_globals; mod typed_through; -mod get_type_dependencies; use proc_macro2::{Span, TokenStream}; use quote::{quote_spanned, ToTokens}; use syn::{Ident, ImplItemFn, ItemImpl}; pub use self::{ - into_script::into_script, script_bindings::script_bindings, script_globals::script_globals, - typed_through::typed_through, - get_type_dependencies::get_type_dependencies + get_type_dependencies::get_type_dependencies, into_script::into_script, + script_bindings::script_bindings, script_globals::script_globals, typed_through::typed_through, }; pub(crate) fn impl_fn_to_namespace_builder_registration(fun: &ImplItemFn) -> TokenStream { diff --git a/crates/bevy_mod_scripting_derive/src/lib.rs b/crates/bevy_mod_scripting_derive/src/lib.rs index 18753b3d91..ed091dc6dc 100644 --- a/crates/bevy_mod_scripting_derive/src/lib.rs +++ b/crates/bevy_mod_scripting_derive/src/lib.rs @@ -2,8 +2,6 @@ mod derive; - - #[proc_macro_derive(TypedThrough)] /// Default implementation for the `TypedThrough` trait pub fn typed_through(input: proc_macro::TokenStream) -> proc_macro::TokenStream { @@ -54,17 +52,13 @@ pub fn script_globals( /// Derive macro for generating `GetTypeDependencies` implementations. #[proc_macro_derive(GetTypeDependencies, attributes(get_type_dependencies))] -pub fn get_type_dependencies( - input: proc_macro::TokenStream, -) -> proc_macro::TokenStream { +pub fn get_type_dependencies(input: proc_macro::TokenStream) -> proc_macro::TokenStream { derive::get_type_dependencies(input.into()).into() } /// Proc macro equivalent of `GetTypeDependencies` which does not generate a type, purely the impl. /// Useful for generating implementations against remote types. #[proc_macro] -pub fn impl_get_type_dependencies( - input: proc_macro::TokenStream, -) -> proc_macro::TokenStream { +pub fn impl_get_type_dependencies(input: proc_macro::TokenStream) -> proc_macro::TokenStream { derive::get_type_dependencies(input.into()).into() }