From 0355b9dfaba4500f64d907f6b5f264426a22bb07 Mon Sep 17 00:00:00 2001 From: Smit Barmase Date: Fri, 16 May 2025 19:11:37 +0530 Subject: [PATCH] editor: Fix line comments not extending when adding new line immediately after slash (#30824) This PR fixes a bug where comments don't extend when cursor is right next to the second slash. We added `// ` as a prefix character to correctly position the cursor after a new line, but this broke comment validation by including that trailing space, which it shouldn't. Now both line comments and block comments (already handled in JSDoc PR) can extend right after the prefix without needing an additional space. Before: https://github.com/user-attachments/assets/ca4d4c1b-b9b9-4f1b-b47a-56ae35776f41 After: https://github.com/user-attachments/assets/b3408e1e-3efe-4787-ba68-d33cd2ea8563 Release Notes: - Fixed issue where comments weren't extending when adding new line immediately after comment prefix (`//`). --- crates/editor/src/editor.rs | 30 ++++++++++++++++-------------- crates/editor/src/editor_tests.rs | 24 +++++++++++++++++++++++- 2 files changed, 39 insertions(+), 15 deletions(-) diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 3f926fe8975e6d83b9d13dc81d44e0e37e80b696..e62dd933d5554119a471192bd64ca69d05924e76 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -3954,26 +3954,28 @@ impl Editor { let (snapshot, range) = buffer.buffer_line_for_row(MultiBufferRow(start_point.row))?; - let mut index_of_first_non_whitespace = 0; + let num_of_whitespaces = snapshot + .chars_for_range(range.clone()) + .take_while(|c| c.is_whitespace()) + .count(); let comment_candidate = snapshot .chars_for_range(range) - .skip_while(|c| { - let should_skip = c.is_whitespace(); - if should_skip { - index_of_first_non_whitespace += 1; - } - should_skip - }) + .skip(num_of_whitespaces) .take(max_len_of_delimiter) .collect::(); - let comment_prefix = delimiters.iter().find(|comment_prefix| { - comment_candidate.starts_with(comment_prefix.as_ref()) - })?; + let (delimiter, trimmed_len) = + delimiters.iter().find_map(|delimiter| { + let trimmed = delimiter.trim_end(); + if comment_candidate.starts_with(trimmed) { + Some((delimiter, trimmed.len())) + } else { + None + } + })?; let cursor_is_placed_after_comment_marker = - index_of_first_non_whitespace + comment_prefix.len() - <= start_point.column as usize; + num_of_whitespaces + trimmed_len <= start_point.column as usize; if cursor_is_placed_after_comment_marker { - Some(comment_prefix.clone()) + Some(delimiter.clone()) } else { None } diff --git a/crates/editor/src/editor_tests.rs b/crates/editor/src/editor_tests.rs index d169c2febef9ba93a702845163ac48d68f81e5fe..8ba938c90753fae2d8a6557dc93f8325e43ecdc3 100644 --- a/crates/editor/src/editor_tests.rs +++ b/crates/editor/src/editor_tests.rs @@ -2755,7 +2755,7 @@ async fn test_newline_comments(cx: &mut TestAppContext) { let language = Arc::new(Language::new( LanguageConfig { - line_comments: vec!["//".into()], + line_comments: vec!["// ".into()], ..LanguageConfig::default() }, None, @@ -2770,7 +2770,29 @@ async fn test_newline_comments(cx: &mut TestAppContext) { cx.update_editor(|e, window, cx| e.newline(&Newline, window, cx)); cx.assert_editor_state(indoc! {" // Foo + // ˇ + "}); + // Ensure that we add comment prefix when existing line contains space + cx.update_editor(|e, window, cx| e.newline(&Newline, window, cx)); + cx.assert_editor_state( + indoc! {" + // Foo + //s + // ˇ + "} + .replace("s", " ") // s is used as space placeholder to prevent format on save + .as_str(), + ); + // Ensure that we add comment prefix when existing line does not contain space + cx.set_state(indoc! {" + // Foo //ˇ + "}); + cx.update_editor(|e, window, cx| e.newline(&Newline, window, cx)); + cx.assert_editor_state(indoc! {" + // Foo + // + // ˇ "}); // Ensure that if cursor is before the comment start, we do not actually insert a comment prefix. cx.set_state(indoc! {"