@@ -79,36 +79,33 @@ fn position(
79
79
position_encoding : & PositionEncoding ,
80
80
span : & DiagnosticSpan ,
81
81
line_offset : usize ,
82
- column_offset : usize ,
82
+ column_offset_utf32 : usize ,
83
83
) -> lsp_types:: Position {
84
84
let line_index = line_offset - span. line_start ;
85
85
86
- let mut true_column_offset = column_offset;
87
- if let Some ( line) = span. text . get ( line_index) {
88
- if line. text . chars ( ) . count ( ) == line. text . len ( ) {
89
- // all one byte utf-8 char
90
- return lsp_types:: Position {
91
- line : ( line_offset as u32 ) . saturating_sub ( 1 ) ,
92
- character : ( column_offset as u32 ) . saturating_sub ( 1 ) ,
93
- } ;
94
- }
95
- let mut char_offset = 0 ;
96
- for c in line. text . chars ( ) {
97
- char_offset += 1 ;
98
- if char_offset > column_offset {
99
- break ;
86
+ let column_offset_encoded = match span. text . get ( line_index) {
87
+ // Fast path.
88
+ Some ( line) if line. text . is_ascii ( ) => column_offset_utf32,
89
+ Some ( line) => {
90
+ let line_prefix_len = line
91
+ . text
92
+ . char_indices ( )
93
+ . take ( column_offset_utf32)
94
+ . last ( )
95
+ . map ( |( pos, c) | pos + c. len_utf8 ( ) )
96
+ . unwrap_or ( 0 ) ;
97
+ let line_prefix = & line. text [ ..line_prefix_len] ;
98
+ match position_encoding {
99
+ PositionEncoding :: Utf8 => line_prefix. len ( ) ,
100
+ PositionEncoding :: Wide ( enc) => enc. measure ( line_prefix) ,
100
101
}
101
- let len = match position_encoding {
102
- PositionEncoding :: Utf8 => c. len_utf8 ( ) ,
103
- PositionEncoding :: Wide ( w) => w. measure ( & c. to_string ( ) ) ,
104
- } ;
105
- true_column_offset += len - 1 ;
106
102
}
107
- }
103
+ None => column_offset_utf32,
104
+ } ;
108
105
109
106
lsp_types:: Position {
110
107
line : ( line_offset as u32 ) . saturating_sub ( 1 ) ,
111
- character : ( true_column_offset as u32 ) . saturating_sub ( 1 ) ,
108
+ character : ( column_offset_encoded as u32 ) . saturating_sub ( 1 ) ,
112
109
}
113
110
}
114
111
0 commit comments