mirror of https://github.com/zkat/miette.git
Add tests, fix remaining bug in label implementation, make label implementation strictly more flexible using to_owned over clone
Signed-off-by: Justus Fluegel <justusfluegel@gmail.com> Signed-off-by: Justus Flügel <justusfluegel@gmail.com>
This commit is contained in:
parent
89d30a3b37
commit
37f9e979de
|
|
@ -208,10 +208,14 @@ impl Labels {
|
||||||
Some(quote! {
|
Some(quote! {
|
||||||
miette::macro_helpers::OptionalWrapper::<#ty>::new().to_option(&self.#span)
|
miette::macro_helpers::OptionalWrapper::<#ty>::new().to_option(&self.#span)
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|#var| #ctor(
|
.map(|#var| {
|
||||||
#display,
|
use ::std::borrow::ToOwned;
|
||||||
(*#var).clone(),
|
|
||||||
))
|
#ctor(
|
||||||
|
#display,
|
||||||
|
(*#var).to_owned(),
|
||||||
|
)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
let collections_chain = self.0.iter().filter_map(|label| {
|
let collections_chain = self.0.iter().filter_map(|label| {
|
||||||
|
|
@ -236,7 +240,8 @@ impl Labels {
|
||||||
let display = #display;
|
let display = #display;
|
||||||
::std::iter::IntoIterator::into_iter(&self.#span).map(move |span| {
|
::std::iter::IntoIterator::into_iter(&self.#span).map(move |span| {
|
||||||
use miette::macro_helpers::{ToLabelSpanWrapper,ToLabeledSpan};
|
use miette::macro_helpers::{ToLabelSpanWrapper,ToLabeledSpan};
|
||||||
let mut labeled_span = ToLabelSpanWrapper::to_labeled_span(span.clone());
|
use ::std::borrow::ToOwned;
|
||||||
|
let mut labeled_span = ToLabelSpanWrapper::to_labeled_span(span.to_owned());
|
||||||
if display.is_some() && labeled_span.label().is_none() {
|
if display.is_some() && labeled_span.label().is_none() {
|
||||||
labeled_span.set_label(display.clone())
|
labeled_span.set_label(display.clone())
|
||||||
}
|
}
|
||||||
|
|
@ -296,10 +301,15 @@ impl Labels {
|
||||||
|
|
||||||
Some(quote! {
|
Some(quote! {
|
||||||
miette::macro_helpers::OptionalWrapper::<#ty>::new().to_option(#field)
|
miette::macro_helpers::OptionalWrapper::<#ty>::new().to_option(#field)
|
||||||
.map(|#var| #ctor(
|
.as_ref()
|
||||||
#display,
|
.map(|#var| {
|
||||||
#var.clone(),
|
use ::std::borrow::ToOwned;
|
||||||
))
|
|
||||||
|
#ctor(
|
||||||
|
#display,
|
||||||
|
(*#var).to_owned(),
|
||||||
|
)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
let collections_chain = labels.0.iter().filter_map(|label| {
|
let collections_chain = labels.0.iter().filter_map(|label| {
|
||||||
|
|
@ -322,9 +332,12 @@ impl Labels {
|
||||||
Some(quote! {
|
Some(quote! {
|
||||||
.chain({
|
.chain({
|
||||||
let display = #display;
|
let display = #display;
|
||||||
#field.iter().map(move |span| {
|
::std::iter::IntoIterator::into_iter(#field).map(move |span| {
|
||||||
use miette::macro_helpers::{ToLabelSpanWrapper,ToLabeledSpan};
|
use miette::macro_helpers::{ToLabelSpanWrapper,ToLabeledSpan};
|
||||||
let mut labeled_span = ToLabelSpanWrapper::to_labeled_span(span.clone());
|
use ::std::borrow::ToOwned;
|
||||||
|
let mut labeled_span = ToLabelSpanWrapper::to_labeled_span(
|
||||||
|
span.to_owned()
|
||||||
|
);
|
||||||
if display.is_some() && labeled_span.label().is_none() {
|
if display.is_some() && labeled_span.label().is_none() {
|
||||||
labeled_span.set_label(display.clone());
|
labeled_span.set_label(display.clone());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,8 @@ pub struct RequiredTraitBound {
|
||||||
source_code: bool,
|
source_code: bool,
|
||||||
into_source_span: bool,
|
into_source_span: bool,
|
||||||
std_into_iter: bool,
|
std_into_iter: bool,
|
||||||
std_clone: bool,
|
std_deref: bool,
|
||||||
|
std_to_owned: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RequiredTraitBound {
|
impl RequiredTraitBound {
|
||||||
|
|
@ -56,9 +57,13 @@ impl RequiredTraitBound {
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.std_clone {
|
if self.std_deref {
|
||||||
|
bounds.push(TypeParamBound::Trait(syn::parse_quote!(::std::ops::Deref)))
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.std_to_owned {
|
||||||
bounds.push(TypeParamBound::Trait(syn::parse_quote!(
|
bounds.push(TypeParamBound::Trait(syn::parse_quote!(
|
||||||
::std::clone::Clone
|
::std::borrow::ToOwned
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -80,7 +85,6 @@ impl RequiredTraitBound {
|
||||||
|
|
||||||
fn register_label_usage(&mut self) {
|
fn register_label_usage(&mut self) {
|
||||||
self.into_source_span = true;
|
self.into_source_span = true;
|
||||||
self.std_clone = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn register_collection_usage(&mut self) {
|
fn register_collection_usage(&mut self) {
|
||||||
|
|
@ -95,6 +99,14 @@ impl RequiredTraitBound {
|
||||||
self.miette_diagnostic = true;
|
self.miette_diagnostic = true;
|
||||||
self.r#static = true;
|
self.r#static = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn register_deref_usage(&mut self) {
|
||||||
|
self.std_deref = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn register_to_owned_usage(&mut self) {
|
||||||
|
self.std_to_owned = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TraitBoundStore(HashMap<(Option<BoundLifetimes>, Type), RequiredTraitBound>);
|
pub struct TraitBoundStore(HashMap<(Option<BoundLifetimes>, Type), RequiredTraitBound>);
|
||||||
|
|
@ -354,12 +366,22 @@ impl TraitBoundStore {
|
||||||
pub fn register_label_usage(&mut self, r#type: &Type) {
|
pub fn register_label_usage(&mut self, r#type: &Type) {
|
||||||
let r#type = Self::extract_option(r#type).unwrap_or(r#type);
|
let r#type = Self::extract_option(r#type).unwrap_or(r#type);
|
||||||
|
|
||||||
let Some(r#type) = self.check_generic_usage(r#type) else {
|
let Some(ty) = self.check_generic_usage(r#type) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let type_opts = self.0.entry((None, r#type.clone())).or_default();
|
let type_opts = self.0.entry((None, ty.clone())).or_default();
|
||||||
type_opts.register_label_usage()
|
|
||||||
|
type_opts.register_to_owned_usage();
|
||||||
|
|
||||||
|
let type_opts_to_owned = self
|
||||||
|
.0
|
||||||
|
.entry((
|
||||||
|
None,
|
||||||
|
syn::parse_quote!(<#ty as ::std::borrow::ToOwned>::Owned),
|
||||||
|
))
|
||||||
|
.or_default();
|
||||||
|
type_opts_to_owned.register_label_usage();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn register_label_collection_usage(&mut self, r#type: &Type) {
|
pub fn register_label_collection_usage(&mut self, r#type: &Type) {
|
||||||
|
|
@ -385,7 +407,25 @@ impl TraitBoundStore {
|
||||||
syn::parse_quote!(<#ty as ::std::iter::IntoIterator>::Item),
|
syn::parse_quote!(<#ty as ::std::iter::IntoIterator>::Item),
|
||||||
))
|
))
|
||||||
.or_default();
|
.or_default();
|
||||||
type_opts_item.register_label_usage();
|
type_opts_item.register_deref_usage();
|
||||||
|
|
||||||
|
let type_opts_deref_item = self
|
||||||
|
.0
|
||||||
|
.entry((
|
||||||
|
Some(syn::parse_quote!(for<'__miette_internal_lt>)),
|
||||||
|
syn::parse_quote!(<<#ty as ::std::iter::IntoIterator>::Item as ::std::ops::Deref>::Target),
|
||||||
|
))
|
||||||
|
.or_default();
|
||||||
|
type_opts_deref_item.register_to_owned_usage();
|
||||||
|
|
||||||
|
let type_opts_deref_to_owned_item = self
|
||||||
|
.0
|
||||||
|
.entry((
|
||||||
|
Some(syn::parse_quote!(for<'__miette_internal_lt>)),
|
||||||
|
syn::parse_quote!(<<<#ty as ::std::iter::IntoIterator>::Item as ::std::ops::Deref>::Target as ::std::borrow::ToOwned>::Owned),
|
||||||
|
))
|
||||||
|
.or_default();
|
||||||
|
type_opts_deref_to_owned_item.register_label_usage();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn register_related_usage(&mut self, r#type: &Type) {
|
pub fn register_related_usage(&mut self, r#type: &Type) {
|
||||||
|
|
|
||||||
|
|
@ -145,3 +145,133 @@ fn attr_not_required() {
|
||||||
let expectation = LabeledSpan::new(Some("this bit here".into()), 9usize, 4usize);
|
let expectation = LabeledSpan::new(Some("this bit here".into()), 9usize, 4usize);
|
||||||
assert_eq!(err_span, expectation);
|
assert_eq!(err_span, expectation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn assert_impl_diagnostic<T: Diagnostic>() {}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn transparent_generic() {
|
||||||
|
#[derive(Debug, Diagnostic, Error)]
|
||||||
|
enum Combined<T> {
|
||||||
|
#[error(transparent)]
|
||||||
|
#[diagnostic(transparent)]
|
||||||
|
Other(T),
|
||||||
|
#[error("foo")]
|
||||||
|
Custom,
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_impl_diagnostic::<Combined<miette::MietteDiagnostic>>();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn generic_label() {
|
||||||
|
#[derive(Debug, Diagnostic, Error)]
|
||||||
|
#[error("foo")]
|
||||||
|
struct Combined<T> {
|
||||||
|
#[label]
|
||||||
|
label: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_impl_diagnostic::<Combined<SourceSpan>>();
|
||||||
|
assert_impl_diagnostic::<Combined<(usize, usize)>>();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn generic_source_code() {
|
||||||
|
#[derive(Debug, Diagnostic, Error)]
|
||||||
|
#[error("foo")]
|
||||||
|
struct Combined<T> {
|
||||||
|
#[source_code]
|
||||||
|
label: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_impl_diagnostic::<Combined<String>>();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn generic_optional_source_code() {
|
||||||
|
#[derive(Debug, Diagnostic, Error)]
|
||||||
|
#[error("foo")]
|
||||||
|
struct Combined<T> {
|
||||||
|
#[source_code]
|
||||||
|
label: Option<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_impl_diagnostic::<Combined<String>>();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn generic_label_primary() {
|
||||||
|
#[derive(Debug, Diagnostic, Error)]
|
||||||
|
#[error("foo")]
|
||||||
|
struct Combined<T> {
|
||||||
|
#[label(primary)]
|
||||||
|
label: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_impl_diagnostic::<Combined<SourceSpan>>();
|
||||||
|
assert_impl_diagnostic::<Combined<(usize, usize)>>();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn generic_label_collection() {
|
||||||
|
#[derive(Debug, Diagnostic, Error)]
|
||||||
|
#[error("foo")]
|
||||||
|
struct Combined<T> {
|
||||||
|
#[label(collection)]
|
||||||
|
label: Vec<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_impl_diagnostic::<Combined<SourceSpan>>();
|
||||||
|
assert_impl_diagnostic::<Combined<(usize, usize)>>();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn generic_label_generic_collection() {
|
||||||
|
#[derive(Debug, Diagnostic, Error)]
|
||||||
|
#[error("foo")]
|
||||||
|
struct Combined<T> {
|
||||||
|
#[label(collection)]
|
||||||
|
label: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_impl_diagnostic::<Combined<Vec<SourceSpan>>>();
|
||||||
|
assert_impl_diagnostic::<Combined<Vec<(usize, usize)>>>();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn generic_related() {
|
||||||
|
#[derive(Debug, Diagnostic, Error)]
|
||||||
|
#[error("foo")]
|
||||||
|
struct Combined<T> {
|
||||||
|
#[related]
|
||||||
|
label: Vec<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_impl_diagnostic::<Combined<miette::MietteDiagnostic>>();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn generic_diagnostic_source() {
|
||||||
|
#[derive(Debug, Diagnostic, Error)]
|
||||||
|
enum Combined<T> {
|
||||||
|
#[error(transparent)]
|
||||||
|
Other(#[diagnostic_source] T),
|
||||||
|
#[error("foo")]
|
||||||
|
Custom,
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_impl_diagnostic::<Combined<miette::MietteDiagnostic>>();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn generic_not_influencing_default() {
|
||||||
|
#[derive(Debug, Diagnostic, Error)]
|
||||||
|
enum Combined<T> {
|
||||||
|
#[error("bar")]
|
||||||
|
Other(T),
|
||||||
|
#[error("foo")]
|
||||||
|
Custom,
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_impl_diagnostic::<Combined<i32>>();
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue