Auto-import duplication because of redundant `additionalTextEdits` sent by LSP in Zed
Describe the bug
Whenever I try to import anything from Svelte, the import ... from the autoimport gets duplicated.
More details on the issue at Zed's repo: https://github.com/zed-industries/zed/issues/19214#issue-2588344463
(Video by @ArturGalstyan1)
https://private-user-images.githubusercontent.com/152854677/376570126-f3bb6ea6-50d2-43a0-ab34-2a3b7ab8a0ee.mov?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MzM2ODc2NTgsIm5iZiI6MTczMzY4NzM1OCwicGF0aCI6Ii8xNTI4NTQ2NzcvMzc2NTcwMTI2LWYzYmI2ZWE2LTUwZDItNDNhMC1hYjM0LTJhM2I3YWI4YTBlZS5tb3Y_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjQxMjA4JTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI0MTIwOFQxOTQ5MThaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT04MGM5OTAwMWY0NzE3MTNiMTEyYzcwODcyZDI0OTJiOTc1MzE2MTc1M2UyZDdkMzk2NGIxYTVjZTY4MTQ1NTM1JlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCJ9.W7CRGwKQC517kqRuoarE4NK3hh1nKuCkN8_7qADtnC0
I think there's two problems here:
- Zed's lack of safeguards against processing redundant
additionalTextEdits. - Svelte's LSP sending redundant
additionalTextEdits.
Wondering if the Svelte folks know if this is an issue worth fixing or if Zed just needs to tweak their request.
This issue does not exist in VSCode by the way. I compared the logs and Zed just sends additionalTextData when it selects an import under the dropdown.
Reproduction
- Install Zed
- Install the Svelte Extension in Zed (Cmd + Shift + X)
- Go to any
.sveltefile. - Write any import like
page, then ctrl + space to get.
You can also debug the language server by opening the command palette (Cmd + Shift + P), then clicking on RPC Messages under svelte-language-server:
Expected behaviour
No duplicate imports
System Info
- OS: macOS 15.1.1
- IDE: Zed: v0.164.2 (Zed)
- I unfortunately can't find the Language Server version. I assume latest as of now. This is the code that the Zed Svelte Extension uses to initialize the LSP.
Which package is the issue about?
svelte-language-server
Additional Information, eg. Screenshots
If this is just expected behavior from the LSP, feel free to close! Thank you!
Can you check if Zed sent the resolve request twice? I can't think of another possibility where this might happen. We only have two places where we set additionalTextEdits. One is to split part of TextEdit to additionalTextEdits but I didn't see textEdit in your log. https://github.com/sveltejs/language-tools/blob/02db54de1f2fc44d958d67113a9d0fb41a8f6fe7/packages/language-server/src/plugins/typescript/features/CompletionProvider.ts#L874-L885
The other is to add the edit either to an empty array or existing if any already exists. But since there isn't any other place where we set it, unless the same code ran twice it should always be the former. If this is the case, We could remove the redundant concat but you should still ask why Zed sent the request twice since it's just a waste of time.
https://github.com/sveltejs/language-tools/blob/02db54de1f2fc44d958d67113a9d0fb41a8f6fe7/packages/language-server/src/plugins/typescript/features/CompletionProvider.ts#L983-L985
Thanks for getting back! @jasonlyu123. So yeah I think you're 100% right. Thanks for narrowing this down! It is definitely the "Zed sends the request twice" case. I wasn't able to catch it the first time because I assumed that the ctrl + space hotkey only gets suggestions. Not resolve completions. It in-fact resolves completions for every single item in the suggestions.
I honestly don't know why though.
https://github.com/user-attachments/assets/a17c9f4a-49d4-459b-81bb-6d975bc545ac
Thank you for the discussion. From Zed's side, this is indeed a bug and https://github.com/zed-industries/zed/pull/22448 fixes it, in the next release there will be one resolve request per item only.
No strong opinions, but I find this behavior confusing in general, as no other servers (vtsls, rust-analyzer, pyright, etc.) are doing nothing similar.
I see a small hint to this in https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#completionItem
/**
* A data entry field that is preserved on a completion item between
* a completion and a completion resolve request.
*/
as something that the language server manages, and can omit in the first resolve response.
As far as I remember, one of the reasons is that we had additional text edits before resolving to workaround a VSCode behaviour. I can check if it's still needed or if there is another way to solve it.
I just think it still makes sense to ask if it's intentional for Zed to resolve the completion item twice. It's also the first time I saw a client that does this.