diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 0fdffc32f8dde2088f654dfd4f9f8f0453c2ac70..47fd6abb1370d0286d89de6d864ada9e693f15c4 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -1790,7 +1790,7 @@ impl ClipboardSelection { // selections, scroll behavior, was newest selection reversed type SelectSyntaxNodeHistoryState = ( - Box<[Selection]>, + Box<[Selection]>, SelectSyntaxNodeScrollBehavior, bool, ); @@ -16590,6 +16590,10 @@ impl Editor { SelectSyntaxNodeScrollBehavior::CursorBottom }; + let old_selections: Box<[Selection]> = old_selections + .iter() + .map(|s| s.map(|offset| buffer.anchor_before(offset))) + .collect(); self.select_syntax_node_history.push(( old_selections, scroll_behavior, @@ -16612,9 +16616,15 @@ impl Editor { selection.reversed = is_selection_reversed; } + let snapshot = self.buffer.read(cx).snapshot(cx); + let selections: Vec> = selections + .iter() + .map(|s| s.map(|anchor| anchor.to_offset(&snapshot))) + .collect(); + self.select_syntax_node_history.disable_clearing = true; self.change_selections(SelectionEffects::no_scroll(), window, cx, |s| { - s.select(selections.to_vec()); + s.select(selections); }); self.select_syntax_node_history.disable_clearing = false; diff --git a/crates/editor/src/editor_tests.rs b/crates/editor/src/editor_tests.rs index 577cedc04a50eacaa1d207c96ca215095084d25b..562b08d516095e086ea40cf60281da1367345999 100644 --- a/crates/editor/src/editor_tests.rs +++ b/crates/editor/src/editor_tests.rs @@ -23113,6 +23113,61 @@ async fn test_toggle_deletion_hunk_at_start_of_file( cx.assert_state_with_diff(hunk_expanded); } +#[gpui::test] +async fn test_select_smaller_syntax_node_after_diff_hunk_collapse( + executor: BackgroundExecutor, + cx: &mut TestAppContext, +) { + init_test(cx, |_| {}); + + let mut cx = EditorTestContext::new(cx).await; + cx.update_buffer(|buffer, cx| buffer.set_language(Some(rust_lang()), cx)); + + cx.set_state( + &r#" + fn main() { + let x = ˇ1; + } + "# + .unindent(), + ); + + let diff_base = r#" + fn removed_one() { + println!("this function was deleted"); + } + + fn removed_two() { + println!("this function was also deleted"); + } + + fn main() { + let x = 1; + } + "# + .unindent(); + cx.set_head_text(&diff_base); + executor.run_until_parked(); + + cx.update_editor(|editor, window, cx| { + editor.expand_all_diff_hunks(&ExpandAllDiffHunks, window, cx); + }); + executor.run_until_parked(); + + cx.update_editor(|editor, window, cx| { + editor.select_larger_syntax_node(&SelectLargerSyntaxNode, window, cx); + }); + + cx.update_editor(|editor, window, cx| { + editor.collapse_all_diff_hunks(&CollapseAllDiffHunks, window, cx); + }); + executor.run_until_parked(); + + cx.update_editor(|editor, window, cx| { + editor.select_smaller_syntax_node(&SelectSmallerSyntaxNode, window, cx); + }); +} + #[gpui::test] async fn test_expand_first_line_diff_hunk_keeps_deleted_lines_visible( executor: BackgroundExecutor,