1
2
3
4
5 package modernize
6
7 import (
8 "go/ast"
9 "go/token"
10
11 "golang.org/x/tools/go/analysis"
12 "golang.org/x/tools/go/analysis/passes/inspect"
13 "golang.org/x/tools/internal/analysis/analyzerutil"
14 "golang.org/x/tools/internal/astutil"
15 "golang.org/x/tools/internal/refactor"
16 "golang.org/x/tools/internal/versions"
17 )
18
19 var ForVarAnalyzer = &analysis.Analyzer{
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",
25 }
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54 func forvar(pass *analysis.Pass) (any, error) {
55 for curFile := range filesUsingGoVersion(pass, versions.Go1_22) {
56 for curLoop := range curFile.Preorder((*ast.RangeStmt)(nil)) {
57 loop := curLoop.Node().(*ast.RangeStmt)
58 if loop.Tok != token.DEFINE {
59 continue
60 }
61 isLoopVarRedecl := func(stmt ast.Stmt) bool {
62 if assign, ok := stmt.(*ast.AssignStmt); ok &&
63 assign.Tok == token.DEFINE &&
64 len(assign.Lhs) == len(assign.Rhs) {
65
66 for i, lhs := range assign.Lhs {
67 if !(astutil.EqualSyntax(lhs, assign.Rhs[i]) &&
68 (astutil.EqualSyntax(lhs, loop.Key) ||
69 astutil.EqualSyntax(lhs, loop.Value))) {
70 return false
71 }
72 }
73 return true
74 }
75 return false
76 }
77
78
79
80
81 for _, stmt := range loop.Body.List {
82 if isLoopVarRedecl(stmt) {
83
84
85 } else if ifstmt, ok := stmt.(*ast.IfStmt); ok &&
86 ifstmt.Init != nil &&
87 len(loop.Body.List) == 1 &&
88 isLoopVarRedecl(ifstmt.Init) {
89
90
91 stmt = ifstmt.Init
92 } else {
93 break
94 }
95
96 curStmt, _ := curLoop.FindNode(stmt)
97 edits := refactor.DeleteStmt(pass.Fset.File(stmt.Pos()), curStmt)
98 if len(edits) > 0 {
99 pass.Report(analysis.Diagnostic{
100 Pos: stmt.Pos(),
101 End: stmt.End(),
102 Message: "copying variable is unneeded",
103 SuggestedFixes: []analysis.SuggestedFix{{
104 Message: "Remove unneeded redeclaration",
105 TextEdits: edits,
106 }},
107 })
108 }
109 }
110 }
111 }
112 return nil, nil
113 }
114
View as plain text