From c5a27c81bcb1182e80e7101cc5a068d3692c60f6 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 da7836033a9269e2622fb36302a3ba9f41fe33a0..8ea1be5f4bff7c9f6ed6141586fe7d8f0654e322 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 30964331bc6df5fd9e4e9be331c9f75e94fc927b..062e6335e9e2194e282990b88bf52a07cc4292bf 100644 --- a/crates/editor/src/editor_tests.rs +++ b/crates/editor/src/editor_tests.rs @@ -3011,6 +3011,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| {