@@ -18,20 +18,54 @@ use crate::diagnostics::utils::{
1818 should_generate_arg, type_is_bool, type_is_unit, type_matches_path,
1919} ;
2020
21- /// What kind of diagnostic is being derived - a fatal/error/warning or a lint?
22- #[ derive( Clone , Copy , PartialEq , Eq ) ]
23- pub ( crate ) enum DiagnosticDeriveKind {
24- Diagnostic ,
25- LintDiagnostic ,
21+ pub ( crate ) fn each_variant < ' s , F > ( structure : & mut Structure < ' s > , f : F ) -> TokenStream
22+ where
23+ F : for < ' v > Fn ( DiagnosticDeriveVariantBuilder , & VariantInfo < ' v > ) -> TokenStream ,
24+ {
25+ let ast = structure. ast ( ) ;
26+ let span = ast. span ( ) . unwrap ( ) ;
27+ match ast. data {
28+ syn:: Data :: Struct ( ..) | syn:: Data :: Enum ( ..) => ( ) ,
29+ syn:: Data :: Union ( ..) => {
30+ span_err ( span, "diagnostic derives can only be used on structs and enums" ) . emit ( ) ;
31+ }
32+ }
33+
34+ if matches ! ( ast. data, syn:: Data :: Enum ( ..) ) {
35+ for attr in & ast. attrs {
36+ span_err ( attr. span ( ) . unwrap ( ) , "unsupported type attribute for diagnostic derive enum" )
37+ . emit ( ) ;
38+ }
39+ }
40+
41+ structure. bind_with ( |_| synstructure:: BindStyle :: Move ) ;
42+ let variants = structure. each_variant ( |variant| {
43+ let span = match structure. ast ( ) . data {
44+ syn:: Data :: Struct ( ..) => span,
45+ // There isn't a good way to get the span of the variant, so the variant's
46+ // name will need to do.
47+ _ => variant. ast ( ) . ident . span ( ) . unwrap ( ) ,
48+ } ;
49+ let builder = DiagnosticDeriveVariantBuilder {
50+ span,
51+ field_map : build_field_mapping ( variant) ,
52+ formatting_init : TokenStream :: new ( ) ,
53+ message : None ,
54+ code : None ,
55+ } ;
56+ f ( builder, variant)
57+ } ) ;
58+
59+ quote ! {
60+ match self {
61+ #variants
62+ }
63+ }
2664}
2765
2866/// Tracks persistent information required for a specific variant when building up individual calls
29- /// to diagnostic methods for generated diagnostic derives - both `Diagnostic` for
30- /// fatal/errors/warnings and `LintDiagnostic` for lints.
67+ /// to diagnostic methods for generated diagnostic derives.
3168pub ( crate ) struct DiagnosticDeriveVariantBuilder {
32- /// The kind for the entire type.
33- pub kind : DiagnosticDeriveKind ,
34-
3569 /// Initialization of format strings for code suggestions.
3670 pub formatting_init : TokenStream ,
3771
@@ -51,60 +85,6 @@ pub(crate) struct DiagnosticDeriveVariantBuilder {
5185 pub code : SpannedOption < ( ) > ,
5286}
5387
54- impl DiagnosticDeriveKind {
55- /// Call `f` for the struct or for each variant of the enum, returning a `TokenStream` with the
56- /// tokens from `f` wrapped in an `match` expression. Emits errors for use of derive on unions
57- /// or attributes on the type itself when input is an enum.
58- pub ( crate ) fn each_variant < ' s , F > ( self , structure : & mut Structure < ' s > , f : F ) -> TokenStream
59- where
60- F : for < ' v > Fn ( DiagnosticDeriveVariantBuilder , & VariantInfo < ' v > ) -> TokenStream ,
61- {
62- let ast = structure. ast ( ) ;
63- let span = ast. span ( ) . unwrap ( ) ;
64- match ast. data {
65- syn:: Data :: Struct ( ..) | syn:: Data :: Enum ( ..) => ( ) ,
66- syn:: Data :: Union ( ..) => {
67- span_err ( span, "diagnostic derives can only be used on structs and enums" ) . emit ( ) ;
68- }
69- }
70-
71- if matches ! ( ast. data, syn:: Data :: Enum ( ..) ) {
72- for attr in & ast. attrs {
73- span_err (
74- attr. span ( ) . unwrap ( ) ,
75- "unsupported type attribute for diagnostic derive enum" ,
76- )
77- . emit ( ) ;
78- }
79- }
80-
81- structure. bind_with ( |_| synstructure:: BindStyle :: Move ) ;
82- let variants = structure. each_variant ( |variant| {
83- let span = match structure. ast ( ) . data {
84- syn:: Data :: Struct ( ..) => span,
85- // There isn't a good way to get the span of the variant, so the variant's
86- // name will need to do.
87- _ => variant. ast ( ) . ident . span ( ) . unwrap ( ) ,
88- } ;
89- let builder = DiagnosticDeriveVariantBuilder {
90- kind : self ,
91- span,
92- field_map : build_field_mapping ( variant) ,
93- formatting_init : TokenStream :: new ( ) ,
94- message : None ,
95- code : None ,
96- } ;
97- f ( builder, variant)
98- } ) ;
99-
100- quote ! {
101- match self {
102- #variants
103- }
104- }
105- }
106- }
107-
10888impl DiagnosticDeriveVariantBuilder {
10989 pub ( crate ) fn primary_message ( & self ) -> Option < & Message > {
11090 match self . message . as_ref ( ) {
@@ -358,20 +338,11 @@ impl DiagnosticDeriveVariantBuilder {
358338 // `arg` call will not be generated.
359339 ( Meta :: Path ( _) , "skip_arg" ) => return Ok ( quote ! { } ) ,
360340 ( Meta :: Path ( _) , "primary_span" ) => {
361- match self . kind {
362- DiagnosticDeriveKind :: Diagnostic => {
363- report_error_if_not_applied_to_span ( attr, & info) ?;
341+ report_error_if_not_applied_to_span ( attr, & info) ?;
364342
365- return Ok ( quote ! {
366- diag. span( #binding) ;
367- } ) ;
368- }
369- DiagnosticDeriveKind :: LintDiagnostic => {
370- throw_invalid_attr ! ( attr, |diag| {
371- diag. help( "the `primary_span` field attribute is not valid for lint diagnostics" )
372- } )
373- }
374- }
343+ return Ok ( quote ! {
344+ diag. span( #binding) ;
345+ } ) ;
375346 }
376347 ( Meta :: Path ( _) , "subdiagnostic" ) => {
377348 return Ok ( quote ! { diag. subdiagnostic( #binding) ; } ) ;
0 commit comments