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