use proc_macro2::{Span, TokenStream}; use quote::quote; use syn::{ parenthesized, parse::{Parse, ParseStream}, Token, }; use crate::{ diagnostic::{DiagnosticConcreteArgs, DiagnosticDef}, forward::WhichFn, utils::gen_all_variants_with, }; pub struct Severity(pub syn::Ident); 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::()?; let sev = get_severity(&str.value(), str.span())?; Ok(Severity(syn::Ident::new(&sev, str.span()))) } else { let ident = content.parse::()?; let sev = get_severity(&ident.to_string(), ident.span())?; Ok(Severity(syn::Ident::new(&sev, ident.span()))) } } else { input.parse::()?; let str = input.parse::()?; let sev = get_severity(&str.value(), str.span())?; Ok(Severity(syn::Ident::new(&sev, str.span()))) } } else { Err(syn::Error::new( ident.span(), "MIETTE BUG: not a severity option", )) } } } fn get_severity(input: &str, span: Span) -> syn::Result { match input.to_lowercase().as_ref() { "error" | "err" => Ok("Error".into()), "warning" | "warn" => Ok("Warning".into()), "advice" | "adv" | "info" => Ok("Advice".into()), _ => Err(syn::Error::new( span, "Invalid severity level. Only Error, Warning, and Advice are supported.", )), } } impl Severity { pub(crate) fn gen_enum(variants: &[DiagnosticDef]) -> Option { gen_all_variants_with( variants, WhichFn::Severity, |ident, fields, DiagnosticConcreteArgs { severity, .. }| { let severity = &severity.as_ref()?.0; let fields = match fields { syn::Fields::Named(_) => quote! { { .. } }, syn::Fields::Unnamed(_) => quote! { (..) }, syn::Fields::Unit => quote! {}, }; Some( quote! { Self::#ident #fields => std::option::Option::Some(miette::Severity::#severity), }, ) }, ) } pub(crate) fn gen_struct(&self) -> Option { let sev = &self.0; Some(quote! { fn severity(&self) -> std::option::Option { Some(miette::Severity::#sev) } }) } }