22
33use crate :: diagnostics:: diagnostic_builder:: { DiagnosticDeriveBuilder , DiagnosticDeriveKind } ;
44use crate :: diagnostics:: error:: { span_err, DiagnosticDeriveError } ;
5- use crate :: diagnostics:: utils:: { build_field_mapping , SetOnce } ;
5+ use crate :: diagnostics:: utils:: SetOnce ;
66use proc_macro2:: TokenStream ;
77use quote:: quote;
8- use syn:: spanned:: Spanned ;
98use synstructure:: Structure ;
109
1110/// The central struct for constructing the `into_diagnostic` method from an annotated struct.
@@ -18,13 +17,7 @@ pub(crate) struct DiagnosticDerive<'a> {
1817impl < ' a > DiagnosticDerive < ' a > {
1918 pub ( crate ) fn new ( diag : syn:: Ident , handler : syn:: Ident , structure : Structure < ' a > ) -> Self {
2019 Self {
21- builder : DiagnosticDeriveBuilder {
22- diag,
23- fields : build_field_mapping ( & structure) ,
24- kind : DiagnosticDeriveKind :: Diagnostic ,
25- code : None ,
26- slug : None ,
27- } ,
20+ builder : DiagnosticDeriveBuilder { diag, kind : DiagnosticDeriveKind :: Diagnostic } ,
2821 handler,
2922 structure,
3023 }
@@ -33,52 +26,35 @@ impl<'a> DiagnosticDerive<'a> {
3326 pub ( crate ) fn into_tokens ( self ) -> TokenStream {
3427 let DiagnosticDerive { mut structure, handler, mut builder } = self ;
3528
36- let ast = structure. ast ( ) ;
37- let implementation = {
38- if let syn:: Data :: Struct ( ..) = ast. data {
39- let preamble = builder. preamble ( & structure) ;
40- let ( attrs, args) = builder. body ( & mut structure) ;
41-
42- let span = ast. span ( ) . unwrap ( ) ;
43- let diag = & builder. diag ;
44- let init = match builder. slug . value ( ) {
45- None => {
46- span_err ( span, "diagnostic slug not specified" )
47- . help ( & format ! (
48- "specify the slug as the first argument to the `#[diag(...)]` attribute, \
49- such as `#[diag(typeck::example_error)]`",
50- ) )
51- . emit ( ) ;
52- return DiagnosticDeriveError :: ErrorHandled . to_compile_error ( ) ;
53- }
54- Some ( slug) => {
55- quote ! {
56- let mut #diag = #handler. struct_diagnostic( rustc_errors:: fluent:: #slug) ;
57- }
58- }
59- } ;
60-
61- quote ! {
62- #init
63- #preamble
64- match self {
65- #attrs
66- }
67- match self {
68- #args
29+ let implementation = builder. each_variant ( & mut structure, |mut builder, variant| {
30+ let preamble = builder. preamble ( & variant) ;
31+ let body = builder. body ( & variant) ;
32+
33+ let diag = & builder. parent . diag ;
34+ let init = match builder. slug . value_ref ( ) {
35+ None => {
36+ span_err ( builder. span , "diagnostic slug not specified" )
37+ . help ( & format ! (
38+ "specify the slug as the first argument to the `#[diag(...)]` \
39+ attribute, such as `#[diag(typeck::example_error)]`",
40+ ) )
41+ . emit ( ) ;
42+ return DiagnosticDeriveError :: ErrorHandled . to_compile_error ( ) ;
43+ }
44+ Some ( slug) => {
45+ quote ! {
46+ let mut #diag = #handler. struct_diagnostic( rustc_errors:: fluent:: #slug) ;
6947 }
70- #diag
7148 }
72- } else {
73- span_err (
74- ast. span ( ) . unwrap ( ) ,
75- "`#[derive(Diagnostic)]` can only be used on structs" ,
76- )
77- . emit ( ) ;
49+ } ;
7850
79- DiagnosticDeriveError :: ErrorHandled . to_compile_error ( )
51+ quote ! {
52+ #init
53+ #preamble
54+ #body
55+ #diag
8056 }
81- } ;
57+ } ) ;
8258
8359 structure. gen_impl ( quote ! {
8460 gen impl <' __diagnostic_handler_sess, G >
@@ -107,68 +83,43 @@ pub(crate) struct LintDiagnosticDerive<'a> {
10783impl < ' a > LintDiagnosticDerive < ' a > {
10884 pub ( crate ) fn new ( diag : syn:: Ident , structure : Structure < ' a > ) -> Self {
10985 Self {
110- builder : DiagnosticDeriveBuilder {
111- diag,
112- fields : build_field_mapping ( & structure) ,
113- kind : DiagnosticDeriveKind :: LintDiagnostic ,
114- code : None ,
115- slug : None ,
116- } ,
86+ builder : DiagnosticDeriveBuilder { diag, kind : DiagnosticDeriveKind :: LintDiagnostic } ,
11787 structure,
11888 }
11989 }
12090
12191 pub ( crate ) fn into_tokens ( self ) -> TokenStream {
12292 let LintDiagnosticDerive { mut structure, mut builder } = self ;
12393
124- let ast = structure. ast ( ) ;
125- let implementation = {
126- if let syn:: Data :: Struct ( ..) = ast. data {
127- let preamble = builder. preamble ( & structure) ;
128- let ( attrs, args) = builder. body ( & mut structure) ;
129-
130- let diag = & builder. diag ;
131- let span = ast. span ( ) . unwrap ( ) ;
132- let init = match builder. slug . value ( ) {
133- None => {
134- span_err ( span, "diagnostic slug not specified" )
135- . help ( & format ! (
136- "specify the slug as the first argument to the attribute, such as \
137- `#[diag(typeck::example_error)]`",
138- ) )
139- . emit ( ) ;
140- return DiagnosticDeriveError :: ErrorHandled . to_compile_error ( ) ;
141- }
142- Some ( slug) => {
143- quote ! {
144- let mut #diag = #diag. build( rustc_errors:: fluent:: #slug) ;
145- }
146- }
147- } ;
148-
149- let implementation = quote ! {
150- #init
151- #preamble
152- match self {
153- #attrs
154- }
155- match self {
156- #args
94+ let implementation = builder. each_variant ( & mut structure, |mut builder, variant| {
95+ let preamble = builder. preamble ( & variant) ;
96+ let body = builder. body ( & variant) ;
97+
98+ let diag = & builder. parent . diag ;
99+ let init = match builder. slug . value_ref ( ) {
100+ None => {
101+ span_err ( builder. span , "diagnostic slug not specified" )
102+ . help ( & format ! (
103+ "specify the slug as the first argument to the attribute, such as \
104+ `#[diag(typeck::example_error)]`",
105+ ) )
106+ . emit ( ) ;
107+ return DiagnosticDeriveError :: ErrorHandled . to_compile_error ( ) ;
108+ }
109+ Some ( slug) => {
110+ quote ! {
111+ let mut #diag = #diag. build( rustc_errors:: fluent:: #slug) ;
157112 }
158- #diag. emit( ) ;
159- } ;
160-
161- implementation
162- } else {
163- span_err (
164- ast. span ( ) . unwrap ( ) ,
165- "`#[derive(LintDiagnostic)]` can only be used on structs" ,
166- )
167- . emit ( ) ;
113+ }
114+ } ;
168115
169- DiagnosticDeriveError :: ErrorHandled . to_compile_error ( )
116+ quote ! {
117+ #init
118+ #preamble
119+ #body
120+ #diag. emit( ) ;
170121 }
171- } ;
122+ } ) ;
172123
173124 let diag = & builder. diag ;
174125 structure. gen_impl ( quote ! {
0 commit comments