aboutsummaryrefslogtreecommitdiff
path: root/vendor/miette-derive/src/diagnostic.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/miette-derive/src/diagnostic.rs')
-rw-r--r--vendor/miette-derive/src/diagnostic.rs397
1 files changed, 0 insertions, 397 deletions
diff --git a/vendor/miette-derive/src/diagnostic.rs b/vendor/miette-derive/src/diagnostic.rs
deleted file mode 100644
index 0173d2a..0000000
--- a/vendor/miette-derive/src/diagnostic.rs
+++ /dev/null
@@ -1,397 +0,0 @@
-use proc_macro2::TokenStream;
-use quote::quote;
-use syn::{punctuated::Punctuated, DeriveInput, Token};
-
-use crate::code::Code;
-use crate::diagnostic_arg::DiagnosticArg;
-use crate::diagnostic_source::DiagnosticSource;
-use crate::forward::{Forward, WhichFn};
-use crate::help::Help;
-use crate::label::Labels;
-use crate::related::Related;
-use crate::severity::Severity;
-use crate::source_code::SourceCode;
-use crate::url::Url;
-
-pub enum Diagnostic {
- Struct {
- generics: syn::Generics,
- ident: syn::Ident,
- fields: syn::Fields,
- args: DiagnosticDefArgs,
- },
- Enum {
- ident: syn::Ident,
- generics: syn::Generics,
- variants: Vec<DiagnosticDef>,
- },
-}
-
-pub struct DiagnosticDef {
- pub ident: syn::Ident,
- pub fields: syn::Fields,
- pub args: DiagnosticDefArgs,
-}
-
-pub enum DiagnosticDefArgs {
- Transparent(Forward),
- Concrete(Box<DiagnosticConcreteArgs>),
-}
-
-impl DiagnosticDefArgs {
- pub(crate) fn forward_or_override_enum(
- &self,
- variant: &syn::Ident,
- which_fn: WhichFn,
- mut f: impl FnMut(&DiagnosticConcreteArgs) -> Option<TokenStream>,
- ) -> Option<TokenStream> {
- match self {
- Self::Transparent(forward) => Some(forward.gen_enum_match_arm(variant, which_fn)),
- Self::Concrete(concrete) => f(concrete).or_else(|| {
- concrete
- .forward
- .as_ref()
- .map(|forward| forward.gen_enum_match_arm(variant, which_fn))
- }),
- }
- }
-}
-
-#[derive(Default)]
-pub struct DiagnosticConcreteArgs {
- pub code: Option<Code>,
- pub severity: Option<Severity>,
- pub help: Option<Help>,
- pub labels: Option<Labels>,
- pub source_code: Option<SourceCode>,
- pub url: Option<Url>,
- pub forward: Option<Forward>,
- pub related: Option<Related>,
- pub diagnostic_source: Option<DiagnosticSource>,
-}
-
-impl DiagnosticConcreteArgs {
- fn for_fields(fields: &syn::Fields) -> Result<Self, syn::Error> {
- let labels = Labels::from_fields(fields)?;
- let source_code = SourceCode::from_fields(fields)?;
- let related = Related::from_fields(fields)?;
- let help = Help::from_fields(fields)?;
- let diagnostic_source = DiagnosticSource::from_fields(fields)?;
- Ok(DiagnosticConcreteArgs {
- code: None,
- help,
- related,
- severity: None,
- labels,
- url: None,
- forward: None,
- source_code,
- diagnostic_source,
- })
- }
-
- fn add_args(
- &mut self,
- attr: &syn::Attribute,
- args: impl Iterator<Item = DiagnosticArg>,
- errors: &mut Vec<syn::Error>,
- ) {
- for arg in args {
- match arg {
- DiagnosticArg::Transparent => {
- errors.push(syn::Error::new_spanned(attr, "transparent not allowed"));
- }
- DiagnosticArg::Forward(to_field) => {
- if self.forward.is_some() {
- errors.push(syn::Error::new_spanned(
- attr,
- "forward has already been specified",
- ));
- }
- self.forward = Some(to_field);
- }
- DiagnosticArg::Code(new_code) => {
- if self.code.is_some() {
- errors.push(syn::Error::new_spanned(
- attr,
- "code has already been specified",
- ));
- }
- self.code = Some(new_code);
- }
- DiagnosticArg::Severity(sev) => {
- if self.severity.is_some() {
- errors.push(syn::Error::new_spanned(
- attr,
- "severity has already been specified",
- ));
- }
- self.severity = Some(sev);
- }
- DiagnosticArg::Help(hl) => {
- if self.help.is_some() {
- errors.push(syn::Error::new_spanned(
- attr,
- "help has already been specified",
- ));
- }
- self.help = Some(hl);
- }
- DiagnosticArg::Url(u) => {
- if self.url.is_some() {
- errors.push(syn::Error::new_spanned(
- attr,
- "url has already been specified",
- ));
- }
- self.url = Some(u);
- }
- }
- }
- }
-}
-
-impl DiagnosticDefArgs {
- fn parse(
- _ident: &syn::Ident,
- fields: &syn::Fields,
- attrs: &[&syn::Attribute],
- allow_transparent: bool,
- ) -> syn::Result<Self> {
- let mut errors = Vec::new();
-
- // Handle the only condition where Transparent is allowed
- if allow_transparent && attrs.len() == 1 {
- if let Ok(args) =
- attrs[0].parse_args_with(Punctuated::<DiagnosticArg, Token![,]>::parse_terminated)
- {
- if matches!(args.first(), Some(DiagnosticArg::Transparent)) {
- let forward = Forward::for_transparent_field(fields)?;
- return Ok(Self::Transparent(forward));
- }
- }
- }
-
- // Create errors for any appearances of Transparent
- let error_message = if allow_transparent {
- "diagnostic(transparent) not allowed in combination with other args"
- } else {
- "diagnostic(transparent) not allowed here"
- };
- fn is_transparent(d: &DiagnosticArg) -> bool {
- matches!(d, DiagnosticArg::Transparent)
- }
-
- let mut concrete = DiagnosticConcreteArgs::for_fields(fields)?;
- for attr in attrs {
- let args =
- attr.parse_args_with(Punctuated::<DiagnosticArg, Token![,]>::parse_terminated);
- let args = match args {
- Ok(args) => args,
- Err(error) => {
- errors.push(error);
- continue;
- }
- };
-
- if args.iter().any(is_transparent) {
- errors.push(syn::Error::new_spanned(attr, error_message));
- }
-
- let args = args
- .into_iter()
- .filter(|x| !matches!(x, DiagnosticArg::Transparent));
-
- concrete.add_args(attr, args, &mut errors);
- }
-
- let combined_error = errors.into_iter().reduce(|mut lhs, rhs| {
- lhs.combine(rhs);
- lhs
- });
- if let Some(error) = combined_error {
- Err(error)
- } else {
- Ok(DiagnosticDefArgs::Concrete(Box::new(concrete)))
- }
- }
-}
-
-impl Diagnostic {
- pub fn from_derive_input(input: DeriveInput) -> Result<Self, syn::Error> {
- let input_attrs = input
- .attrs
- .iter()
- .filter(|x| x.path().is_ident("diagnostic"))
- .collect::<Vec<&syn::Attribute>>();
- Ok(match input.data {
- syn::Data::Struct(data_struct) => {
- let args = DiagnosticDefArgs::parse(
- &input.ident,
- &data_struct.fields,
- &input_attrs,
- true,
- )?;
-
- Diagnostic::Struct {
- fields: data_struct.fields,
- ident: input.ident,
- generics: input.generics,
- args,
- }
- }
- syn::Data::Enum(syn::DataEnum { variants, .. }) => {
- let mut vars = Vec::new();
- for var in variants {
- let mut variant_attrs = input_attrs.clone();
- variant_attrs
- .extend(var.attrs.iter().filter(|x| x.path().is_ident("diagnostic")));
- let args =
- DiagnosticDefArgs::parse(&var.ident, &var.fields, &variant_attrs, true)?;
- vars.push(DiagnosticDef {
- ident: var.ident,
- fields: var.fields,
- args,
- });
- }
- Diagnostic::Enum {
- ident: input.ident,
- generics: input.generics,
- variants: vars,
- }
- }
- syn::Data::Union(_) => {
- return Err(syn::Error::new(
- input.ident.span(),
- "Can't derive Diagnostic for Unions",
- ))
- }
- })
- }
-
- pub fn gen(&self) -> TokenStream {
- match self {
- Self::Struct {
- ident,
- fields,
- generics,
- args,
- } => {
- let (impl_generics, ty_generics, where_clause) = &generics.split_for_impl();
- match args {
- DiagnosticDefArgs::Transparent(forward) => {
- let code_method = forward.gen_struct_method(WhichFn::Code);
- let help_method = forward.gen_struct_method(WhichFn::Help);
- let url_method = forward.gen_struct_method(WhichFn::Url);
- let labels_method = forward.gen_struct_method(WhichFn::Labels);
- let source_code_method = forward.gen_struct_method(WhichFn::SourceCode);
- let severity_method = forward.gen_struct_method(WhichFn::Severity);
- let related_method = forward.gen_struct_method(WhichFn::Related);
- let diagnostic_source_method =
- forward.gen_struct_method(WhichFn::DiagnosticSource);
-
- quote! {
- impl #impl_generics miette::Diagnostic for #ident #ty_generics #where_clause {
- #code_method
- #help_method
- #url_method
- #labels_method
- #severity_method
- #source_code_method
- #related_method
- #diagnostic_source_method
- }
- }
- }
- DiagnosticDefArgs::Concrete(concrete) => {
- let forward = |which| {
- concrete
- .forward
- .as_ref()
- .map(|fwd| fwd.gen_struct_method(which))
- };
- let code_body = concrete
- .code
- .as_ref()
- .and_then(|x| x.gen_struct())
- .or_else(|| forward(WhichFn::Code));
- let help_body = concrete
- .help
- .as_ref()
- .and_then(|x| x.gen_struct(fields))
- .or_else(|| forward(WhichFn::Help));
- let sev_body = concrete
- .severity
- .as_ref()
- .and_then(|x| x.gen_struct())
- .or_else(|| forward(WhichFn::Severity));
- let rel_body = concrete
- .related
- .as_ref()
- .and_then(|x| x.gen_struct())
- .or_else(|| forward(WhichFn::Related));
- let url_body = concrete
- .url
- .as_ref()
- .and_then(|x| x.gen_struct(ident, fields))
- .or_else(|| forward(WhichFn::Url));
- let labels_body = concrete
- .labels
- .as_ref()
- .and_then(|x| x.gen_struct(fields))
- .or_else(|| forward(WhichFn::Labels));
- let src_body = concrete
- .source_code
- .as_ref()
- .and_then(|x| x.gen_struct(fields))
- .or_else(|| forward(WhichFn::SourceCode));
- let diagnostic_source = concrete
- .diagnostic_source
- .as_ref()
- .and_then(|x| x.gen_struct())
- .or_else(|| forward(WhichFn::DiagnosticSource));
- quote! {
- impl #impl_generics miette::Diagnostic for #ident #ty_generics #where_clause {
- #code_body
- #help_body
- #sev_body
- #rel_body
- #url_body
- #labels_body
- #src_body
- #diagnostic_source
- }
- }
- }
- }
- }
- Self::Enum {
- ident,
- generics,
- variants,
- } => {
- let (impl_generics, ty_generics, where_clause) = &generics.split_for_impl();
- let code_body = Code::gen_enum(variants);
- let help_body = Help::gen_enum(variants);
- let sev_body = Severity::gen_enum(variants);
- let labels_body = Labels::gen_enum(variants);
- let src_body = SourceCode::gen_enum(variants);
- let rel_body = Related::gen_enum(variants);
- let url_body = Url::gen_enum(ident, variants);
- let diagnostic_source_body = DiagnosticSource::gen_enum(variants);
- quote! {
- impl #impl_generics miette::Diagnostic for #ident #ty_generics #where_clause {
- #code_body
- #help_body
- #sev_body
- #labels_body
- #src_body
- #rel_body
- #url_body
- #diagnostic_source_body
- }
- }
- }
- }
- }
-}