about summary refs log tree commit diff
diff options
context:
space:
mode:
authorroife <roifewu@gmail.com>2024-06-15 23:34:04 +0800
committerroife <roifewu@gmail.com>2024-06-15 23:35:29 +0800
commit9ce8a96755aa56bd73c74f106195ac5abf97fd67 (patch)
tree3142a9c95e3b4d3ef7286a9ab3bd22f2e540b283
parente0c1b2bf75c742af8a6637e25e9b5148de8c444a (diff)
downloadrust-9ce8a96755aa56bd73c74f106195ac5abf97fd67.tar.gz
rust-9ce8a96755aa56bd73c74f106195ac5abf97fd67.zip
fix: handle character boundaries for wide chars in extend_selection
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/extend_selection.rs22
1 files changed, 21 insertions, 1 deletions
diff --git a/src/tools/rust-analyzer/crates/ide/src/extend_selection.rs b/src/tools/rust-analyzer/crates/ide/src/extend_selection.rs
index b706e959d34..e8d6dc97341 100644
--- a/src/tools/rust-analyzer/crates/ide/src/extend_selection.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/extend_selection.rs
@@ -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 = "════════"; }"#,
+            ],
+        );
+    }
 }