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: completions overwrite text after cursor on insert #34011
Comments
Thank you for filing a gopls issue! Please take a look at the Troubleshooting section of the gopls Wiki page, and make sure that you have provided all of the relevant information here. |
Not related, but I think it's a bit funny to have gopherbot yell at me for submitting an issue using |
Thanks for reporting. Filed #34042 for the GopherBot issue. |
/cc @muirrn Edit: Sorry, wrong Muir again! |
There is definitely something to improve here, but I'm not sure changing it to never overwrite the postfix is the solution. In general we can't be sure if your intent is to prepend something new or to replace entirely. In your example, you might instead want to replace It also would be a bit weird for gopls to leave an invalid identifier after performing a completion (e.g. leaving On master, deep completions give you another option. In your example, I get a completion candidate for A maybe good idea is to augment the deep completion matching to take into account the postfix. In your example One other workaround is to insert an extra "." (or space) before completing, i.e. |
Personally, I don't find leaving invalid code after a completion "wrong", at least not in the course of editing. Every editor/IDE I've used has the same behavior, where a completion will insert what you asked it to, then you're left to finish it off (including Go completion, pre-gopls). Overwriting the whole token to the right is unexpected and I spend more time trying to undo things than the benefit I might get when it does the right thing. I get that gopls itself has no idea what the intent is when a user types something, but my guess says that deleting code is usually not what the user wants to do when accepting a completion (and LSP initially only supporting Deep completions are something I've never seen until gopls (and they're interesting, if not sometimes offputting; I've been using master for a while now), but I feel like using them as the solution to this problem is not entirely correct, since there are cases where there wouldn't be a match. I constructed this case to be short enough to show the overwrite, but it doesn't really represent a piece of code I've ever written. Inserting an extra |
At the least, it'd be nice to have an option to force gopls to use insert-only edits, just to have it match everything else my editor is doing and not trip me up all the time... |
We may very well end up just going with this behavior, but I'd like see if there is a smarter approach that does what the user wants and saves time/keystrokes vs the status quo.
Can you give an example where you don't want to overwrite but the postfix doesn't match a deep completion?
Can you elaborate on this? I'm very interested in feedback regarding deep completions. |
The most obvious case is when there's a method call in the middle. The example I gave really only works because it's a single extra thing and is a member access. I'd have to go looking for a better example, as I wrote down this bug to report (and then waited a bit too long before sending it in...)
I'd have to sit down and code and see if I can produce any specific examples, but my main issue has been that they've almost never been what I wanted, and seemed to appear at the top in some cases. An odd case I can come up with from playing around is when you're just starting to type the package name, and it's suggesting stuff inside the package before you've finished it at random. For example, if I start to type Another thing is that it seems like gopls will try to pick the "best" completion item based on an expected type, so the deep completions will often show up first, even though I'm much less likely to want to access something that's a deep completion away. |
Not sure I understand, exactly. Hopefully you come across a good example you can share.
It is true that the deep completions in that case are a bit arbitrary, but it is convenient if, for example, you are trying to call opentracing.DoSomething() you can probably just type "DoSo" or "otds" or maybe just "ds" and complete straight to what you want. If you don't know what you want, "opentracing" the package is still the first candidate, like you said. But, it sounds like the deep candidates are still distracting to some degree. We can probably do a better job filtering out low quality candidates.
Deep candidates will always be ranked below non-deep candidates, so if deep candidates show up first it means either there are no non-deep candidates that match the type, or your search prefix matches the deep candidates much better than the non-deep candidates. Do you have an example where a deep candidate you did not want was ranked higher than a non-deep candidate you did want? The general goal is deep candidates never get in your way and often save a lot of typing. If you have examples where they slowed you down I'd love to see so I can improve things. |
Change https://golang.org/cl/196119 mentions this issue: |
@muirrn Forgive me for not commenting on gerrit (haven't used it yet), but wouldn't that CL not fix this issue per se? It says that it only works if the prefix is empty, which to me seems like will never be the case in normal usage, as presumably one would want to type a few characters to select the right completion rather than using no prefix and arrowing through until the right selection is found. I get that it's a middle ground, but it's not exactly what I thought would happen. Forgive me for not giving more feedback; I've been busy and haven't had any interesting thoughts about deep completion to share. |
Yes, you are right of course. Let me try again later. |
What did you do?
A constructed example:
I'd like to replace
t.DoSomething()
witht.Left.DoSomething()
. I start typingLeft
after the.
and accept the completion.What did you expect to see?
Left
gets inserted after I select the completion; everything to the right of my cursor stays.What did you see instead?
DoSomething
is deleted and replaced withLeft
. I have to retypeDoSomething
to put it back. This is a reduced example of this happening, and it gets a bit more annoying when you don't realize it was deleted and have to undo and type it all manually (especially if you don't remember what got deleted).I don't think this behavior matches the completions of other languages, or VS Code's fallback word-level completions (which also just insert without touching anything to the right).
Build info
Built on master just to keep it recent, but happens on 0.1.3 and has on previous versions as well.
Go info
The text was updated successfully, but these errors were encountered: