@@ -228,7 +228,10 @@ pub(crate) enum AttributeOrder {
228
228
KeepLast ,
229
229
}
230
230
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
+ }
232
235
233
236
/// Alternative to [`AttributeParser`] that automatically handles state management.
234
237
/// 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 {
262
265
pub ( crate ) struct Combine < T : CombineAttributeParser < S > , S : Stage > (
263
266
PhantomData < ( S , T ) > ,
264
267
ThinVec < <T as CombineAttributeParser < S > >:: Item > ,
268
+ Option < Span > ,
265
269
) ;
266
270
267
271
impl < T : CombineAttributeParser < S > , S : Stage > Default for Combine < T , S > {
268
272
fn default ( ) -> Self {
269
- Self ( Default :: default ( ) , Default :: default ( ) )
273
+ Self ( Default :: default ( ) , Default :: default ( ) , Default :: default ( ) )
270
274
}
271
275
}
272
276
273
277
impl < T : CombineAttributeParser < S > , S : Stage > AttributeParser < S > for Combine < T , S > {
274
278
const ATTRIBUTES : AcceptMapping < Self , S > = & [ (
275
279
T :: PATH ,
276
280
<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
+ } ,
278
288
) ] ;
279
289
280
290
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
+ }
282
299
}
283
300
}
0 commit comments