diff --git a/Cargo.toml b/Cargo.toml index 0533533d..3703f793 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,6 +25,7 @@ unicode-width = { version = "0.1.8", optional = true } supports-hyperlinks = { version = "1.1.0", optional = true } supports-color = { version = "1.0.2", optional = true } supports-unicode = { version = "1.0.0", optional = true } +itertools = { version = "0.10.1", optional = true } [dev-dependencies] semver = "1.0.4" @@ -47,7 +48,8 @@ fancy = [ "unicode-width", "supports-hyperlinks", "supports-color", - "supports-unicode" + "supports-unicode", + "itertools" ] [workspace] diff --git a/miette-derive/src/diagnostic.rs b/miette-derive/src/diagnostic.rs index db75868c..50d47c4e 100644 --- a/miette-derive/src/diagnostic.rs +++ b/miette-derive/src/diagnostic.rs @@ -6,8 +6,9 @@ use crate::code::Code; use crate::diagnostic_arg::DiagnosticArg; use crate::forward::{Forward, WhichFn}; use crate::help::Help; +use crate::label::Labels; use crate::severity::Severity; -use crate::snippets::Snippets; +use crate::source_code::SourceCode; use crate::url::Url; pub enum Diagnostic { @@ -32,7 +33,7 @@ pub struct DiagnosticDef { pub enum DiagnosticDefArgs { Transparent(Forward), - Concrete(DiagnosticConcreteArgs), + Concrete(Box), } impl DiagnosticDefArgs { @@ -59,7 +60,8 @@ pub struct DiagnosticConcreteArgs { pub code: Option, pub severity: Option, pub help: Option, - pub snippets: Option, + pub labels: Option, + pub source_code: Option, pub url: Option, pub forward: Option, } @@ -99,14 +101,16 @@ impl DiagnosticConcreteArgs { } } } - let snippets = Snippets::from_fields(fields)?; + let labels = Labels::from_fields(fields)?; + let source_code = SourceCode::from_fields(fields)?; let concrete = DiagnosticConcreteArgs { code, help, severity, - snippets, + labels, url, forward, + source_code, }; Ok(concrete) } @@ -141,7 +145,7 @@ impl DiagnosticDefArgs { .into_iter() .filter(|x| !matches!(x, DiagnosticArg::Transparent)); let concrete = DiagnosticConcreteArgs::parse(ident, fields, attr, args)?; - Ok(DiagnosticDefArgs::Concrete(concrete)) + Ok(DiagnosticDefArgs::Concrete(Box::new(concrete))) } } @@ -208,16 +212,18 @@ impl Diagnostic { 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 snippets_method = forward.gen_struct_method(WhichFn::Snippets); quote! { impl #impl_generics miette::Diagnostic for #ident #ty_generics #where_clause { #code_method #help_method #url_method + #labels_method #severity_method - #snippets_method + #source_code_method } } } @@ -243,24 +249,29 @@ impl Diagnostic { .as_ref() .and_then(|x| x.gen_struct()) .or_else(|| forward(WhichFn::Severity)); - let snip_body = concrete - .snippets - .as_ref() - .and_then(|x| x.gen_struct(fields)) - .or_else(|| forward(WhichFn::Snippets)); 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)); quote! { impl #impl_generics miette::Diagnostic for #ident #ty_generics #where_clause { #code_body #help_body #sev_body - #snip_body #url_body + #labels_body + #src_body } } } @@ -275,14 +286,16 @@ impl Diagnostic { let code_body = Code::gen_enum(variants); let help_body = Help::gen_enum(variants); let sev_body = Severity::gen_enum(variants); - let snip_body = Snippets::gen_enum(variants); + let labels_body = Labels::gen_enum(variants); + let src_body = SourceCode::gen_enum(variants); let url_body = Url::gen_enum(ident, variants); quote! { impl #impl_generics miette::Diagnostic for #ident #ty_generics #where_clause { #code_body #help_body #sev_body - #snip_body + #labels_body + #src_body #url_body } } diff --git a/miette-derive/src/forward.rs b/miette-derive/src/forward.rs index 36177d62..3d765ab4 100644 --- a/miette-derive/src/forward.rs +++ b/miette-derive/src/forward.rs @@ -35,7 +35,8 @@ pub enum WhichFn { Help, Url, Severity, - Snippets, + Labels, + SourceCode, } impl WhichFn { @@ -45,7 +46,8 @@ impl WhichFn { Self::Help => quote! { help() }, Self::Url => quote! { url() }, Self::Severity => quote! { severity() }, - Self::Snippets => quote! { snippets() }, + Self::Labels => quote! { labels() }, + Self::SourceCode => quote! { source_code() }, } } @@ -63,11 +65,11 @@ impl WhichFn { Self::Severity => quote! { fn severity(&self) -> std::option::Option }, - Self::Snippets => quote! { - fn snippets(&self) -> std::option::Option + '_>> + Self::Labels => quote! { + fn labels(&self) -> std::option::Option + '_>> }, - Self::Related => quote! { - fn related<'a>(&'a self) -> std::option::Option + 'a>> + Self::SourceCode => quote! { + fn source_code(&self) -> std::option::Option<&dyn miette::SourceCode> }, } } diff --git a/miette-derive/src/label.rs b/miette-derive/src/label.rs new file mode 100644 index 00000000..5aed7623 --- /dev/null +++ b/miette-derive/src/label.rs @@ -0,0 +1,179 @@ +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