-
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: completion offers too many irrelevant candidates in struct literal #32768
Comments
My argument is that completion should follow the language spec and not be influenced by linters (this particular vet check is not a fatal error, but more of a warning). The language lets you use implicit field names, so gopls completions should support that case. And it isn't some esoteric language feature that no one uses. Many people disable the composite key vet check because they feel there is nothing wrong with using implicit field names in their own code. Note that gopls lists the field names first (so the noise should be less impactful), and once you have one key-value field in your literal it will stop suggesting lexical completions for later keys. One easy improvement would be to list a "stricter" set of lexical completions. Instead of including every object and type name, it only lists objects and types that match the struct field. That would cut your list down to:
|
I'm not aware of any such distinction in
My understanding is that this is a current check, largely for reasons of backward compatibility. If you don't use a keyed literal, then new fields can't be added; it's a breaking change. With that response, I'll chicken out and say that we should probably avoid debating the merits of this particular vet check here 😄
I'm looking to provide an out-of-the-box sensible default behaviour for At the risk of providing a config soup, it's possible this behaviour could remain but behind a config option.
I edited my original post because I failed to mention package-level candidates. So the list could potentially be much longer, assuming their respective types match the struct's fields. |
I would rather the default gopls behavior not exclude "legitimate" completions. People use implicit field names so I think it is better to have some false positive "noise" than false negatives. |
I agree with @muir in this case. I think we actually had this conversation on a code review once - at some point, @myitcv, for the record, the |
@stamblerre, I think you meant @muirrn rather than me. |
@stamblerre @muirrn - ok well I've done my bit/best trying to convince you 😄. For structs outside of the current package I still believe it's the correct thing to do (only provide field names) given the current default behaviour of For now at the very least we need to exclude candidates that are not the correct type. @muirrn is that the intention of https://go-review.googlesource.com/c/tools/+/183941?
Not sure what you mean here - can you expand? |
All I meant is that, when testing, we don't check against builtin candidates because it's too much noise (see https://github.com/golang/tools/blob/fb37f6ba82613749b0b522aa509da78361849fc3/internal/lsp/lsp_test.go#L163). I think that I'd be willing to revisit this discussion at some point in the future when things are a bit more stable, and we have a better sense of what users want. However, you are completely right that something like |
It's possible to avoid that issue by setting appropriate min candidate score inside the client (VSCode, for example). In order to make that safe, users may need a guarantee that candidates that satisfy If we set that threshold to 1.01, this is a list for completion for the given example:
Field names have highest score, other candidates are for the case where you want to use As a side note, I believe things like |
Since the decision was to include lexical completions in this case, can we close out this issue? |
Yes, absolutely. Please open a new issue if something else comes up. |
Could I gently nudge you to reopen or reconsider this issue? :) It's been over a year, and as someone who has started using gopls recently (I know I'm late), I'm surprised at the outcome of this issue.
Personally, I don't think this is a good argument. I'd even go as far as saying that gopls should not have easy or well-documented ways to disable vet checks. The whole point of vet is that it has zero false positives, and practically everyone should follow its advice. If a check is not useful enough, or has too many false positives, it wouldn't have met vet's criteria.
This change is for unkeyed composite literals for exported structs declared in other packages. Unkeyed composite literals with local types would continue to work the same. |
@mvdan Are you arguing against the additional noise of superfluous completion candidates, or against gopls offering completions that fail go vet? |
@muirdm I'm arguing against gopls offering completions which fail go vet, yes. I made some extra arguments in the comment above against making vet configurable at a high level, but the reason I want to reopen this issue is what you said. |
Thanks for clarifying. Slightly tangential, but with the advent of modules could the "composites" vet check be changed to allow implicit field names that cross package boundaries within the same module? Anyway, I think it makes sense in this case for gopls to not offer completions that fail vet, as configured. I would still want to be able to disable the "composites" vet analyzer in gopls (or have the analyzer relax its check to module scope). |
Continuing the slightly tangential point 😄 but I'm not sure how the advent of modules changes the vet rule?
I'll re-open this issue for now then, because there doesn't seem like much point opening a duplicate, and it saves us discussing on a closed issue. @stamblerre - what are your thoughts on reducing the scope of the completion candidates, according to
As I've mentioned before, and @mvdan mentions above, I think we need to take care to not undo the (almost) zero-option nature of |
The "composites" vet check flags implicit field names used in struct literals only if the struct type is imported from another package. I presume it doesn't flag struct types defined in your current package since if you add another field to the struct you will certainly be able to update composite literals in the struct's package accordingly. The same could not be said for someone else using your package as a library and using implicit field names (i.e. adding a new struct field causes a compilation error for them that you cannot avoid). However, within a single module it seems like we now have the same certainty that we can fix all broken composite literals within the module when adding a new field to the struct. |
I think that's reasonable. Modules came long after these vet checks were designed. It's also true that vet checks are only aware of packages, not modules, so I'm not sure how feasible this restriction would be in practice. Could you file a cmd/vet issue about it? It should be considered and tracked separately, I think. We could then make gopls follow whatever vet decides to do. |
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
Consider the following example:
If completion is attempted at the position of the comment
// attempt completion
the following list of candidates is returned:In this case, because
S
is declared in another package, vet will enforce that use of the struct type in a composite literal must be keyed:https://play.golang.org/p/-H5Fnm5c9zj
Hence I believe the only valid candidates are:
In any case, if
S
were declared in the same package, the list of candidates is not actually correct: it appears to be the valid key names plus all the predeclared identifiers, plus package-scope identifiers, regardless of whether they are applicable.My proposal would be that regardless of whether
S
is declared in the current package or not, the list of candidates be limited to the valid key names. This feels like a more sensible default; far less noise in the majority of cases.I realise this is subjective... so other thoughts welcomed!
cc @stamblerre @ianthehat
The text was updated successfully, but these errors were encountered: