1
Fork 0

Auto merge of #17426 - roife:fix-issue-17420, r=Veykril

fix: handle character boundaries for wide chars in extend_selection

fix #17420.

When calling 'extend_selection' within a string, r-a attempts to locate the current word at the cursor. This is done by finding the first char before the cursor which is not a letter, digit, or underscore.

The position of this character is referred to as `start_idx`, and the word is considered to start from `start_idx + 1`. However, for wide characters, `start_idx + 1` is not character boundaries, which leading to panic. We should use `ceil_char_boundary` to ensure that the idx is always on character boundaries.
This commit is contained in:
bors 2024-06-19 08:13:18 +00:00
commit cbbdf1e8b1

View file

@ -210,7 +210,13 @@ fn extend_single_word_in_comment_or_string(
let start_idx = before.rfind(non_word_char)? as u32;
let end_idx = after.find(non_word_char).unwrap_or(after.len()) as u32;
let from: TextSize = (start_idx + 1).into();
// FIXME: use `ceil_char_boundary` from `std::str` when it gets stable
// https://github.com/rust-lang/rust/issues/93743
fn ceil_char_boundary(text: &str, index: u32) -> u32 {
(index..).find(|&index| text.is_char_boundary(index as usize)).unwrap_or(text.len() as u32)
}
let from: TextSize = ceil_char_boundary(text, start_idx + 1).into();
let to: TextSize = (cursor_position + end_idx).into();
let range = TextRange::new(from, to);
@ -662,4 +668,18 @@ fn main() { let (
],
);
}
#[test]
fn extend_selection_inside_str_with_wide_char() {
// should not panic
do_check(
r#"fn main() { let x = "═$0═══════"; }"#,
&[
r#""════════""#,
r#"let x = "════════";"#,
r#"{ let x = "════════"; }"#,
r#"fn main() { let x = "════════"; }"#,
],
);
}
}