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<Self> { | |
let ident = input.parse::<syn::Ident>()?; | |
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::<syn::LitStr>()?; | |
let sev = get_severity(&str.value(), str.span())?; | |
Ok(Severity(syn::Ident::new(&sev, str.span()))) | |
} else { | |
let ident = content.parse::<syn::Ident>()?; | |
let sev = get_severity(&ident.to_string(), ident.span())?; | |
Ok(Severity(syn::Ident::new(&sev, ident.span()))) | |
} | |
} else { | |
input.parse::<Token![=]>()?; | |
let str = input.parse::<syn::LitStr>()?; | |
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<String> { | |
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<TokenStream> { | |
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<TokenStream> { | |
let sev = &self.0; | |
Some(quote! { | |
fn severity(&self) -> std::option::Option<miette::Severity> { | |
Some(miette::Severity::#sev) | |
} | |
}) | |
} | |
} |