aboutsummaryrefslogtreecommitdiff
path: root/vendor/miette-derive/src
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/miette-derive/src')
-rw-r--r--vendor/miette-derive/src/code.rs80
-rw-r--r--vendor/miette-derive/src/diagnostic.rs397
-rw-r--r--vendor/miette-derive/src/diagnostic_arg.rs42
-rw-r--r--vendor/miette-derive/src/diagnostic_source.rs78
-rw-r--r--vendor/miette-derive/src/fmt.rs235
-rw-r--r--vendor/miette-derive/src/forward.rs161
-rw-r--r--vendor/miette-derive/src/help.rs146
-rw-r--r--vendor/miette-derive/src/label.rs207
-rw-r--r--vendor/miette-derive/src/lib.rs32
-rw-r--r--vendor/miette-derive/src/related.rs79
-rw-r--r--vendor/miette-derive/src/severity.rs89
-rw-r--r--vendor/miette-derive/src/source_code.rs81
-rw-r--r--vendor/miette-derive/src/url.rs139
-rw-r--r--vendor/miette-derive/src/utils.rs140
14 files changed, 1906 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))
+ }
+ })
+ }
+}
diff --git a/vendor/miette-derive/src/diagnostic.rs b/vendor/miette-derive/src/diagnostic.rs
new file mode 100644
index 0000000..0173d2a
--- /dev/null
+++ b/vendor/miette-derive/src/diagnostic.rs
@@ -0,0 +1,397 @@
+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
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/vendor/miette-derive/src/diagnostic_arg.rs b/vendor/miette-derive/src/diagnostic_arg.rs
new file mode 100644
index 0000000..bade6f0
--- /dev/null
+++ b/vendor/miette-derive/src/diagnostic_arg.rs
@@ -0,0 +1,42 @@
+use syn::parse::{Parse, ParseStream};
+
+use crate::code::Code;
+use crate::forward::Forward;
+use crate::help::Help;
+use crate::severity::Severity;
+use crate::url::Url;
+
+pub enum DiagnosticArg {
+ Transparent,
+ Code(Code),
+ Severity(Severity),
+ Help(Help),
+ Url(Url),
+ Forward(Forward),
+}
+
+impl Parse for DiagnosticArg {
+ fn parse(input: ParseStream) -> syn::Result<Self> {
+ let ident = input.fork().parse::<syn::Ident>()?;
+ if ident == "transparent" {
+ // consume the token
+ let _: syn::Ident = input.parse()?;
+ Ok(DiagnosticArg::Transparent)
+ } else if ident == "forward" {
+ Ok(DiagnosticArg::Forward(input.parse()?))
+ } else if ident == "code" {
+ Ok(DiagnosticArg::Code(input.parse()?))
+ } else if ident == "severity" {
+ Ok(DiagnosticArg::Severity(input.parse()?))
+ } else if ident == "help" {
+ Ok(DiagnosticArg::Help(input.parse()?))
+ } else if ident == "url" {
+ Ok(DiagnosticArg::Url(input.parse()?))
+ } else {
+ Err(syn::Error::new(
+ ident.span(),
+ "Unrecognized diagnostic option",
+ ))
+ }
+ }
+}
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))
+ }
+ })
+ }
+}
diff --git a/vendor/miette-derive/src/fmt.rs b/vendor/miette-derive/src/fmt.rs
new file mode 100644
index 0000000..692c5ad
--- /dev/null
+++ b/vendor/miette-derive/src/fmt.rs
@@ -0,0 +1,235 @@
+// NOTE: Most code in this file is taken straight from `thiserror`.
+use std::collections::HashSet as Set;
+use std::iter::FromIterator;
+
+use proc_macro2::{Delimiter, Group, TokenStream, TokenTree};
+use quote::{format_ident, quote, quote_spanned, ToTokens};
+use syn::ext::IdentExt;
+use syn::parse::{ParseStream, Parser};
+use syn::{braced, bracketed, parenthesized, Ident, Index, LitStr, Member, Result, Token};
+
+#[derive(Clone)]
+pub struct Display {
+ pub fmt: LitStr,
+ pub args: TokenStream,
+ pub has_bonus_display: bool,
+}
+
+impl ToTokens for Display {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ let fmt = &self.fmt;
+ let args = &self.args;
+ tokens.extend(quote! {
+ write!(__formatter, #fmt #args)
+ });
+ }
+}
+
+impl Display {
+ // Transform `"error {var}"` to `"error {}", var`.
+ pub fn expand_shorthand(&mut self, members: &Set<Member>) {
+ let raw_args = self.args.clone();
+ let mut named_args = explicit_named_args.parse2(raw_args).unwrap();
+
+ let span = self.fmt.span();
+ let fmt = self.fmt.value();
+ let mut read = fmt.as_str();
+ let mut out = String::new();
+ let mut args = self.args.clone();
+ let mut has_bonus_display = false;
+
+ let mut has_trailing_comma = false;
+ if let Some(TokenTree::Punct(punct)) = args.clone().into_iter().last() {
+ if punct.as_char() == ',' {
+ has_trailing_comma = true;
+ }
+ }
+
+ while let Some(brace) = read.find('{') {
+ out += &read[..brace + 1];
+ read = &read[brace + 1..];
+ if read.starts_with('{') {
+ out.push('{');
+ read = &read[1..];
+ continue;
+ }
+ let next = match read.chars().next() {
+ Some(next) => next,
+ None => return,
+ };
+ let member = match next {
+ '0'..='9' => {
+ let int = take_int(&mut read);
+ let member = match int.parse::<u32>() {
+ Ok(index) => Member::Unnamed(Index { index, span }),
+ Err(_) => return,
+ };
+ if !members.contains(&member) {
+ out += &int;
+ continue;
+ }
+ member
+ }
+ 'a'..='z' | 'A'..='Z' | '_' => {
+ let mut ident = take_ident(&mut read);
+ ident.set_span(span);
+ Member::Named(ident)
+ }
+ _ => continue,
+ };
+ let local = match &member {
+ Member::Unnamed(index) => format_ident!("_{}", index),
+ Member::Named(ident) => ident.clone(),
+ };
+ let mut formatvar = local.clone();
+ if formatvar.to_string().starts_with("r#") {
+ formatvar = format_ident!("r_{}", formatvar);
+ }
+ if formatvar.to_string().starts_with('_') {
+ // Work around leading underscore being rejected by 1.40 and
+ // older compilers. https://github.com/rust-lang/rust/pull/66847
+ formatvar = format_ident!("field_{}", formatvar);
+ }
+ out += &formatvar.to_string();
+ if !named_args.insert(formatvar.clone()) {
+ // Already specified in the format argument list.
+ continue;
+ }
+ if !has_trailing_comma {
+ args.extend(quote_spanned!(span=> ,));
+ }
+ args.extend(quote_spanned!(span=> #formatvar = #local));
+ if read.starts_with('}') && members.contains(&member) {
+ has_bonus_display = true;
+ // args.extend(quote_spanned!(span=> .as_display()));
+ }
+ has_trailing_comma = false;
+ }
+
+ out += read;
+ self.fmt = LitStr::new(&out, self.fmt.span());
+ self.args = args;
+ self.has_bonus_display = has_bonus_display;
+ }
+}
+
+fn explicit_named_args(input: ParseStream) -> Result<Set<Ident>> {
+ let mut named_args = Set::new();
+
+ while !input.is_empty() {
+ if input.peek(Token![,]) && input.peek2(Ident::peek_any) && input.peek3(Token![=]) {
+ input.parse::<Token![,]>()?;
+ let ident = input.call(Ident::parse_any)?;
+ input.parse::<Token![=]>()?;
+ named_args.insert(ident);
+ } else {
+ input.parse::<TokenTree>()?;
+ }
+ }
+
+ Ok(named_args)
+}
+
+fn take_int(read: &mut &str) -> String {
+ let mut int = String::new();
+ for (i, ch) in read.char_indices() {
+ match ch {
+ '0'..='9' => int.push(ch),
+ _ => {
+ *read = &read[i..];
+ break;
+ }
+ }
+ }
+ int
+}
+
+fn take_ident(read: &mut &str) -> Ident {
+ let mut ident = String::new();
+ let raw = read.starts_with("r#");
+ if raw {
+ ident.push_str("r#");
+ *read = &read[2..];
+ }
+ for (i, ch) in read.char_indices() {
+ match ch {
+ 'a'..='z' | 'A'..='Z' | '0'..='9' | '_' => ident.push(ch),
+ _ => {
+ *read = &read[i..];
+ break;
+ }
+ }
+ }
+ Ident::parse_any.parse_str(&ident).unwrap()
+}
+
+pub fn parse_token_expr(input: ParseStream, mut begin_expr: bool) -> Result<TokenStream> {
+ let mut tokens = Vec::new();
+ while !input.is_empty() {
+ if begin_expr && input.peek(Token![.]) {
+ if input.peek2(Ident) {
+ input.parse::<Token![.]>()?;
+ begin_expr = false;
+ continue;
+ }
+ if input.peek2(syn::LitInt) {
+ input.parse::<Token![.]>()?;
+ let int: Index = input.parse()?;
+ let ident = format_ident!("_{}", int.index, span = int.span);
+ tokens.push(TokenTree::Ident(ident));
+ begin_expr = false;
+ continue;
+ }
+ }
+
+ begin_expr = input.peek(Token![break])
+ || input.peek(Token![continue])
+ || input.peek(Token![if])
+ || input.peek(Token![in])
+ || input.peek(Token![match])
+ || input.peek(Token![mut])
+ || input.peek(Token![return])
+ || input.peek(Token![while])
+ || input.peek(Token![+])
+ || input.peek(Token![&])
+ || input.peek(Token![!])
+ || input.peek(Token![^])
+ || input.peek(Token![,])
+ || input.peek(Token![/])
+ || input.peek(Token![=])
+ || input.peek(Token![>])
+ || input.peek(Token![<])
+ || input.peek(Token![|])
+ || input.peek(Token![%])
+ || input.peek(Token![;])
+ || input.peek(Token![*])
+ || input.peek(Token![-]);
+
+ let token: TokenTree = if input.peek(syn::token::Paren) {
+ let content;
+ let delimiter = parenthesized!(content in input);
+ let nested = parse_token_expr(&content, true)?;
+ let mut group = Group::new(Delimiter::Parenthesis, nested);
+ group.set_span(delimiter.span.join());
+ TokenTree::Group(group)
+ } else if input.peek(syn::token::Brace) {
+ let content;
+ let delimiter = braced!(content in input);
+ let nested = parse_token_expr(&content, true)?;
+ let mut group = Group::new(Delimiter::Brace, nested);
+ group.set_span(delimiter.span.join());
+ TokenTree::Group(group)
+ } else if input.peek(syn::token::Bracket) {
+ let content;
+ let delimiter = bracketed!(content in input);
+ let nested = parse_token_expr(&content, true)?;
+ let mut group = Group::new(Delimiter::Bracket, nested);
+ group.set_span(delimiter.span.join());
+ TokenTree::Group(group)
+ } else {
+ input.parse()?
+ };
+ tokens.push(token);
+ }
+ Ok(TokenStream::from_iter(tokens))
+}
diff --git a/vendor/miette-derive/src/forward.rs b/vendor/miette-derive/src/forward.rs
new file mode 100644
index 0000000..171019a
--- /dev/null
+++ b/vendor/miette-derive/src/forward.rs
@@ -0,0 +1,161 @@
+use proc_macro2::TokenStream;
+use quote::{format_ident, quote};
+use syn::{
+ parenthesized,
+ parse::{Parse, ParseStream},
+ spanned::Spanned,
+};
+
+pub enum Forward {
+ Unnamed(usize),
+ Named(syn::Ident),
+}
+
+impl Parse for Forward {
+ fn parse(input: ParseStream) -> syn::Result<Self> {
+ let forward = input.parse::<syn::Ident>()?;
+ if forward != "forward" {
+ return Err(syn::Error::new(forward.span(), "msg"));
+ }
+ let content;
+ parenthesized!(content in input);
+ let looky = content.lookahead1();
+ if looky.peek(syn::LitInt) {
+ let int: syn::LitInt = content.parse()?;
+ let index = int.base10_parse()?;
+ return Ok(Forward::Unnamed(index));
+ }
+ Ok(Forward::Named(content.parse()?))
+ }
+}
+
+#[derive(Copy, Clone)]
+pub enum WhichFn {
+ Code,
+ Help,
+ Url,
+ Severity,
+ Labels,
+ SourceCode,
+ Related,
+ DiagnosticSource,
+}
+
+impl WhichFn {
+ pub fn method_call(&self) -> TokenStream {
+ match self {
+ Self::Code => quote! { code() },
+ Self::Help => quote! { help() },
+ Self::Url => quote! { url() },
+ Self::Severity => quote! { severity() },
+ Self::Labels => quote! { labels() },
+ Self::SourceCode => quote! { source_code() },
+ Self::Related => quote! { related() },
+ Self::DiagnosticSource => quote! { diagnostic_source() },
+ }
+ }
+
+ pub fn signature(&self) -> TokenStream {
+ match self {
+ Self::Code => quote! {
+ fn code(& self) -> std::option::Option<std::boxed::Box<dyn std::fmt::Display + '_>>
+ },
+ Self::Help => quote! {
+ fn help(& self) -> std::option::Option<std::boxed::Box<dyn std::fmt::Display + '_>>
+ },
+ Self::Url => quote! {
+ fn url(& self) -> std::option::Option<std::boxed::Box<dyn std::fmt::Display + '_>>
+ },
+ Self::Severity => quote! {
+ fn severity(&self) -> std::option::Option<miette::Severity>
+ },
+ Self::Related => quote! {
+ fn related(&self) -> std::option::Option<std::boxed::Box<dyn std::iter::Iterator<Item = &dyn miette::Diagnostic> + '_>>
+ },
+ Self::Labels => quote! {
+ fn labels(&self) -> std::option::Option<std::boxed::Box<dyn std::iter::Iterator<Item = miette::LabeledSpan> + '_>>
+ },
+ Self::SourceCode => quote! {
+ fn source_code(&self) -> std::option::Option<&dyn miette::SourceCode>
+ },
+ Self::DiagnosticSource => quote! {
+ fn diagnostic_source(&self) -> std::option::Option<&dyn miette::Diagnostic>
+ },
+ }
+ }
+
+ pub fn catchall_arm(&self) -> TokenStream {
+ quote! { _ => std::option::Option::None }
+ }
+}
+
+impl Forward {
+ pub fn for_transparent_field(fields: &syn::Fields) -> syn::Result<Self> {
+ let make_err = || {
+ syn::Error::new(
+ fields.span(),
+ "you can only use #[diagnostic(transparent)] with exactly one field",
+ )
+ };
+ match fields {
+ syn::Fields::Named(named) => {
+ let mut iter = named.named.iter();
+ let field = iter.next().ok_or_else(make_err)?;
+ if iter.next().is_some() {
+ return Err(make_err());
+ }
+ let field_name = field
+ .ident
+ .clone()
+ .unwrap_or_else(|| format_ident!("unnamed"));
+ Ok(Self::Named(field_name))
+ }
+ syn::Fields::Unnamed(unnamed) => {
+ if unnamed.unnamed.iter().len() != 1 {
+ return Err(make_err());
+ }
+ Ok(Self::Unnamed(0))
+ }
+ _ => Err(syn::Error::new(
+ fields.span(),
+ "you cannot use #[diagnostic(transparent)] with a unit struct or a unit variant",
+ )),
+ }
+ }
+
+ pub fn gen_struct_method(&self, which_fn: WhichFn) -> TokenStream {
+ let signature = which_fn.signature();
+ let method_call = which_fn.method_call();
+
+ let field_name = match self {
+ Forward::Named(field_name) => quote!(#field_name),
+ Forward::Unnamed(index) => {
+ let index = syn::Index::from(*index);
+ quote!(#index)
+ }
+ };
+
+ quote! {
+ #[inline]
+ #signature {
+ self.#field_name.#method_call
+ }
+ }
+ }
+
+ pub fn gen_enum_match_arm(&self, variant: &syn::Ident, which_fn: WhichFn) -> TokenStream {
+ let method_call = which_fn.method_call();
+ match self {
+ Forward::Named(field_name) => quote! {
+ Self::#variant { #field_name, .. } => #field_name.#method_call,
+ },
+ Forward::Unnamed(index) => {
+ let underscores: Vec<_> = core::iter::repeat(quote! { _, }).take(*index).collect();
+ let unnamed = format_ident!("unnamed");
+ quote! {
+ Self::#variant ( #(#underscores)* #unnamed, .. ) => #unnamed.#method_call,
+ }
+ }
+ }
+ }
+}
diff --git a/vendor/miette-derive/src/help.rs b/vendor/miette-derive/src/help.rs
new file mode 100644
index 0000000..1c21054
--- /dev/null
+++ b/vendor/miette-derive/src/help.rs
@@ -0,0 +1,146 @@
+use proc_macro2::TokenStream;
+use quote::{format_ident, quote};
+use syn::{
+ parenthesized,
+ parse::{Parse, ParseStream},
+ spanned::Spanned,
+ Fields, Token,
+};
+
+use crate::{
+ diagnostic::{DiagnosticConcreteArgs, DiagnosticDef},
+ utils::{display_pat_members, gen_all_variants_with},
+};
+use crate::{
+ fmt::{self, Display},
+ forward::WhichFn,
+};
+
+pub enum Help {
+ Display(Display),
+ Field(syn::Member, Box<syn::Type>),
+}
+
+impl Parse for Help {
+ fn parse(input: ParseStream) -> syn::Result<Self> {
+ let ident = input.parse::<syn::Ident>()?;
+ if ident == "help" {
+ let la = input.lookahead1();
+ if la.peek(syn::token::Paren) {
+ let content;
+ parenthesized!(content in input);
+ let fmt = content.parse()?;
+ let args = if content.is_empty() {
+ TokenStream::new()
+ } else {
+ fmt::parse_token_expr(&content, false)?
+ };
+ let display = Display {
+ fmt,
+ args,
+ has_bonus_display: false,
+ };
+ Ok(Help::Display(display))
+ } else {
+ input.parse::<Token![=]>()?;
+ Ok(Help::Display(Display {
+ fmt: input.parse()?,
+ args: TokenStream::new(),
+ has_bonus_display: false,
+ }))
+ }
+ } else {
+ Err(syn::Error::new(ident.span(), "not a help"))
+ }
+ }
+}
+
+impl Help {
+ 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("help") {
+ let help = 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(Help::Field(help, Box::new(field.ty.clone()))));
+ }
+ }
+ }
+ Ok(None)
+ }
+ pub(crate) fn gen_enum(variants: &[DiagnosticDef]) -> Option<TokenStream> {
+ gen_all_variants_with(
+ variants,
+ WhichFn::Help,
+ |ident, fields, DiagnosticConcreteArgs { help, .. }| {
+ let (display_pat, display_members) = display_pat_members(fields);
+ match &help.as_ref()? {
+ Help::Display(display) => {
+ let (fmt, args) = display.expand_shorthand_cloned(&display_members);
+ Some(quote! {
+ Self::#ident #display_pat => std::option::Option::Some(std::boxed::Box::new(format!(#fmt #args))),
+ })
+ }
+ Help::Field(member, ty) => {
+ let help = match &member {
+ syn::Member::Named(ident) => ident.clone(),
+ syn::Member::Unnamed(syn::Index { index, .. }) => {
+ format_ident!("_{}", index)
+ }
+ };
+ let var = quote! { __miette_internal_var };
+ Some(quote! {
+ Self::#ident #display_pat => {
+ use miette::macro_helpers::ToOption;
+ miette::macro_helpers::OptionalWrapper::<#ty>::new().to_option(&#help).as_ref().map(|#var| -> std::boxed::Box<dyn std::fmt::Display + '_> { std::boxed::Box::new(format!("{}", #var)) })
+ },
+ })
+ }
+ }
+ },
+ )
+ }
+
+ pub(crate) fn gen_struct(&self, fields: &Fields) -> Option<TokenStream> {
+ let (display_pat, display_members) = display_pat_members(fields);
+ match self {
+ Help::Display(display) => {
+ let (fmt, args) = display.expand_shorthand_cloned(&display_members);
+ Some(quote! {
+ fn help(&self) -> std::option::Option<std::boxed::Box<dyn std::fmt::Display + '_>> {
+ #[allow(unused_variables, deprecated)]
+ let Self #display_pat = self;
+ std::option::Option::Some(std::boxed::Box::new(format!(#fmt #args)))
+ }
+ })
+ }
+ Help::Field(member, ty) => {
+ let var = quote! { __miette_internal_var };
+ Some(quote! {
+ fn help(&self) -> std::option::Option<std::boxed::Box<dyn std::fmt::Display + '_>> {
+ #[allow(unused_variables, deprecated)]
+ let Self #display_pat = self;
+ use miette::macro_helpers::ToOption;
+ miette::macro_helpers::OptionalWrapper::<#ty>::new().to_option(&self.#member).as_ref().map(|#var| -> std::boxed::Box<dyn std::fmt::Display + '_> { std::boxed::Box::new(format!("{}", #var)) })
+ }
+ })
+ }
+ }
+ }
+}
diff --git a/vendor/miette-derive/src/label.rs b/vendor/miette-derive/src/label.rs
new file mode 100644
index 0000000..e0bc70a
--- /dev/null
+++ b/vendor/miette-derive/src/label.rs
@@ -0,0 +1,207 @@
+use proc_macro2::TokenStream;
+use quote::{format_ident, quote};
+use syn::{
+ parenthesized,
+ parse::{Parse, ParseStream},
+ spanned::Spanned,
+ Token,
+};
+
+use crate::{
+ diagnostic::{DiagnosticConcreteArgs, DiagnosticDef},
+ fmt::{self, Display},
+ forward::WhichFn,
+ utils::{display_pat_members, gen_all_variants_with},
+};
+
+pub struct Labels(Vec<Label>);
+
+struct Label {
+ label: Option<Display>,
+ ty: syn::Type,
+ span: syn::Member,
+}
+
+struct LabelAttr {
+ label: Option<Display>,
+}
+
+impl Parse for LabelAttr {
+ fn parse(input: ParseStream) -> syn::Result<Self> {
+ // Skip a token.
+ // This should receive one of:
+ // - label = "..."
+ // - label("...")
+ let _ = input.step(|cursor| {
+ if let Some((_, next)) = cursor.token_tree() {
+ Ok(((), next))
+ } else {
+ Err(cursor.error("unexpected empty attribute"))
+ }
+ });
+ let la = input.lookahead1();
+ let label = if la.peek(syn::token::Paren) {
+ // #[label("{}", x)]
+ let content;
+ parenthesized!(content in input);
+ if content.peek(syn::LitStr) {
+ let fmt = content.parse()?;
+ let args = if content.is_empty() {
+ TokenStream::new()
+ } else {
+ fmt::parse_token_expr(&content, false)?
+ };
+ let display = Display {
+ fmt,
+ args,
+ has_bonus_display: false,
+ };
+ Some(display)
+ } else {
+ return Err(syn::Error::new(input.span(), "Invalid argument to label() attribute. The first argument must be a literal string."));
+ }
+ } else if la.peek(Token![=]) {
+ // #[label = "blabla"]
+ input.parse::<Token![=]>()?;
+ Some(Display {
+ fmt: input.parse()?,
+ args: TokenStream::new(),
+ has_bonus_display: false,
+ })
+ } else {
+ None
+ };
+ Ok(LabelAttr { label })
+ }
+}
+
+impl Labels {
+ pub 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>> {
+ let mut labels = Vec::new();
+ for (i, field) in fields.iter().enumerate() {
+ for attr in &field.attrs {
+ if attr.path().is_ident("label") {
+ let span = if let Some(ident) = field.ident.clone() {
+ syn::Member::Named(ident)
+ } else {
+ syn::Member::Unnamed(syn::Index {
+ index: i as u32,
+ span: field.span(),
+ })
+ };
+ use quote::ToTokens;
+ let LabelAttr { label } =
+ syn::parse2::<LabelAttr>(attr.meta.to_token_stream())?;
+ labels.push(Label {
+ label,
+ span,
+ ty: field.ty.clone(),
+ });
+ }
+ }
+ }
+ if labels.is_empty() {
+ Ok(None)
+ } else {
+ Ok(Some(Labels(labels)))
+ }
+ }
+
+ pub(crate) fn gen_struct(&self, fields: &syn::Fields) -> Option<TokenStream> {
+ let (display_pat, display_members) = display_pat_members(fields);
+ let labels = self.0.iter().map(|highlight| {
+ let Label { span, label, ty } = highlight;
+ let var = quote! { __miette_internal_var };
+ if let Some(display) = label {
+ let (fmt, args) = display.expand_shorthand_cloned(&display_members);
+ quote! {
+ miette::macro_helpers::OptionalWrapper::<#ty>::new().to_option(&self.#span)
+ .map(|#var| miette::LabeledSpan::new_with_span(
+ std::option::Option::Some(format!(#fmt #args)),
+ #var.clone(),
+ ))
+ }
+ } else {
+ quote! {
+ miette::macro_helpers::OptionalWrapper::<#ty>::new().to_option(&self.#span)
+ .map(|#var| miette::LabeledSpan::new_with_span(
+ std::option::Option::None,
+ #var.clone(),
+ ))
+ }
+ }
+ });
+ Some(quote! {
+ #[allow(unused_variables)]
+ fn labels(&self) -> std::option::Option<std::boxed::Box<dyn std::iter::Iterator<Item = miette::LabeledSpan> + '_>> {
+ use miette::macro_helpers::ToOption;
+ let Self #display_pat = self;
+ std::option::Option::Some(Box::new(vec![
+ #(#labels),*
+ ].into_iter().filter(Option::is_some).map(Option::unwrap)))
+ }
+ })
+ }
+
+ pub(crate) fn gen_enum(variants: &[DiagnosticDef]) -> Option<TokenStream> {
+ gen_all_variants_with(
+ variants,
+ WhichFn::Labels,
+ |ident, fields, DiagnosticConcreteArgs { labels, .. }| {
+ let (display_pat, display_members) = display_pat_members(fields);
+ labels.as_ref().and_then(|labels| {
+ let variant_labels = labels.0.iter().map(|label| {
+ let Label { span, label, ty } = label;
+ let field = match &span {
+ syn::Member::Named(ident) => ident.clone(),
+ syn::Member::Unnamed(syn::Index { index, .. }) => {
+ format_ident!("_{}", index)
+ }
+ };
+ let var = quote! { __miette_internal_var };
+ if let Some(display) = label {
+ let (fmt, args) = display.expand_shorthand_cloned(&display_members);
+ quote! {
+ miette::macro_helpers::OptionalWrapper::<#ty>::new().to_option(#field)
+ .map(|#var| miette::LabeledSpan::new_with_span(
+ std::option::Option::Some(format!(#fmt #args)),
+ #var.clone(),
+ ))
+ }
+ } else {
+ quote! {
+ miette::macro_helpers::OptionalWrapper::<#ty>::new().to_option(#field)
+ .map(|#var| miette::LabeledSpan::new_with_span(
+ std::option::Option::None,
+ #var.clone(),
+ ))
+ }
+ }
+ });
+ let variant_name = ident.clone();
+ match &fields {
+ syn::Fields::Unit => None,
+ _ => Some(quote! {
+ Self::#variant_name #display_pat => {
+ use miette::macro_helpers::ToOption;
+ std::option::Option::Some(std::boxed::Box::new(vec![
+ #(#variant_labels),*
+ ].into_iter().filter(Option::is_some).map(Option::unwrap)))
+ }
+ }),
+ }
+ })
+ },
+ )
+ }
+}
diff --git a/vendor/miette-derive/src/lib.rs b/vendor/miette-derive/src/lib.rs
new file mode 100644
index 0000000..0f7e64e
--- /dev/null
+++ b/vendor/miette-derive/src/lib.rs
@@ -0,0 +1,32 @@
+use quote::quote;
+use syn::{parse_macro_input, DeriveInput};
+
+use diagnostic::Diagnostic;
+
+mod code;
+mod diagnostic;
+mod diagnostic_arg;
+mod diagnostic_source;
+mod fmt;
+mod forward;
+mod help;
+mod label;
+mod related;
+mod severity;
+mod source_code;
+mod url;
+mod utils;
+
+#[proc_macro_derive(
+ Diagnostic,
+ attributes(diagnostic, source_code, label, related, help, diagnostic_source)
+)]
+pub fn derive_diagnostic(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
+ let input = parse_macro_input!(input as DeriveInput);
+ let cmd = match Diagnostic::from_derive_input(input) {
+ Ok(cmd) => cmd.gen(),
+ Err(err) => return err.to_compile_error().into(),
+ };
+ // panic!("{:#}", cmd.to_token_stream());
+ quote!(#cmd).into()
+}
diff --git a/vendor/miette-derive/src/related.rs b/vendor/miette-derive/src/related.rs
new file mode 100644
index 0000000..9b7f9e1
--- /dev/null
+++ b/vendor/miette-derive/src/related.rs
@@ -0,0 +1,79 @@
+use proc_macro2::TokenStream;
+use quote::{format_ident, quote};
+use syn::spanned::Spanned;
+
+use crate::{
+ diagnostic::{DiagnosticConcreteArgs, DiagnosticDef},
+ forward::WhichFn,
+ utils::{display_pat_members, gen_all_variants_with},
+};
+
+pub struct Related(syn::Member);
+
+impl Related {
+ 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("related") {
+ let related = 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(Related(related)));
+ }
+ }
+ }
+ Ok(None)
+ }
+
+ pub(crate) fn gen_enum(variants: &[DiagnosticDef]) -> Option<TokenStream> {
+ gen_all_variants_with(
+ variants,
+ WhichFn::Related,
+ |ident, fields, DiagnosticConcreteArgs { related, .. }| {
+ let (display_pat, _display_members) = display_pat_members(fields);
+ related.as_ref().map(|related| {
+ let rel = match &related.0 {
+ syn::Member::Named(ident) => ident.clone(),
+ syn::Member::Unnamed(syn::Index { index, .. }) => {
+ format_ident!("_{}", index)
+ }
+ };
+ quote! {
+ Self::#ident #display_pat => {
+ std::option::Option::Some(std::boxed::Box::new(
+ #rel.iter().map(|x| -> &(dyn miette::Diagnostic) { &*x })
+ ))
+ }
+ }
+ })
+ },
+ )
+ }
+
+ pub(crate) fn gen_struct(&self) -> Option<TokenStream> {
+ let rel = &self.0;
+ Some(quote! {
+ fn related<'a>(&'a self) -> std::option::Option<std::boxed::Box<dyn std::iter::Iterator<Item = &'a dyn miette::Diagnostic> + 'a>> {
+ use ::core::borrow::Borrow;
+ std::option::Option::Some(std::boxed::Box::new(
+ self.#rel.iter().map(|x| -> &(dyn miette::Diagnostic) { &*x.borrow() })
+ ))
+ }
+ })
+ }
+}
diff --git a/vendor/miette-derive/src/severity.rs b/vendor/miette-derive/src/severity.rs
new file mode 100644
index 0000000..4f26e4e
--- /dev/null
+++ b/vendor/miette-derive/src/severity.rs
@@ -0,0 +1,89 @@
+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)
+ }
+ })
+ }
+}
diff --git a/vendor/miette-derive/src/source_code.rs b/vendor/miette-derive/src/source_code.rs
new file mode 100644
index 0000000..62f28e7
--- /dev/null
+++ b/vendor/miette-derive/src/source_code.rs
@@ -0,0 +1,81 @@
+use proc_macro2::TokenStream;
+use quote::{format_ident, quote};
+use syn::spanned::Spanned;
+
+use crate::{
+ diagnostic::{DiagnosticConcreteArgs, DiagnosticDef},
+ forward::WhichFn,
+ utils::{display_pat_members, gen_all_variants_with},
+};
+
+pub struct SourceCode {
+ source_code: syn::Member,
+}
+
+impl SourceCode {
+ pub 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("source_code") {
+ let source_code = 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(SourceCode { source_code }));
+ }
+ }
+ }
+ Ok(None)
+ }
+
+ pub(crate) fn gen_struct(&self, fields: &syn::Fields) -> Option<TokenStream> {
+ let (display_pat, _display_members) = display_pat_members(fields);
+ let src = &self.source_code;
+ Some(quote! {
+ #[allow(unused_variables)]
+ fn source_code(&self) -> std::option::Option<&dyn miette::SourceCode> {
+ let Self #display_pat = self;
+ Some(&self.#src)
+ }
+ })
+ }
+
+ pub(crate) fn gen_enum(variants: &[DiagnosticDef]) -> Option<TokenStream> {
+ gen_all_variants_with(
+ variants,
+ WhichFn::SourceCode,
+ |ident, fields, DiagnosticConcreteArgs { source_code, .. }| {
+ let (display_pat, _display_members) = display_pat_members(fields);
+ source_code.as_ref().and_then(|source_code| {
+ let field = match &source_code.source_code {
+ syn::Member::Named(ident) => ident.clone(),
+ syn::Member::Unnamed(syn::Index { index, .. }) => {
+ format_ident!("_{}", index)
+ }
+ };
+ let variant_name = ident.clone();
+ match &fields {
+ syn::Fields::Unit => None,
+ _ => Some(quote! {
+ Self::#variant_name #display_pat => std::option::Option::Some(#field),
+ }),
+ }
+ })
+ },
+ )
+ }
+}
diff --git a/vendor/miette-derive/src/url.rs b/vendor/miette-derive/src/url.rs
new file mode 100644
index 0000000..734d1a4
--- /dev/null
+++ b/vendor/miette-derive/src/url.rs
@@ -0,0 +1,139 @@
+use proc_macro2::TokenStream;
+use quote::quote;
+use syn::{
+ parenthesized,
+ parse::{Parse, ParseStream},
+ Fields, Token,
+};
+
+use crate::{
+ diagnostic::{DiagnosticConcreteArgs, DiagnosticDef},
+ utils::{display_pat_members, gen_all_variants_with, gen_unused_pat},
+};
+use crate::{
+ fmt::{self, Display},
+ forward::WhichFn,
+};
+
+pub enum Url {
+ Display(Display),
+ DocsRs,
+}
+
+impl Parse for Url {
+ fn parse(input: ParseStream) -> syn::Result<Self> {
+ let ident = input.parse::<syn::Ident>()?;
+ if ident == "url" {
+ let la = input.lookahead1();
+ if la.peek(syn::token::Paren) {
+ let content;
+ parenthesized!(content in input);
+ if content.peek(syn::LitStr) {
+ let fmt = content.parse()?;
+ let args = if content.is_empty() {
+ TokenStream::new()
+ } else {
+ fmt::parse_token_expr(&content, false)?
+ };
+ let display = Display {
+ fmt,
+ args,
+ has_bonus_display: false,
+ };
+ Ok(Url::Display(display))
+ } else {
+ let option = content.parse::<syn::Ident>()?;
+ if option == "docsrs" {
+ Ok(Url::DocsRs)
+ } else {
+ Err(syn::Error::new(option.span(), "Invalid argument to url() sub-attribute. It must be either a string or a plain `docsrs` identifier"))
+ }
+ }
+ } else {
+ input.parse::<Token![=]>()?;
+ Ok(Url::Display(Display {
+ fmt: input.parse()?,
+ args: TokenStream::new(),
+ has_bonus_display: false,
+ }))
+ }
+ } else {
+ Err(syn::Error::new(ident.span(), "not a url"))
+ }
+ }
+}
+
+impl Url {
+ pub(crate) fn gen_enum(
+ enum_name: &syn::Ident,
+ variants: &[DiagnosticDef],
+ ) -> Option<TokenStream> {
+ gen_all_variants_with(
+ variants,
+ WhichFn::Url,
+ |ident, fields, DiagnosticConcreteArgs { url, .. }| {
+ let (pat, fmt, args) = match url.as_ref()? {
+ // fall through to `_ => None` below
+ Url::Display(display) => {
+ let (display_pat, display_members) = display_pat_members(fields);
+ let (fmt, args) = display.expand_shorthand_cloned(&display_members);
+ (display_pat, fmt.value(), args)
+ }
+ Url::DocsRs => {
+ let pat = gen_unused_pat(fields);
+ let fmt =
+ "https://docs.rs/{crate_name}/{crate_version}/{mod_name}/{item_path}"
+ .into();
+ let item_path = format!("enum.{}.html#variant.{}", enum_name, ident);
+ let args = quote! {
+ ,
+ crate_name=env!("CARGO_PKG_NAME"),
+ crate_version=env!("CARGO_PKG_VERSION"),
+ mod_name=env!("CARGO_PKG_NAME").replace('-', "_"),
+ item_path=#item_path
+ };
+ (pat, fmt, args)
+ }
+ };
+ Some(quote! {
+ Self::#ident #pat => std::option::Option::Some(std::boxed::Box::new(format!(#fmt #args))),
+ })
+ },
+ )
+ }
+
+ pub(crate) fn gen_struct(
+ &self,
+ struct_name: &syn::Ident,
+ fields: &Fields,
+ ) -> Option<TokenStream> {
+ let (pat, fmt, args) = match self {
+ Url::Display(display) => {
+ let (display_pat, display_members) = display_pat_members(fields);
+ let (fmt, args) = display.expand_shorthand_cloned(&display_members);
+ (display_pat, fmt.value(), args)
+ }
+ Url::DocsRs => {
+ let pat = gen_unused_pat(fields);
+ let fmt =
+ "https://docs.rs/{crate_name}/{crate_version}/{mod_name}/{item_path}".into();
+ let item_path = format!("struct.{}.html", struct_name);
+ let args = quote! {
+ ,
+ crate_name=env!("CARGO_PKG_NAME"),
+ crate_version=env!("CARGO_PKG_VERSION"),
+ mod_name=env!("CARGO_PKG_NAME").replace('-', "_"),
+ item_path=#item_path
+ };
+ (pat, fmt, args)
+ }
+ };
+ Some(quote! {
+ fn url(&self) -> std::option::Option<std::boxed::Box<dyn std::fmt::Display + '_>> {
+ #[allow(unused_variables, deprecated)]
+ let Self #pat = self;
+ std::option::Option::Some(std::boxed::Box::new(format!(#fmt #args)))
+ }
+ })
+ }
+}
diff --git a/vendor/miette-derive/src/utils.rs b/vendor/miette-derive/src/utils.rs
new file mode 100644
index 0000000..b867849
--- /dev/null
+++ b/vendor/miette-derive/src/utils.rs
@@ -0,0 +1,140 @@
+use proc_macro2::TokenStream;
+use quote::{format_ident, quote, ToTokens};
+use syn::{
+ parse::{Parse, ParseStream},
+ spanned::Spanned,
+};
+
+pub(crate) enum MemberOrString {
+ Member(syn::Member),
+ String(syn::LitStr),
+}
+
+impl ToTokens for MemberOrString {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ use MemberOrString::*;
+ match self {
+ Member(member) => member.to_tokens(tokens),
+ String(string) => string.to_tokens(tokens),
+ }
+ }
+}
+
+impl Parse for MemberOrString {
+ fn parse(input: ParseStream) -> syn::Result<Self> {
+ let lookahead = input.lookahead1();
+ if lookahead.peek(syn::Ident) || lookahead.peek(syn::LitInt) {
+ Ok(MemberOrString::Member(input.parse()?))
+ } else if lookahead.peek(syn::LitStr) {
+ Ok(MemberOrString::String(input.parse()?))
+ } else {
+ Err(syn::Error::new(
+ input.span(),
+ "Expected a string or a field reference.",
+ ))
+ }
+ }
+}
+
+use crate::{
+ diagnostic::{DiagnosticConcreteArgs, DiagnosticDef},
+ forward::WhichFn,
+};
+
+pub(crate) fn gen_all_variants_with(
+ variants: &[DiagnosticDef],
+ which_fn: WhichFn,
+ mut f: impl FnMut(&syn::Ident, &syn::Fields, &DiagnosticConcreteArgs) -> Option<TokenStream>,
+) -> Option<TokenStream> {
+ let pairs = variants
+ .iter()
+ .filter_map(|def| {
+ def.args
+ .forward_or_override_enum(&def.ident, which_fn, |concrete| {
+ f(&def.ident, &def.fields, concrete)
+ })
+ })
+ .collect::<Vec<_>>();
+ if pairs.is_empty() {
+ return None;
+ }
+ let signature = which_fn.signature();
+ let catchall = which_fn.catchall_arm();
+ Some(quote! {
+ #signature {
+ #[allow(unused_variables, deprecated)]
+ match self {
+ #(#pairs)*
+ #catchall
+ }
+ }
+ })
+}
+
+use crate::fmt::Display;
+use std::collections::HashSet;
+
+pub(crate) fn gen_unused_pat(fields: &syn::Fields) -> TokenStream {
+ match fields {
+ syn::Fields::Named(_) => quote! { { .. } },
+ syn::Fields::Unnamed(_) => quote! { ( .. ) },
+ syn::Fields::Unit => quote! {},
+ }
+}
+
+/// Goes in the slot `let Self #pat = self;` or `match self { Self #pat => ...
+/// }`.
+fn gen_fields_pat(fields: &syn::Fields) -> TokenStream {
+ let member_idents = fields.iter().enumerate().map(|(i, field)| {
+ field
+ .ident
+ .as_ref()
+ .cloned()
+ .unwrap_or_else(|| format_ident!("_{}", i))
+ });
+ match fields {
+ syn::Fields::Named(_) => quote! {
+ { #(#member_idents),* }
+ },
+ syn::Fields::Unnamed(_) => quote! {
+ ( #(#member_idents),* )
+ },
+ syn::Fields::Unit => quote! {},
+ }
+}
+
+/// The returned tokens go in the slot `let Self #pat = self;` or `match self {
+/// Self #pat => ... }`. The members can be passed to
+/// `Display::expand_shorthand[_cloned]`.
+pub(crate) fn display_pat_members(fields: &syn::Fields) -> (TokenStream, HashSet<syn::Member>) {
+ let pat = gen_fields_pat(fields);
+ let members: HashSet<syn::Member> = fields
+ .iter()
+ .enumerate()
+ .map(|(i, field)| {
+ if let Some(ident) = field.ident.as_ref().cloned() {
+ syn::Member::Named(ident)
+ } else {
+ syn::Member::Unnamed(syn::Index {
+ index: i as u32,
+ span: field.span(),
+ })
+ }
+ })
+ .collect();
+ (pat, members)
+}
+
+impl Display {
+ /// Returns `(fmt, args)` which must be passed to some kind of format macro
+ /// without tokens in between, i.e. `format!(#fmt #args)`.
+ pub(crate) fn expand_shorthand_cloned(
+ &self,
+ members: &HashSet<syn::Member>,
+ ) -> (syn::LitStr, TokenStream) {
+ let mut display = self.clone();
+ display.expand_shorthand(members);
+ let Display { fmt, args, .. } = display;
+ (fmt, args)
+ }
+}