@@ -89,11 +89,10 @@ fn parse_struct_attributes(class: &Struct) -> ParseResult<ClassAttributes> {
89
89
90
90
/// Returns field names and 1 base field, if available
91
91
fn parse_fields ( class : & Struct ) -> ParseResult < Fields > {
92
- let mut all_field_names = vec ! [ ] ;
93
- let mut exported_fields = vec ! [ ] ;
92
+ let mut all_fields = vec ! [ ] ;
94
93
let mut base_field = Option :: < Field > :: None ;
95
94
96
- let fields : Vec < ( NamedField , Punct ) > = match & class. fields {
95
+ let named_fields : Vec < ( NamedField , Punct ) > = match & class. fields {
97
96
StructFields :: Unit => {
98
97
vec ! [ ]
99
98
}
@@ -105,42 +104,50 @@ fn parse_fields(class: &Struct) -> ParseResult<Fields> {
105
104
} ;
106
105
107
106
// Attributes on struct fields
108
- for ( field , _punct) in fields {
107
+ for ( named_field , _punct) in named_fields {
109
108
let mut is_base = false ;
109
+ let mut field = Field :: new ( & named_field) ;
110
110
111
111
// #[base]
112
- if let Some ( parser) = KvParser :: parse ( & field . attributes , "base" ) ? {
113
- if let Some ( prev_base) = base_field {
112
+ if let Some ( parser) = KvParser :: parse ( & named_field . attributes , "base" ) ? {
113
+ if let Some ( prev_base) = base_field. as_ref ( ) {
114
114
bail (
115
115
format ! (
116
- "#[base] allowed for at most 1 field, already applied to '{}' " ,
116
+ "#[base] allowed for at most 1 field, already applied to `{}` " ,
117
117
prev_base. name
118
118
) ,
119
119
parser. span ( ) ,
120
120
) ?;
121
121
}
122
122
is_base = true ;
123
- base_field = Some ( Field :: new ( & field) ) ;
123
+ parser. finish ( ) ?;
124
+ }
125
+
126
+ // #[init]
127
+ if let Some ( mut parser) = KvParser :: parse ( & named_field. attributes , "init" ) ? {
128
+ let default = parser. handle_expr ( "default" ) ?;
129
+ field. default = default;
124
130
parser. finish ( ) ?;
125
131
}
126
132
127
133
// #[export]
128
- if let Some ( mut parser) = KvParser :: parse ( & field . attributes , "export" ) ? {
129
- let exported_field = ExportedField :: new_from_kv ( Field :: new ( & field ) , & mut parser) ?;
130
- exported_fields . push ( exported_field ) ;
134
+ if let Some ( mut parser) = KvParser :: parse ( & named_field . attributes , "export" ) ? {
135
+ let export = FieldExport :: new_from_kv ( & mut parser) ?;
136
+ field . export = Some ( export ) ;
131
137
parser. finish ( ) ?;
132
138
}
133
139
134
140
// Exported or Rust-only fields
135
- if !is_base {
136
- all_field_names. push ( field. name . clone ( ) )
141
+ if is_base {
142
+ base_field = Some ( field) ;
143
+ } else {
144
+ all_fields. push ( field) ;
137
145
}
138
146
}
139
147
140
148
Ok ( Fields {
141
- all_field_names ,
149
+ all_fields ,
142
150
base_field,
143
- exported_fields,
144
151
} )
145
152
}
146
153
@@ -153,27 +160,31 @@ struct ClassAttributes {
153
160
}
154
161
155
162
struct Fields {
156
- all_field_names : Vec < Ident > ,
163
+ /// All fields except `base_field`.
164
+ all_fields : Vec < Field > ,
165
+ /// The field annotated with `#[base]`.
157
166
base_field : Option < Field > ,
158
- exported_fields : Vec < ExportedField > ,
159
167
}
160
168
161
169
struct Field {
162
170
name : Ident ,
163
171
ty : TyExpr ,
172
+ default : Option < TokenStream > ,
173
+ export : Option < FieldExport > ,
164
174
}
165
175
166
176
impl Field {
167
177
fn new ( field : & NamedField ) -> Self {
168
178
Self {
169
179
name : field. name . clone ( ) ,
170
180
ty : field. ty . clone ( ) ,
181
+ default : None ,
182
+ export : None ,
171
183
}
172
184
}
173
185
}
174
186
175
- struct ExportedField {
176
- field : Field ,
187
+ struct FieldExport {
177
188
getter : GetterSetter ,
178
189
setter : GetterSetter ,
179
190
hint : Option < ExportHint > ,
@@ -219,8 +230,8 @@ impl ExportHint {
219
230
}
220
231
}
221
232
222
- impl ExportedField {
223
- pub fn new_from_kv ( field : Field , parser : & mut KvParser ) -> ParseResult < ExportedField > {
233
+ impl FieldExport {
234
+ pub fn new_from_kv ( parser : & mut KvParser ) -> ParseResult < FieldExport > {
224
235
let mut getter = GetterSetter :: parse ( parser, "get" ) ?;
225
236
let mut setter = GetterSetter :: parse ( parser, "set" ) ?;
226
237
if getter == GetterSetter :: Omitted && setter == GetterSetter :: Omitted {
@@ -238,8 +249,7 @@ impl ExportedField {
238
249
} )
239
250
. transpose ( ) ?;
240
251
241
- Ok ( ExportedField {
242
- field,
252
+ Ok ( FieldExport {
243
253
getter,
244
254
setter,
245
255
hint,
@@ -254,8 +264,13 @@ fn make_godot_init_impl(class_name: &Ident, fields: Fields) -> TokenStream {
254
264
TokenStream :: new ( )
255
265
} ;
256
266
257
- let rest_init = fields. all_field_names . into_iter ( ) . map ( |field| {
258
- quote ! { #field: std:: default :: Default :: default ( ) , }
267
+ let rest_init = fields. all_fields . into_iter ( ) . map ( |field| {
268
+ let field_name = field. name ;
269
+ let value_expr = match field. default {
270
+ None => quote ! ( :: std:: default :: Default :: default ( ) ) ,
271
+ Some ( default) => default,
272
+ } ;
273
+ quote ! { #field_name: #value_expr, }
259
274
} ) ;
260
275
261
276
quote ! {
@@ -295,20 +310,21 @@ fn make_deref_impl(class_name: &Ident, fields: &Fields) -> TokenStream {
295
310
296
311
fn make_exports_impl ( class_name : & Ident , fields : & Fields ) -> TokenStream {
297
312
let mut getter_setter_impls = Vec :: new ( ) ;
298
- let mut export_tokens = Vec :: with_capacity ( fields . exported_fields . len ( ) ) ;
313
+ let mut export_tokens = Vec :: new ( ) ;
299
314
300
- for exported_field in & fields. exported_fields {
301
- let field_name = exported_field. field . name . to_string ( ) ;
315
+ for field in & fields. all_fields {
316
+ let Some ( export) = & field. export else { continue ; } ;
317
+ let field_name = field. name . to_string ( ) ;
302
318
let field_ident = ident ( & field_name) ;
303
- let field_type = exported_field . field . ty . clone ( ) ;
319
+ let field_type = field. ty . clone ( ) ;
304
320
305
321
let ExportHint {
306
322
hint_type,
307
323
description,
308
- } = exported_field . hint . clone ( ) . unwrap_or_else ( ExportHint :: none) ;
324
+ } = export . hint . clone ( ) . unwrap_or_else ( ExportHint :: none) ;
309
325
310
326
let getter_name;
311
- match & exported_field . getter {
327
+ match & export . getter {
312
328
GetterSetter :: Omitted => {
313
329
getter_name = "" . to_owned ( ) ;
314
330
}
@@ -334,7 +350,7 @@ fn make_exports_impl(class_name: &Ident, fields: &Fields) -> TokenStream {
334
350
}
335
351
336
352
let setter_name;
337
- match & exported_field . setter {
353
+ match & export . setter {
338
354
GetterSetter :: Omitted => {
339
355
setter_name = "" . to_owned ( ) ;
340
356
}
0 commit comments