Fix insertion modes for completions without edit ranges (#64139)

Closes https://github.com/zed-industries/zed/issues/64118


https://github.com/user-attachments/assets/f2152411-6011-4d87-8c8e-d83bed0afbbc

`ty` returns completion text without a `textEdit` or a completion-list
default edit range:

```json
{"label":"value2=","insertText":"value2="}
```

The [LSP
specification](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#completionItem)
explicitly states:

> The `insertText` is subject to interpretation by the client side.

For the reported example, `ˇ` marks the cursor:

```py
test(value1, ˇvalue2)
```

Previously, Zed inferred only a range covering the existing `value2`.
Without an insert range, completion acceptance bypassed
`completions.lsp_insert_mode` and replaced that argument with `value2=`,
producing:

```py
test(value1, value2=)
```

The patch also infers an insert range, ending at the cursor rather than
the end of the word.
This lets the existing setting choose between inserting before `value2`
and replacing it.
When a prefix has already been typed, insertion replaces that prefix
while preserving the text after the cursor.

With the unchanged default, `"replace_suffix"`, Zed replaces text after
the cursor only when it is a suffix of the completion’s label.
Here, `value2` is not a suffix of `value2=`, so Zed inserts and
produces:

```py
test(value1, value2=value2)
```

The suffix and subsequence checks now use the raw LSP `label`, not
decorated menu text or `filterText`.
These checks select the edit range; `insertText` still supplies the
inserted text in this example.

Release Notes:

- Fixed insertion modes for completions without edit ranges
67ebcd9517Kirill Bulatov committed on 9/16/2026, 4:03:26 PM· committed by GitHubparent9930d2c
5 files changedLine totals unavailable