Skip to content

Commit 75fea09

Browse files
authoredFeb 17, 2024··
fix(label-collections): Label collection fixes and cleanup (#343)
* feat(collection): add label(collection) documentation to lib.rs * feat(collection): remove repeated formatting of label text Because of a typo, the label text was being formatted multiple times per label in a collection. With the fix, the text is formatted only once per collection * feat(collection): chain iterators rather than extend vector Since we are going to iterate anyway, instead of growing the label vector, chain the iterators. This should be more efficient. In some cases, this also remove a compilation warning about the label vector being unnecessarily mutable. * feat(collection): remove unnecessary `OptionalWrapper` - In a label collection, there is no need for a `None` label. One should just not add that label - Code wise it is also incorrect. The wrapper will be for a vector of spans, not for individual spans. It happens to work anyway, but this was not the intended use.
1 parent a18a644 commit 75fea09

File tree

2 files changed

+88
-38
lines changed

2 files changed

+88
-38
lines changed
 

‎miette-derive/src/label.rs

+36-38
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,6 @@ impl Labels {
162162

163163
pub(crate) fn gen_struct(&self, fields: &syn::Fields) -> Option<TokenStream> {
164164
let (display_pat, display_members) = display_pat_members(fields);
165-
let labels_gen_var = quote! { labels };
166165
let labels = self.0.iter().filter_map(|highlight| {
167166
let Label {
168167
span,
@@ -194,11 +193,11 @@ impl Labels {
194193
))
195194
})
196195
});
197-
let collections = self.0.iter().filter_map(|label| {
196+
let collections_chain = self.0.iter().filter_map(|label| {
198197
let Label {
199198
span,
200199
label,
201-
ty,
200+
ty: _,
202201
lbl_ty,
203202
} = label;
204203
if *lbl_ty != LabelType::Collection {
@@ -211,18 +210,17 @@ impl Labels {
211210
quote! { std::option::Option::None }
212211
};
213212
Some(quote! {
214-
let display = #display;
215-
#labels_gen_var.extend(self.#span.iter().map(|label| {
216-
miette::macro_helpers::OptionalWrapper::<#ty>::new().to_option(label)
217-
.map(|span| {
218-
use miette::macro_helpers::{ToLabelSpanWrapper,ToLabeledSpan};
219-
let mut labeled_span = ToLabelSpanWrapper::to_labeled_span(span.clone());
220-
if #display.is_some() && labeled_span.label().is_none() {
221-
labeled_span.set_label(#display)
222-
}
223-
labeled_span
224-
})
225-
}));
213+
.chain({
214+
let display = #display;
215+
self.#span.iter().map(move |span| {
216+
use miette::macro_helpers::{ToLabelSpanWrapper,ToLabeledSpan};
217+
let mut labeled_span = ToLabelSpanWrapper::to_labeled_span(span.clone());
218+
if display.is_some() && labeled_span.label().is_none() {
219+
labeled_span.set_label(display.clone())
220+
}
221+
Some(labeled_span)
222+
})
223+
})
226224
})
227225
});
228226

@@ -232,12 +230,13 @@ impl Labels {
232230
use miette::macro_helpers::ToOption;
233231
let Self #display_pat = self;
234232

235-
let mut #labels_gen_var = vec![
233+
let labels_iter = vec![
236234
#(#labels),*
237-
];
238-
#(#collections)*
235+
]
236+
.into_iter()
237+
#(#collections_chain)*;
239238

