Skip to content

Commit

Permalink
gopls/internal/analysis: add skipped analysis simplify on generated code
Browse files Browse the repository at this point in the history
On generated code, gopls always suggest to simplify code produced literals polluting the "Problems" pane in IDE, while properly refusing to format file on save because it is generated code.

This change will make simplifycompositelit, simplifyrange, simplifyslice skipped on generated code, so it will not polluting the "Problems" pane in IDE.

Fixes golang/go#67733

Change-Id: I99b3f083ce96594f360576f530cfc7f4b77c1cc1
Reviewed-on: https://go-review.googlesource.com/c/tools/+/598835
Reviewed-by: 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>
  • Loading branch information
idnandre authored and findleyr committed Aug 6, 2024
1 parent f855a53 commit 4653e48
Show file tree
Hide file tree
Showing 18 changed files with 298 additions and 9 deletions.
6 changes: 6 additions & 0 deletions gopls/doc/analyzers.md
Original file line number Diff line number Diff line change
Expand Up @@ -636,6 +636,8 @@ will be simplified to:

This is one of the simplifications that "gofmt -s" applies.

This analyzer ignores generated code.

Default: on.

Package documentation: [simplifycompositelit](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/simplifycompositelit)
Expand All @@ -662,6 +664,8 @@ will be simplified to:

This is one of the simplifications that "gofmt -s" applies.

This analyzer ignores generated code.

Default: on.

Package documentation: [simplifyrange](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/simplifyrange)
Expand All @@ -680,6 +684,8 @@ will be simplified to:

This is one of the simplifications that "gofmt -s" applies.

This analyzer ignores generated code.

Default: on.

Package documentation: [simplifyslice](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/simplifyslice)
Expand Down
2 changes: 2 additions & 0 deletions gopls/internal/analysis/simplifycompositelit/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,6 @@
// []T{{}, {}}
//
// This is one of the simplifications that "gofmt -s" applies.
//
// This analyzer ignores generated code.
package simplifycompositelit
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/analysis/passes/inspect"
"golang.org/x/tools/go/ast/inspector"
"golang.org/x/tools/gopls/internal/util/astutil"
"golang.org/x/tools/internal/analysisinternal"
)

Expand All @@ -34,9 +35,21 @@ var Analyzer = &analysis.Analyzer{
}

