@@ -228,7 +228,10 @@ pub(crate) enum AttributeOrder {
228228 KeepLast ,
229229}
230230
231- type ConvertFn < E > = fn ( ThinVec < E > ) -> AttributeKind ;
231+ pub ( crate ) enum ConvertFn < E > {
232+ Simple ( fn ( ThinVec < E > ) -> AttributeKind ) ,
233+ WithFirstAttributeSpan ( fn ( ThinVec < E > , Span ) -> AttributeKind ) ,
234+ }
232235
233236/// Alternative to [`AttributeParser`] that automatically handles state management.
234237/// If multiple attributes appear on an element, combines the values of each into a
@@ -262,22 +265,36 @@ pub(crate) trait CombineAttributeParser<S: Stage>: 'static {
262265pub ( crate ) struct Combine < T : CombineAttributeParser < S > , S : Stage > (
263266 PhantomData < ( S , T ) > ,
264267 ThinVec < <T as CombineAttributeParser < S > >:: Item > ,
268+ Option < Span > ,
265269) ;
266270
267271impl < T : CombineAttributeParser < S > , S : Stage > Default for Combine < T , S > {
268272 fn default ( ) -> Self {
269- Self ( Default :: default ( ) , Default :: default ( ) )
273+ Self ( Default :: default ( ) , Default :: default ( ) , Default :: default ( ) )
270274 }
271275}
272276
273277impl < T : CombineAttributeParser < S > , S : Stage > AttributeParser < S > for Combine < T , S > {
274278 const ATTRIBUTES : AcceptMapping < Self , S > = & [ (
275279 T :: PATH ,
276280 <T as CombineAttributeParser < S > >:: TEMPLATE ,
277- |group : & mut Combine < T , S > , cx, args| group. 1 . extend ( T :: extend ( cx, args) ) ,
281+ |group : & mut Combine < T , S > , cx, args| {
282+ // Keep track of the span of the first attribute, for diagnostics
283+ if group. 2 . is_none ( ) {
284+ group. 2 = Some ( cx. attr_span ) ;
285+ }
286+ group. 1 . extend ( T :: extend ( cx, args) )
287+ } ,
278288 ) ] ;
279289
280290 fn finalize ( self , _cx : & FinalizeContext < ' _ , ' _ , S > ) -> Option < AttributeKind > {
281- if self . 1 . is_empty ( ) { None } else { Some ( T :: CONVERT ( self . 1 ) ) }
291+ if let Some ( first_span) = self . 2 {
292+ Some ( match T :: CONVERT {
293+ ConvertFn :: Simple ( f) => f ( self . 1 ) ,
294+ ConvertFn :: WithFirstAttributeSpan ( f) => f ( self . 1 , first_span) ,
295+ } )
296+ } else {
297+ None
298+ }
282299 }
283300}
0 commit comments