use proc_macro2::TokenStream; use quote::quote; use syn::{ parenthesized, parse::{Parse, ParseStream}, Token, }; use crate::diagnostic::{Diagnostic, DiagnosticVariant}; pub struct Severity(pub syn::Path); impl Parse for Severity { fn parse(input: ParseStream) -> syn::Result { let ident = input.parse::()?; if ident == "severity" { let la = input.lookahead1(); if la.peek(syn::token::Paren) { let content; parenthesized!(content in input); let la = content.lookahead1(); if la.peek(syn::LitStr) { let str = content.parse::()?; Ok(Severity(str.parse()?)) } else { let path = content.parse::()?; Ok(Severity(path)) } } else { input.parse::()?; Ok(Severity(input.parse::()?.parse()?)) } } else { Err(syn::Error::new(ident.span(), "not a severity level.")) } } } impl Severity { pub(crate) fn gen_enum( _diag: &Diagnostic, variants: &[DiagnosticVariant], ) -> Option { let sev_pairs = variants .iter() .filter(|v| v.severity.is_some()) .map( |DiagnosticVariant { ident, severity, .. }| { let severity = &severity.as_ref().unwrap().0; quote! { Self::#ident => std::option::Option::Some(miette::Severity::#severity), } }, ) .collect::>(); if sev_pairs.is_empty() { None } else { Some(quote! { fn severity(&self) -> std::option::Option { match self { #(#sev_pairs)* _ => None, } } }) } } pub(crate) fn gen_struct(&self) -> Option { let sev = &self.0; Some(quote! { fn severity(&self) -> std::option::Option { Some(miette::Severity::#sev) } }) } }