func run(pass *analysis.Pass) (interface{}, error) {
// Gather information whether file is generated or not
generated := make(map[*token.File]bool)
for _, file := range pass.Files {
if astutil.IsGenerated(file) {
generated[pass.Fset.File(file.Pos())] = true
}
}

inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
nodeFilter := []ast.Node{(*ast.CompositeLit)(nil)}
inspect.Preorder(nodeFilter, func(n ast.Node) {
if _, ok := generated[pass.Fset.File(n.Pos())]; ok {
return // skip checking if it's generated code
}

expr := n.(*ast.CompositeLit)

outer := expr
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@ import (

func Test(t *testing.T) {
testdata := analysistest.TestData()
analysistest.RunWithSuggestedFixes(t, testdata, simplifycompositelit.Analyzer, "a")
analysistest.RunWithSuggestedFixes(t, testdata, simplifycompositelit.Analyzer, "a", "generatedcode")
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright 2024 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Code generated with somegen DO NOT EDIT.

package testdata

type T struct {
x, y int
}

var _ = [42]T{
T{}, // No simplification fix is offered in generated code.
T{1, 2}, // No simplification fix is offered in generated code.
T{3, 4}, // No simplification fix is offered in generated code.
}
2 changes: 2 additions & 0 deletions gopls/internal/analysis/simplifyrange/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,6 @@
// for range v {...}
//
// This is one of the simplifications that "gofmt -s" applies.
//
// This analyzer ignores generated code.
package simplifyrange
13 changes: 13 additions & 0 deletions gopls/internal/analysis/simplifyrange/simplifyrange.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/analysis/passes/inspect"
"golang.org/x/tools/go/ast/inspector"
"golang.org/x/tools/gopls/internal/util/astutil"
"golang.org/x/tools/internal/analysisinternal"
)

Expand All @@ -29,11 +30,23 @@ var Analyzer = &analysis.Analyzer{
}

func run(pass *analysis.Pass) (interface{}, error) {
// Gather information whether file is generated or not
generated := make(map[*token.File]bool)
for _, file := range pass.Files {
if astutil.IsGenerated(file) {
generated[pass.Fset.File(file.Pos())] = true
}
}

inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
nodeFilter := []ast.Node{
(*ast.RangeStmt)(nil),
}
inspect.Preorder(nodeFilter, func(n ast.Node) {
if _, ok := generated[pass.Fset.File(n.Pos())]; ok {
return // skip checking if it's generated code
}

var copy *ast.RangeStmt // shallow-copy the AST before modifying
{
x := *n.(*ast.RangeStmt)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (

func Test(t *testing.T) {
testdata := analysistest.TestData()
analysistest.RunWithSuggestedFixes(t, testdata, simplifyrange.Analyzer, "a")
analysistest.RunWithSuggestedFixes(t, testdata, simplifyrange.Analyzer, "a", "generatedcode")
if slices.Contains(build.Default.ReleaseTags, "go1.23") { // uses iter.Seq
analysistest.RunWithSuggestedFixes(t, testdata, simplifyrange.Analyzer, "rangeoverfunc")
}
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright 2024 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Code generated with somegen DO NOT EDIT.

package testdata

import "log"

func mgeneratedcode() {
maps := make(map[string]string)
for k, _ := range maps { // No simplification fix is offered in generated code.
log.Println(k)
}
for _ = range maps { // No simplification fix is offered in generated code.
}
}
2 changes: 2 additions & 0 deletions gopls/internal/analysis/simplifyslice/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,6 @@
// s[a:]
//
// This is one of the simplifications that "gofmt -s" applies.
//
// This analyzer ignores generated code.
package simplifyslice
14 changes: 14 additions & 0 deletions gopls/internal/analysis/simplifyslice/simplifyslice.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ import (
"fmt"
"go/ast"
"go/printer"
"go/token"

"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/analysis/passes/inspect"
"golang.org/x/tools/go/ast/inspector"
"golang.org/x/tools/gopls/internal/util/astutil"
"golang.org/x/tools/internal/analysisinternal"
)

Expand All @@ -37,11 +39,23 @@ var Analyzer = &analysis.Analyzer{
// x, y := b[:n], b[n:]

func run(pass *analysis.Pass) (interface{}, error) {
// Gather information whether file is generated or not
generated := make(map[*token.File]bool)
for _, file := range pass.Files {
if astutil.IsGenerated(file) {
generated[pass.Fset.File(file.Pos())] = true
}
}

inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
nodeFilter := []ast.Node{
(*ast.SliceExpr)(nil),
}
inspect.Preorder(nodeFilter, func(n ast.Node) {
if _, ok := generated[pass.Fset.File(n.Pos())]; ok {
return // skip checking if it's generated code
}

expr := n.(*ast.SliceExpr)
// - 3-index slices always require the 2nd and 3rd index
if expr.Max != nil {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@ import (

func Test(t *testing.T) {
testdata := analysistest.TestData()
analysistest.RunWithSuggestedFixes(t, testdata, simplifyslice.Analyzer, "a", "typeparams")
analysistest.RunWithSuggestedFixes(t, testdata, simplifyslice.Analyzer, "a", "generatedcode", "typeparams")
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Copyright 2024 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Code generated with somegen DO NOT EDIT.

package testdata

var (
a [10]byte
b [20]float32
s []int
t struct {
s []byte
}

_ = a[0:]
_ = a[1:10]
_ = a[2:len(a)] // No simplification fix is offered in generated code.
_ = a[3:(len(a))]
_ = a[len(a)-1 : len(a)] // No simplification fix is offered in generated code.
_ = a[2:len(a):len(a)]

_ = a[:]
_ = a[:10]
_ = a[:len(a)] // No simplification fix is offered in generated code.
_ = a[:(len(a))]
_ = a[:len(a)-1]
_ = a[:len(a):len(a)]

_ = s[0:]
_ = s[1:10]
_ = s[2:len(s)] // No simplification fix is offered in generated code.
_ = s[3:(len(s))]
_ = s[len(a) : len(s)-1]
_ = s[0:len(b)]
_ = s[2:len(s):len(s)]

_ = s[:]
_ = s[:10]
_ = s[:len(s)] // No simplification fix is offered in generated code.
_ = s[:(len(s))]
_ = s[:len(s)-1]
_ = s[:len(b)]
_ = s[:len(s):len(s)]

_ = t.s[0:]
_ = t.s[1:10]
_ = t.s[2:len(t.s)]
_ = t.s[3:(len(t.s))]
_ = t.s[len(a) : len(t.s)-1]
_ = t.s[0:len(b)]
_ = t.s[2:len(t.s):len(t.s)]

_ = t.s[:]
_ = t.s[:10]
_ = t.s[:len(t.s)]
_ = t.s[:(len(t.s))]
_ = t.s[:len(t.s)-1]
_ = t.s[:len(b)]
_ = t.s[:len(t.s):len(t.s)]
)

func _() {
s := s[0:len(s)] // No simplification fix is offered in generated code.
_ = s
}

func m() {
maps := []int{}
_ = maps[1:len(maps)] // No simplification fix is offered in generated code.
}
Loading

0 comments on commit 4653e48

Please sign in to comment.