New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(lsp): inlay hints #23984
feat(lsp): inlay hints #23984
Conversation
6581372
to
5f3e69f
Compare
if not M.__buffers[cb_bufnr].enabled then | ||
return true | ||
end | ||
reset_timer(cb_bufnr) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not sure is the good way create timer for each buffer , and in on_lines
callback has changedtick
param you can use pass to request like make_request(cb_bufnr, changedtick)
, and when lsp request callback running check nvim_get_buf_chagnetick
make a compare. if before_changetick < nvim_get_buf_changetick
do defer reqeust again. some undo/redo also increase changetick
and also some change without text chang also increase changtick
. this is my thought and I do it on documentsymbol request . it combine 1000ms change to one request .
https://github.com/nvimdev/lspsaga.nvim/blob/3546dca5560b6868612acc567f6f3c07cf61c076/lua/lspsaga/symbol/init.lua#L25
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like this myself, is there a better way of remembering which buffers have inlay hints enabled (to handle workspace/inlayHint/refresh
)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changedtick
isn't exactly the way to do version comparisons in LSP. You'd useutil.buf_versions[bufnr]
since there are some situations where the changedtick increases but the LSP-aware document version does not, and we care only about which document version the LSP server knows about for a particular request. Using changedtick could actually cause the local cache of inlay hints to be out of sync with the LSP server's understanding of where they should be.
Anyway, this looks like a debounce timer? Seems ok to me. You want to avoid making new inlay hint requests until there's been a bit of time with no edit activity (after someone stops typing for a bit). Making a request on every on_lines
event would be way too many requests. The alternative is to do it on a few autocmd events which might trigger less often than a dedicated timer would.
As for your other question, I think you just use your __buffers
table in the refresh
handler. If someone disables inlay hints for a buffer, just clear the cache for that buffer (and cancel any pending requests). I don't think it needs to be more complicated than that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is what I was doing, except how do you cancel pending requests?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i had point it out changetick
increase without text changed and this change will not trigger on_lines
callback . and there has on_changedtick
in nvim_buf_attach
. these problem i had comment in prev :-) each buffer has a timer I am very confused this way . worker thread of luv will grow with the buffers count .. maybe you can ref vscode implement get some idea.
https://github.com/microsoft/vscode/tree/main/src/vs/editor/contrib/inlayHints
if not M.__buffers[cb_bufnr].enabled then | ||
return true | ||
end | ||
reset_timer(cb_bufnr) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changedtick
isn't exactly the way to do version comparisons in LSP. You'd useutil.buf_versions[bufnr]
since there are some situations where the changedtick increases but the LSP-aware document version does not, and we care only about which document version the LSP server knows about for a particular request. Using changedtick could actually cause the local cache of inlay hints to be out of sync with the LSP server's understanding of where they should be.
Anyway, this looks like a debounce timer? Seems ok to me. You want to avoid making new inlay hint requests until there's been a bit of time with no edit activity (after someone stops typing for a bit). Making a request on every on_lines
event would be way too many requests. The alternative is to do it on a few autocmd events which might trigger less often than a dedicated timer would.
As for your other question, I think you just use your __buffers
table in the refresh
handler. If someone disables inlay hints for a buffer, just clear the cache for that buffer (and cancel any pending requests). I don't think it needs to be more complicated than that?
f1ebab2
to
564463e
Compare
This comment was marked as outdated.
This comment was marked as outdated.
Inlay hints can be quite obtrusive (even moreso than diagnostics); they should definitely be under the user's control. (I refer to the semantic tokens decision, which triggered a deluge of "my highlight is suddenly broken!!eleven!" issues for nvim-treesitter.) |
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
To avoid more mistakes can we look at |
I believe the possibility of (easily) toggling diagnostics is something that's been missing from that API as well. I do agree (as I've written before) that it makes sense to look at this (toggling "code overlays") as a general issue. |
Given that inlay hints are requested by the client it's also up to the client to control it. The server has no business controlling client behaviour. The capabilities indicate resolve support and dynamic registration support, not general on/off A user could change the server capability, to trick the client into thinking it's not supported, but dynamic capabilities make that problematic too. (We currently use this approach to turn semantic tokens off, but we may have to move away from that). A
Inlay hints was always the first thing I turned off in intellij as it's very intrusive. We can discuss the default but it definitely needs an option to turn it off. And I'd say not just the display but the requests as well. Users who don't use it shouldn't need to spend processing power on it. |
a372219
to
8391894
Compare
This comment was marked as outdated.
This comment was marked as outdated.
@justinmk I think vscode has a thing where it shows inlay hints as long as you hold certain keys Not saying this should be the reference, just addressing
|
FWIW I didn’t think that either until I tried it. And my almost immediate thought was that I wanted to be able to flip them on when needed, but disable them otherwise. Personally, I find them far too noisy to leave enabled all the time. |
But the client also declares its capabilities (
Let's forget that. coc.nvim for example, suggests there is a ridiculous amount of configuration people want to fiddle with. Can't jam that all into
And also "specific buffers" (sigh)--but I think that is not an important use-case.
I could imagine a ProposalTo unblock this PR, all that's needed is:
|
This PR adds automatic refresh and a public interface on top of neovim#23736 Closes neovim#18086
- add on_reload, on_detach handlers in `enable()` buf_attach, and LspDetach autocommand in case of manual detach - change M.__buffers to __buffers
resolve bufnr checks for nil now
runtime/doc/lsp.txt
Outdated
|
||
Parameters: ~ | ||
• {enable} (boolean|nil) true/false to enable/disable, nil to toggle | ||
• {bufnr} (integer|nil) Buffer handle, or nil for current |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Convention is:
- 0 = current buffer
nil
= all buffers (don't necessarily need to implement this here)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be nice to do this in a follow-up, though, as now you can't just map to vim.lsp.buf.inlay_hints()
(like you can with most other vim.lsp.buf
functions).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM (after CI is passing), will wait for other approvals, ping after a few days if not merged already.
Thanks for your persistence and patience!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approved this, but I think we should look into doing some API adjustments before this gets released.
Inlay hints have optional textEdits
, and we could (or should?) allow users to apply them. That will likely need another function. With the current approach this would mean something like vim.lsp.buf.inlay_hints_run()
(or apply
or apply_edits
or whatever). Which would just forward to _inlay_hints.xy()
.
I'm thinking maybe we could go with a callable module approach similar to how vim.iter
works. We'd have vim.lsp.inlay_hints()
to toggle, enable or disable and could add additional functionality as needed in vim.lsp.inlay_hints.xy()
.
This would remove the indirection/forwarding to a private module, and we could keep stuff properly encapsulated via lua local
s and it's module system.
The same approach would also work for codelens
. We could toggle/enable/disable via vim.lsp.codelens()
, but we still have vim.lsp.codelens.on_codelens
for the handler and vim.lsp.codelens.run()
to execute a lens.
Enable with: ```lua {"neovim/nvim-lspconfig", opts = {inlay_hints = {enabled = true}}} ```
Implements inlay hints by adding automatic refresh and a public interface on top of #23736
Closes #18086