
# 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`.
92 lines
3.1 KiB
Rust
92 lines
3.1 KiB
Rust
use crate::derive_data::StructField;
|
|
use crate::field_attributes::{DefaultBehavior, ReflectIgnoreBehavior};
|
|
use bevy_macro_utils::fq_std::{FQBox, FQDefault};
|
|
use quote::quote;
|
|
use std::collections::HashMap;
|
|
use syn::spanned::Spanned;
|
|
use syn::Path;
|
|
|
|
type ReflectionIndex = usize;
|
|
|
|
/// Collected serialization data used to generate a `SerializationData` type.
|
|
pub(crate) struct SerializationDataDef {
|
|
/// Maps a field's _reflection_ index to its [`SkippedFieldDef`] if marked as `#[reflect(skip_serializing)]`.
|
|
skipped: HashMap<ReflectionIndex, SkippedFieldDef>,
|
|
}
|
|
|
|
impl SerializationDataDef {
|
|
/// Attempts to create a new `SerializationDataDef` from the given collection of fields.
|
|
///
|
|
/// Returns `Ok(Some(data))` if there are any fields needing to be skipped during serialization.
|
|
/// Otherwise, returns `Ok(None)`.
|
|
pub fn new(fields: &[StructField<'_>]) -> Result<Option<Self>, syn::Error> {
|
|
let mut skipped = HashMap::default();
|
|
|
|
for field in fields {
|
|
match field.attrs.ignore {
|
|
ReflectIgnoreBehavior::IgnoreSerialization => {
|
|
skipped.insert(
|
|
field.reflection_index.ok_or_else(|| {
|
|
syn::Error::new(
|
|
field.data.span(),
|
|
"internal error: field is missing a reflection index",
|
|
)
|
|
})?,
|
|
SkippedFieldDef::new(field)?,
|
|
);
|
|
}
|
|
_ => continue,
|
|
}
|
|
}
|
|
|
|
if skipped.is_empty() {
|
|
Ok(None)
|
|
} else {
|
|
Ok(Some(Self { skipped }))
|
|
}
|
|
}
|
|
|
|
/// Returns a `TokenStream` containing an initialized `SerializationData` type.
|
|
pub fn as_serialization_data(&self, bevy_reflect_path: &Path) -> proc_macro2::TokenStream {
|
|
let fields =
|
|
self.skipped
|
|
.iter()
|
|
.map(|(reflection_index, SkippedFieldDef { default_fn })| {
|
|
quote! {(
|
|
#reflection_index,
|
|
#bevy_reflect_path::serde::SkippedField::new(#default_fn)
|
|
)}
|
|
});
|
|
quote! {
|
|
#bevy_reflect_path::serde::SerializationData::new(
|
|
::core::iter::IntoIterator::into_iter([#(#fields),*])
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Collected field data used to generate a `SkippedField` type.
|
|
pub(crate) struct SkippedFieldDef {
|
|
/// The default function for this field.
|
|
///
|
|
/// This is of type `fn() -> Box<dyn Reflect>`.
|
|
default_fn: proc_macro2::TokenStream,
|
|
}
|
|
|
|
impl SkippedFieldDef {
|
|
pub fn new(field: &StructField<'_>) -> Result<Self, syn::Error> {
|
|
let ty = &field.data.ty;
|
|
|
|
let default_fn = match &field.attrs.default {
|
|
DefaultBehavior::Func(func) => quote! {
|
|
|| { #FQBox::new(#func()) }
|
|
},
|
|
_ => quote! {
|
|
|| { #FQBox::new(<#ty as #FQDefault>::default()) }
|
|
},
|
|
};
|
|
|
|
Ok(Self { default_fn })
|
|
}
|
|
}
|