From 69d7ea7b606f2321307623795c152ccffc1d01e5 Mon Sep 17 00:00:00 2001 From: Smit Barmase Date: Sat, 5 Apr 2025 05:14:15 +0530 Subject: [PATCH] buffer: Fix broken auto indent when pasting code starting with new line (#28134) Closes #26907 Currently, in case of new line to find delta, it is comparing old first line indent with new second line indent. This results into incorrect indentation. This PR fixes this delta calculation by passing correct second line indent in that particular case. - [X] Add Test Before: https://github.com/user-attachments/assets/065deba0-be19-4643-a784-d248a8e7c891 After: https://github.com/user-attachments/assets/a0037043-4bd8-460f-b8ba-b7da7bdbe1ea Release Notes: - Fixed issue where pasting code starting with new line resulted incorrect auto indent. --- crates/language/src/buffer.rs | 11 +++++-- crates/language/src/buffer_tests.rs | 50 +++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 3 deletions(-) diff --git a/crates/language/src/buffer.rs b/crates/language/src/buffer.rs index bf2b41497641a52b47b68d8e152cd817e791a875..5e3cb56a4974f20676d5bbed64201540fce2bfa7 100644 --- a/crates/language/src/buffer.rs +++ b/crates/language/src/buffer.rs @@ -2210,7 +2210,12 @@ impl Buffer { original_indent_columns, } = &mode { - original_indent_column = Some( + original_indent_column = Some(if new_text.starts_with('\n') { + indent_size_for_text( + new_text[range_of_insertion_to_indent.clone()].chars(), + ) + .len + } else { original_indent_columns .get(ix) .copied() @@ -2220,8 +2225,8 @@ impl Buffer { new_text[range_of_insertion_to_indent.clone()].chars(), ) .len - }), - ); + }) + }); // Avoid auto-indenting the line after the edit. if new_text[range_of_insertion_to_indent.clone()].ends_with('\n') { diff --git a/crates/language/src/buffer_tests.rs b/crates/language/src/buffer_tests.rs index 76316b264051a35fa5aa013ac69459213de22235..dbe54b5c6d41765588108bad05025eeb06bd5fd6 100644 --- a/crates/language/src/buffer_tests.rs +++ b/crates/language/src/buffer_tests.rs @@ -1712,6 +1712,56 @@ fn test_autoindent_block_mode(cx: &mut App) { }); } +#[gpui::test] +fn test_autoindent_block_mode_with_newline(cx: &mut App) { + init_settings(cx, |_| {}); + + cx.new(|cx| { + let text = r#" + fn a() { + b(); + } + "# + .unindent(); + let mut buffer = Buffer::local(text, cx).with_language(Arc::new(rust_lang()), cx); + + // First line contains just '\n', it's indentation is stored in "original_indent_columns" + let original_indent_columns = vec![Some(4)]; + let inserted_text = r#" + + c(); + d(); + e(); + "# + .unindent(); + buffer.edit( + [(Point::new(2, 0)..Point::new(2, 0), inserted_text.clone())], + Some(AutoindentMode::Block { + original_indent_columns: original_indent_columns.clone(), + }), + cx, + ); + + // While making edit, we ignore first line as it only contains '\n' + // hence second line indent is used to calculate delta + assert_eq!( + buffer.text(), + r#" + fn a() { + b(); + + c(); + d(); + e(); + } + "# + .unindent() + ); + + buffer + }); +} + #[gpui::test] fn test_autoindent_block_mode_without_original_indent_columns(cx: &mut App) { init_settings(cx, |_| {});