Skip to content

Commit e90dc6a

Browse files
committed
Clamp Position::character to line length
LSP says about Position::character > If the character value is greater than the line length it defaults back to the line length. but from_proto::offset() doesn't implement this. A client might for example request code actions for a whole line by sending Position::character=99999. I don't think there is ever a reason (besides laziness) why the client can't specify the line length instead but I guess we should not crash but follow protocol. Technically it should be a warning, not an error but warning is not shown by default so keep it at error I guess. Fixes #18240
1 parent cf0c848 commit e90dc6a

File tree

3 files changed

+12
-4
lines changed

3 files changed

+12
-4
lines changed

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ test-fixture = { path = "./crates/test-fixture" }
9696
test-utils = { path = "./crates/test-utils" }
9797

9898
# In-tree crates that are published separately and follow semver. See lib/README.md
99-
line-index = { version = "0.1.1" }
99+
line-index = { version = "0.1.2" }
100100
la-arena = { version = "0.3.1" }
101101
lsp-server = { version = "0.7.6" }
102102

crates/rust-analyzer/src/lsp/from_proto.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,18 @@ pub(crate) fn offset(
3535
.ok_or_else(|| format_err!("Invalid wide col offset"))?
3636
}
3737
};
38-
let text_size = line_index.index.offset(line_col).ok_or_else(|| {
38+
let line_range = line_index.index.line(line_col.line).ok_or_else(|| {
3939
format_err!("Invalid offset {line_col:?} (line index length: {:?})", line_index.index.len())
4040
})?;
41-
Ok(text_size)
41+
let col = TextSize::from(line_col.col);
42+
let clamped_len = col.min(line_range.len());
43+
if clamped_len < col {
44+
tracing::error!(
45+
"Position {line_col:?} column exceeds line length {}, clamping it",
46+
u32::from(line_range.len()),
47+
);
48+
}
49+
Ok(line_range.start() + clamped_len)
4250
}
4351

4452
pub(crate) fn text_range(

crates/rust-analyzer/src/lsp/to_proto.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -705,7 +705,7 @@ pub(crate) fn semantic_tokens(
705705
let token_index = semantic_tokens::type_index(ty);
706706
let modifier_bitset = mods.0;
707707

708-
for mut text_range in line_index.index.lines(highlight_range.range) {
708+
for mut text_range in line_index.index.lines_in_range(highlight_range.range) {
709709
if text[text_range].ends_with('\n') {
710710
text_range =
711711
TextRange::new(text_range.start(), text_range.end() - TextSize::of('\n'));

0 commit comments

Comments
 (0)