Skip to content

Commit a4c2d9f

Browse files
committed
Auto merge of rust-lang#17003 - krobelus:utf8-positions-multibyte, r=Veykril
Fix off-by-one error converting to LSP UTF8 offsets with multi-byte char On this file, ```rust fn main() { let 된장 = 1; } ``` when using `"positionEncodings":["utf-16"]` I get an "unused variable" diagnostic on the variable name (codepoint offset range `8..10`). So far so good. When using `positionEncodings":["utf-8"]`, I expect to get the equivalent range in bytes (LSP: "Character offsets count UTF-8 code units (e.g bytes)."), which is `8..14`, because both characters are 3 bytes in UTF-8. However I actually get `10..14`. Looks like this is because we accidentally treat a 1-based index as an offset value: when converting from our internal char-indices to LSP byte offsets, we look at one character to many. This causes wrong results if the extra character is a multi-byte one, such as when computing the start coordinate of 된장. Fix that by actually passing an offset. While at it, fix the variable name of the line number, which is not an offset (yet). Originally reported at kakoune-lsp/kakoune-lsp#740
2 parents 772051c + 5eb184c commit a4c2d9f

File tree

1 file changed

+11
-6
lines changed
  • src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics

1 file changed

+11
-6
lines changed

src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics/to_proto.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,13 @@ fn location(
6868
let range = {
6969
let position_encoding = snap.config.position_encoding();
7070
lsp_types::Range::new(
71-
position(&position_encoding, span, span.line_start, span.column_start),
72-
position(&position_encoding, span, span.line_end, span.column_end),
71+
position(
72+
&position_encoding,
73+
span,
74+
span.line_start,
75+
span.column_start.saturating_sub(1),
76+
),
77+
position(&position_encoding, span, span.line_end, span.column_end.saturating_sub(1)),
7378
)
7479
};
7580
lsp_types::Location::new(uri, range)
@@ -78,10 +83,10 @@ fn location(
7883
fn position(
7984
position_encoding: &PositionEncoding,
8085
span: &DiagnosticSpan,
81-
line_offset: usize,
86+
line_number: usize,
8287
column_offset_utf32: usize,
8388
) -> lsp_types::Position {
84-
let line_index = line_offset - span.line_start;
89+
let line_index = line_number - span.line_start;
8590

8691
let column_offset_encoded = match span.text.get(line_index) {
8792
// Fast path.
@@ -104,8 +109,8 @@ fn position(
104109
};
105110

106111
lsp_types::Position {
107-
line: (line_offset as u32).saturating_sub(1),
108-
character: (column_offset_encoded as u32).saturating_sub(1),
112+
line: (line_number as u32).saturating_sub(1),
113+
character: column_offset_encoded as u32,
109114
}
110115
}
111116

0 commit comments

Comments
 (0)