diff --git a/helix-lsp/src/lib.rs b/helix-lsp/src/lib.rs index ec89e1f821865..1bcba9c852f87 100644 --- a/helix-lsp/src/lib.rs +++ b/helix-lsp/src/lib.rs @@ -330,14 +330,24 @@ pub mod util { }; let text = doc.slice(..); - let (removed_start, removed_end) = completion_range( + let (start, end) = completion_range( text, edit_offset, replace_mode, selection.primary().cursor(text), ) .expect("transaction must be valid for primary selection"); - let removed_text = text.slice(removed_start..removed_end); + + // Some LSPs are sending completion edits beyond the end of the document. For example, pyright for python. + // + // In https://github.com/helix-editor/helix/pull/10279, there was the addition of a `+ 1` to fix an off by one + // error, but this has now ran into another for some LSP's that don't report the proper range, leading to an + // index out of bounds panic. The "solution" here is to default to the "correct" way first, and if that is out + // of bounds, it tries again with the `end - 1`, hopefully bringing it back into the correct range. If even + // that isn't correct, we panic as before. + let removed_text = text + .get_slice(start..end) + .map_or_else(|| text.slice(start..end - 1), |replaced| replaced); let (transaction, mut selection) = Transaction::change_by_selection_ignore_overlapping( doc,