From 4653e48eb85159eef93c4634029cd73b0430f1e0 Mon Sep 17 00:00:00 2001 From: idnandre Date: Wed, 17 Jul 2024 17:27:50 +0700 Subject: [PATCH] gopls/internal/analysis: add skipped analysis simplify on generated code 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 LUCI-TryBot-Result: Go LUCI Reviewed-by: Robert Findley --- gopls/doc/analyzers.md | 6 ++ .../analysis/simplifycompositelit/doc.go | 2 + .../simplifycompositelit.go | 13 ++++ .../simplifycompositelit_test.go | 2 +- .../src/generatedcode/generatedcode.go | 17 +++++ .../src/generatedcode/generatedcode.go.golden | 17 +++++ gopls/internal/analysis/simplifyrange/doc.go | 2 + .../analysis/simplifyrange/simplifyrange.go | 13 ++++ .../simplifyrange/simplifyrange_test.go | 2 +- .../src/generatedcode/generatedcode.go | 18 +++++ .../src/generatedcode/generatedcode.go.golden | 18 +++++ gopls/internal/analysis/simplifyslice/doc.go | 2 + .../analysis/simplifyslice/simplifyslice.go | 14 ++++ .../simplifyslice/simplifyslice_test.go | 2 +- .../src/generatedcode/generatedcode.go | 72 +++++++++++++++++++ .../src/generatedcode/generatedcode.go.golden | 72 +++++++++++++++++++ gopls/internal/doc/api.json | 12 ++-- gopls/internal/util/astutil/util.go | 23 ++++++ 18 files changed, 298 insertions(+), 9 deletions(-) create mode 100644 gopls/internal/analysis/simplifycompositelit/testdata/src/generatedcode/generatedcode.go create mode 100644 gopls/internal/analysis/simplifycompositelit/testdata/src/generatedcode/generatedcode.go.golden create mode 100644 gopls/internal/analysis/simplifyrange/testdata/src/generatedcode/generatedcode.go create mode 100644 gopls/internal/analysis/simplifyrange/testdata/src/generatedcode/generatedcode.go.golden create mode 100644 gopls/internal/analysis/simplifyslice/testdata/src/generatedcode/generatedcode.go create mode 100644 gopls/internal/analysis/simplifyslice/testdata/src/generatedcode/generatedcode.go.golden diff --git a/gopls/doc/analyzers.md b/gopls/doc/analyzers.md index 45db766719f..f78f1bdf732 100644 --- a/gopls/doc/analyzers.md +++ b/gopls/doc/analyzers.md @@ -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) @@ -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) @@ -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) diff --git a/gopls/internal/analysis/simplifycompositelit/doc.go b/gopls/internal/analysis/simplifycompositelit/doc.go index fe40596746e..bda74c7db3f 100644 --- a/gopls/internal/analysis/simplifycompositelit/doc.go +++ b/gopls/internal/analysis/simplifycompositelit/doc.go @@ -19,4 +19,6 @@ // []T{{}, {}} // // This is one of the simplifications that "gofmt -s" applies. +// +// This analyzer ignores generated code. package simplifycompositelit diff --git a/gopls/internal/analysis/simplifycompositelit/simplifycompositelit.go b/gopls/internal/analysis/simplifycompositelit/simplifycompositelit.go index c651206b05f..1bdce1d658c 100644 --- a/gopls/internal/analysis/simplifycompositelit/simplifycompositelit.go +++ b/gopls/internal/analysis/simplifycompositelit/simplifycompositelit.go @@ -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" ) @@ -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 diff --git a/gopls/internal/analysis/simplifycompositelit/simplifycompositelit_test.go b/gopls/internal/analysis/simplifycompositelit/simplifycompositelit_test.go index a355616e3fe..4445a0cbb2f 100644 --- a/gopls/internal/analysis/simplifycompositelit/simplifycompositelit_test.go +++ b/gopls/internal/analysis/simplifycompositelit/simplifycompositelit_test.go @@ -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") } diff --git a/gopls/internal/analysis/simplifycompositelit/testdata/src/generatedcode/generatedcode.go b/gopls/internal/analysis/simplifycompositelit/testdata/src/generatedcode/generatedcode.go new file mode 100644 index 00000000000..7b11dc5ba47 --- /dev/null +++ b/gopls/internal/analysis/simplifycompositelit/testdata/src/generatedcode/generatedcode.go @@ -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. +} diff --git a/gopls/internal/analysis/simplifycompositelit/testdata/src/generatedcode/generatedcode.go.golden b/gopls/internal/analysis/simplifycompositelit/testdata/src/generatedcode/generatedcode.go.golden new file mode 100644 index 00000000000..7b11dc5ba47 --- /dev/null +++ b/gopls/internal/analysis/simplifycompositelit/testdata/src/generatedcode/generatedcode.go.golden @@ -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. +} diff --git a/gopls/internal/analysis/simplifyrange/doc.go b/gopls/internal/analysis/simplifyrange/doc.go index f55ed56b35b..3d1145e0b09 100644 --- a/gopls/internal/analysis/simplifyrange/doc.go +++ b/gopls/internal/analysis/simplifyrange/doc.go @@ -27,4 +27,6 @@ // for range v {...} // // This is one of the simplifications that "gofmt -s" applies. +// +// This analyzer ignores generated code. package simplifyrange diff --git a/gopls/internal/analysis/simplifyrange/simplifyrange.go b/gopls/internal/analysis/simplifyrange/simplifyrange.go index 537e0e97081..ce9d450582b 100644 --- a/gopls/internal/analysis/simplifyrange/simplifyrange.go +++ b/gopls/internal/analysis/simplifyrange/simplifyrange.go @@ -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" ) @@ -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) diff --git a/gopls/internal/analysis/simplifyrange/simplifyrange_test.go b/gopls/internal/analysis/simplifyrange/simplifyrange_test.go index fd927c56df1..973144c30e8 100644 --- a/gopls/internal/analysis/simplifyrange/simplifyrange_test.go +++ b/gopls/internal/analysis/simplifyrange/simplifyrange_test.go @@ -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") } diff --git a/gopls/internal/analysis/simplifyrange/testdata/src/generatedcode/generatedcode.go b/gopls/internal/analysis/simplifyrange/testdata/src/generatedcode/generatedcode.go new file mode 100644 index 00000000000..36b935c77eb --- /dev/null +++ b/gopls/internal/analysis/simplifyrange/testdata/src/generatedcode/generatedcode.go @@ -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. + } +} diff --git a/gopls/internal/analysis/simplifyrange/testdata/src/generatedcode/generatedcode.go.golden b/gopls/internal/analysis/simplifyrange/testdata/src/generatedcode/generatedcode.go.golden new file mode 100644 index 00000000000..36b935c77eb --- /dev/null +++ b/gopls/internal/analysis/simplifyrange/testdata/src/generatedcode/generatedcode.go.golden @@ -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. + } +} diff --git a/gopls/internal/analysis/simplifyslice/doc.go b/gopls/internal/analysis/simplifyslice/doc.go index 2fb4c461054..4c6808acd53 100644 --- a/gopls/internal/analysis/simplifyslice/doc.go +++ b/gopls/internal/analysis/simplifyslice/doc.go @@ -19,4 +19,6 @@ // s[a:] // // This is one of the simplifications that "gofmt -s" applies. +// +// This analyzer ignores generated code. package simplifyslice diff --git a/gopls/internal/analysis/simplifyslice/simplifyslice.go b/gopls/internal/analysis/simplifyslice/simplifyslice.go index 0c7cc3ff284..343fca8b185 100644 --- a/gopls/internal/analysis/simplifyslice/simplifyslice.go +++ b/gopls/internal/analysis/simplifyslice/simplifyslice.go @@ -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" ) @@ -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 { diff --git a/gopls/internal/analysis/simplifyslice/simplifyslice_test.go b/gopls/internal/analysis/simplifyslice/simplifyslice_test.go index 969161e3c90..7fc5f9af451 100644 --- a/gopls/internal/analysis/simplifyslice/simplifyslice_test.go +++ b/gopls/internal/analysis/simplifyslice/simplifyslice_test.go @@ -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") } diff --git a/gopls/internal/analysis/simplifyslice/testdata/src/generatedcode/generatedcode.go b/gopls/internal/analysis/simplifyslice/testdata/src/generatedcode/generatedcode.go new file mode 100644 index 00000000000..a291600d11f --- /dev/null +++ b/gopls/internal/analysis/simplifyslice/testdata/src/generatedcode/generatedcode.go @@ -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. +} diff --git a/gopls/internal/analysis/simplifyslice/testdata/src/generatedcode/generatedcode.go.golden b/gopls/internal/analysis/simplifyslice/testdata/src/generatedcode/generatedcode.go.golden new file mode 100644 index 00000000000..a291600d11f --- /dev/null +++ b/gopls/internal/analysis/simplifyslice/testdata/src/generatedcode/generatedcode.go.golden @@ -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. +} diff --git a/gopls/internal/doc/api.json b/gopls/internal/doc/api.json index 7de6006fb8a..322707dd085 100644 --- a/gopls/internal/doc/api.json +++ b/gopls/internal/doc/api.json @@ -524,17 +524,17 @@ }, { "Name": "\"simplifycompositelit\"", - "Doc": "check for composite literal simplifications\n\nAn array, slice, or map composite literal of the form:\n\n\t[]T{T{}, T{}}\n\nwill be simplified to:\n\n\t[]T{{}, {}}\n\nThis is one of the simplifications that \"gofmt -s\" applies.", + "Doc": "check for composite literal simplifications\n\nAn array, slice, or map composite literal of the form:\n\n\t[]T{T{}, T{}}\n\nwill be simplified to:\n\n\t[]T{{}, {}}\n\nThis is one of the simplifications that \"gofmt -s\" applies.\n\nThis analyzer ignores generated code.", "Default": "true" }, { "Name": "\"simplifyrange\"", - "Doc": "check for range statement simplifications\n\nA range of the form:\n\n\tfor x, _ = range v {...}\n\nwill be simplified to:\n\n\tfor x = range v {...}\n\nA range of the form:\n\n\tfor _ = range v {...}\n\nwill be simplified to:\n\n\tfor range v {...}\n\nThis is one of the simplifications that \"gofmt -s\" applies.", + "Doc": "check for range statement simplifications\n\nA range of the form:\n\n\tfor x, _ = range v {...}\n\nwill be simplified to:\n\n\tfor x = range v {...}\n\nA range of the form:\n\n\tfor _ = range v {...}\n\nwill be simplified to:\n\n\tfor range v {...}\n\nThis is one of the simplifications that \"gofmt -s\" applies.\n\nThis analyzer ignores generated code.", "Default": "true" }, { "Name": "\"simplifyslice\"", - "Doc": "check for slice simplifications\n\nA slice expression of the form:\n\n\ts[a:len(s)]\n\nwill be simplified to:\n\n\ts[a:]\n\nThis is one of the simplifications that \"gofmt -s\" applies.", + "Doc": "check for slice simplifications\n\nA slice expression of the form:\n\n\ts[a:len(s)]\n\nwill be simplified to:\n\n\ts[a:]\n\nThis is one of the simplifications that \"gofmt -s\" applies.\n\nThis analyzer ignores generated code.", "Default": "true" }, { @@ -1186,19 +1186,19 @@ }, { "Name": "simplifycompositelit", - "Doc": "check for composite literal simplifications\n\nAn array, slice, or map composite literal of the form:\n\n\t[]T{T{}, T{}}\n\nwill be simplified to:\n\n\t[]T{{}, {}}\n\nThis is one of the simplifications that \"gofmt -s\" applies.", + "Doc": "check for composite literal simplifications\n\nAn array, slice, or map composite literal of the form:\n\n\t[]T{T{}, T{}}\n\nwill be simplified to:\n\n\t[]T{{}, {}}\n\nThis is one of the simplifications that \"gofmt -s\" applies.\n\nThis analyzer ignores generated code.", "URL": "https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/simplifycompositelit", "Default": true }, { "Name": "simplifyrange", - "Doc": "check for range statement simplifications\n\nA range of the form:\n\n\tfor x, _ = range v {...}\n\nwill be simplified to:\n\n\tfor x = range v {...}\n\nA range of the form:\n\n\tfor _ = range v {...}\n\nwill be simplified to:\n\n\tfor range v {...}\n\nThis is one of the simplifications that \"gofmt -s\" applies.", + "Doc": "check for range statement simplifications\n\nA range of the form:\n\n\tfor x, _ = range v {...}\n\nwill be simplified to:\n\n\tfor x = range v {...}\n\nA range of the form:\n\n\tfor _ = range v {...}\n\nwill be simplified to:\n\n\tfor range v {...}\n\nThis is one of the simplifications that \"gofmt -s\" applies.\n\nThis analyzer ignores generated code.", "URL": "https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/simplifyrange", "Default": true }, { "Name": "simplifyslice", - "Doc": "check for slice simplifications\n\nA slice expression of the form:\n\n\ts[a:len(s)]\n\nwill be simplified to:\n\n\ts[a:]\n\nThis is one of the simplifications that \"gofmt -s\" applies.", + "Doc": "check for slice simplifications\n\nA slice expression of the form:\n\n\ts[a:len(s)]\n\nwill be simplified to:\n\n\ts[a:]\n\nThis is one of the simplifications that \"gofmt -s\" applies.\n\nThis analyzer ignores generated code.", "URL": "https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/simplifyslice", "Default": true }, diff --git a/gopls/internal/util/astutil/util.go b/gopls/internal/util/astutil/util.go index ac7515d1daf..b9cf9a03c1d 100644 --- a/gopls/internal/util/astutil/util.go +++ b/gopls/internal/util/astutil/util.go @@ -7,6 +7,7 @@ package astutil import ( "go/ast" "go/token" + "strings" "golang.org/x/tools/internal/typeparams" ) @@ -69,3 +70,25 @@ L: // unpack receiver type func NodeContains(n ast.Node, pos token.Pos) bool { return n.Pos() <= pos && pos <= n.End() } + +// IsGenerated check if a file is generated code +func IsGenerated(file *ast.File) bool { + // TODO: replace this implementation with calling function ast.IsGenerated when go1.21 is assured + for _, group := range file.Comments { + for _, comment := range group.List { + if comment.Pos() > file.Package { + break // after package declaration + } + // opt: check Contains first to avoid unnecessary array allocation in Split. + const prefix = "// Code generated " + if strings.Contains(comment.Text, prefix) { + for _, line := range strings.Split(comment.Text, "\n") { + if strings.HasPrefix(line, prefix) && strings.HasSuffix(line, " DO NOT EDIT.") { + return true + } + } + } + } + } + return false +}