diff --git a/src/renderer/render.rs b/src/renderer/render.rs index 283fe77..8cf7ffa 100644 --- a/src/renderer/render.rs +++ b/src/renderer/render.rs @@ -1721,6 +1721,14 @@ fn emit_suggestion_default( // logic to show the whole prior snippet, but the current output is not // too bad to begin with, so we side-step that issue here. for (i, line) in snippet.lines().enumerate() { + let tabs: usize = line + .chars() + .take(span_start.char) + .map(|ch| match ch { + '\t' => 3, + _ => 0, + }) + .sum(); let line = normalize_whitespace(line); // Going lower than buffer_offset (+ 1) would mean // overwriting existing content in the buffer @@ -1732,26 +1740,36 @@ fn emit_suggestion_default( // the column of the part span end. // On all others, we highlight the whole line. let start = if i == 0 { - (padding as isize + span_start_pos as isize) as usize + (padding as isize + (span_start.char + tabs) as isize) as usize } else { padding }; let end = if i == 0 { - (padding as isize + span_start_pos as isize + line.len() as isize) + (padding as isize + + (span_start.char + tabs) as isize + + line.chars().count() as isize) as usize } else if i == newlines - 1 { - (padding as isize + span_end_pos as isize) as usize + (padding as isize + (span_end.char + tabs) as isize) as usize } else { - (padding as isize + line.len() as isize) as usize + (padding as isize + line.chars().count() as isize) as usize }; buffer.set_style_range(row, start, end, ElementStyle::Removal, true); } } else { + let tabs: usize = snippet + .chars() + .take(span_start.char) + .map(|ch| match ch { + '\t' => 3, + _ => 0, + }) + .sum(); // The removed code fits all in one line. buffer.set_style_range( row_num - 2, - (padding as isize + span_start_pos as isize) as usize, - (padding as isize + span_end_pos as isize) as usize, + (padding as isize + (span_start.char + tabs) as isize) as usize, + (padding as isize + (span_end.char + tabs) as isize) as usize, ElementStyle::Removal, true, ); diff --git a/tests/color/highlight_diff_line_with_wide_characters.ascii.term.svg b/tests/color/highlight_diff_line_with_wide_characters.ascii.term.svg new file mode 100644 index 0000000..de62e3c --- /dev/null +++ b/tests/color/highlight_diff_line_with_wide_characters.ascii.term.svg @@ -0,0 +1,54 @@ + + + + + + + error[E0422]: cannot find struct, variant or union type `哈哈哈哈` in this scope + + --> $DIR/highlight_diff_line_with_wide_characters.rs:3:18 + + | + + 1 | struct 啊啊啊啊 {} + + | ------------------ similarly named struct `啊啊啊啊` defined here + + 2 | + + 3 | const 哦哦: 啊啊啊啊 = 哈哈哈哈 {}; // some comment + + | ^^^^^^^^ here + + | + + help: a struct with a similar name exists: `啊啊啊啊` + + | + + 3 - const 哦哦: 啊啊啊啊 = 哈哈哈哈 {}; // some comment + + 3 + const 哦哦: 啊啊啊啊 = 啊啊啊啊 {}; // some comment + + | + + + + diff --git a/tests/color/highlight_diff_line_with_wide_characters.rs b/tests/color/highlight_diff_line_with_wide_characters.rs new file mode 100644 index 0000000..ec29de7 --- /dev/null +++ b/tests/color/highlight_diff_line_with_wide_characters.rs @@ -0,0 +1,44 @@ +use annotate_snippets::{renderer::DecorStyle, AnnotationKind, Level, Patch, Renderer, Snippet}; + +use snapbox::{assert_data_eq, file}; + +#[test] +fn case() { + let source = r#"struct 啊啊啊啊 {} + +const 哦哦: 啊啊啊啊 = 哈哈哈哈 {}; // some comment"#; + + let path = "$DIR/highlight_diff_line_with_wide_characters.rs"; + + let report = &[ + Level::ERROR + .primary_title("cannot find struct, variant or union type `哈哈哈哈` in this scope") + .id("E0422") + .element( + Snippet::source(source) + .path(path) + .annotation(AnnotationKind::Primary.span(53..65).label("here")) + .annotation( + AnnotationKind::Context + .span(0..22) + .label("similarly named struct `啊啊啊啊` defined here"), + ), + ), + Level::HELP + .secondary_title("a struct with a similar name exists: `啊啊啊啊`") + .element( + Snippet::source(source) + .path(path) + .patch(Patch::new(53..65, "啊啊啊啊")), + ), + ]; + + let expected_ascii = file!["highlight_diff_line_with_wide_characters.ascii.term.svg": TermSvg]; + let renderer = Renderer::styled(); + assert_data_eq!(renderer.render(report), expected_ascii); + + let expected_unicode = + file!["highlight_diff_line_with_wide_characters.unicode.term.svg": TermSvg]; + let renderer = renderer.decor_style(DecorStyle::Unicode); + assert_data_eq!(renderer.render(report), expected_unicode); +} diff --git a/tests/color/highlight_diff_line_with_wide_characters.unicode.term.svg b/tests/color/highlight_diff_line_with_wide_characters.unicode.term.svg new file mode 100644 index 0000000..fe3154e --- /dev/null +++ b/tests/color/highlight_diff_line_with_wide_characters.unicode.term.svg @@ -0,0 +1,54 @@ + + + + + + + error[E0422]: cannot find struct, variant or union type `哈哈哈哈` in this scope + + ╭▸ $DIR/highlight_diff_line_with_wide_characters.rs:3:18 + + + + 1 struct 啊啊啊啊 {} + + ────────────────── similarly named struct `啊啊啊啊` defined here + + 2 + + 3 const 哦哦: 啊啊啊啊 = 哈哈哈哈 {}; // some comment + + ━━━━━━━━ here + + ╰╴ + + help: a struct with a similar name exists: `啊啊啊啊` + + ╭╴ + + 3 - const 哦哦: 啊啊啊啊 = 哈哈哈哈 {}; // some comment + + 3 + const 哦哦: 啊啊啊啊 = 啊啊啊啊 {}; // some comment + + ╰╴ + + + + diff --git a/tests/color/main.rs b/tests/color/main.rs index 7d78f4b..77ec70f 100644 --- a/tests/color/main.rs +++ b/tests/color/main.rs @@ -9,6 +9,7 @@ mod fold_ann_multiline; mod fold_bad_origin_line; mod fold_leading; mod fold_trailing; +mod highlight_diff_line_with_wide_characters; mod highlight_duplicated_diff_lines; mod highlight_source; mod issue_9;