Skip to content

Commit

Permalink
Merge pull request #5 from karamaru-alpha/feat/karamaru/ignore-alias
Browse files Browse the repository at this point in the history
feat: ignore-alias option
  • Loading branch information
karamaru-alpha committed Mar 3, 2024
2 parents e186835 + 0c1b7e6 commit d5889e2
Show file tree
Hide file tree
Showing 9 changed files with 95 additions and 30 deletions.
4 changes: 2 additions & 2 deletions cmd/copyloopvar/main.go
@@ -1,9 +1,9 @@
package main

import (
"golang.org/x/tools/go/analysis/unitchecker"
"golang.org/x/tools/go/analysis/singlechecker"

"github.com/karamaru-alpha/copyloopvar"
)

func main() { unitchecker.Main(copyloopvar.Analyzer) }
func main() { singlechecker.Main(copyloopvar.Analyzer) }
30 changes: 28 additions & 2 deletions copyloopvar.go
Expand Up @@ -19,6 +19,14 @@ var Analyzer = &analysis.Analyzer{
},
}

var (
ignoreAlias bool
)

func init() {
Analyzer.Flags.BoolVar(&ignoreAlias, "ignore-alias", false, "ignore aliasing of loop variables")
}

func run(pass *analysis.Pass) (any, error) {
inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)

Expand Down Expand Up @@ -56,14 +64,23 @@ func checkRangeStmt(pass *analysis.Pass, rangeStmt *ast.RangeStmt) {
if assignStmt.Tok != token.DEFINE {
continue
}
for _, rh := range assignStmt.Rhs {
for i, rh := range assignStmt.Rhs {
right, ok := rh.(*ast.Ident)
if !ok {
continue
}
if right.Name != key.Name && (value != nil && right.Name != value.Name) {
continue
}
if ignoreAlias {
left, ok := assignStmt.Lhs[i].(*ast.Ident)
if !ok {
continue
}
if left.Name != right.Name {
continue
}
}
pass.Report(analysis.Diagnostic{
Pos: assignStmt.Pos(),
Message: fmt.Sprintf(`The copy of the 'for' variable "%s" can be deleted (Go 1.22+)`, right.Name),
Expand Down Expand Up @@ -94,14 +111,23 @@ func checkForStmt(pass *analysis.Pass, forStmt *ast.ForStmt) {
if assignStmt.Tok != token.DEFINE {
continue
}
for _, rh := range assignStmt.Rhs {
for i, rh := range assignStmt.Rhs {
right, ok := rh.(*ast.Ident)
if !ok {
continue
}
if _, ok := initVarNameMap[right.Name]; !ok {
continue
}
if ignoreAlias {
left, ok := assignStmt.Lhs[i].(*ast.Ident)
if !ok {
continue
}
if left.Name != right.Name {
continue
}
}
pass.Report(analysis.Diagnostic{
Pos: assignStmt.Pos(),
Message: fmt.Sprintf(`The copy of the 'for' variable "%s" can be deleted (Go 1.22+)`, right.Name),
Expand Down
15 changes: 13 additions & 2 deletions copyloopvar_test.go
Expand Up @@ -8,6 +8,17 @@ import (
)

func TestAnalyzer(t *testing.T) {
testdata := testutil.WithModules(t, analysistest.TestData(), nil)
analysistest.Run(t, testdata, Analyzer, "a")
t.Run("basic", func(t *testing.T) {
testdata := testutil.WithModules(t, analysistest.TestData(), nil)
analysistest.Run(t, testdata, Analyzer, "basic")
})

t.Run("ignore-alias", func(t *testing.T) {
err := Analyzer.Flags.Set("ignore-alias", "true")
if err != nil {
t.Error(err)
}
testdata := testutil.WithModules(t, analysistest.TestData(), nil)
analysistest.Run(t, testdata, Analyzer, "ignorealias")
})
}
3 changes: 0 additions & 3 deletions testdata/src/a/go.mod

This file was deleted.

21 changes: 0 additions & 21 deletions testdata/src/a/main.go

This file was deleted.

3 changes: 3 additions & 0 deletions testdata/src/basic/go.mod
@@ -0,0 +1,3 @@
module basic

go 1.21
23 changes: 23 additions & 0 deletions testdata/src/basic/main.go
@@ -0,0 +1,23 @@
package main

func main() {
for i, v := range []int{1, 2, 3} {
i := i // want `The copy of the 'for' variable "i" can be deleted \(Go 1\.22\+\)`
_i := i // want `The copy of the 'for' variable "i" can be deleted \(Go 1\.22\+\)`
v := v // want `The copy of the 'for' variable "v" can be deleted \(Go 1\.22\+\)`
_v := v // want `The copy of the 'for' variable "v" can be deleted \(Go 1\.22\+\)`
a, b := 1, i // want `The copy of the 'for' variable "i" can be deleted \(Go 1\.22\+\)`
c, d := 1, v // want `The copy of the 'for' variable "v" can be deleted \(Go 1\.22\+\)`
_, _, _, _, _, _, _, _ = i, _i, v, _v, a, b, c, d
}

for i, j := 1, 1; i+j <= 3; i++ {
i := i // want `The copy of the 'for' variable "i" can be deleted \(Go 1\.22\+\)`
_i := i // want `The copy of the 'for' variable "i" can be deleted \(Go 1\.22\+\)`
j := j // want `The copy of the 'for' variable "j" can be deleted \(Go 1\.22\+\)`
_j := j // want `The copy of the 'for' variable "j" can be deleted \(Go 1\.22\+\)`
a, b := 1, i // want `The copy of the 'for' variable "i" can be deleted \(Go 1\.22\+\)`
c, d := 1, j // want `The copy of the 'for' variable "j" can be deleted \(Go 1\.22\+\)`
_, _, _, _, _, _, _, _ = i, _i, j, _j, a, b, c, d
}
}
3 changes: 3 additions & 0 deletions testdata/src/ignorealias/go.mod
@@ -0,0 +1,3 @@
module ignorealias

go 1.21
23 changes: 23 additions & 0 deletions testdata/src/ignorealias/main.go
@@ -0,0 +1,23 @@
package main

func main() {
for i, v := range []int{1, 2, 3} {
i := i // want `The copy of the 'for' variable "i" can be deleted \(Go 1\.22\+\)`
_i := i
v := v // want `The copy of the 'for' variable "v" can be deleted \(Go 1\.22\+\)`
_v := v
a, b := 1, i
c, d := 1, v
_, _, _, _, _, _, _, _ = i, _i, v, _v, a, b, c, d
}

for i, j := 1, 1; i+j <= 3; i++ {
i := i // want `The copy of the 'for' variable "i" can be deleted \(Go 1\.22\+\)`
_i := i
j := j // want `The copy of the 'for' variable "j" can be deleted \(Go 1\.22\+\)`
_j := j
a, b := 1, i
c, d := 1, j
_, _, _, _, _, _, _, _ = i, _i, j, _j, a, b, c, d
}
}

0 comments on commit d5889e2

Please sign in to comment.