fix: preserve visible declaration names under scope overlays

This commit is contained in:
Valdemar Lorenzen
2026-10-16 11:22:17 +02:00
parent d654522ad4
commit 7b950210b8
3 changed files with 56 additions and 1 deletions
+53
View File
@@ -4166,6 +4166,31 @@ fn draw_diff_scope_labels(
let Some(y) = y.checked_sub(1).filter(|&y| y >= content.y) else {
continue;
};
let previous = &viewport.rows[screen - 1];
let previous_focus = if unified {
diff.display_focus(previous.position.display)
.unwrap_or(focus)
} else {
focus
};
let previous_side = usize::from(previous_focus == Focus::After);
if previous.scope == [false; 2]
&& let Some(previous_scope) =
syntax.scopes(diff, previous.position.display)[previous_side]
&& diff.display_source_row(previous_focus, previous.position.display)
== Some(previous_scope.name.row)
{
let source = if previous_side == 0 {
&file.before
} else {
&file.after
};
let prefix = &source[previous_scope.name.row][..previous_scope.name.column];
let column = display_column(prefix, usize::MAX);
if lefts[pane] <= column && column < lefts[pane].saturating_add(width) {
continue;
}
}
y
} else {
if !row.scope[side] {
@@ -8349,6 +8374,34 @@ mod tests {
}
}
#[test]
fn diff_scope_overlay_preserves_visible_declaration_above() {
let before = "pub fn old_name() {\n shared_call_with_a_long_argument_name();\n}\n";
let after = "fn new_name() {\n shared_call_with_a_long_argument_name();\n}\n";
for focus in [Focus::Before, Focus::After] {
let mut file = syntax_diff_file("scope.rs", before, after);
file.hunks = crate::diff::line_hunks(&file.before, false, &file.after, false);
let mut diff = diff_comparison(vec![file]);
diff.files_visible = false;
diff.set_view_mode(ViewMode::Unified);
diff.focus = focus;
diff.top = diff.source_display_row(Focus::Before, 0).unwrap();
diff.left_before = 4;
diff.left_after = 4;
let mut terminal = Terminal::new(ratatui::backend::TestBackend::new(100, 20)).unwrap();
let mut panels = WheelPanels::default();
render_diff(&mut terminal, &diff, &mut panels);
let pane = usize::from(focus == Focus::After);
let area = diff_inner(panels.diff.as_ref().unwrap().regions[pane + 1].0);
let first = pane_screen(&terminal, Rect::new(area.x, area.y, area.width, 1));
assert!(
first.contains("fn old_name()"),
"Visible declaration was covered: {first}"
);
assert!(!first.contains("+ new_name"));
}
}
#[test]
fn diff_scope_labels_follow_declaration_visibility() {
let before = "@decorate()\nclass PolicyActiveStatusEnum(BaseEnum):\n ACTIVE = 1\n EXPIRED = 2\n FUTURE = 3\n UNKNOWN = 4\n";