
# Objective - Some of the "large" crates have sub-crates, usually for things such as macros. - For an example, see [`bevy_ecs_macros` at `bevy_ecs/macros`](4f9f987099/crates/bevy_ecs/macros
). - The one crate that does not follow this convention is [`bevy_reflect_derive`](4f9f987099/crates/bevy_reflect/bevy_reflect_derive
), which is in the `bevy_reflect/bevy_reflect_derive` folder and not `bevy_reflect/derive` or `bevy_reflect/macros`. ## Solution - Rename folder `bevy_reflect_derive` to `derive`. - I chose to use `derive` instead of `macros` because the crate name itself ends in `_derive`. (One of only two crates to actually use this convention, funnily enough.) ## Testing - Build and test `bevy_reflect` and `bevy_reflect_derive`. - Apply the following patch to `publish.sh` to run it in `--dry-run` mode, to test that the path has been successfully updated: - If you have any security concerns about applying random diffs, feel free to skip this step. Worst case scenario it fails and Cart has to manually publish a few crates. ```bash # Apply patch to make `publish.sh` *not* actually publish anything. git apply path/to/foo.patch # Make `publish.sh` executable. chmod +x tools/publish.sh # Execute `publish.sh`. ./tools/publish.sh ``` ```patch diff --git a/tools/publish.sh b/tools/publish.sh index b020bad28..fbcc09281 100644 --- a/tools/publish.sh +++ b/tools/publish.sh @@ -49,7 +49,7 @@ crates=( if [ -n "$(git status --porcelain)" ]; then echo "You have local changes!" - exit 1 + # exit 1 fi pushd crates @@ -61,15 +61,15 @@ do cp ../LICENSE-APACHE "$crate" pushd "$crate" git add LICENSE-MIT LICENSE-APACHE - cargo publish --no-verify --allow-dirty + cargo publish --no-verify --allow-dirty --dry-run popd - sleep 20 + # sleep 20 done popd echo "Publishing root crate" -cargo publish --allow-dirty +cargo publish --allow-dirty --dry-run echo "Cleaning local state" git reset HEAD --hard ``` --- ## Changelog - Moved `bevy_reflect_derive` from `crates/bevy_reflect/bevy_reflect_derive` to `crates/bevy_reflect/derive`.
97 lines
4.2 KiB
Rust
97 lines
4.2 KiB
Rust
use bevy_macro_utils::{
|
|
fq_std::{FQBox, FQClone, FQOption, FQResult},
|
|
BevyManifest,
|
|
};
|
|
use proc_macro::TokenStream;
|
|
use quote::quote;
|
|
use syn::{parse::Parse, parse_macro_input, Attribute, ItemTrait, Token};
|
|
|
|
pub(crate) struct TraitInfo {
|
|
item_trait: ItemTrait,
|
|
}
|
|
|
|
impl Parse for TraitInfo {
|
|
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
|
let attrs = input.call(Attribute::parse_outer)?;
|
|
let lookahead = input.lookahead1();
|
|
if lookahead.peek(Token![pub]) || lookahead.peek(Token![trait]) {
|
|
let mut item_trait: ItemTrait = input.parse()?;
|
|
item_trait.attrs = attrs;
|
|
Ok(TraitInfo { item_trait })
|
|
} else {
|
|
Err(lookahead.error())
|
|
}
|
|
}
|
|
}
|
|
|
|
/// A trait attribute macro that allows a reflected type to be downcast to a trait object.
|
|
///
|
|
/// This generates a struct that takes the form `ReflectMyTrait`. An instance of this struct can then be
|
|
/// used to perform the conversion.
|
|
pub(crate) fn reflect_trait(_args: &TokenStream, input: TokenStream) -> TokenStream {
|
|
let trait_info = parse_macro_input!(input as TraitInfo);
|
|
let item_trait = &trait_info.item_trait;
|
|
let trait_ident = &item_trait.ident;
|
|
let trait_vis = &item_trait.vis;
|
|
let reflect_trait_ident = crate::utility::get_reflect_ident(&item_trait.ident.to_string());
|
|
let bevy_reflect_path = BevyManifest::default().get_path("bevy_reflect");
|
|
|
|
let struct_doc = format!(
|
|
" A type generated by the #[reflect_trait] macro for the `{trait_ident}` trait.\n\n This allows casting from `dyn Reflect` to `dyn {trait_ident}`.",
|
|
);
|
|
let get_doc = format!(
|
|
" Downcast a `&dyn Reflect` type to `&dyn {trait_ident}`.\n\n If the type cannot be downcast, `None` is returned.",
|
|
);
|
|
let get_mut_doc = format!(
|
|
" Downcast a `&mut dyn Reflect` type to `&mut dyn {trait_ident}`.\n\n If the type cannot be downcast, `None` is returned.",
|
|
);
|
|
let get_box_doc = format!(
|
|
" Downcast a `Box<dyn Reflect>` type to `Box<dyn {trait_ident}>`.\n\n If the type cannot be downcast, this will return `Err(Box<dyn Reflect>)`.",
|
|
);
|
|
|
|
TokenStream::from(quote! {
|
|
#item_trait
|
|
|
|
#[doc = #struct_doc]
|
|
#[derive(#FQClone)]
|
|
#trait_vis struct #reflect_trait_ident {
|
|
get_func: fn(&dyn #bevy_reflect_path::Reflect) -> #FQOption<&dyn #trait_ident>,
|
|
get_mut_func: fn(&mut dyn #bevy_reflect_path::Reflect) -> #FQOption<&mut dyn #trait_ident>,
|
|
get_boxed_func: fn(#FQBox<dyn #bevy_reflect_path::Reflect>) -> #FQResult<#FQBox<dyn #trait_ident>, #FQBox<dyn #bevy_reflect_path::Reflect>>,
|
|
}
|
|
|
|
impl #reflect_trait_ident {
|
|
#[doc = #get_doc]
|
|
pub fn get<'a>(&self, reflect_value: &'a dyn #bevy_reflect_path::Reflect) -> #FQOption<&'a dyn #trait_ident> {
|
|
(self.get_func)(reflect_value)
|
|
}
|
|
|
|
#[doc = #get_mut_doc]
|
|
pub fn get_mut<'a>(&self, reflect_value: &'a mut dyn #bevy_reflect_path::Reflect) -> #FQOption<&'a mut dyn #trait_ident> {
|
|
(self.get_mut_func)(reflect_value)
|
|
}
|
|
|
|
#[doc = #get_box_doc]
|
|
pub fn get_boxed(&self, reflect_value: #FQBox<dyn #bevy_reflect_path::Reflect>) -> #FQResult<#FQBox<dyn #trait_ident>, #FQBox<dyn #bevy_reflect_path::Reflect>> {
|
|
(self.get_boxed_func)(reflect_value)
|
|
}
|
|
}
|
|
|
|
impl<T: #trait_ident + #bevy_reflect_path::Reflect> #bevy_reflect_path::FromType<T> for #reflect_trait_ident {
|
|
fn from_type() -> Self {
|
|
Self {
|
|
get_func: |reflect_value| {
|
|
<dyn #bevy_reflect_path::Reflect>::downcast_ref::<T>(reflect_value).map(|value| value as &dyn #trait_ident)
|
|
},
|
|
get_mut_func: |reflect_value| {
|
|
<dyn #bevy_reflect_path::Reflect>::downcast_mut::<T>(reflect_value).map(|value| value as &mut dyn #trait_ident)
|
|
},
|
|
get_boxed_func: |reflect_value| {
|
|
<dyn #bevy_reflect_path::Reflect>::downcast::<T>(reflect_value).map(|value| value as #FQBox<dyn #trait_ident>)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
})
|
|
}
|