-
-
Notifications
You must be signed in to change notification settings - Fork 895
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
Do not resolve during annotate, enrich documentation with details (Fix #3201) (Fix #3905) #4625
base: master
Are you sure you want to change the base?
Conversation
The implementation in this PR relies on the auto-documentation being automatically triggered. I would like to avoid that and always have the candidate resolved as it's displayed. The annotation update is called for displayed candidates and is a good function to trigger resolving asynchronously. Also, we can configure the client's capability to not have partial completion item responses at all. The reason why we make it have partial completion item responses is to make the completion list return as quickly as possible without unnecessary and/or large item property strings. The other properties can be retrieved later with Please see #4591 for the issue with completion items not being resolved without the document's update as well. To avoid the width suddenly changing, I think the user can disable
This is a good feature. I agree we should do this. |
I think we are beginning to see this one-size-fits-all
The documentation is already resolved synchronously in HEAD, I didn't change this, I only changed detail resolution. Detail should be resolved when it's needed, which is largely determined by the server. Even when
The problem is exactly because the first time the candidates are displayed, they may not be resolved, there is also no guarantee they will be resolved the next time they are displayed, or the third time, they will be resolved whenever the server feels like it's time to send back a response because, asynchronicity, so what ends up happening is the annotation appearing in the completion popup erratically.
Nobody is arguing with that, for languages where it makes sense, like TypeScript or Python, the language servers often do not send down
Fine, but they should not affect how the completion candidate list is displayed, but only how text are inserted or replaced, and displaying documentation. Resolving for insertion, replacement, indentation etc are already done in the exit function. If you want to speed up insertion in case resolution in the exit function is slow, you can call
This is crazy. Are you suggesting that every user should adjust this defcustom buffer-local in mode hooks as opposed to simply shipping with a default behavior that makes sense for the vast majority if not all cases?
CAPF is pull-based. How do you "trigger a refresh" of all the completion frontends now and in the future? Also, what does it have to do with VS Code? |
The The spec from LSP said that
So, from 3.16, instead of the default
I think as long as we provide enough customization for the user, it would be okay as there's no one-size-fits-all solution. The default should be as close to the VsCode behavior as possible. So, if the VsCode doesn't do the candidate annotation (which Emacs does) then we should configure
I'm not sure but the behavior of showing document pop can be argued as erratically as well, as it suddenly appears, blocking since the user will experience hang if the server is slow to return the result, unlike
This would be I think that your main argument is that we shouldn't treat the resolved completion item and the original completion item as a same entity and always use the original completion even if it's lacking information. My counterargument is that they're the same and we should use the latest information if possible. The reason is that it provides more information to the user. Btw, here is an example behavior with a place-holder on annotation string. The code change (defun lsp-completion--annotate (item)
"Annotate ITEM detail."
(-let* (((&plist 'lsp-completion-item completion-item
'lsp-completion-resolved resolved)
(text-properties-at 0 item))
((&CompletionItem :detail? :kind? :label-details?) completion-item))
(lsp-completion--resolve-async item #'ignore)
(concat (when lsp-completion-show-detail
(if resolved
(when detail? (concat " " (s-replace-regexp "\r" "" detail?)))
" <loading...>"))
(when (and lsp-completion-show-label-description label-details?)
(when-let* ((description (and label-details? (lsp:label-details-description label-details?))))
(format " %s" description)))
(when lsp-completion-show-kind
(when-let* ((kind-name (and kind? (aref lsp-completion--item-kind kind?))))
(format " (%s)" kind-name)))))) |
Ok, this PR works just as well. When the initial partial completion item has no detail, after a resolution, the detail will be prepended to the document.
So load them when you need them, I don't know why we keep circling back to this. This PR has nothing to do with these other lazily resolved properties. It's already done in the exit function.
I believe the central issue here is, ts-ls doesn't always return detail in the response of
I don't understand this sentence. Can you rephrase? The response to
Yes, that's why If spamming the server is a problem, these completion frontend should implement debounce with
Yes, which is already handled when corfu-popupinfo/corfu-info/company-quickhelp etc calls
I beg you please don't even try this. I'm working on corfu-pixel-perfect, it does have the ability to refresh, but it's a little complicated for vanilla corfu. I think company box has this ability as well, but not sure about company. Basically, don't do this as this is highly dependent on third-party packages. You don't need it, and the outcome is undesirable as the width will either erratically expand or the candidate line is squished and truncated in all sorts of ways.
I don't think this is VS Code's behavior... |
e30d4dd
to
5bc2096
Compare
Ok here's more information. It turns out, VS Code remembers the last value of ^SPC (Show more or less), and the way to change it is hidden in a hint in the status bar which is off by default. When "Show More" is active, the detail is prepended to the documentation. When "Show Less" is active, the detail is rendered on the popup menu on selection if it is not in the response from In addition, if a completion item has no detail from In order to accomplish this in lsp-mode, we will need to cooperate with completion frontends, I guess this is where your idea of "refresh" comes in. What we can do is, keep the separation of unresolved and resolved completion item as done in this PR , do not resolve async when the annotation function is called, but instead, the completion frontends should call |
6e3b7d7
to
1111c94
Compare
1111c94
to
b305fdd
Compare
More reasons to separate the unresolved and resolved completion item: the details for the same label can be different in the responses in textDocument/completion{
"data": {
"cacheId": 964
},
"detail": "@nestjs/common/utils/shared.utils",
"kind": 6,
"label": "isObject",
"sortText": "�16",
"textEdit": {
"insert": {
"end": {
"character": 3,
"line": 2
},
"start": {
"character": 0,
"line": 2
}
},
"newText": "isObject",
"replace": {
"end": {
"character": 3,
"line": 2
},
"start": {
"character": 0,
"line": 2
}
}
}
} completionItem/resolve
|
5461d9c
to
d967ae0
Compare
d967ae0
to
f85bece
Compare
Problem
When using
typescript-language-server
, the initial call totextDocument/completion
does not return anydetail
ordocumentation
for any of the completion items. I suppose the reason for this is many Javascript signatures are extremely long, often they are 5x to 10x longer than the label, they are unreadable when displaying beside the label on one line, so the server forces the client to makecompletionItem/resolve
requests to resolve the item detail and documentation individually, and it's up to the client to prepend the signature to the documentation, as is done in VS Code.VS Code Typescript
This approach presents a problem to
lsp-mode
in that the CAPF function caches the partial completion item response as a text property on each candidate string, and when a completion frontend such ascompany
orcorfu
callslsp-completion--annotate
to get a suffix, every call will issue an asynccompletionItem/resolve
request to modify the cached completion item in place while returning just a kind or an empty string initially, depending on some variables. This means the first completion popup will only have the kinds or simply no suffix at all, and then on the next refresh after a selection change, in the case of company, all of the candidates in the pop up will suddenly be annotated, and in the case of corfu, the previous selection will suddenly be annotated. In both cases the popup width will suddenly expand greatly, often times as wide as the window size. This is fundamentally because lsp-mode assumes the partial completion item response fromtextDocument/completion
is meant to be used the same way as the fully resolved completion item response fromcompletionItem/resolve
.This PR reimplements
lsp-completion--make-item
,lsp-completion--annotate
andlsp-completion--get-documentation
to separate the two different usages. In addition, the signature fromdetail
is now prepended to the document if it has not been prepended by the language server already.LSP ts-ls
LSP pyright
LSP gopls
LSP rust-analyzer
LSP jdtls