diff options
Diffstat (limited to 'vendor/miette-derive/src/diagnostic_source.rs')
-rw-r--r-- | vendor/miette-derive/src/diagnostic_source.rs | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/vendor/miette-derive/src/diagnostic_source.rs b/vendor/miette-derive/src/diagnostic_source.rs new file mode 100644 index 0000000..1104eb7 --- /dev/null +++ b/vendor/miette-derive/src/diagnostic_source.rs @@ -0,0 +1,78 @@ +use proc_macro2::TokenStream; +use quote::quote; +use syn::spanned::Spanned; + +use crate::forward::WhichFn; +use crate::{ + diagnostic::{DiagnosticConcreteArgs, DiagnosticDef}, + utils::{display_pat_members, gen_all_variants_with}, +}; + +pub struct DiagnosticSource(syn::Member); + +impl DiagnosticSource { + pub(crate) fn from_fields(fields: &syn::Fields) -> syn::Result<Option<Self>> { + match fields { + syn::Fields::Named(named) => Self::from_fields_vec(named.named.iter().collect()), + syn::Fields::Unnamed(unnamed) => { + Self::from_fields_vec(unnamed.unnamed.iter().collect()) + } + syn::Fields::Unit => Ok(None), + } + } + + fn from_fields_vec(fields: Vec<&syn::Field>) -> syn::Result<Option<Self>> { + for (i, field) in fields.iter().enumerate() { + for attr in &field.attrs { + if attr.path().is_ident("diagnostic_source") { + let diagnostic_source = if let Some(ident) = field.ident.clone() { + syn::Member::Named(ident) + } else { + syn::Member::Unnamed(syn::Index { + index: i as u32, + span: field.span(), + }) + }; + return Ok(Some(DiagnosticSource(diagnostic_source))); + } + } + } + Ok(None) + } + + pub(crate) fn gen_enum(variants: &[DiagnosticDef]) -> Option<TokenStream> { + gen_all_variants_with( + variants, + WhichFn::DiagnosticSource, + |ident, + fields, + DiagnosticConcreteArgs { + diagnostic_source, .. + }| { + let (display_pat, _display_members) = display_pat_members(fields); + diagnostic_source.as_ref().map(|diagnostic_source| { + let rel = match &diagnostic_source.0 { + syn::Member::Named(ident) => ident.clone(), + syn::Member::Unnamed(syn::Index { index, .. }) => { + quote::format_ident!("_{}", index) + } + }; + quote! { + Self::#ident #display_pat => { + std::option::Option::Some(std::borrow::Borrow::borrow(#rel)) + } + } + }) + }, + ) + } + + pub(crate) fn gen_struct(&self) -> Option<TokenStream> { + let rel = &self.0; + Some(quote! { + fn diagnostic_source<'a>(&'a self) -> std::option::Option<&'a dyn miette::Diagnostic> { + std::option::Option::Some(std::borrow::Borrow::borrow(&self.#rel)) + } + }) + } +} |