From f98876d0cd5715bc3508749ee79cd0826a168f2b Mon Sep 17 00:00:00 2001 From: Benjamin Lee Date: Fri, 3 Nov 2023 23:16:31 -0700 Subject: [PATCH] fix graphical bug when empty span not aligned to char boundary MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previous output looked like this: ---- single_line_with_wide_char_unaligned_span_empty stdout ---- Error: oops::my::bad × oops! ╭─[bad_file.rs:2:4] 1 │ source 2 │ 👼🏼text · ─▲ · ╰── this bit here 3 │ here ╰──── help: try doing it better next time? Note that the .max(start + 1) term is still necessary in the nonempty branch, since it's possible to have a nonempty span covering zero-width text. --- src/handlers/graphical.rs | 6 +++++- tests/graphical.rs | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src/handlers/graphical.rs b/src/handlers/graphical.rs index 44d92b7..82f2f9b 100644 --- a/src/handlers/graphical.rs +++ b/src/handlers/graphical.rs @@ -718,7 +718,11 @@ impl GraphicalReportHandler { let byte_start = hl.offset(); let byte_end = hl.offset() + hl.len(); let start = self.visual_offset(line, byte_start, true).max(highest); - let end = self.visual_offset(line, byte_end, false).max(start + 1); + let end = if hl.len() == 0 { + start + 1 + } else { + self.visual_offset(line, byte_end, false).max(start + 1) + }; let vbar_offset = (start + end) / 2; let num_left = vbar_offset - start; diff --git a/tests/graphical.rs b/tests/graphical.rs index 31db4dc..d24879a 100644 --- a/tests/graphical.rs +++ b/tests/graphical.rs @@ -1321,3 +1321,40 @@ fn single_line_with_wide_char_unaligned_span_end() -> Result<(), MietteError> { assert_eq!(expected, out); Ok(()) } + +#[test] +fn single_line_with_wide_char_unaligned_span_empty() -> Result<(), MietteError> { + #[derive(Debug, Diagnostic, Error)] + #[error("oops!")] + #[diagnostic(code(oops::my::bad), help("try doing it better next time?"))] + struct MyBad { + #[source_code] + src: NamedSource, + #[label("this bit here")] + highlight: SourceSpan, + } + + let src = "source\n 👼🏼text\n here".to_string(); + let err = MyBad { + src: NamedSource::new("bad_file.rs", src), + highlight: (10, 0).into(), + }; + let out = fmt_report(err.into()); + println!("Error: {}", out); + let expected = r#"oops::my::bad + + × oops! + ╭─[bad_file.rs:2:4] + 1 │ source + 2 │ 👼🏼text + · ▲ + · ╰── this bit here + 3 │ here + ╰──── + help: try doing it better next time? +"# + .trim_start() + .to_string(); + assert_eq!(expected, out); + Ok(()) +}