@@ -229,7 +229,7 @@ pub(crate) enum AttributeOrder {
229229 KeepLast ,
230230}
231231
232- type ConvertFn < E > = fn ( ThinVec < E > ) -> AttributeKind ;
232+ type ConvertFn < E > = fn ( ThinVec < E > , Span ) -> AttributeKind ;
233233
234234/// Alternative to [`AttributeParser`] that automatically handles state management.
235235/// If multiple attributes appear on an element, combines the values of each into a
@@ -260,25 +260,40 @@ pub(crate) trait CombineAttributeParser<S: Stage>: 'static {
260260
261261/// Use in combination with [`CombineAttributeParser`].
262262/// `Combine<T: CombineAttributeParser>` implements [`AttributeParser`].
263- pub ( crate ) struct Combine < T : CombineAttributeParser < S > , S : Stage > (
264- PhantomData < ( S , T ) > ,
265- ThinVec < <T as CombineAttributeParser < S > >:: Item > ,
266- ) ;
263+ pub ( crate ) struct Combine < T : CombineAttributeParser < S > , S : Stage > {
264+ phantom : PhantomData < ( S , T ) > ,
265+ /// A list of all items produced by parsing attributes so far. One attribute can produce any amount of items.
266+ items : ThinVec < <T as CombineAttributeParser < S > >:: Item > ,
267+ /// The full span of the first attribute that was encountered.
268+ first_span : Option < Span > ,
269+ }
267270
268271impl < T : CombineAttributeParser < S > , S : Stage > Default for Combine < T , S > {
269272 fn default ( ) -> Self {
270- Self ( Default :: default ( ) , Default :: default ( ) )
273+ Self {
274+ phantom : Default :: default ( ) ,
275+ items : Default :: default ( ) ,
276+ first_span : Default :: default ( ) ,
277+ }
271278 }
272279}
273280
274281impl < T : CombineAttributeParser < S > , S : Stage > AttributeParser < S > for Combine < T , S > {
275282 const ATTRIBUTES : AcceptMapping < Self , S > = & [ (
276283 T :: PATH ,
277284 <T as CombineAttributeParser < S > >:: TEMPLATE ,
278- |group : & mut Combine < T , S > , cx, args| group. 1 . extend ( T :: extend ( cx, args) ) ,
285+ |group : & mut Combine < T , S > , cx, args| {
286+ // Keep track of the span of the first attribute, for diagnostics
287+ group. first_span . get_or_insert ( cx. attr_span ) ;
288+ group. items . extend ( T :: extend ( cx, args) )
289+ } ,
279290 ) ] ;
280291
281292 fn finalize ( self , _cx : & FinalizeContext < ' _ , ' _ , S > ) -> Option < AttributeKind > {
282- if self . 1 . is_empty ( ) { None } else { Some ( T :: CONVERT ( self . 1 ) ) }
293+ if let Some ( first_span) = self . first_span {
294+ Some ( T :: CONVERT ( self . items , first_span) )
295+ } else {
296+ None
297+ }
283298 }
284299}
0 commit comments