Skip to content

Commit

Permalink
fix(graphical): render cause chains for inner errors (#330)
Browse files Browse the repository at this point in the history
The default `GraphicalReportHandler` disables the printing of cause
chains for any inner errors (errors `related()` to a source diagnostic)
when it disables nested footer printing. This results in lost cause
chain information when printing with the default report handler.
  • Loading branch information
TheLostLambda authored Jan 31, 2024
1 parent 55bfc42 commit cb2ae2e
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 6 deletions.
16 changes: 10 additions & 6 deletions src/handlers/graphical.rs
Original file line number Diff line number Diff line change
Expand Up @@ -317,9 +317,10 @@ impl GraphicalReportHandler {
ErrorKind::Diagnostic(diag) => {
let mut inner = String::new();

// Don't print footer for inner errors
let mut inner_renderer = self.clone();
// Don't print footer for inner errors
inner_renderer.footer = None;
// Cause chains are already flattened, so don't double-print the nested error
inner_renderer.with_cause_chain = false;
inner_renderer.render_report(&mut inner, diag)?;

Expand Down Expand Up @@ -362,19 +363,22 @@ impl GraphicalReportHandler {
parent_src: Option<&dyn SourceCode>,
) -> fmt::Result {
if let Some(related) = diagnostic.related() {
let mut inner_renderer = self.clone();
// Re-enable the printing of nested cause chains for related errors
inner_renderer.with_cause_chain = true;
writeln!(f)?;
for rel in related {
match rel.severity() {
Some(Severity::Error) | None => write!(f, "Error: ")?,
Some(Severity::Warning) => write!(f, "Warning: ")?,
Some(Severity::Advice) => write!(f, "Advice: ")?,
};
self.render_header(f, rel)?;
self.render_causes(f, rel)?;
inner_renderer.render_header(f, rel)?;
inner_renderer.render_causes(f, rel)?;
let src = rel.source_code().or(parent_src);
self.render_snippets(f, rel, src)?;
self.render_footer(f, rel)?;
self.render_related(f, rel, src)?;
inner_renderer.render_snippets(f, rel, src)?;
inner_renderer.render_footer(f, rel)?;
inner_renderer.render_related(f, rel, src)?;
}
}
Ok(())
Expand Down
82 changes: 82 additions & 0 deletions tests/test_diagnostic_source_macro.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,3 +194,85 @@ fn test_nested_diagnostic_source_is_output() {

assert_eq!(expected, out);
}

#[derive(Debug, miette::Diagnostic, thiserror::Error)]
#[error("A multi-error happened")]
struct MultiError {
#[related]
related_errs: Vec<Box<dyn Diagnostic>>,
}

#[cfg(feature = "fancy-no-backtrace")]
#[test]
fn test_nested_cause_chains_for_related_errors_are_output() {
let inner_error = TestStructError {
asdf_inner_foo: SourceError {
code: String::from("This is another error"),
help: String::from("You should fix this"),
label: (3, 4),
},
};
let first_error = NestedError {
code: String::from("right here"),
label: (6, 4),
the_other_err: Box::new(inner_error),
};
let second_error = SourceError {
code: String::from("You're actually a mess"),
help: String::from("Get a grip..."),
label: (3, 4),
};
let multi_error = MultiError {
related_errs: vec![Box::new(first_error), Box::new(second_error)],
};
let diag = NestedError {
code: String::from("the outside world"),
label: (6, 4),
the_other_err: Box::new(multi_error),
};
let mut out = String::new();
miette::GraphicalReportHandler::new_themed(miette::GraphicalTheme::unicode_nocolor())
.with_width(80)
.with_footer("Yooo, a footer".to_string())
.render_report(&mut out, &diag)
.unwrap();
println!("{}", out);

let expected = r#" × A nested error happened
╰─▶ × A multi-error happened
Error: × A nested error happened
├─▶ × TestError
╰─▶ × A complex error happened
╭────
1 │ This is another error
· ──┬─
· ╰── here
╰────
help: You should fix this
╭────
1 │ right here
· ──┬─
· ╰── here
╰────
Error: × A complex error happened
╭────
1 │ You're actually a mess
· ──┬─
· ╰── here
╰────
help: Get a grip...
╭────
1 │ the outside world
· ──┬─
· ╰── here
╰────
Yooo, a footer
"#;

assert_eq!(expected, out);
}

0 comments on commit cb2ae2e

Please sign in to comment.