@@ -13,8 +13,8 @@ use syn::{
1313 parse_macro_input,
1414 punctuated:: Punctuated ,
1515 token:: { Comma , Paren , Where } ,
16- Data , DataStruct , DeriveInput , Field , Fields , Generics , Ident , Index , Member , Meta , NestedMeta ,
17- Path ,
16+ Attribute , Data , DataStruct , DeriveInput , Field , Fields , Generics , Ident , Index , Member , Meta ,
17+ NestedMeta , Path ,
1818} ;
1919
2020#[ derive( Default ) ]
@@ -45,11 +45,49 @@ enum DeriveType {
4545static REFLECT_ATTRIBUTE_NAME : & str = "reflect" ;
4646static REFLECT_VALUE_ATTRIBUTE_NAME : & str = "reflect_value" ;
4747
48+ fn active_fields ( punctuated : & Punctuated < Field , Comma > ) -> impl Iterator < Item = ( & Field , usize ) > {
49+ punctuated. iter ( ) . enumerate ( ) . filter_map ( |( idx, field) | {
50+ field
51+ . attrs
52+ . iter ( )
53+ . find ( |attr| * attr. path . get_ident ( ) . as_ref ( ) . unwrap ( ) == REFLECT_ATTRIBUTE_NAME )
54+ . map ( |attr| {
55+ syn:: custom_keyword!( ignore) ;
56+ attr. parse_args :: < Option < ignore > > ( )
57+ . expect ( "Invalid 'property' attribute format." )
58+ . is_none ( )
59+ } )
60+ . unwrap_or ( true )
61+ . then ( || ( field, idx) )
62+ } )
63+ }
64+
65+ fn reflect_attrs ( attrs : & [ Attribute ] ) -> ( ReflectAttrs , Option < DeriveType > ) {
66+ for attribute in attrs. iter ( ) . filter_map ( |attr| attr. parse_meta ( ) . ok ( ) ) {
67+ if let Meta :: List ( meta_list) = attribute {
68+ match meta_list. path . get_ident ( ) {
69+ Some ( ident) if ident == REFLECT_ATTRIBUTE_NAME => {
70+ return ( ReflectAttrs :: from_nested_metas ( & meta_list. nested ) , None )
71+ }
72+ Some ( ident) if ident == REFLECT_VALUE_ATTRIBUTE_NAME => {
73+ return (
74+ ReflectAttrs :: from_nested_metas ( & meta_list. nested ) ,
75+ Some ( DeriveType :: Value ) ,
76+ )
77+ }
78+ _ => { }
79+ }
80+ }
81+ }
82+
83+ Default :: default ( )
84+ }
85+
4886#[ proc_macro_derive( Reflect , attributes( reflect, reflect_value, module) ) ]
4987pub fn derive_reflect ( input : TokenStream ) -> TokenStream {
5088 let ast = parse_macro_input ! ( input as DeriveInput ) ;
5189 let unit_struct_punctuated = Punctuated :: new ( ) ;
52- let ( fields, mut derive_type) = match & ast. data {
90+ let ( fields, derive_type) = match & ast. data {
5391 Data :: Struct ( DataStruct {
5492 fields : Fields :: Named ( fields) ,
5593 ..
@@ -65,66 +103,14 @@ pub fn derive_reflect(input: TokenStream) -> TokenStream {
65103 _ => ( & unit_struct_punctuated, DeriveType :: Value ) ,
66104 } ;
67105
68- let fields_and_args = fields
69- . iter ( )
70- . enumerate ( )
71- . map ( |( i, f) | {
72- (
73- f,
74- f. attrs
75- . iter ( )
76- . find ( |a| * a. path . get_ident ( ) . as_ref ( ) . unwrap ( ) == REFLECT_ATTRIBUTE_NAME )
77- . map ( |a| {
78- syn:: custom_keyword!( ignore) ;
79- let mut attribute_args = PropAttributeArgs { ignore : None } ;
80- a. parse_args_with ( |input : ParseStream | {
81- if input. parse :: < Option < ignore > > ( ) ?. is_some ( ) {
82- attribute_args. ignore = Some ( true ) ;
83- return Ok ( ( ) ) ;
84- }
85- Ok ( ( ) )
86- } )
87- . expect ( "Invalid 'property' attribute format." ) ;
88-
89- attribute_args
90- } ) ,
91- i,
92- )
93- } )
94- . collect :: < Vec < ( & Field , Option < PropAttributeArgs > , usize ) > > ( ) ;
95- let active_fields = fields_and_args
96- . iter ( )
97- . filter ( |( _field, attrs, _i) | {
98- attrs. is_none ( )
99- || match attrs. as_ref ( ) . unwrap ( ) . ignore {
100- Some ( ignore) => !ignore,
101- None => true ,
102- }
103- } )
104- . map ( |( f, _attr, i) | ( * f, * i) )
105- . collect :: < Vec < ( & Field , usize ) > > ( ) ;
106+ let active_fields = active_fields ( & fields) . collect :: < Vec < _ > > ( ) ;
107+
108+ let ( reflect_attrs, modified_derive_type) = reflect_attrs ( & ast. attrs ) ;
109+ let derive_type = modified_derive_type. unwrap_or ( derive_type) ;
106110
107111 let bevy_reflect_path = BevyManifest :: default ( ) . get_path ( "bevy_reflect" ) ;
108112 let type_name = & ast. ident ;
109113
110- let mut reflect_attrs = ReflectAttrs :: default ( ) ;
111- for attribute in ast. attrs . iter ( ) . filter_map ( |attr| attr. parse_meta ( ) . ok ( ) ) {
112- let meta_list = if let Meta :: List ( meta_list) = attribute {
113- meta_list
114- } else {
115- continue ;
116- } ;
117-
118- if let Some ( ident) = meta_list. path . get_ident ( ) {
119- if ident == REFLECT_ATTRIBUTE_NAME {
120- reflect_attrs = ReflectAttrs :: from_nested_metas ( & meta_list. nested ) ;
121- } else if ident == REFLECT_VALUE_ATTRIBUTE_NAME {
122- derive_type = DeriveType :: Value ;
123- reflect_attrs = ReflectAttrs :: from_nested_metas ( & meta_list. nested ) ;
124- }
125- }
126- }
127-
128114 let registration_data = & reflect_attrs. data ;
129115 let get_type_registration_impl = impl_get_type_registration (
130116 type_name,
0 commit comments