Convert an LSP `Position` (line/character) to a character offset into a pre-built char array. Returns `None` when the position is beyond the end of `chars`. Handles UTF-16 column widths, end-of-line clamping, and trailing content without a newline.
(chars: &[char], position: Position)
| 729 | /// Handles UTF-16 column widths, end-of-line clamping, and trailing |
| 730 | /// content without a newline. |
| 731 | pub fn position_to_char_offset(chars: &[char], position: Position) -> Option<usize> { |
| 732 | let target_line = position.line as usize; |
| 733 | let target_col = position.character as usize; |
| 734 | let mut line = 0usize; |
| 735 | let mut col = 0usize; |
| 736 | |
| 737 | for (i, &ch) in chars.iter().enumerate() { |
| 738 | if line == target_line && col == target_col { |
| 739 | return Some(i); |
| 740 | } |
| 741 | if ch == '\n' { |
| 742 | // If we're at the target line and the target column is at or |
| 743 | // past the end of the line, clamp to end-of-line. |
| 744 | if line == target_line { |
| 745 | return Some(i); |
| 746 | } |
| 747 | line += 1; |
| 748 | col = 0; |
| 749 | } else { |
| 750 | col += ch.len_utf16(); |
| 751 | } |
| 752 | } |
| 753 | |
| 754 | // Cursor at very end of content |
| 755 | if line == target_line && col == target_col { |
| 756 | return Some(chars.len()); |
| 757 | } |
| 758 | // Target column past end of last line (no trailing newline) |
| 759 | if line == target_line { |
| 760 | return Some(chars.len()); |
| 761 | } |
| 762 | |
| 763 | None |
| 764 | } |
| 765 | |
| 766 | /// Find which class the cursor (byte offset) is inside. |
| 767 | /// |
no test coverage detected