240-
std::option::Option::Some(Box::new(#labels_gen_var.into_iter().filter(Option::is_some).map(Option::unwrap)))
239+
std::option::Option::Some(Box::new(labels_iter.filter(Option::is_some).map(Option::unwrap)))
241240
}
242241
})
243242
}
@@ -249,7 +248,6 @@ impl Labels {
249248
|ident, fields, DiagnosticConcreteArgs { labels, .. }| {
250249
let (display_pat, display_members) = display_pat_members(fields);
251250
labels.as_ref().and_then(|labels| {
252-
let labels_gen_var = quote! { labels };
253251
let variant_labels = labels.0.iter().filter_map(|label| {
254252
let Label { span, label, ty, lbl_ty } = label;
255253
if *lbl_ty == LabelType::Collection {
@@ -282,8 +280,8 @@ impl Labels {
282280
))
283281
})
284282
});
285-
let collections = labels.0.iter().filter_map(|label| {
286-
let Label { span, label, ty, lbl_ty } = label;
283+
let collections_chain = labels.0.iter().filter_map(|label| {
284+
let Label { span, label, ty: _, lbl_ty } = label;
287285
if *lbl_ty != LabelType::Collection {
288286
return None;
289287
}
@@ -300,18 +298,17 @@ impl Labels {
300298
quote! { std::option::Option::None }
301299
};
302300
Some(quote! {
303-
let display = #display;
304-
#labels_gen_var.extend(#field.iter().map(|label| {
305-
miette::macro_helpers::OptionalWrapper::<#ty>::new().to_option(label)
306-
.map(|span| {
307-
use miette::macro_helpers::{ToLabelSpanWrapper,ToLabeledSpan};
308-
let mut labeled_span = ToLabelSpanWrapper::to_labeled_span(span.clone());
309-
if #display.is_some() && labeled_span.label().is_none() {
310-
labeled_span.set_label(#display)
311-
}
312-
labeled_span
313-
})
314-
}));
301+
.chain({
302+
let display = #display;
303+
#field.iter().map(move |span| {
304+
use miette::macro_helpers::{ToLabelSpanWrapper,ToLabeledSpan};
305+
let mut labeled_span = ToLabelSpanWrapper::to_labeled_span(span.clone());
306+
if display.is_some() && labeled_span.label().is_none() {
307+
labeled_span.set_label(display.clone());
308+
}
309+
Some(labeled_span)
310+
})
311+
})
315312
})
316313
});
317314
let variant_name = ident.clone();
@@ -320,11 +317,12 @@ impl Labels {
320317
_ => Some(quote! {
321318
Self::#variant_name #display_pat => {
322319
use miette::macro_helpers::ToOption;
323-
let mut #labels_gen_var = vec![
320+
let labels_iter = vec![
324321
#(#variant_labels),*
325-
];
326-
#(#collections)*
327-
std::option::Option::Some(std::boxed::Box::new(#labels_gen_var.into_iter().filter(Option::is_some).map(Option::unwrap)))
322+
]
323+
.into_iter()
324+
#(#collections_chain)*;
325+
std::option::Option::Some(std::boxed::Box::new(labels_iter.filter(Option::is_some).map(Option::unwrap)))
328326
}
329327
}),
330328
}

‎src/lib.rs

+52
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
//! - [... handler options](#-handler-options)
4949
//! - [... dynamic diagnostics](#-dynamic-diagnostics)
5050
//! - [... syntax highlighting](#-syntax-highlighting)
51+
//! - [... collection of labels](#-collection-of-labels)
5152
//! - [Acknowledgements](#acknowledgements)
5253
//! - [License](#license)
5354
//!
@@ -672,6 +673,57 @@
672673
//! [`with_syntax_highlighting`](MietteHandlerOpts::with_syntax_highlighting)
673674
//! method. See the [`highlighters`] module docs for more details.
674675
//!
676+
//! ### ... collection of labels
677+
//!
678+
//! When the number of labels is unknown, you can use a collection of `SourceSpan`
679+
//! (or any type convertible into `SourceSpan`). For this, add the `collection`
680+
//! parameter to `label` and use any type than can be iterated over for the field.
681+
//!
682+
//! ```rust,ignore
683+
//! #[derive(Debug, Diagnostic, Error)]
684+
//! #[error("oops!")]
685+
//! struct MyError {
686+
//! #[label("main issue")]
687+
//! primary_span: SourceSpan,
688+
//!
689+
//! #[label(collection, "related to this")]
690+
//! other_spans: Vec<Range<usize>>,
691+
//! }
692+
//!
693+
//! let report: miette::Report = MyError {
694+
//! primary_span: (6, 9).into(),
695+
//! other_spans: vec![19..26, 30..41],
696+
//! }.into();
697+
//!
698+
//! println!("{:?}", report.with_source_code("About something or another or yet another ...".to_string()));
699+
//! ```
700+
//!
701+
//! A collection can also be of `LabeledSpan` if you want to have different text
702+
//! for different labels. Labels with no text will use the one from the `label`
703+
//! attribute
704+
//!
705+
//! ```rust,ignore
706+
//! #[derive(Debug, Diagnostic, Error)]
707+
//! #[error("oops!")]
708+
//! struct MyError {
709+
//! #[label("main issue")]
710+
//! primary_span: SourceSpan,
711+
//!
712+
//! #[label(collection, "related to this")]
713+
//! other_spans: Vec<LabeledSpan>, // LabeledSpan
714+
//! }
715+
//!
716+
//! let report: miette::Report = MyError {
717+
//! primary_span: (6, 9).into(),
718+
//! other_spans: vec![
719+
//! LabeledSpan::new(None, 19, 7), // Use default text `related to this`
720+
//! LabeledSpan::new(Some("and also this".to_string()), 30, 11), // Use specific text
721+
//! ],
722+
//! }.into();
723+
//!
724+
//! println!("{:?}", report.with_source_code("About something or another or yet another ...".to_string()));
725+
//! ```
726+
//!
675727
//! ## MSRV
676728
//!
677729
//! This crate requires rustc 1.70.0 or later.

0 commit comments

Comments
 (0)
Please sign in to comment.