# lsp: Fix some inlay_hints' anchor does not have right bias \(\#64791\) · gitcafe/zed

[View on GitCafe](https://git.cafe/gitcafe/zed/commit/9874229eb724cb6d2a024b8b88c970c2a9f8a68f)

Repository: [gitcafe/zed](https://git.cafe/gitcafe/zed)

Visibility: public

Requested revision: 9874229eb724cb6d2a024b8b88c970c2a9f8a68f

Requested commit: 9874229eb724cb6d2a024b8b88c970c2a9f8a68f

Commit: 9874229eb724cb6d2a024b8b88c970c2a9f8a68f

Tree: cc87f5665264047a5c6e218135e365c1b450977f

Author: HuaGu-Dragon

Committer: GitHub

## Message

```
lsp: Fix some inlay_hints' anchor does not have right bias (#64791)

## Summary

Some inlay hints currently use an incorrect bias, especially hints whose
LSP `kind` is `None`. The previous implementation used a simple rule:

- `Parameter` used `anchor_before`
- all other hint kinds used `anchor_after`

This caused some hints to be rendered at the wrong position

| Scenario | `main` | this PR |
|---|---|---|
| Cursor at EOL after `}` | `{}\| // fn foo` | `{}\| // fn foo` |
| Cursor after `&` | `&\|'_ str` | `&'_ \|str` |
| Type `bar` after `foo` | `foobar\|<'_>(` | `foobar\|<'_>(` |

The second scenario is improved

Unfortunately, `BindingMode` and `reborrow` hints are still not fixed.
Their positions may still be incorrect both before and after this change

## Solution

A previous
[review](https://github.com/zed-industries/zed/pull/64593#discussion_r4082517910)
suggested using padding to determine the bias. This approach works;
however, we can do even better by determining the anchor direction based
on the hint kind and the word surrounding the hint position, allowing us
to make better use of rangeExclusiveHints and other hints whose padding
is not set on both the left and right sides. This is similar to how [VS
Code](https://github.com/microsoft/vscode/blob/c3cbcba676f18ba2d0281d10d43b7ccd63db9a69/src/vs/editor/contrib/inlayHints/browser/inlayHints.ts#L115)
handles it

Therefore, the LSP kind alone is not sufficient to distinguish prefix
hints from suffix hints in every case. This PR uses `surrounding_word`
as a heuristic: it takes the greater of `prev` and `next` as the word
kind, so a hint is treated as a suffix hint when the previous
character’s kind is greater than or equal to the next character’s kind;
otherwise, it is treated as a prefix hint. `None` covers both
directions, such as an RA lifetime after `&` and a `ClosingBrace` after
`}`

## Testing

This PR adds tests for the three scenarios mentioned in the previous
review
And add a test for multiple hints sharing the same LSP position. When
the per-hint rules conflict, all hints should use the same bias
(`anchor_after`), consistent with the main rule

## Showcase

<details>
  <summary>Click to view showcase</summary>


https://github.com/user-attachments/assets/6d48c78a-e5f6-4277-9fd6-73cf6f674a73


https://github.com/user-attachments/assets/7eace941-9bea-4718-b51f-1facf70e9bc3

</details>

## Self-review

- [x] I've reviewed my diff for quality, security, reliability, and
performance.
- [ ] UI changes follow the
[checklist](https://zed.dev/docs/development/ui-checklist).
- [x] Tests cover the new or changed behavior.

Release Notes:

- Fixed incorrect anchor bias for some inlay hints
```

## Parents

- [4c0ead4a3e3726fb229d297c42fde856478b64a8](https://git.cafe/gitcafe/zed/commit/4c0ead4a3e3726fb229d297c42fde856478b64a8?format=markdown)

[Source at this commit](https://git.cafe/gitcafe/zed/tree/9874229eb724cb6d2a024b8b88c970c2a9f8a68f?format=markdown)
