-
Notifications
You must be signed in to change notification settings - Fork 17.9k
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/internal/analysis: add "modernizer" analyzers #70815
Comments
Would it make sense for some of these to be depreciations instead? Particularly looking at x/exp/maps.Clear and the go/* upgrades. |
Even if we were to deprecate maps.Clear (which is perfectly fine function), users would still want a way to migrate their code away from it. So I see deprecation as independent. And in many cases the pattern being "modernized" is not just a simple use of one symbol that could be deprecated. |
Some of these (maybe all 😄 ) are subtler than they appear on the tin.
The core of this is just replacing
Here you have to identify the underlying "resource" that's being freed by the finalizer since that's what
There are so many patterns for splitting a string into lines right now. I'm really curious how we'd pick up on that.
In addition to creating Append methods, ideally this should also rewrite |
Change https://go.dev/cl/635777 mentions this issue: |
Change https://go.dev/cl/635680 mentions this issue: |
Change https://go.dev/cl/635681 mentions this issue: |
This change replaces the body of almost every function in the package with a call to its corresponding std function of the same name and--assumedly--semantics. If proposal golang/go#32816 is accepted, we will annotate each function with a "//go:fix inline" comment so that automated tooling such as golang.org/x/tools/internal/refactor/inline/analyzer can automatically inline the wrappers. (This CL is deemed to fix golang/go#70717 because it reduces maps.Clear to the same status as all the other maps functions.) Updates golang/go#32816 Updates golang/go#70815 Fixes golang/go#70717 Change-Id: I85246df07f903af97673b80024acdcae057b9f63 Reviewed-on: https://go-review.googlesource.com/c/exp/+/635680 Auto-Submit: Alan Donovan <adonovan@google.com> Reviewed-by: Ian Lance Taylor <iant@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Change https://go.dev/cl/636276 mentions this issue: |
Change https://go.dev/cl/637735 mentions this issue: |
Change https://go.dev/cl/638337 mentions this issue: |
This CL is the start of an analyzer that offers a suite of code transformations to modernize Go code, by taking advantage of newer features of the language when it would clarify the code to do so. Because it reports diagnostics on correct code, its severity is downgraded to INFO. Only one is implemented so far: the replacement of if/else conditional assignments by a call to min or max. + relnote and test Updates golang/go#70815 Change-Id: I686db57c2b95dfa399b44e5c6fdc478272cee084 Reviewed-on: https://go-review.googlesource.com/c/tools/+/635777 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Robert Findley <rfindley@google.com>
This CL adds a modernizer for calls to sort.Slice, where the less function is the natural order: sort.Slice(s, func(i, j int) bool { return s[i] < s[j] }) => slices.Sort(s) (Ditto SliceStable -> SortStable.) The foldingrange test was tweaked to avoid triggering this fix. Updates golang/go#70815 Change-Id: I755351c77aab8ddf7f21369c0f980e8d3334fc01 Reviewed-on: https://go-review.googlesource.com/c/tools/+/635681 Reviewed-by: Robert Findley <rfindley@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Auto-Submit: Alan Donovan <adonovan@google.com>
Also, modernize our tests in this manner. Also, remove existing "useany" analyzer, which is subsumed by this one. The fact that useany was off by default suggest that perhaps modernize may need to be as well; but perhaps severity=INFO will suffice. Updates golang/go#70815 Change-Id: Iba1662993fb8a1c50b2d843ad9425bbddafc927f Reviewed-on: https://go-review.googlesource.com/c/tools/+/636276 Auto-Submit: Alan Donovan <adonovan@google.com> Reviewed-by: Robert Findley <rfindley@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Change https://go.dev/cl/638595 mentions this issue: |
This CL adds the first modernizer for the "slices" package. It offers to replace an append (or tower of nested appends) to a clipped slice by a call to slices.Concat or slices.Clone. Examples: append(append(append(x[:0:0], a...), b...), c...) -> slices.Concat(a, b, c) append(append(slices.Clip(a), b...) -> slices.Concat(a, b) append([]T{}, a...) -> slices.Clone(a) append([]string(nil), os.Environ()...) -> os.Environ() It takes care not to offer fixes that would eliminate potentially important side effects such as to y's array in this example: append(y[:0], x...) -> slices.Clone(x) (unsound) However, it does not attempt to preserve the nilness of base in append(base, empty...) when the second argument is empty. Updates golang/go#70815 Change-Id: I5ea13bbf8bfd0b78a9fb71aef4c14848b860cc3a Reviewed-on: https://go-review.googlesource.com/c/tools/+/637735 Reviewed-by: Robert Findley <rfindley@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This CL adds a modernizer for go1.24's testing.B.Loop. It replaces for/range loops over b.N by b.Loop() and deletes any preceding calls to b.{Start,Stop,Reset}Timer. Updates golang/go#70815 Change-Id: I504c9fed20beaec3c085c64f9ce42d3f6ad435d8 Reviewed-on: https://go-review.googlesource.com/c/tools/+/638337 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Robert Findley <rfindley@google.com>
Change https://go.dev/cl/638875 mentions this issue: |
Change https://go.dev/cl/638436 mentions this issue: |
Thanks; I split this out into its own issue: #71313 |
Adds a new modernizer that suggests removing or replacing instances of "omitempty" on struct fields with "omitzero." Example (before): type Foo struct { A struct{ b int } `json:"name,omitempty" } Example (after - replace): type Foo struct { A struct{ b int } `json:"name,omitzero" } Example (after - remove): type Foo struct { A struct{ b int } `json:"name" } Updates golang/go#70815 Change-Id: I7d651880340d24929ea5cae4751557a1f60e5f8e Reviewed-on: https://go-review.googlesource.com/c/tools/+/640041 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Robert Findley <rfindley@google.com>
Made that a sub-issue of this one. Neat! We're living in the future. |
Adds a new modernizer that suggests replacing instances of append(s[:i], s[i+k:]...) with slices.Delete(s, i, i+k) Handles other variations like append(s[:i-1], s[i:]...) and append(s[:i+2], s[i+3:]...) Updates golang/go#70815 Change-Id: I71981d6e8d6973bca17153b95f2eb9f1f229522d Reviewed-on: https://go-review.googlesource.com/c/tools/+/641357 Reviewed-by: Alan Donovan <adonovan@google.com> Reviewed-by: Robert Findley <rfindley@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
A modernization I often do by hand is using {strings,bytes}.Cut{,Prefix,Suffix}. |
It doesn't turn up a single instance in the entire k8s codebase (~3MLoC), so the juice is not worth the squeeze. |
😅 Thank you for testing that out. |
Change https://go.dev/cl/646916 mentions this issue: |
Would |
@apocelipes see #71270 |
This CL adds a modernizer for 3-clause for loops that offers a fix to replace them with go1.22 "range n" loops. Updates golang/go#70815 Change-Id: I347179b8a308f380a9a894aa811ced66f7605df1 Reviewed-on: https://go-review.googlesource.com/c/tools/+/646916 Auto-Submit: Alan Donovan <adonovan@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Robert Findley <rfindley@google.com>
Change https://go.dev/cl/647355 mentions this issue: |
By moving the main.go file, gopls users will be able to run $ go run golang.org/x/tools/gopls/internal/analysis/modernize/cmd/modernize@latest -fix after the gopls release to apply all modernizer fixes en masse. Updates golang/go#70815 Change-Id: I25352b7b77653c177310dfea7a050741949890f9 Reviewed-on: https://go-review.googlesource.com/c/tools/+/647355 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Robert Findley <rfindley@google.com>
When I tried to run this, I got an error. Is this expected?
|
Yes, it is expected: gopls release tags are on a branch that doesn't have the Also: If building from head, beware that the three-way merge CL hasn't landed yet, so -fix may make a mess of things. |
@adonovan When you are done, could you please also turn this into a more regular pass so we can monitor and fix regressions in that area using a golanci-lint integration of that linter? |
Do you mean: can we publish the modernize analyzer as a subpackage of go/analysis/passes, so that golangci-lint can include it in its set? That's certainly something we could do, though of course every new API symbol requires a proposal; but we are at the beginning of a series of discussions about how to generalize modernizers (and by implication analyzers in general) so that they can be defined by third-party projects too. We should probably wait till that picture emerges clearly before committing to publish the modernize analyzer. |
There's one Currently at HEAD (44b61a1d174cc06329b20f5de60c2b0c800741a4):
package main
import "fmt"
func main() {
var x, y int
if x <= 0 { // a value of -1 or 0 will use a default value (30)
y = 30
} else {
y = x
}
fmt.Print(y)
} Applying the suggested fix doesn't yield an equivalent result: package main
import "fmt"
func main() {
var x, y int
y = max(x, 0)
fmt.Print(y)
} |
Thanks @spencerschrock; I've split this into its own issue, #71721. |
Change https://go.dev/cl/649457 mentions this issue: |
One thought: when suggesting to replace In general I think the same applies to any suggestions to use the |
Between generics, iterators, min and max, new standard packages such as
slices
,maps
, andcmp
, there are a large number of new ways to write Go code more concisely and no less clearly. We should develop "modernizer" analyzer(s) that identify such opportunities and offer suggested fixes.Many of these are already implemented in
staticcheck
(see S1000 et seq); we would just need to enable them.When the appropriate fix is to inline a call to a deprecated function whose body illustrates the recommended approach (e.g. a call to a more modern function, as in the case of the functions in the golang.org/x/exp/maps package), these will be handled by annotating the deprecated function as prescribed by proposal #32816, and letting the inliner take care of it.
Examples:
return false
andreturn true
steps in the slices package as wildcards that match "equal and opposite" actions--not just return statements--in the user code. (CL 640576)maps.Keys(m) + slices.Collect (or loop equivalent of Keys+Collect) + sort ->slices.Sorted(maps.Keys(m))
. Eliminate temporaries when used once inrange _
. Downside: de-optimizes preallocation of correct array size; perhaps best left until resolution of proposal: maps: helper to loop over the maps in predictable order #68598.append(s[:i], s[i+k:]...)
->slices.Delete(s, i, i+k)
, where k is a non-negative constantawkward logic in slice.Sort's less function →if cmp := cmp.Compare(x, y); cmp != 0 { return cmp < 0 }
sort.Slice -> slices.SortFunc, eliminating the indicesSetFinalizer → AddCleanupuse strings.Lines instead of strings.Split("\n") (but: "\r"?!) or text.scanner(strings.NewReader)/Scan/Text[]byte(fmt.Sprintf...)
→fmt.Appendf(nil, ...)
(https://go.dev/cl/638436)implementing {Text,Binary}Appender for types that currently implement {Text,Binary}Marshalerctx, cancel := context.WithCancel(context.Background()); defer cancel()
in tests withctx := t.Context()
.for i := 0; i < n; i++ {}
=>for i := range n {}
(CL 646916)They should of course all respect the effective version of Go determined by go.mod and build tags.
@aclements
The text was updated successfully, but these errors were encountered: