Skip to content

Commit

Permalink
fix(graphical): fix wrapping of related errors
Browse files Browse the repository at this point in the history
  • Loading branch information
TheLostLambda committed Mar 27, 2024
1 parent 4426f9c commit 786d11b
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 24 deletions.
5 changes: 3 additions & 2 deletions src/handlers/graphical.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,16 +265,15 @@ impl GraphicalReportHandler {
);
write!(header, "{}", link)?;
writeln!(f, "{}", header)?;
writeln!(f)?;
} else if let Some(code) = diagnostic.code() {
write!(header, "{}", code.style(severity_style),)?;
if self.links == LinkStyle::Text && diagnostic.url().is_some() {
let url = diagnostic.url().unwrap(); // safe
write!(header, " ({})", url.style(self.theme.styles.link))?;
}
writeln!(f, "{}", header)?;
writeln!(f)?;
}
writeln!(f)?;
Ok(())
}

Expand Down Expand Up @@ -358,6 +357,8 @@ impl GraphicalReportHandler {
inner_renderer.termwidth -= rest_indent.width();
inner_renderer.render_report(&mut inner, diag)?;

// If there was no header, remove the leading newline
let inner = inner.trim_start_matches('\n');
writeln!(f, "{}", self.wrap(&inner, opts))?;
}
ErrorKind::StdError(err) => {
Expand Down
130 changes: 114 additions & 16 deletions tests/graphical.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,15 @@ fn word_wrap_options() -> Result<(), MietteError> {
let out =
fmt_report_with_settings(Report::msg("abcdefghijklmnopqrstuvwxyz"), |handler| handler);

let expected = " × abcdefghijklmnopqrstuvwxyz\n".to_string();
let expected = "\n × abcdefghijklmnopqrstuvwxyz\n".to_string();
assert_eq!(expected, out);

// A long word can break with a smaller width
let out = fmt_report_with_settings(Report::msg("abcdefghijklmnopqrstuvwxyz"), |handler| {
handler.with_width(10)
});
let expected = r#" × abcd
let expected = r#"
× abcd
│ efgh
│ ijkl
│ mnop
Expand All @@ -81,15 +82,16 @@ fn word_wrap_options() -> Result<(), MietteError> {
let out = fmt_report_with_settings(Report::msg("abcdefghijklmnopqrstuvwxyz"), |handler| {
handler.with_width(10).with_break_words(false)
});
let expected = " × abcdefghijklmnopqrstuvwxyz\n".to_string();
let expected = "\n × abcdefghijklmnopqrstuvwxyz\n".to_string();
assert_eq!(expected, out);

// Breaks should start at the boundary of each word if possible
let out = fmt_report_with_settings(
Report::msg("12 123 1234 12345 123456 1234567 1234567890"),
|handler| handler.with_width(10),
);
let expected = r#" × 12
let expected = r#"
× 12
│ 123
│ 1234
│ 1234
Expand All @@ -110,7 +112,8 @@ fn word_wrap_options() -> Result<(), MietteError> {
Report::msg("12 123 1234 12345 123456 1234567 1234567890"),
|handler| handler.with_width(10).with_break_words(false),
);
let expected = r#" × 12
let expected = r#"
× 12
│ 123
│ 1234
│ 12345
Expand All @@ -126,7 +129,8 @@ fn word_wrap_options() -> Result<(), MietteError> {
Report::msg("a-b a-b-c a-b-c-d a-b-c-d-e a-b-c-d-e-f a-b-c-d-e-f-g a-b-c-d-e-f-g-h"),
|handler| handler.with_width(10).with_break_words(false),
);
let expected = r#" × a-b
let expected = r#"
× a-b
│ a-b-
│ c a-
│ b-c-
Expand Down Expand Up @@ -158,7 +162,8 @@ fn word_wrap_options() -> Result<(), MietteError> {
.with_word_splitter(textwrap::WordSplitter::NoHyphenation)
},
);
let expected = r#" × a-b
let expected = r#"
× a-b
│ a-b-c
│ a-b-c-d
│ a-b-c-d-e
Expand All @@ -174,7 +179,8 @@ fn word_wrap_options() -> Result<(), MietteError> {
Report::msg("a/b a/b/c a/b/c/d a/b/c/d/e a/b/c/d/e/f a/b/c/d/e/f/g a/b/c/d/e/f/g/h"),
|handler| handler.with_width(10).with_break_words(false),
);
let expected = r#" × a/b
let expected = r#"
× a/b
│ a/b/
│ c a/
│ b/c/
Expand Down Expand Up @@ -206,7 +212,8 @@ fn word_wrap_options() -> Result<(), MietteError> {
.with_word_separator(textwrap::WordSeparator::AsciiSpace)
},
);
let expected = r#" × a/b
let expected = r#"
× a/b
│ a/b/c
│ a/b/c/d
│ a/b/c/d/e
Expand All @@ -227,7 +234,8 @@ fn wrap_option() -> Result<(), MietteError> {
Report::msg("abc def ghi jkl mno pqr stu vwx yz abc def ghi jkl mno pqr stu vwx yz"),
|handler| handler.with_width(15),
);
let expected = r#" × abc def
let expected = r#"
× abc def
│ ghi jkl
│ mno pqr
│ stu vwx
Expand All @@ -246,15 +254,16 @@ fn wrap_option() -> Result<(), MietteError> {
|handler| handler.with_width(15).with_wrap_lines(false),
);
let expected =
" × abc def ghi jkl mno pqr stu vwx yz abc def ghi jkl mno pqr stu vwx yz\n".to_string();
"\n × abc def ghi jkl mno pqr stu vwx yz abc def ghi jkl mno pqr stu vwx yz\n".to_string();
assert_eq!(expected, out);

// Then, user-defined new lines should be preserved wrapping is disabled
let out = fmt_report_with_settings(
Report::msg("abc def ghi jkl mno pqr stu vwx yz\nabc def ghi jkl mno pqr stu vwx yz\nabc def ghi jkl mno pqr stu vwx yz"),
|handler| handler.with_width(15).with_wrap_lines(false),
);
let expected = r#" × abc def ghi jkl mno pqr stu vwx yz
let expected = r#"
× abc def ghi jkl mno pqr stu vwx yz
│ abc def ghi jkl mno pqr stu vwx yz
│ abc def ghi jkl mno pqr stu vwx yz
"#
Expand Down Expand Up @@ -314,6 +323,91 @@ fn wrapping_nested_errors() -> Result<(), MietteError> {
Ok(())
}

#[test]
fn wrapping_related_errors() -> Result<(), MietteError> {
#[derive(Debug, Diagnostic, Error)]
#[error("This is the parent error, the error withhhhh the children, kiddos, pups, as it were, and so on...")]
#[diagnostic(
code(mama::error),
help(
"try doing it better next time? I mean, you could have also done better thisssss time, but no?"
)
)]
struct MamaError {
#[diagnostic_source]
baby: BrotherError,
}

#[derive(Debug, Diagnostic, Error)]
#[error("Welcome to the brother-error brotherhood — where all of the wee baby errors join into a formidable force")]
#[diagnostic(code(brother::error))]
struct BrotherError {
#[related]
brethren: Vec<Box<dyn Diagnostic + Send + Sync>>,
}

#[derive(Debug, Diagnostic, Error)]
#[error("Wah wah: I may be small, but I'll cause a proper bout of trouble — justt try wrapping this mess of a line, buddo!")]
#[diagnostic(help(
"it cannot be helped... woulddddddd you really want to get rid of an error that's so cute?"
))]
struct BabyError;

#[derive(Debug, Diagnostic, Error)]
#[error("Wah wah: I may be small, but I'll cause a proper bout of trouble — justt try wrapping this mess of a line, buddo!")]
#[diagnostic(severity(Warning))]
struct BabyWarning;

#[derive(Debug, Diagnostic, Error)]
#[error("Wah wah: I may be small, but I'll cause a proper bout of trouble — justt try wrapping this mess of a line, buddo!")]
#[diagnostic(severity(Advice))]
struct BabyAdvice;

let err = MamaError {
baby: BrotherError {
brethren: vec![BabyError.into(), BabyWarning.into(), BabyAdvice.into()],
},
};
let out = fmt_report_with_settings(err.into(), |handler| handler.with_width(50));
let expected = r#"mama::error
× This is the parent error, the error withhhhh
│ the children, kiddos, pups, as it were, and
│ so on...
╰─▶ brother::error
× Welcome to the brother-error
│ brotherhood — where all of the wee
│ baby errors join into a formidable
│ force
Error:
× Wah wah: I may be small, but I'll
│ cause a proper bout of trouble — justt
│ try wrapping this mess of a line,
│ buddo!
help: it cannot be helped... woulddddddd
you really want to get rid of an
error that's so cute?
Warning:
⚠ Wah wah: I may be small, but I'll
│ cause a proper bout of trouble — justt
│ try wrapping this mess of a line,
│ buddo!
Advice:
☞ Wah wah: I may be small, but I'll
│ cause a proper bout of trouble — justt
│ try wrapping this mess of a line,
│ buddo!
help: try doing it better next time? I mean,
you could have also done better thisssss
time, but no?
"#;
assert_eq!(expected, out);
Ok(())
}

#[test]
fn empty_source() -> Result<(), MietteError> {
#[derive(Debug, Diagnostic, Error)]
Expand Down Expand Up @@ -376,7 +470,8 @@ if true {
let out = fmt_report(err.into());
println!("Error: {}", out);

let expected = r#" × oops!
let expected = r#"
× oops!
╭─[issue:1:1]
1 │ ╭─▶ if true {
2 │ │ a
Expand Down Expand Up @@ -411,7 +506,8 @@ fn single_line_highlight_span_full_line() {
let out = fmt_report(err.into());
println!("Error: {}", out);

let expected = r#" × oops!
let expected = r#"
× oops!
╭─[issue:2:1]
1 │ source
2 │ text
Expand Down Expand Up @@ -1673,7 +1769,8 @@ fn zero_length_eol_span() {
let out = fmt_report(err.into());
println!("Error: {}", out);

let expected = r#" × oops!
let expected = r#"
× oops!
╭─[issue:2:1]
1 │ this is the first line
2 │ this is the second line
Expand Down Expand Up @@ -1707,7 +1804,8 @@ fn primary_label() {
println!("Error: {}", out);

// line 2 should be the primary, not line 1
let expected = r#" × oops!
let expected = r#"
× oops!
╭─[issue:2:2]
1 │ this is the first line
· ────
Expand Down
18 changes: 12 additions & 6 deletions tests/test_diagnostic_source_macro.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,8 @@ fn test_diagnostic_source_pass_extra_info() {
.render_report(&mut out, &diag)
.unwrap();
println!("Error: {}", out);
let expected = r#" × TestError
let expected = r#"
× TestError
╰─▶ × A complex error happened
╭─[1:2]
1 │ Hello
Expand Down Expand Up @@ -138,7 +139,8 @@ fn test_diagnostic_source_is_output() {
.unwrap();
println!("{}", out);

let expected = r#" × TestError
let expected = r#"
× TestError
╰─▶ × A complex error happened
╭────
1 │ right here
Expand Down Expand Up @@ -186,7 +188,8 @@ fn test_nested_diagnostic_source_is_output() {
.unwrap();
println!("{}", out);

let expected = r#" × A nested error happened
let expected = r#"
× A nested error happened
├─▶ × TestError
╰─▶ × A complex error happened
Expand Down Expand Up @@ -252,10 +255,12 @@ fn test_nested_cause_chains_for_related_errors_are_output() {
.unwrap();
println!("{}", out);

let expected = r#" × A nested error happened
let expected = r#"
× A nested error happened
╰─▶ × A multi-error happened
Error: × A nested error happened
Error:
× A nested error happened
├─▶ × TestError
╰─▶ × A complex error happened
Expand All @@ -271,7 +276,8 @@ fn test_nested_cause_chains_for_related_errors_are_output() {
· ──┬─
· ╰── here
╰────
Error: × A complex error happened
Error:
× A complex error happened
╭────
1 │ You're actually a mess
· ──┬─
Expand Down

0 comments on commit 786d11b

Please sign in to comment.