1
1
use std:: { collections:: BTreeMap , marker:: PhantomData , ops:: Deref } ;
2
2
3
3
use quote:: format_ident;
4
- use syn:: { spanned:: Spanned , Attribute , Ident , Path } ;
4
+ use syn:: { spanned:: Spanned , Attribute , Ident , Path , Type } ;
5
5
6
6
use crate :: {
7
7
attrs:: common:: { ContainerAttributes , ItemAttributes , ValidateVersions } ,
@@ -21,7 +21,7 @@ use crate::{
21
21
pub ( crate ) trait Item < I , A > : Sized
22
22
where
23
23
A : for < ' i > TryFrom < & ' i I > + Attributes ,
24
- I : Named + Spanned ,
24
+ I : InnerItem ,
25
25
{
26
26
/// Creates a new versioned item (struct field or enum variant) by consuming
27
27
/// the parsed [Field](syn::Field) or [Variant](syn::Variant) and validating
43
43
fn get_ident ( & self , version : & ContainerVersion ) -> Option < & Ident > ;
44
44
}
45
45
46
+ pub ( crate ) trait InnerItem : Named + Spanned {
47
+ fn ty ( & self ) -> Type ;
48
+ }
49
+
46
50
/// This trait enables access to the ident of named items, like fields and
47
51
/// variants.
48
52
///
@@ -87,7 +91,7 @@ pub(crate) trait Attributes {
87
91
pub ( crate ) struct VersionedItem < I , A >
88
92
where
89
93
A : for < ' i > TryFrom < & ' i I > + Attributes ,
90
- I : Named + Spanned ,
94
+ I : InnerItem ,
91
95
{
92
96
pub ( crate ) original_attributes : Vec < Attribute > ,
93
97
pub ( crate ) chain : Option < VersionChain > ,
@@ -99,7 +103,7 @@ impl<I, A> Item<I, A> for VersionedItem<I, A>
99
103
where
100
104
syn:: Error : for < ' i > From < <A as TryFrom < & ' i I > >:: Error > ,
101
105
A : for < ' i > TryFrom < & ' i I > + Attributes + ValidateVersions < I > ,
102
- I : Named + Spanned ,
106
+ I : InnerItem ,
103
107
{
104
108
fn new ( item : I , container_attrs : & ContainerAttributes ) -> syn:: Result < Self > {
105
109
// We use the TryFrom trait here, because the type parameter `A` can use
@@ -135,6 +139,8 @@ where
135
139
// requires access to the item ident to infer the item ident for
136
140
// the latest change.
137
141
let mut ident = item. cleaned_ident ( ) ;
142
+ let mut ty = item. ty ( ) ;
143
+
138
144
let mut actions = BTreeMap :: new ( ) ;
139
145
140
146
actions. insert (
@@ -147,20 +153,33 @@ where
147
153
) ;
148
154
149
155
for change in common_attributes. changes . iter ( ) . rev ( ) {
150
- let from = if let Some ( from) = change. from_name . as_deref ( ) {
156
+ dbg ! ( & ty, & change. since) ;
157
+ let from_ident = if let Some ( from) = change. from_name . as_deref ( ) {
151
158
format_ident ! ( "{from}" )
152
159
} else {
153
160
ident. clone ( )
154
161
} ;
155
162
163
+ // TODO (@Techassi): This is an awful lot of cloning, can we get
164
+ // rid of it?
165
+ let from_ty = change
166
+ . from_type
167
+ . as_ref ( )
168
+ . map ( |sv| sv. deref ( ) . clone ( ) )
169
+ . unwrap_or ( ty. clone ( ) ) ;
170
+
156
171
actions. insert (
157
172
* change. since ,
158
173
ItemStatus :: Change {
159
- from_ident : from . clone ( ) ,
174
+ from_ident : from_ident . clone ( ) ,
160
175
to_ident : ident,
176
+ from_type : from_ty. clone ( ) ,
177
+ to_type : ty,
161
178
} ,
162
179
) ;
163
- ident = from;
180
+
181
+ ident = from_ident;
182
+ ty = from_ty;
164
183
}
165
184
166
185
// After the last iteration above (if any) we use the ident for the
@@ -171,6 +190,7 @@ where
171
190
ItemStatus :: Addition {
172
191
default_fn : added. default_fn . deref ( ) . clone ( ) ,
173
192
ident,
193
+ ty,
174
194
} ,
175
195
) ;
176
196
}
@@ -182,24 +202,39 @@ where
182
202
inner : item,
183
203
} )
184
204
} else if !common_attributes. changes . is_empty ( ) {
185
- let mut actions = BTreeMap :: new ( ) ;
186
205
let mut ident = item. ident ( ) . clone ( ) ;
206
+ let mut ty = item. ty ( ) ;
207
+
208
+ let mut actions = BTreeMap :: new ( ) ;
187
209
188
210
for change in common_attributes. changes . iter ( ) . rev ( ) {
189
- let from = if let Some ( from) = change. from_name . as_deref ( ) {
211
+ dbg ! ( & ty, & change. since) ;
212
+ let from_ident = if let Some ( from) = change. from_name . as_deref ( ) {
190
213
format_ident ! ( "{from}" )
191
214
} else {
192
215
ident. clone ( )
193
216
} ;
194
217
218
+ // TODO (@Techassi): This is an awful lot of cloning, can we get
219
+ // rid of it?
220
+ let from_ty = change
221
+ . from_type
222
+ . as_ref ( )
223
+ . map ( |sv| sv. deref ( ) . clone ( ) )
224
+ . unwrap_or ( ty. clone ( ) ) ;
225
+
195
226
actions. insert (
196
227
* change. since ,
197
228
ItemStatus :: Change {
198
- from_ident : from . clone ( ) ,
229
+ from_ident : from_ident . clone ( ) ,
199
230
to_ident : ident,
231
+ from_type : from_ty. clone ( ) ,
232
+ to_type : ty,
200
233
} ,
201
234
) ;
202
- ident = from;
235
+
236
+ ident = from_ident;
237
+ ty = from_ty;
203
238
}
204
239
205
240
// After the last iteration above (if any) we use the ident for the
@@ -210,6 +245,7 @@ where
210
245
ItemStatus :: Addition {
211
246
default_fn : added. default_fn . deref ( ) . clone ( ) ,
212
247
ident,
248
+ ty,
213
249
} ,
214
250
) ;
215
251
}
@@ -229,6 +265,7 @@ where
229
265
ItemStatus :: Addition {
230
266
default_fn : added. default_fn . deref ( ) . clone ( ) ,
231
267
ident : item. ident ( ) . clone ( ) ,
268
+ ty : item. ty ( ) ,
232
269
} ,
233
270
) ;
234
271
@@ -314,10 +351,15 @@ pub(crate) enum ItemStatus {
314
351
Addition {
315
352
ident : Ident ,
316
353
default_fn : Path ,
354
+ // NOTE (@Techassi): We need to carry idents and type information in
355
+ // nearly every status. Ideally, we would store this in separate maps.
356
+ ty : Type ,
317
357
} ,
318
358
Change {
319
359
from_ident : Ident ,
320
360
to_ident : Ident ,
361
+ from_type : Type ,
362
+ to_type : Type ,
321
363
} ,
322
364
Deprecation {
323
365
previous_ident : Ident ,
0 commit comments