1 #![deny(unused_must_use)]
3 use crate::diagnostics::diagnostic_builder::{DiagnosticDeriveBuilder, DiagnosticDeriveKind};
4 use crate::diagnostics::error::{span_err, DiagnosticDeriveError};
5 use crate::diagnostics::utils::SetOnce;
6 use proc_macro2::TokenStream;
8 use synstructure::Structure;
10 /// The central struct for constructing the `into_diagnostic` method from an annotated struct.
11 pub(crate) struct DiagnosticDerive<'a> {
12 structure: Structure<'a>,
14 builder: DiagnosticDeriveBuilder,
17 impl<'a> DiagnosticDerive<'a> {
18 pub(crate) fn new(diag: syn::Ident, handler: syn::Ident, structure: Structure<'a>) -> Self {
20 builder: DiagnosticDeriveBuilder { diag, kind: DiagnosticDeriveKind::Diagnostic },
26 pub(crate) fn into_tokens(self) -> TokenStream {
27 let DiagnosticDerive { mut structure, handler, mut builder } = self;
29 let implementation = builder.each_variant(&mut structure, |mut builder, variant| {
30 let preamble = builder.preamble(&variant);
31 let body = builder.body(&variant);
33 let diag = &builder.parent.diag;
34 let init = match builder.slug.value_ref() {
36 span_err(builder.span, "diagnostic slug not specified")
38 "specify the slug as the first argument to the `#[diag(...)]` \
39 attribute, such as `#[diag(typeck::example_error)]`",
42 return DiagnosticDeriveError::ErrorHandled.to_compile_error();
46 let mut #diag = #handler.struct_diagnostic(rustc_errors::fluent::#slug);
59 structure.gen_impl(quote! {
60 gen impl<'__diagnostic_handler_sess, G>
61 rustc_errors::IntoDiagnostic<'__diagnostic_handler_sess, G>
63 where G: rustc_errors::EmissionGuarantee
67 #handler: &'__diagnostic_handler_sess rustc_errors::Handler
68 ) -> rustc_errors::DiagnosticBuilder<'__diagnostic_handler_sess, G> {
69 use rustc_errors::IntoDiagnosticArg;
77 /// The central struct for constructing the `decorate_lint` method from an annotated struct.
78 pub(crate) struct LintDiagnosticDerive<'a> {
79 structure: Structure<'a>,
80 builder: DiagnosticDeriveBuilder,
83 impl<'a> LintDiagnosticDerive<'a> {
84 pub(crate) fn new(diag: syn::Ident, structure: Structure<'a>) -> Self {
86 builder: DiagnosticDeriveBuilder { diag, kind: DiagnosticDeriveKind::LintDiagnostic },
91 pub(crate) fn into_tokens(self) -> TokenStream {
92 let LintDiagnosticDerive { mut structure, mut builder } = self;
94 let implementation = builder.each_variant(&mut structure, |mut builder, variant| {
95 let preamble = builder.preamble(&variant);
96 let body = builder.body(&variant);
98 let diag = &builder.parent.diag;
107 let msg = builder.each_variant(&mut structure, |mut builder, variant| {
108 // HACK(wafflelapkin): initialize slug (???)
109 let _preamble = builder.preamble(&variant);
111 match builder.slug.value_ref() {
113 span_err(builder.span, "diagnostic slug not specified")
115 "specify the slug as the first argument to the attribute, such as \
116 `#[diag(typeck::example_error)]`",
119 return DiagnosticDeriveError::ErrorHandled.to_compile_error();
121 Some(slug) => quote! { rustc_errors::fluent::#slug.into() },
125 let diag = &builder.diag;
126 structure.gen_impl(quote! {
127 gen impl<'__a> rustc_errors::DecorateLint<'__a, ()> for @Self {
128 fn decorate_lint<'__b>(self, #diag: &'__b mut rustc_errors::DiagnosticBuilder<'__a, ()>) -> &'__b mut rustc_errors::DiagnosticBuilder<'__a, ()> {
129 use rustc_errors::IntoDiagnosticArg;
133 fn msg(&self) -> rustc_errors::DiagnosticMessage {