flux_macros/diagnostics/
diagnostic.rs1#![deny(unused_must_use)]
2
3use proc_macro2::TokenStream;
4use quote::quote;
5use synstructure::Structure;
6
7use crate::diagnostics::diagnostic_builder::each_variant;
8use crate::diagnostics::error::DiagnosticDeriveError;
9
10pub(crate) struct DiagnosticDerive<'a> {
12 structure: Structure<'a>,
13}
14
15impl<'a> DiagnosticDerive<'a> {
16 pub(crate) fn new(structure: Structure<'a>) -> Self {
17 Self { structure }
18 }
19
20 pub(crate) fn into_tokens(self) -> TokenStream {
21 let DiagnosticDerive { mut structure } = self;
22 let implementation = each_variant(&mut structure, |mut builder, variant| {
23 let preamble = builder.preamble(variant);
24 let body = builder.body(variant);
25
26 let Some(message) = builder.primary_message() else {
27 return DiagnosticDeriveError::ErrorHandled.to_compile_error();
28 };
29 let message = message.diag_message();
30
31 let init = quote! {
32 let mut diag = rustc_errors::Diag::new(
33 dcx,
34 level,
35 #message
36 );
37 };
38
39 let formatting_init = &builder.formatting_init;
40 quote! {
41 #init
42 #formatting_init
43 #preamble
44 #body
45 diag
46 }
47 });
48
49 structure.gen_impl(quote! {
51 gen impl<'_sess> rustc_errors::Diagnostic<'_sess> for @Self {
52 #[track_caller]
53 fn into_diag(
54 self,
55 dcx: rustc_errors::DiagCtxtHandle<'_sess>,
56 level: rustc_errors::Level
57 ) -> rustc_errors::Diag<'_sess> {
58 #implementation
59 }
60 }
61 })
62 }
63}