Skip to content

Commit efd8c43

Browse files
adonovangopherbot
authored andcommitted
go/analysis: don't apply fixes to generated files
This change causes the analysis drivers unitchecker, {single,multi}checker, and analysistest to discard any fix any of whose edits is in a generated Go source file (as defined by ast.IsGenerated). gopls's analysis driver is not yet covered. (It would be nice if more of the "fix" logic of analysistest could be consolidated with the various checkers.) + test of analysistest (via modernize_test) + test of unitchecker Fixes golang/go#75948 Change-Id: I96a4abf605657392a6dbb58b22a036dc8f9f6d44 Reviewed-on: https://go-review.googlesource.com/c/tools/+/718505 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Auto-Submit: Alan Donovan <adonovan@google.com> Reviewed-by: Hongxiang Jiang <hxjiang@golang.org>
1 parent 44dda2b commit efd8c43

30 files changed

+151
-156
lines changed

go/analysis/analysistest/analysistest.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ package analysistest
88
import (
99
"bytes"
1010
"fmt"
11+
"go/ast"
1112
"go/format"
1213
"go/token"
1314
"go/types"
@@ -157,6 +158,8 @@ func RunWithSuggestedFixes(t Testing, dir string, a *analysis.Analyzer, patterns
157158
}
158159
}
159160

161+
generated := make(map[*token.File]bool)
162+
160163
// Process each result (package) separately, matching up the suggested
161164
// fixes into a diff, which we will compare to the .golden file. We have
162165
// to do this per-result in case a file appears in two packages, such as in
@@ -170,6 +173,16 @@ func RunWithSuggestedFixes(t Testing, dir string, a *analysis.Analyzer, patterns
170173
for _, result := range results {
171174
act := result.Action
172175

176+
// Compute set of generated files.
177+
for _, file := range internal.ActionPass(act).Files {
178+
// Memoize, since there may be many actions
179+
// for the same package (list of files).
180+
tokFile := act.Package.Fset.File(file.Pos())
181+
if _, seen := generated[tokFile]; !seen {
182+
generated[tokFile] = ast.IsGenerated(file)
183+
}
184+
}
185+
173186
// For each fix, split its edits by file and convert to diff form.
174187
var (
175188
// fixEdits: message -> fixes -> filename -> edits
@@ -182,12 +195,21 @@ func RunWithSuggestedFixes(t Testing, dir string, a *analysis.Analyzer, patterns
182195
)
183196
for _, diag := range act.Diagnostics {
184197
// Fixes are validated upon creation in Pass.Report.
198+
fixloop:
185199
for _, fix := range diag.SuggestedFixes {
186200
// Assert that lazy fixes have a Category (#65578, #65087).
187201
if inTools && len(fix.TextEdits) == 0 && diag.Category == "" {
188202
t.Errorf("missing Diagnostic.Category for SuggestedFix without TextEdits (gopls requires the category for the name of the fix command")
189203
}
190204

205+
// Skip any fix that edits a generated file.
206+
for _, edit := range fix.TextEdits {
207+
file := act.Package.Fset.File(edit.Pos)
208+
if generated[file] {
209+
continue fixloop
210+
}
211+
}
212+
191213
// Convert edits to diff form.
192214
// Group fixes by message and file.
193215
edits := make(map[string][]diff.Edit)

go/analysis/internal/checker/checker.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ func Run(args []string, analyzers []*analysis.Analyzer) (exitcode int) {
198198
fixActions[i] = driverutil.FixAction{
199199
Name: act.String(),
200200
Pkg: act.Package.Types,
201+
Files: act.Package.Syntax,
201202
FileSet: act.Package.Fset,
202203
ReadFileFunc: pass.ReadFile,
203204
Diagnostics: act.Diagnostics,

go/analysis/passes/modernize/any.go

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,19 @@ import (
1010
"golang.org/x/tools/go/analysis"
1111
"golang.org/x/tools/go/analysis/passes/inspect"
1212
"golang.org/x/tools/internal/analysis/analyzerutil"
13-
"golang.org/x/tools/internal/analysis/generated"
1413
"golang.org/x/tools/internal/versions"
1514
)
1615

1716
var AnyAnalyzer = &analysis.Analyzer{
18-
Name: "any",
19-
Doc: analyzerutil.MustExtractDoc(doc, "any"),
20-
Requires: []*analysis.Analyzer{
21-
generated.Analyzer,
22-
inspect.Analyzer,
23-
},
24-
Run: runAny,
25-
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#any",
17+
Name: "any",
18+
Doc: analyzerutil.MustExtractDoc(doc, "any"),
19+
Requires: []*analysis.Analyzer{inspect.Analyzer},
20+
Run: runAny,
21+
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#any",
2622
}
2723

2824
// The any pass replaces interface{} with go1.18's 'any'.
2925
func runAny(pass *analysis.Pass) (any, error) {
30-
skipGenerated(pass)
31-
3226
for curFile := range filesUsingGoVersion(pass, versions.Go1_18) {
3327
for curIface := range curFile.Preorder((*ast.InterfaceType)(nil)) {
3428
iface := curIface.Node().(*ast.InterfaceType)

go/analysis/passes/modernize/bloop.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import (
1616
"golang.org/x/tools/go/ast/inspector"
1717
"golang.org/x/tools/go/types/typeutil"
1818
"golang.org/x/tools/internal/analysis/analyzerutil"
19-
"golang.org/x/tools/internal/analysis/generated"
2019
typeindexanalyzer "golang.org/x/tools/internal/analysis/typeindex"
2120
"golang.org/x/tools/internal/astutil"
2221
"golang.org/x/tools/internal/moreiters"
@@ -29,7 +28,6 @@ var BLoopAnalyzer = &analysis.Analyzer{
2928
Name: "bloop",
3029
Doc: analyzerutil.MustExtractDoc(doc, "bloop"),
3130
Requires: []*analysis.Analyzer{
32-
generated.Analyzer,
3331
inspect.Analyzer,
3432
typeindexanalyzer.Analyzer,
3533
},
@@ -46,8 +44,6 @@ var BLoopAnalyzer = &analysis.Analyzer{
4644
// for i := 0; i < b.N; i++ {} => for b.Loop() {}
4745
// for range b.N {}
4846
func bloop(pass *analysis.Pass) (any, error) {
49-
skipGenerated(pass)
50-
5147
if !typesinternal.Imports(pass.Pkg, "testing") {
5248
return nil, nil
5349
}

go/analysis/passes/modernize/errorsastype.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import (
1515
"golang.org/x/tools/go/ast/edge"
1616
"golang.org/x/tools/go/ast/inspector"
1717
"golang.org/x/tools/internal/analysis/analyzerutil"
18-
"golang.org/x/tools/internal/analysis/generated"
1918
typeindexanalyzer "golang.org/x/tools/internal/analysis/typeindex"
2019
"golang.org/x/tools/internal/astutil"
2120
"golang.org/x/tools/internal/goplsexport"
@@ -29,7 +28,7 @@ var errorsastypeAnalyzer = &analysis.Analyzer{
2928
Name: "errorsastype",
3029
Doc: analyzerutil.MustExtractDoc(doc, "errorsastype"),
3130
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#errorsastype",
32-
Requires: []*analysis.Analyzer{generated.Analyzer, typeindexanalyzer.Analyzer},
31+
Requires: []*analysis.Analyzer{typeindexanalyzer.Analyzer},
3332
Run: errorsastype,
3433
}
3534

@@ -79,8 +78,6 @@ func init() {
7978
//
8079
// - if errors.As(err, myerr) && othercond { ... }
8180
func errorsastype(pass *analysis.Pass) (any, error) {
82-
skipGenerated(pass)
83-
8481
var (
8582
index = pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index)
8683
info = pass.TypesInfo

go/analysis/passes/modernize/fmtappendf.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import (
1414
"golang.org/x/tools/go/analysis/passes/inspect"
1515
"golang.org/x/tools/go/ast/edge"
1616
"golang.org/x/tools/internal/analysis/analyzerutil"
17-
"golang.org/x/tools/internal/analysis/generated"
1817
typeindexanalyzer "golang.org/x/tools/internal/analysis/typeindex"
1918
"golang.org/x/tools/internal/astutil"
2019
"golang.org/x/tools/internal/typesinternal/typeindex"
@@ -25,7 +24,6 @@ var FmtAppendfAnalyzer = &analysis.Analyzer{
2524
Name: "fmtappendf",
2625
Doc: analyzerutil.MustExtractDoc(doc, "fmtappendf"),
2726
Requires: []*analysis.Analyzer{
28-
generated.Analyzer,
2927
inspect.Analyzer,
3028
typeindexanalyzer.Analyzer,
3129
},
@@ -36,8 +34,6 @@ var FmtAppendfAnalyzer = &analysis.Analyzer{
3634
// The fmtappend function replaces []byte(fmt.Sprintf(...)) by
3735
// fmt.Appendf(nil, ...), and similarly for Sprint, Sprintln.
3836
func fmtappendf(pass *analysis.Pass) (any, error) {
39-
skipGenerated(pass)
40-
4137
index := pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index)
4238
for _, fn := range []types.Object{
4339
index.Object("fmt", "Sprintf"),

go/analysis/passes/modernize/forvar.go

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,17 @@ import (
1111
"golang.org/x/tools/go/analysis"
1212
"golang.org/x/tools/go/analysis/passes/inspect"
1313
"golang.org/x/tools/internal/analysis/analyzerutil"
14-
"golang.org/x/tools/internal/analysis/generated"
1514
"golang.org/x/tools/internal/astutil"
1615
"golang.org/x/tools/internal/refactor"
1716
"golang.org/x/tools/internal/versions"
1817
)
1918

2019
var ForVarAnalyzer = &analysis.Analyzer{
21-
Name: "forvar",
22-
Doc: analyzerutil.MustExtractDoc(doc, "forvar"),
23-
Requires: []*analysis.Analyzer{
24-
generated.Analyzer,
25-
inspect.Analyzer,
26-
},
27-
Run: forvar,
28-
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#forvar",
20+
Name: "forvar",
21+
Doc: analyzerutil.MustExtractDoc(doc, "forvar"),
22+
Requires: []*analysis.Analyzer{inspect.Analyzer},
23+
Run: forvar,
24+
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#forvar",
2925
}
3026

3127
// forvar offers to fix unnecessary copying of a for variable
@@ -43,8 +39,6 @@ var ForVarAnalyzer = &analysis.Analyzer{
4339
// is declared implicitly before executing the post statement and initialized to the
4440
// value of the previous iteration's variable at that moment.")
4541
func forvar(pass *analysis.Pass) (any, error) {
46-
skipGenerated(pass)
47-
4842
for curFile := range filesUsingGoVersion(pass, versions.Go1_22) {
4943
for curLoop := range curFile.Preorder((*ast.RangeStmt)(nil)) {
5044
loop := curLoop.Node().(*ast.RangeStmt)

go/analysis/passes/modernize/maps.go

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import (
1616
"golang.org/x/tools/go/analysis/passes/inspect"
1717
"golang.org/x/tools/go/ast/inspector"
1818
"golang.org/x/tools/internal/analysis/analyzerutil"
19-
"golang.org/x/tools/internal/analysis/generated"
2019
"golang.org/x/tools/internal/astutil"
2120
"golang.org/x/tools/internal/refactor"
2221
"golang.org/x/tools/internal/typeparams"
@@ -25,14 +24,11 @@ import (
2524
)
2625

2726
var MapsLoopAnalyzer = &analysis.Analyzer{
28-
Name: "mapsloop",
29-
Doc: analyzerutil.MustExtractDoc(doc, "mapsloop"),
30-
Requires: []*analysis.Analyzer{
31-
generated.Analyzer,
32-
inspect.Analyzer,
33-
},
34-
Run: mapsloop,
35-
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#mapsloop",
27+
Name: "mapsloop",
28+
Doc: analyzerutil.MustExtractDoc(doc, "mapsloop"),
29+
Requires: []*analysis.Analyzer{inspect.Analyzer},
30+
Run: mapsloop,
31+
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#mapsloop",
3632
}
3733

3834
// The mapsloop pass offers to simplify a loop of map insertions:
@@ -56,8 +52,6 @@ var MapsLoopAnalyzer = &analysis.Analyzer{
5652
// m = make(M)
5753
// m = M{}
5854
func mapsloop(pass *analysis.Pass) (any, error) {
59-
skipGenerated(pass)
60-
6155
// Skip the analyzer in packages where its
6256
// fixes would create an import cycle.
6357
if within(pass, "maps", "bytes", "runtime") {

go/analysis/passes/modernize/minmax.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import (
1616
"golang.org/x/tools/go/ast/edge"
1717
"golang.org/x/tools/go/ast/inspector"
1818
"golang.org/x/tools/internal/analysis/analyzerutil"
19-
"golang.org/x/tools/internal/analysis/generated"
2019
typeindexanalyzer "golang.org/x/tools/internal/analysis/typeindex"
2120
"golang.org/x/tools/internal/astutil"
2221
"golang.org/x/tools/internal/typeparams"
@@ -28,7 +27,6 @@ var MinMaxAnalyzer = &analysis.Analyzer{
2827
Name: "minmax",
2928
Doc: analyzerutil.MustExtractDoc(doc, "minmax"),
3029
Requires: []*analysis.Analyzer{
31-
generated.Analyzer,
3230
inspect.Analyzer,
3331
typeindexanalyzer.Analyzer,
3432
},
@@ -57,8 +55,6 @@ var MinMaxAnalyzer = &analysis.Analyzer{
5755
// - "x := a" or "x = a" or "var x = a" in pattern 2
5856
// - "x < b" or "a < b" in pattern 2
5957
func minmax(pass *analysis.Pass) (any, error) {
60-
skipGenerated(pass)
61-
6258
// Check for user-defined min/max functions that can be removed
6359
checkUserDefinedMinMax(pass)
6460

go/analysis/passes/modernize/modernize.go

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import (
2020
"golang.org/x/tools/go/ast/edge"
2121
"golang.org/x/tools/go/ast/inspector"
2222
"golang.org/x/tools/internal/analysis/analyzerutil"
23-
"golang.org/x/tools/internal/analysis/generated"
2423
"golang.org/x/tools/internal/astutil"
2524
"golang.org/x/tools/internal/moreiters"
2625
"golang.org/x/tools/internal/packagepath"
@@ -59,18 +58,6 @@ var Suite = []*analysis.Analyzer{
5958

6059
// -- helpers --
6160

62-
// skipGenerated decorates pass.Report to suppress diagnostics in generated files.
63-
func skipGenerated(pass *analysis.Pass) {
64-
report := pass.Report
65-
pass.Report = func(diag analysis.Diagnostic) {
66-
generated := pass.ResultOf[generated.Analyzer].(*generated.Result)
67-
if generated.IsGenerated(diag.Pos) {
68-
return // skip
69-
}
70-
report(diag)
71-
}
72-
}
73-
7461
// formatExprs formats a comma-separated list of expressions.
7562
func formatExprs(fset *token.FileSet, exprs []ast.Expr) string {
7663
var buf strings.Builder

0 commit comments

Comments
 (0)