-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
allow LSP insert text to replace non-matching prefixes (#5469) #5487
Conversation
…5469) Most LSPs will complete case-insensitive matches, particularly from lowercase to uppercase. In some cases, notably Pyright, this is given as a simple insert text instead of TextEdit. When this happens, the prefix text was left unedited.
In a quick test, this does not seem to fix #4131. It looks a bit to me like gopls has bad completion in the first place. Given this input: input
The response contains this: response
{
"label": "string",
"labelDetails": {},
"kind": 7,
"sortText": "00029",
"filterText": "string",
"insertTextFormat": 1,
"textEdit": {
"range": {
"start": {
"line": 3,
"character": 11
},
"end": {
"line": 3,
"character": 11
}
},
"newText": "string"
}
} I'm not sure at the moment how other client LSPs handle it. I'll give it a shot with nvim real quick. |
In nvim, the gopls suggested response is: { filterText = "string", insertTextFormat = 2, kind = 7, label = "string", labelDetails = vim.empty_dict(), sortText = "00029", textEdit = { newText = "string", range = { ["end"] = { character = 11, line = 3 }, start = { character = 11, line = 3 } } } } So nvim handles the textEdit differently, too. The gopls issue seems unrelated to what this PR addresses. |
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 looked at how nvim-cmp handles this and the LSP spec again and I am pretty sure this is correct. To quote the spec:
Completion item provides an insertText / label without a text edit: in the model the client should filter against what the user has already typed using the word boundary rules of the language (e.g. resolving the word under the cursor position). The reason for this mode is that it makes it extremely easy for a server to implement a basic completion list and get it filtered on the client.
start_offset
is the start of the previous word so everything up to that should be replaced.
This will technically generate transactions that are a bit larger then they need to be but I doubt that will realistically ever matter as completions are usually pretty small.
The golps issue is a similar but unrelated issue as they do send an text edit |
Thanks for the spec reference. I'm still curious how nvim is handling the gopls case, because the textEdit range appears to not be correct, and nvim still gets the right result. According to the next section in the spec, a TextEdit with the same start and endpoints should be a plain insert. I might be simply missing something, but I guess that's not totally relevant to this PR or issue anyway. |
I have been digging intot his and at this point I am pretty sure its actually an upstream issue with the language server. Clearly sending and empty edit range is supposed to be an insertion and they have been receiving and (sometimes) fixing issues for that too. In particular I found the following commdnt: I think the response here is odd. They are quoting the lsp standard and say that what they do.is not standard compliant and that is the reason for the bug but then they go on to state that vscode handels this fine and they don't see a reason it shouldn't work so it's ok? Why even have a standard then? We could add some kind of workaround (we should port it from vscode if anybody can find where it's happening) although I am in favor of reporting it upstream instead of.bending.over backwards for non standard compliant severs. I also looked at nvim-cmp and Laplace (gave up with vscode):
|
Wow. So no major LSP client is actually spec compliant on TextEdit completions, including VSCode. That's surprising. I'd rather be correct and complain upstream than violate the spec and paper over the difference. Based on the linked issue, it does seem like they might have fixed the issue in gopls in the main branch as of a few weeks ago: golang/go#57384 |
Emacs LSP actually also has an open issue about it. They handle it the same way helix does and there are others too (for nvim alone there are like 4? LSP completions clients or more and some of those gopls issue were filed by nvim people so some of them probably handle this correctly). I didn't bother to look for more implementations tough. I do agree that we should stick to the standard. |
Right, I'm mostly just shocked about VSCode. If one implementation should be fully spec compliant, it should be the editor that the standard was created for. |
This probably also solves #1819 since we replace everything from the starting offset onwards |
This change only affects LSP servers that do not send a |
I missed something while reviewing this PR: It removes the ability to complete at multiple cursors at once. I included this PR in #5728 as I was already making multiple changes to the same code that would cause conflicts and fixed that problem. I kept the commit from this PR to give credit. |
Was included in #5728 |
closes #5469
Most LSPs will complete case-insensitive matches, particularly from lowercase to uppercase. In some cases, notably Pyright, this is given as a simple insert text instead of TextEdit. When this happens, the prefix text was left unedited.
This change seems to fix it for me. I'm not sure if there are other side effects to doing it this way, though. If another LSP gave an insert text that was just the rest to be inserted, I imagine this would still cause problems. But the previous method would also fail in that case with repeated text. If you typed
su
and the suggestion wassurration
, it would be ambiguous in that case whether that was to be inserted (makingsusurration
) or replaced entirely (makingsurration
).