editor: Fix block comment incorrectly continues to next line in some cases (#31204)
smit
created 6 months ago
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.
Change summary
crates/editor/src/editor.rs | 36 +++++++++++++++-----------------
crates/editor/src/editor_tests.rs | 26 +++++++++++++++++++++++
2 files changed, 43 insertions(+), 19 deletions(-)
Detailed changes
@@ -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();
}
@@ -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| {