@@ -264,7 +264,7 @@ impl<T: NoArgsAttributeParser<S>, S: Stage> SingleAttributeParser<S> for Without
264264 }
265265}
266266
267- type ConvertFn < E > = fn ( ThinVec < E > ) -> AttributeKind ;
267+ type ConvertFn < E > = fn ( ThinVec < E > , Span ) -> AttributeKind ;
268268
269269/// Alternative to [`AttributeParser`] that automatically handles state management.
270270/// 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 {
295295
296296/// Use in combination with [`CombineAttributeParser`].
297297/// `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+ }
302305
303306impl < T : CombineAttributeParser < S > , S : Stage > Default for Combine < T , S > {
304307 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+ }
306313 }
307314}
308315
309316impl < T : CombineAttributeParser < S > , S : Stage > AttributeParser < S > for Combine < T , S > {
310317 const ATTRIBUTES : AcceptMapping < Self , S > = & [ (
311318 T :: PATH ,
312319 <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+ } ,
314325 ) ] ;
315326
316327 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+ }
318333 }
319334}
0 commit comments