@@ -5,8 +5,8 @@ use crate::diagnostics::error::{
5
5
} ;
6
6
use crate :: diagnostics:: utils:: {
7
7
build_field_mapping, is_doc_comment, report_error_if_not_applied_to_span, report_type_error,
8
- should_generate_arg, type_is_bool, type_is_unit, type_matches_path, FieldInfo , FieldInnerTy ,
9
- FieldMap , HasFieldMap , SetOnce , SpannedOption , SubdiagnosticKind ,
8
+ should_generate_arg, slugify , type_is_bool, type_is_unit, type_matches_path, FieldInfo ,
9
+ FieldInnerTy , FieldMap , HasFieldMap , SetOnce , SpannedOption , SubdiagnosticKind ,
10
10
} ;
11
11
use proc_macro2:: { Ident , Span , TokenStream } ;
12
12
use quote:: { format_ident, quote, quote_spanned} ;
@@ -29,10 +29,10 @@ pub(crate) enum SlugOrRawFluent {
29
29
///
30
30
/// e.g. `#[diag(foo_bar)]`
31
31
Slug ( Path ) ,
32
- /// Literal string containing the Fluent message.
32
+ /// Literal string containing the Fluent message and its computed slug .
33
33
///
34
34
/// e.g. `#[diag_raw(message = "raw fluent content")]`
35
- RawFluent ( LitStr ) ,
35
+ RawFluent ( String , LitStr ) ,
36
36
}
37
37
38
38
/// Tracks persistent information required for a specific variant when building up individual calls
@@ -60,6 +60,7 @@ pub(crate) struct DiagnosticDeriveVariantBuilder {
60
60
/// multiple specifications.
61
61
pub code : SpannedOption < ( ) > ,
62
62
63
+ pub generated_slug : String ,
63
64
pub args : Vec < TokenStream > ,
64
65
}
65
66
@@ -96,8 +97,14 @@ impl DiagnosticDeriveKind {
96
97
}
97
98
}
98
99
100
+ let generated_slug = slugify ( & structure. ast ( ) . ident . to_string ( ) ) ;
99
101
structure. bind_with ( |_| synstructure:: BindStyle :: Move ) ;
100
102
let variants = structure. each_variant ( |variant| {
103
+ let mut generated_slug = generated_slug. clone ( ) ;
104
+ if matches ! ( ast. data, syn:: Data :: Enum ( ..) ) {
105
+ generated_slug. push_str ( "_" ) ;
106
+ generated_slug. push_str ( & slugify ( & variant. ast ( ) . ident . to_string ( ) ) ) ;
107
+ }
101
108
let span = match structure. ast ( ) . data {
102
109
syn:: Data :: Struct ( ..) => span,
103
110
// There isn't a good way to get the span of the variant, so the variant's
@@ -111,6 +118,7 @@ impl DiagnosticDeriveKind {
111
118
formatting_init : TokenStream :: new ( ) ,
112
119
slug : None ,
113
120
code : None ,
121
+ generated_slug,
114
122
args : Vec :: new ( ) ,
115
123
} ;
116
124
f ( builder, variant)
@@ -157,9 +165,10 @@ impl DiagnosticDeriveVariantBuilder {
157
165
/// Parse a `SubdiagnosticKind` from an `Attribute`.
158
166
fn parse_subdiag_attribute (
159
167
& self ,
168
+ generated_slug : & str ,
160
169
attr : & Attribute ,
161
170
) -> Result < Option < ( SubdiagnosticKind , SlugOrRawFluent , bool ) > , DiagnosticDeriveError > {
162
- let Some ( subdiag) = SubdiagnosticVariant :: from_attr ( attr, self ) ? else {
171
+ let Some ( subdiag) = SubdiagnosticVariant :: from_attr ( generated_slug , attr, self ) ? else {
163
172
// Some attributes aren't errors - like documentation comments - but also aren't
164
173
// subdiagnostics.
165
174
return Ok ( None ) ;
@@ -228,7 +237,10 @@ impl DiagnosticDeriveVariantBuilder {
228
237
229
238
if path. is_ident ( "message" ) {
230
239
self . slug . set_once (
231
- SlugOrRawFluent :: RawFluent ( nested. parse :: < LitStr > ( ) ?) ,
240
+ SlugOrRawFluent :: RawFluent (
241
+ self . generated_slug . clone ( ) ,
242
+ nested. parse :: < LitStr > ( ) ?,
243
+ ) ,
232
244
path. span ( ) . unwrap ( ) ,
233
245
) ;
234
246
return Ok ( ( ) ) ;
@@ -252,7 +264,9 @@ impl DiagnosticDeriveVariantBuilder {
252
264
return Ok ( tokens) ;
253
265
}
254
266
255
- let Some ( ( subdiag, slug, _no_span) ) = self . parse_subdiag_attribute ( attr) ? else {
267
+ let Some ( ( subdiag, slug, _no_span) ) =
268
+ self . parse_subdiag_attribute ( & self . generated_slug , attr) ?
269
+ else {
256
270
// Some attributes aren't errors - like documentation comments - but also aren't
257
271
// subdiagnostics.
258
272
return Ok ( quote ! { } ) ;
@@ -278,7 +292,7 @@ impl DiagnosticDeriveVariantBuilder {
278
292
let ident = field. ident . as_ref ( ) . unwrap ( ) ;
279
293
let ident = format_ident ! ( "{}" , ident) ; // strip `r#` prefix, if present
280
294
281
- if matches ! ( self . slug. value_ref( ) , Some ( SlugOrRawFluent :: RawFluent ( _) ) ) {
295
+ if matches ! ( self . slug. value_ref( ) , Some ( SlugOrRawFluent :: RawFluent ( _, _ ) ) ) {
282
296
// Cloning should not be necessary once there are no `diag.arg` calls.
283
297
self . args . push ( quote ! {
284
298
args. insert( stringify!( #ident) . into( ) , #field_binding. clone( ) . into_diagnostic_arg( ) ) ;
@@ -370,7 +384,14 @@ impl DiagnosticDeriveVariantBuilder {
370
384
_ => ( ) ,
371
385
}
372
386
373
- let Some ( ( subdiag, slug, _no_span) ) = self . parse_subdiag_attribute ( attr) ? else {
387
+ let mut generated_slug = self . generated_slug . clone ( ) ;
388
+ if let Some ( field_name) = & info. binding . ast ( ) . ident {
389
+ generated_slug. push_str ( "_" ) ;
390
+ generated_slug. push_str ( & slugify ( & field_name. to_string ( ) ) ) ;
391
+ }
392
+ let Some ( ( subdiag, slug, _no_span) ) =
393
+ self . parse_subdiag_attribute ( & generated_slug, attr) ?
394
+ else {
374
395
// Some attributes aren't errors - like documentation comments - but also aren't
375
396
// subdiagnostics.
376
397
return Ok ( quote ! { } ) ;
@@ -432,8 +453,8 @@ impl DiagnosticDeriveVariantBuilder {
432
453
#style
433
454
) ;
434
455
} ) ,
435
- SlugOrRawFluent :: RawFluent ( raw) => Ok ( quote ! {
436
- let raw = dcx. raw_translate( "foo" , #raw, args. iter( ) ) ;
456
+ SlugOrRawFluent :: RawFluent ( slug , raw) => Ok ( quote ! {
457
+ let raw = dcx. raw_translate( #slug , #raw, args. iter( ) ) ;
437
458
diag. span_suggestions_with_style(
438
459
#span_field,
439
460
raw,
@@ -466,9 +487,9 @@ impl DiagnosticDeriveVariantBuilder {
466
487
) ;
467
488
}
468
489
}
469
- SlugOrRawFluent :: RawFluent ( raw) => {
490
+ SlugOrRawFluent :: RawFluent ( slug , raw) => {
470
491
quote ! {
471
- let raw = dcx. raw_translate( "foo" , #raw, args. iter( ) ) ;
492
+ let raw = dcx. raw_translate( #slug , #raw, args. iter( ) ) ;
472
493
diag. #fn_name( #field_binding, raw) ;
473
494
}
474
495
}
@@ -484,9 +505,9 @@ impl DiagnosticDeriveVariantBuilder {
484
505
diag. #kind( crate :: fluent_generated:: #fluent_attr_identifier) ;
485
506
}
486
507
}
487
- SlugOrRawFluent :: RawFluent ( raw) => {
508
+ SlugOrRawFluent :: RawFluent ( slug , raw) => {
488
509
quote ! {
489
- let raw = dcx. raw_translate( "foo" , #raw, args. iter( ) ) ;
510
+ let raw = dcx. raw_translate( #slug , #raw, args. iter( ) ) ;
490
511
diag. #kind( raw) ;
491
512
}
492
513
}
0 commit comments