From dd4e8b9e66b4ec816514b457a014dff46904d16e Mon Sep 17 00:00:00 2001 From: smit Date: Thu, 22 May 2025 23:27:03 +0530 Subject: [PATCH] editor: Fix block comment incorrectly continues to next line in some cases (#31204) Closes #31138 Fix edge case where adding newline if there is text afterwards end delimiter of multiline comment, would continue the comment prefix. This is fixed by checking for end delimiter on whole line instead of just assuming it would always be at end. - [x] Tests Release Notes: - Fixed the issue where in some cases the block comment continues to the next line even though the comment block is already closed. --- crates/editor/src/editor.rs | 36 +++++++++++++++---------------- crates/editor/src/editor_tests.rs | 26 ++++++++++++++++++++++ 2 files changed, 43 insertions(+), 19 deletions(-) diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 1f39f9ed7b..5835529fa6 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -4044,31 +4044,29 @@ impl Editor { }; let cursor_is_before_end_tag_if_exists = { - let num_of_whitespaces_rev = snapshot - .reversed_chars_for_range(range.clone()) - .take_while(|c| c.is_whitespace()) - .count(); - let mut line_iter = snapshot - .reversed_chars_for_range(range) - .skip(num_of_whitespaces_rev); - let end_tag_exists = end_tag - .chars() - .rev() - .all(|char| line_iter.next() == Some(char)); - if end_tag_exists { - let max_point = snapshot.line_len(start_point.row) as usize; - let ordering = (num_of_whitespaces_rev - + end_tag.len() - + start_point.column as usize) - .cmp(&max_point); + let mut char_position = 0u32; + let mut end_tag_offset = None; + + 'outer: for chunk in snapshot.text_for_range(range.clone()) { + if let Some(byte_pos) = chunk.find(&**end_tag) { + let chars_before_match = + chunk[..byte_pos].chars().count() as u32; + end_tag_offset = + Some(char_position + chars_before_match); + break 'outer; + } + char_position += chunk.chars().count() as u32; + } + + if let Some(end_tag_offset) = end_tag_offset { let cursor_is_before_end_tag = - ordering != Ordering::Greater; + start_point.column <= end_tag_offset; if cursor_is_after_start_tag { if cursor_is_before_end_tag { insert_extra_newline = true; } let cursor_is_at_start_of_end_tag = - ordering == Ordering::Equal; + start_point.column == end_tag_offset; if cursor_is_at_start_of_end_tag { indent_on_extra_newline.len = (*len).into(); } diff --git a/crates/editor/src/editor_tests.rs b/crates/editor/src/editor_tests.rs index d1ad72234a..d0af01f884 100644 --- a/crates/editor/src/editor_tests.rs +++ b/crates/editor/src/editor_tests.rs @@ -3012,6 +3012,32 @@ async fn test_newline_documentation_comments(cx: &mut TestAppContext) { */ ˇ "}); + + // Ensure that inline comment followed by code + // doesn't add comment prefix on newline + cx.set_state(indoc! {" + /** */ textˇ + "}); + cx.update_editor(|e, window, cx| e.newline(&Newline, window, cx)); + cx.assert_editor_state(indoc! {" + /** */ text + ˇ + "}); + + // Ensure that text after comment end tag + // doesn't add comment prefix on newline + cx.set_state(indoc! {" + /** + * + */ˇtext + "}); + cx.update_editor(|e, window, cx| e.newline(&Newline, window, cx)); + cx.assert_editor_state(indoc! {" + /** + * + */ + ˇtext + "}); } // Ensure that comment continuations can be disabled. update_test_language_settings(cx, |settings| {