Skip to content

Commit

Permalink
Cleanup bevy_reflect a bit more
Browse files Browse the repository at this point in the history
  • Loading branch information
nicopap committed Jun 26, 2022
1 parent 0cf2029 commit d4df183
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 24 deletions.
4 changes: 2 additions & 2 deletions crates/bevy_reflect/bevy_reflect_derive/src/enum_utility.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
derive_data::{EnumVariantFields, ReflectEnum},
utility::field_ident_or_indexed,
utility::ident_or_index,
};
use proc_macro2::Ident;
use quote::{quote, ToTokens};
Expand Down Expand Up @@ -36,7 +36,7 @@ pub(crate) fn get_variant_constructors(
};
let mut reflect_index: usize = 0;
let constructor_fields = fields.iter().enumerate().map(|(declar_index, field)| {
let field_ident = field_ident_or_indexed(declar_index, field.data.ident.as_ref());
let field_ident = ident_or_index(field.data.ident.as_ref(), declar_index);
let field_value = if field.attrs.ignore {
quote! { Default::default() }
} else {
Expand Down
33 changes: 14 additions & 19 deletions crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,22 +291,28 @@ fn generate_impls(reflect_enum: &ReflectEnum, ref_index: &Ident, ref_name: &Iden
}
(reflect_idx, constructor_argument)
}
let mut info_type = |variant, info_type, arguments| {
let mut add_fields_branch = |variant, info_type, arguments, field_len| {
let variant = Ident::new(variant, Span::call_site());
let info_type = Ident::new(info_type, Span::call_site());
variant_info.push(quote! {
#bevy_reflect_path::VariantInfo::#variant(
#bevy_reflect_path::#info_type::new(#arguments)
)
});
variant
enum_field_len.push(quote! {
#unit{..} => #field_len
});
enum_variant_name.push(quote! {
#unit{..} => #name
});
enum_variant_type.push(quote! {
#unit{..} => #bevy_reflect_path::VariantType::#variant
});
};
let (variant, field_len) = match &variant.fields {
match &variant.fields {
EnumVariantFields::Unit => {
let variant = info_type("Unit", "UnitVariantInfo", quote!(#name));
(variant, 0usize)
add_fields_branch("Unit", "UnitVariantInfo", quote!(#name), 0usize);
}

EnumVariantFields::Unnamed(fields) => {
let (field_len, argument) = for_fields(fields, |reflect_idx, declar, field| {
let declar_field = syn::Index::from(declar);
Expand All @@ -317,8 +323,7 @@ fn generate_impls(reflect_enum: &ReflectEnum, ref_index: &Ident, ref_name: &Iden
quote! { #bevy_reflect_path::UnnamedField::new::<#field_ty>(#reflect_idx) }
});
let arguments = quote!(#name, &[ #(#argument),* ]);
let variant = info_type("Tuple", "TupleVariantInfo", arguments);
(variant, field_len)
add_fields_branch("Tuple", "TupleVariantInfo", arguments, field_len);
}
EnumVariantFields::Named(fields) => {
let (field_len, argument) = for_fields(fields, |reflect_idx, _, field| {
Expand All @@ -341,19 +346,9 @@ fn generate_impls(reflect_enum: &ReflectEnum, ref_index: &Ident, ref_name: &Iden
quote! { #bevy_reflect_path::NamedField::new::<#field_ty, _>(#field_name) }
});
let arguments = quote!(#name, &[ #(#argument),* ]);
let variant = info_type("Struct", "StructVariantInfo", arguments);
(variant, field_len)
add_fields_branch("Struct", "StructVariantInfo", arguments, field_len);
}
};
enum_field_len.push(quote! {
#unit{..} => #field_len
});
enum_variant_name.push(quote! {
#unit{..} => #name
});
enum_variant_type.push(quote! {
#unit{..} => #bevy_reflect_path::VariantType::#variant
});
}

EnumImpls {
Expand Down
25 changes: 22 additions & 3 deletions crates/bevy_reflect/bevy_reflect_derive/src/utility.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,29 @@ pub(crate) struct ResultSifter<T> {
errors: Option<syn::Error>,
}

pub(crate) fn field_ident_or_indexed(index: usize, ident: Option<&Ident>) -> Member {
ident.as_ref().map_or_else(
/// Returns a `Member` made of `ident` or `index` if `ident` is None.
///
/// Rust struct syntax allows for `Struct { foo: "string" }` with explicitly
/// named fields. It allows the `Struct { 0: "string" }` syntax when the struct
/// is declared as a tuple struct.
///
/// ```
/// # fn main() {
/// struct Foo { field: &'static str }
/// struct Bar(&'static str);
/// let Foo { field } = Foo { field: "hi" };
/// let Bar { 0: field } = Bar { 0: "hello" };
/// let Bar(field) = Bar("hello"); // more common syntax
/// # }
/// ```
///
/// This function helps field access in context where you are declaring either
/// a tuple struct or a struct with named fields. If you don't have a field name,
/// it means you need to access the struct through an index.
pub(crate) fn ident_or_index(ident: Option<&Ident>, index: usize) -> Member {
ident.map_or_else(
|| Member::Unnamed(index.into()),
|&ident| Member::Named(ident.clone()),
|ident| Member::Named(ident.clone()),
)
}

Expand Down

0 comments on commit d4df183

Please sign in to comment.