Skip to content

Commit f4e3c96

Browse files
committed
fix(diagnostics): preserve wrapped source text
1 parent 8e81a06 commit f4e3c96

1 file changed

Lines changed: 86 additions & 1 deletion

File tree

src/editor/rendering.rs

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3072,7 +3072,10 @@ impl Editor {
30723072
if line_width > segment.end_col {
30733073
continue;
30743074
}
3075-
let content_end = gutter_width + 1 + line_width.saturating_sub(segment.start_col);
3075+
let content_end = gutter_width
3076+
+ 1
3077+
+ segment.visual_offset
3078+
+ line_width.saturating_sub(segment.start_col);
30763079
let indicator_x = content_end + 5; // Add some padding
30773080

30783081
// Skip if diagnostic would be outside window
@@ -4296,6 +4299,88 @@ mod tests {
42964299
assert_eq!(display_width(&row), 2);
42974300
}
42984301

4302+
#[test]
4303+
fn wrapped_diagnostic_does_not_overwrite_indented_continuation() {
4304+
let root = tempfile::tempdir().unwrap();
4305+
let path = root.path().join("wrapped-diagnostic.rs");
4306+
let line = format!("{}{}SOURCE_TAIL", " ".repeat(12), "x".repeat(50));
4307+
let source = Buffer::new(
4308+
Some(path.to_string_lossy().into_owned()),
4309+
format!("{line}\nfollowing source\n"),
4310+
);
4311+
let mut editor = rendering_test_editor(source);
4312+
let uri = editor.current_buffer().uri().unwrap().unwrap();
4313+
editor
4314+
.diagnostics
4315+
.insert(uri, vec![diagnostic("wrapped diagnostic")]);
4316+
let mut buffer = RenderBuffer::new(60, 12, &Style::default());
4317+
4318+
editor.render(&mut buffer).unwrap();
4319+
4320+
let window = editor.active_window_with_editor_view().unwrap();
4321+
let layout = editor.layout_for_window(&window);
4322+
let continuation = layout
4323+
.rows
4324+
.iter()
4325+
.rev()
4326+
.find(|segment| segment.line == 0)
4327+
.unwrap();
4328+
assert!(!continuation.first_segment);
4329+
assert!(continuation.visual_offset > 5);
4330+
let rows = rendered_rows(&buffer);
4331+
let row = &rows[continuation.row];
4332+
assert!(
4333+
row.contains("SOURCE_TAIL"),
4334+
"diagnostic overwrote source: {row}"
4335+
);
4336+
let source_end = row.find("SOURCE_TAIL").unwrap() + "SOURCE_TAIL".len();
4337+
let diagnostic_start = row.find('■').expect("diagnostic should remain visible");
4338+
assert!(
4339+
diagnostic_start > source_end,
4340+
"diagnostic overlaps source: {row}"
4341+
);
4342+
}
4343+
4344+
#[test]
4345+
fn wrapped_diagnostic_is_hidden_when_continuation_has_no_room() {
4346+
let root = tempfile::tempdir().unwrap();
4347+
let path = root.path().join("cramped-diagnostic.rs");
4348+
let line = format!("{}{}SOURCE_TAIL", " ".repeat(12), "x".repeat(75));
4349+
let source = Buffer::new(
4350+
Some(path.to_string_lossy().into_owned()),
4351+
format!("{line}\nfollowing source\n"),
4352+
);
4353+
let mut editor = rendering_test_editor(source);
4354+
let uri = editor.current_buffer().uri().unwrap().unwrap();
4355+
editor
4356+
.diagnostics
4357+
.insert(uri, vec![diagnostic("cramped diagnostic")]);
4358+
let mut buffer = RenderBuffer::new(60, 12, &Style::default());
4359+
4360+
editor.render(&mut buffer).unwrap();
4361+
4362+
let window = editor.active_window_with_editor_view().unwrap();
4363+
let layout = editor.layout_for_window(&window);
4364+
let continuation = layout
4365+
.rows
4366+
.iter()
4367+
.rev()
4368+
.find(|segment| segment.line == 0)
4369+
.unwrap();
4370+
assert!(!continuation.first_segment);
4371+
let rows = rendered_rows(&buffer);
4372+
let row = &rows[continuation.row];
4373+
assert!(
4374+
row.contains("SOURCE_TAIL"),
4375+
"diagnostic overwrote source: {row}"
4376+
);
4377+
assert!(
4378+
!row.contains('■'),
4379+
"cramped diagnostic should be hidden: {row}"
4380+
);
4381+
assert!(rows.iter().any(|line| line.contains("following source")));
4382+
}
4383+
42994384
#[test]
43004385
fn diagnostics_grouping_ignores_offscreen_lines() {
43014386
let mut first_visible = diagnostic("first visible");

0 commit comments

Comments
 (0)