about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAriel Davis <ariel.z.davis@icloud.com>2023-05-06 00:52:32 -0700
committerAriel Davis <ariel.z.davis@icloud.com>2023-05-06 00:52:32 -0700
commitfcbe73ec1caad761eb6cf1a641fa667ac920076b (patch)
tree13a528a93326c498b2b3e8f414107bdbd4292f31
parent0bb21533c68bc551ef2ec70a3b70bb99b4d2e786 (diff)
downloadrust-fcbe73ec1caad761eb6cf1a641fa667ac920076b.tar.gz
rust-fcbe73ec1caad761eb6cf1a641fa667ac920076b.zip
Refactor position
-rw-r--r--crates/rust-analyzer/src/diagnostics/to_proto.rs41
1 files changed, 19 insertions, 22 deletions
diff --git a/crates/rust-analyzer/src/diagnostics/to_proto.rs b/crates/rust-analyzer/src/diagnostics/to_proto.rs
index c8b2c4edb83..e1d1130ff1b 100644
--- a/crates/rust-analyzer/src/diagnostics/to_proto.rs
+++ b/crates/rust-analyzer/src/diagnostics/to_proto.rs
@@ -79,36 +79,33 @@ fn position(
     position_encoding: &PositionEncoding,
     span: &DiagnosticSpan,
     line_offset: usize,
-    column_offset: usize,
+    column_offset_utf32: usize,
 ) -> lsp_types::Position {
     let line_index = line_offset - span.line_start;
 
-    let mut true_column_offset = column_offset;
-    if let Some(line) = span.text.get(line_index) {
-        if line.text.chars().count() == line.text.len() {
-            // all one byte utf-8 char
-            return lsp_types::Position {
-                line: (line_offset as u32).saturating_sub(1),
-                character: (column_offset as u32).saturating_sub(1),
-            };
-        }
-        let mut char_offset = 0;
-        for c in line.text.chars() {
-            char_offset += 1;
-            if char_offset > column_offset {
-                break;
+    let column_offset_encoded = match span.text.get(line_index) {
+        // Fast path.
+        Some(line) if line.text.is_ascii() => column_offset_utf32,
+        Some(line) => {
+            let line_prefix_len = line
+                .text
+                .char_indices()
+                .take(column_offset_utf32)
+                .last()
+                .map(|(pos, c)| pos + c.len_utf8())
+                .unwrap_or(0);
+            let line_prefix = &line.text[..line_prefix_len];
+            match position_encoding {
+                PositionEncoding::Utf8 => line_prefix.len(),
+                PositionEncoding::Wide(enc) => enc.measure(line_prefix),
             }
-            let len = match position_encoding {
-                PositionEncoding::Utf8 => c.len_utf8(),
-                PositionEncoding::Wide(w) => w.measure(&c.to_string()),
-            };
-            true_column_offset += len - 1;
         }
-    }
+        None => column_offset_utf32,
+    };
 
     lsp_types::Position {
         line: (line_offset as u32).saturating_sub(1),
-        character: (true_column_offset as u32).saturating_sub(1),
+        character: (column_offset_encoded as u32).saturating_sub(1),
     }
 }