diff options
author | Valentin Popov <valentin@popov.link> | 2024-01-08 00:21:28 +0300 |
---|---|---|
committer | Valentin Popov <valentin@popov.link> | 2024-01-08 00:21:28 +0300 |
commit | 1b6a04ca5504955c571d1c97504fb45ea0befee4 (patch) | |
tree | 7579f518b23313e8a9748a88ab6173d5e030b227 /vendor/miette-derive/src/code.rs | |
parent | 5ecd8cf2cba827454317368b68571df0d13d7842 (diff) | |
download | fparkan-1b6a04ca5504955c571d1c97504fb45ea0befee4.tar.xz fparkan-1b6a04ca5504955c571d1c97504fb45ea0befee4.zip |
Initial vendor packages
Signed-off-by: Valentin Popov <valentin@popov.link>
Diffstat (limited to 'vendor/miette-derive/src/code.rs')
-rw-r--r-- | vendor/miette-derive/src/code.rs | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/vendor/miette-derive/src/code.rs b/vendor/miette-derive/src/code.rs new file mode 100644 index 0000000..22dc795 --- /dev/null +++ b/vendor/miette-derive/src/code.rs @@ -0,0 +1,80 @@ +use proc_macro2::TokenStream; +use quote::quote; +use syn::{ + parenthesized, + parse::{Parse, ParseStream}, + Token, +}; + +use crate::{ + diagnostic::{DiagnosticConcreteArgs, DiagnosticDef}, + forward::WhichFn, + utils::gen_all_variants_with, +}; + +#[derive(Debug)] +pub struct Code(pub String); + +impl Parse for Code { + fn parse(input: ParseStream) -> syn::Result<Self> { + let ident = input.parse::<syn::Ident>()?; + if ident == "code" { + 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>()?; + Ok(Code(str.value())) + } else { + let path = content.parse::<syn::Path>()?; + Ok(Code( + path.segments + .iter() + .map(|s| s.ident.to_string()) + .collect::<Vec<_>>() + .join("::"), + )) + } + } else { + input.parse::<Token![=]>()?; + Ok(Code(input.parse::<syn::LitStr>()?.value())) + } + } else { + Err(syn::Error::new(ident.span(), "diagnostic code is required. Use #[diagnostic(code = ...)] or #[diagnostic(code(...))] to define one.")) + } + } +} + +impl Code { + pub(crate) fn gen_enum(variants: &[DiagnosticDef]) -> Option<TokenStream> { + gen_all_variants_with( + variants, + WhichFn::Code, + |ident, fields, DiagnosticConcreteArgs { code, .. }| { + let code = &code.as_ref()?.0; + Some(match fields { + syn::Fields::Named(_) => { + quote! { Self::#ident { .. } => std::option::Option::Some(std::boxed::Box::new(#code)), } + } + syn::Fields::Unnamed(_) => { + quote! { Self::#ident(..) => std::option::Option::Some(std::boxed::Box::new(#code)), } + } + syn::Fields::Unit => { + quote! { Self::#ident => std::option::Option::Some(std::boxed::Box::new(#code)), } + } + }) + }, + ) + } + + pub(crate) fn gen_struct(&self) -> Option<TokenStream> { + let code = &self.0; + Some(quote! { + fn code(&self) -> std::option::Option<std::boxed::Box<dyn std::fmt::Display + '_>> { + std::option::Option::Some(std::boxed::Box::new(#code)) + } + }) + } +} |