@@ -264,7 +264,7 @@ impl<T: NoArgsAttributeParser<S>, S: Stage> SingleAttributeParser<S> for Without
264
264
}
265
265
}
266
266
267
- type ConvertFn < E > = fn ( ThinVec < E > ) -> AttributeKind ;
267
+ type ConvertFn < E > = fn ( ThinVec < E > , Span ) -> AttributeKind ;
268
268
269
269
/// Alternative to [`AttributeParser`] that automatically handles state management.
270
270
/// If multiple attributes appear on an element, combines the values of each into a
@@ -295,25 +295,40 @@ pub(crate) trait CombineAttributeParser<S: Stage>: 'static {
295
295
296
296
/// Use in combination with [`CombineAttributeParser`].
297
297
/// `Combine<T: CombineAttributeParser>` implements [`AttributeParser`].
298
- pub ( crate ) struct Combine < T : CombineAttributeParser < S > , S : Stage > (
299
- PhantomData < ( S , T ) > ,
300
- ThinVec < <T as CombineAttributeParser < S > >:: Item > ,
301
- ) ;
298
+ pub ( crate ) struct Combine < T : CombineAttributeParser < S > , S : Stage > {
299
+ phantom : PhantomData < ( S , T ) > ,
300
+ /// A list of all items produced by parsing attributes so far. One attribute can produce any amount of items.
301
+ items : ThinVec < <T as CombineAttributeParser < S > >:: Item > ,
302
+ /// The full span of the first attribute that was encountered.
303
+ first_span : Option < Span > ,
304
+ }
302
305
303
306
impl < T : CombineAttributeParser < S > , S : Stage > Default for Combine < T , S > {
304
307
fn default ( ) -> Self {
305
- Self ( Default :: default ( ) , Default :: default ( ) )
308
+ Self {
309
+ phantom : Default :: default ( ) ,
310
+ items : Default :: default ( ) ,
311
+ first_span : Default :: default ( ) ,
312
+ }
306
313
}
307
314
}
308
315
309
316
impl < T : CombineAttributeParser < S > , S : Stage > AttributeParser < S > for Combine < T , S > {
310
317
const ATTRIBUTES : AcceptMapping < Self , S > = & [ (
311
318
T :: PATH ,
312
319
<T as CombineAttributeParser < S > >:: TEMPLATE ,
313
- |group : & mut Combine < T , S > , cx, args| group. 1 . extend ( T :: extend ( cx, args) ) ,
320
+ |group : & mut Combine < T , S > , cx, args| {
321
+ // Keep track of the span of the first attribute, for diagnostics
322
+ group. first_span . get_or_insert ( cx. attr_span ) ;
323
+ group. items . extend ( T :: extend ( cx, args) )
324
+ } ,
314
325
) ] ;
315
326
316
327
fn finalize ( self , _cx : & FinalizeContext < ' _ , ' _ , S > ) -> Option < AttributeKind > {
317
- if self . 1 . is_empty ( ) { None } else { Some ( T :: CONVERT ( self . 1 ) ) }
328
+ if let Some ( first_span) = self . first_span {
329
+ Some ( T :: CONVERT ( self . items , first_span) )
330
+ } else {
331
+ None
332
+ }
318
333
}
319
334
}
0 commit comments