From b63d820be23762f10313bce17e9c98cbba7ab9dd Mon Sep 17 00:00:00 2001 From: Smit Barmase Date: Thu, 24 Jul 2025 03:46:29 +0530 Subject: [PATCH] editor: Fix move line up panic when selection is at end of line next to fold marker (#34982) Closes #34826 In move line up method, make use of `prev_line_boundary` which accounts for fold map, etc., for selection start row so that we don't incorrectly calculate row range to move up. Release Notes: - Fixed an issue where `editor: move line up` action sometimes crashed if the cursor was at the end of a line beside a fold marker. --- crates/editor/src/editor.rs | 10 +++++++++- crates/editor/src/editor_tests.rs | 27 +++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index d5448f30f3..a695c8fd0c 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -22258,7 +22258,7 @@ fn consume_contiguous_rows( selections: &mut Peekable>>, ) -> (MultiBufferRow, MultiBufferRow) { contiguous_row_selections.push(selection.clone()); - let start_row = MultiBufferRow(selection.start.row); + let start_row = starting_row(selection, display_map); let mut end_row = ending_row(selection, display_map); while let Some(next_selection) = selections.peek() { @@ -22272,6 +22272,14 @@ fn consume_contiguous_rows( (start_row, end_row) } +fn starting_row(selection: &Selection, display_map: &DisplaySnapshot) -> MultiBufferRow { + if selection.start.column > 0 { + MultiBufferRow(display_map.prev_line_boundary(selection.start).0.row) + } else { + MultiBufferRow(selection.start.row) + } +} + fn ending_row(next_selection: &Selection, display_map: &DisplaySnapshot) -> MultiBufferRow { if next_selection.end.column > 0 || next_selection.is_empty() { MultiBufferRow(display_map.next_line_boundary(next_selection.end).0.row + 1) diff --git a/crates/editor/src/editor_tests.rs b/crates/editor/src/editor_tests.rs index b9ca8c3755..0d69c067ee 100644 --- a/crates/editor/src/editor_tests.rs +++ b/crates/editor/src/editor_tests.rs @@ -5069,6 +5069,33 @@ fn test_move_line_up_down(cx: &mut TestAppContext) { }); } +#[gpui::test] +fn test_move_line_up_selection_at_end_of_fold(cx: &mut TestAppContext) { + init_test(cx, |_| {}); + let editor = cx.add_window(|window, cx| { + let buffer = MultiBuffer::build_simple("\n\n\n\n\n\naaaa\nbbbb\ncccc", cx); + build_editor(buffer, window, cx) + }); + _ = editor.update(cx, |editor, window, cx| { + editor.fold_creases( + vec![Crease::simple( + Point::new(6, 4)..Point::new(7, 4), + FoldPlaceholder::test(), + )], + true, + window, + cx, + ); + editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| { + s.select_ranges([Point::new(7, 4)..Point::new(7, 4)]) + }); + assert_eq!(editor.display_text(cx), "\n\n\n\n\n\naaaa⋯\ncccc"); + editor.move_line_up(&MoveLineUp, window, cx); + let buffer_text = editor.buffer.read(cx).snapshot(cx).text(); + assert_eq!(buffer_text, "\n\n\n\n\naaaa\nbbbb\n\ncccc"); + }); +} + #[gpui::test] fn test_move_line_up_down_with_blocks(cx: &mut TestAppContext) { init_test(cx, |_| {});