Skip to content

Commit dd59d12

Browse files
committed
Support for transparent
1 parent 81c0ad5 commit dd59d12

File tree

3 files changed

+92
-35
lines changed

3 files changed

+92
-35
lines changed

errful-derive/src/lib.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ struct BasicOptions {
2929

3030
/// The severity of the error
3131
severity: Option<syn::Path>,
32+
33+
/// Don’t show the error message for this error when printing a chain
34+
#[darling(default)]
35+
transparent: bool,
3236
}
3337

3438
type Data = ast::Data<EnumVariant, StructField>;
@@ -91,6 +95,14 @@ pub fn derive_errful(input: proc_macro::TokenStream) -> proc_macro::TokenStream
9195
|severity| quote! { &#severity },
9296
);
9397

98+
let transparent_fn = generate_required_value_function(
99+
&opts,
100+
Ident::new("transparent", Span::call_site()),
101+
quote! { bool },
102+
|o| o.transparent,
103+
|transparent| quote! { #transparent },
104+
);
105+
94106
let source_code = find_source_code(&opts.data)?;
95107
let source_code = source_code.map(|source_code| {
96108
quote! {
@@ -117,6 +129,7 @@ pub fn derive_errful(input: proc_macro::TokenStream) -> proc_macro::TokenStream
117129
#url_fn
118130
#code_fn
119131
#severity_fn
132+
#transparent_fn
120133
#labels_fn
121134
#source_code
122135
}
@@ -403,6 +416,45 @@ fn generate_value_function<'a, T: ?Sized + 'a>(
403416
})
404417
}
405418

419+
fn generate_required_value_function<'a, T: 'a>(
420+
opts: &'a Opts,
421+
name: proc_macro2::Ident,
422+
result_t: TokenStream,
423+
proj: impl Fn(&'a BasicOptions) -> T,
424+
quote_t: impl Fn(T) -> TokenStream,
425+
) -> TokenStream {
426+
if let ast::Data::Enum(variants) = &opts.data {
427+
let cases = Vec::from_iter(variants.iter().map(|v| {
428+
let ident = &v.ident;
429+
let quoted = quote_t(proj(&v.basic));
430+
quote! { Self::#ident{..} => #quoted, }
431+
}));
432+
433+
if !cases.is_empty() {
434+
let base_case = {
435+
let quoted = quote_t(proj(&opts.basic));
436+
quote! { _ => #quoted, }
437+
};
438+
439+
return quote! {
440+
fn #name(&self) -> #result_t {
441+
match self {
442+
#(#cases)*
443+
#base_case
444+
}
445+
}
446+
};
447+
}
448+
}
449+
450+
let quoted = quote_t(proj(&opts.basic));
451+
quote! {
452+
fn #name(&self) -> #result_t {
453+
#quoted
454+
}
455+
}
456+
}
457+
406458
fn provide_value<'a, T: ?Sized + 'a>(
407459
opts: &'a Opts,
408460
request: &Ident,

errful/src/formatting/pretty.rs

Lines changed: 34 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,8 @@ impl PrettyDisplay<'_> {
9090
writeln!(f, "{}", line)?;
9191
}
9292

93-
let errful = err.errful();
94-
9593
// output any additional information
96-
self.render_sourcelabels(body_indent, errful, colors, f)?;
94+
self.render_sourcelabels(body_indent, err, colors, f)?;
9795

9896
Ok(())
9997
}
@@ -171,49 +169,50 @@ impl Display for PrettyDisplay<'_> {
171169

172170
// TODO: termwidth
173171
let body_indent = format!("{}", base_color.style(" │ "));
172+
let message_indent = format!("{}", base_color.style(" │ "));
174173
let wrap_opts = if let Some(width) = self.width {
175174
textwrap::Options::new(width)
176175
} else {
177176
textwrap::Options::with_termwidth()
178177
}
179178
.subsequent_indent(&body_indent);
180179

181-
let first_indent = format!(
182-
"{} 0 {} ",
183-
base_color.style(severity.symbol()),
184-
base_color.style("┐")
185-
);
186-
187-
self.print_chain_entry(
188-
f,
189-
wrap_opts.clone().initial_indent(&first_indent),
190-
&body_indent,
191-
err,
192-
&mut colors,
193-
)?;
194-
195-
// message must be indented one more level than the body
196-
let message_indent = format!("{}", base_color.style(" │ "));
197-
198-
let mut index = 1;
199-
let mut next = err.source();
180+
let mut index = 0;
181+
let mut next: Option<&dyn std::error::Error> = Some(self.err);
200182
while let Some(err) = next {
201-
// `:3`: if someone has nested errors a thousand layers deep, i can’t save them
202-
let first_indent = format!("{index:3} {} ", base_color.style("├▷"));
203-
self.print_chain_entry(
204-
f,
205-
wrap_opts
206-
.clone()
207-
.initial_indent(&first_indent)
208-
.subsequent_indent(&message_indent),
209-
&body_indent,
210-
err.errful(),
211-
&mut colors,
212-
)?;
183+
let enhanced = err.errful();
184+
if !enhanced.transparent() {
185+
let first_indent = if index == 0 {
186+
format!(
187+
"{} 0 {} ",
188+
base_color.style(severity.symbol()),
189+
base_color.style("┐")
190+
)
191+
} else {
192+
format!("{index:3} {} ", base_color.style("├▷"))
193+
};
194+
195+
self.print_chain_entry(
196+
f,
197+
if index == 0 {
198+
wrap_opts.clone().initial_indent(&first_indent)
199+
} else {
200+
// message must be indented one more level than the body
201+
wrap_opts
202+
.clone()
203+
.initial_indent(&first_indent)
204+
.subsequent_indent(&message_indent)
205+
},
206+
&body_indent,
207+
enhanced,
208+
&mut colors,
209+
)?;
210+
211+
index += 1;
212+
}
213213

214214
// proceed
215215
next = err.source();
216-
index += 1;
217216
}
218217

219218
// terminate the chain

errful/src/protocol.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,12 @@ pub trait Errful: Error {
142142
fn labels(&self) -> Option<Vec<Label>> {
143143
None
144144
}
145+
146+
/// Whether or not this error should be skipped when printing
147+
/// cause chains.
148+
fn transparent(&self) -> bool {
149+
false
150+
}
145151
}
146152

147153
pub struct Label<'a> {

0 commit comments

Comments
 (0)