-
Notifications
You must be signed in to change notification settings - Fork 17.8k
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
x/tools/gopls: format on save breaks imports when reordered #35388
Comments
Thank you for filing a gopls issue! Please take a look at the Troubleshooting guide, and make sure that you have provided all of the relevant information here. |
Can you reproduce this by running the |
Logs here: https://gist.github.com/zikaeroh/7eb4a0a7d7d21d929185315bd8cdcb45 Here is a screenshot of the bad quoting (since I couldn't get it in the screen recording): |
Thanks! I'll take a look at the logs. Can you also share the output of running |
Interestingly enough, the only time [Trace - 20:38:56.202 PM] Received response 'textDocument/codeAction - (10)' in 1445ms.
Result: [{"title":"Organize Imports","kind":"source.organizeImports","edit":{"changes":{"file:///home/jake/zikaeroh/hortbot/hortbot/internal/cli/flags/ircflags/ircargs.go":[{"range":{"start":{"line":10,"character":3},"end":{"line":11,"character":3}},"newText":""},{"range":{"start":{"line":12,"character":53},"end":{"line":12,"character":53}},"newText":"\"\n\t\"github.com/hortbot/hortbot/internal/pkg/ctxlog"}]}}}] All it's doing here is deleting a line and adding the |
Output:
I am not aware of any other save hook unless the VS Code extension is still trying to run an external tool even though I have not disabled gopls's formatting. For fun, I replaced my |
Thanks for trying that out. I guess we can rule that out then. To confirm with the |
The above tests were done simply with the reorderings. If I only remove an import, I do see it trying to add it back. With
|
Can you try using the imports from |
Hopefully this is what you're looking for: https://gist.github.com/zikaeroh/3300ac58971886fd3f217f9338da2c56
|
Just to try and eliminate the Go extension as the source of the problem, I configured it to run the formatting tool with a bad flag ( |
Yes, that log was helpful - thank you! One thing I noticed about it is that there were a number of |
Is there any plan to not try and use both format and code actions separately in order to manage imports, instead just doing everything as goimports does as a single action? With how formatting and import management have been combined via goimports/goreturns in editors for a good while, I would really like that behavior to continue, rather than trying to do both individually (and then have to deal with figuring out which edits match which version, and bugs like this). |
No, the current plan is actually to separate In general, it is much more correct for us to match edits to a specific version of a file - that's really the issue here. If your editor is slow or something gets out of sync with the client and the server - you will immediately get strange behavior if edits are not associated with a specific version of the file. |
Absolutely, the versions matter and that should be fixed. My only thought was that it seemed like splitting things is complicating a scenario that a lot of people have been using for a while, even if doing a bunch of stuff on format is different than most every other LSP enabled language (mainly because doing something like "find me the right new imports to make this file sane" is such a cheap operation in Go, like so many other things). |
Historically they were combined only because a save hook was the only way to trigger them, and the fact that they are combined is the source of considerable problems. By carefully teasing the functionality apart we can allow users to pick and choose, and authors of a new piece of functionality will no longer need to include a random collection of other save hooks they think are important. Also much of this functionality does not (and should not) need you to save the file to trigger. |
That's fair and reasonable, and I understand and agree with it from that point of view. I was going to stick this on #30843, but I can put my thoughts here too. I'm just thinking towards the day where At the end of the day, if I can hit save and things are formatted and reorganized as they would be if I ran |
Yes, the intention is that the default configuration will be what we believe to be the best normal user experience, which will include those kinds of things. The configuration options will still be there for power users, but the defaults will be sane. |
At the risk of extending this longer (when my bug isn't related, per se), how do you plan on setting the sane defaults when it's the client's job to apply things like fixes? (At least, it's my impression that options like |
Each client needs to decide what the sensible defaults are, we have opinions, and to some extent we hope that clients will respect them so that the unconfigured experience will be reasonably common across all clients, but some things will be different because the model the clients work in is different, and that is okay. |
Since #35243 was fixed, I went and retried formatting/import sorting again as above, but the same behavior persists. https://gist.github.com/zikaeroh/618e23c7292123e62a65dbcb71d2c107 I can see in the log that the code actions now include version numbers, but maybe there's something else that's needed (or #35243 alone wasn't the entire story). |
Taking a look at the logs, it seems like the version numbers are wrong (also, #35584). I'll investigate that further. |
This is a bit of a brain dump from my analysis of the logs here. If you're able to attach a screencast of what you're seeing while a log is being written that would be super helpful for analysis as well. All of the codeActions that suggest modifications to the file:
If we believe that VS Code is actually respecting the versions specified in the responses, we would see these as The only time I see this happen is for the
The behavior here looks reasonable to me, though I might be mistaken. On line 836, there is this
Later on, we see the last codeAction that returns a response:
It looks like this codeAction gets applied, even though the versions of the files are mismatched. The final
This also looks like an import modification, but without any corresponding codeAction. Sorry that this long comment isn't particularly helpful - just wanted to write out the things I noticed before I forgot. Maybe I will make a CL with some additional log statements that you can use to get some more information. In the meantime I will focus on resolving #35584 so that we can be certain the versions are not incorrect. |
Here is a fresh log and screencast:
All actions I performed were either line swaps, undos, or file saves. I captured my VS Code tabs so you can see when I saved. I'd do a recording with key presses, but I'm a bit limited to what I can do from wayland/sway. |
I recently ran into this myself on my Mac. Looking at the logs, it seems like VS Code is still applying code actions even if the versions of the files no longer match up. There is still a larger issue of |
I looked at the logs from https://golang.org/issue/35388#issuecomment-554172456. I'm going to focus on the moment between :19 and :20 where That string appears in the log at 17:45:45.250, so we know that whatever happened probably happened in the few seconds before that. The most likely-looking code actions are:
Note that VS Code sent us two codeAction requests, one for a single character (38) and one for the whole file (40). We respond to both requests with fixes for the whole file. I think it's vaguely plausible that applying those edits twice would produce the file we see at :21. I'm not sure what the bug is here. Maybe we should only return actions in the requested range? Or we shouldn't be sending code actions more than once for the same version? Or the client shouldn't be requesting them? For the record, I also see the same pattern for the following pairs of requests: 10 and 12, 22 and 23, 64 and 63 (out of order responses), 71 and 73, 85 and 86. I haven't worked through any of the others but I think it's pretty plausible that this is the only thing going on. |
Some observations from our experience with
Based on our experience in #35114, We've also seen situations where diagnostics (as a result of analyses) are referring to the incorrect version: #35584. To my mind the first thing to ensure here is that |
Yes, it wasn’t set how gopls should behave when I added this to govim (as in: it didn’t matter what it range it got). Currently govim sends the current cursor position as range, as well as all diagnostics that covers that position. I haven’t used VSCode, could it be that it sends the entire file to be able to show the user an icon next to the lines that have suggested fixes? |
Change https://golang.org/cl/209057 mentions this issue: |
@myitcv True, the code actions in question are against stale versions of the file. But even if they were applied to the wrong version, no single insertion can produce the behavior in the video, because they all start with whitespace. I think they have to be getting composed incorrectly somehow, but looking again I don't see how. |
@zikaeroh: hey, this is a bit of a guess, but can you try setting
in your settings? I have evidence that formatting and organize imports fight each other, at least in VS Code. Edit: wait, never mind, all your formatting responses are empty... |
For what it's worth, I went and tried to set this to get you an answer, and for some reason I can't reproduce this behavior anymore. New logs and screencast:
The way sorting + formatting works is a bit subpar (edits applied pretty far apart in time, sometimes never without another save), but I don't see the sort of corruption I had seen previously. I have no idea what could have changed. I read every commit to x/tools and can't recall seeing anything that would have changed this... vscode-go hasn't updated, so the LS client would be the same, and the most recent VS Code minor release changelog shows nothing interesting. I even deleted Version:
I'll keep testing to see. |
FWIW, I've spent a bunch of time trying to reproduce this, and while I did find a number of glitches, none of them were this one. |
Previously, we would reload if a user's import list decreased or simply changed order. This is not necessary. Now, we only re-run if a new import needs to be loaded. Updates golang/go#35388 Change-Id: I47874afe773dddb835ac27b18895e7a082950dc7 Reviewed-on: https://go-review.googlesource.com/c/tools/+/209057 Reviewed-by: Heschi Kreinick <[email protected]>
I spent a little time doing a bisect (backwards, trying to find the CL that fixed it), and it appears that CL 208265 was the one that fixed the issue for me. Makes sense, as the CL was fixing diagnostics on snapshot clones and mentions the impact on code actions. I'm not a big fan of the relative speed of save/format/organize compared to plain Thanks for looking into this. One fewer race to figure out. 😄 |
Thanks for following up! I'm surprised to hear that |
What did you do?
In https://github.com/hortbot/hortbot/blob/master/internal/cli/flags/ircflags/ircargs.go, swap around some import lines and save.
My Go-related configs:
Though I'd normally configure
local
in the project's settings, since it doesn't make much sense globally.What did you expect to see?
The imports are reordered back to the way they were (or re-sorted by the
local
feature).What did you see instead?
The imports get formatted very wrong. Imports get deleted, duplicated, and sometimes turn out syntatically correct with misplaced quotes. I tried to do a screencap.
https://streamable.com/ffxjz
I also verified this without
go-diff
enabled to see if it was the diff algorithm, but there was no difference.Also, the
local
option is applied at an unknown time. I want things to behave exactly as they do with VS Code + goimports, i.e. "hit save, imports are reordered and fixed", but can't seem to get that to work.Build info
Go info
The text was updated successfully, but these errors were encountered: