Skip to content

Commit

Permalink
Don't warn when loop Op needs to be re-evaluated
Browse files Browse the repository at this point in the history
  • Loading branch information
ckaznocha committed Mar 23, 2024
1 parent 737670c commit 2d0a2a8
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 14 deletions.
76 changes: 62 additions & 14 deletions intrange.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,16 @@ func check(pass *analysis.Pass) func(node ast.Node) {
return
}

var nExpr ast.Expr

switch cond.Op {
case token.LSS: // ;i < x;
case token.LSS: // ;i < n;
if isBenchmark(cond.Y) {
return
}

nExpr = findNExpr(cond.Y)

x, ok := cond.X.(*ast.Ident)
if !ok {
return
Expand All @@ -98,11 +102,13 @@ func check(pass *analysis.Pass) func(node ast.Node) {
if x.Name != initIdent.Name {
return
}
case token.GTR: // ;x > i;
case token.GTR: // ;n > i;
if isBenchmark(cond.X) {
return
}

nExpr = findNExpr(cond.X)

y, ok := cond.Y.(*ast.Ident)
if !ok {
return
Expand Down Expand Up @@ -209,6 +215,7 @@ func check(pass *analysis.Pass) func(node ast.Node) {

bc := &bodyChecker{
initIdent: initIdent,
nExpr: nExpr,
}

ast.Inspect(forStmt.Body, bc.check)
Expand All @@ -224,6 +231,29 @@ func check(pass *analysis.Pass) func(node ast.Node) {
}
}

func findNExpr(expr ast.Expr) ast.Expr {
switch e := expr.(type) {
case *ast.CallExpr:
if e.Fun.(*ast.Ident).Name != "len" {
return nil
}

if len(e.Args) != 1 {
return nil
}

return findNExpr(e.Args[0])
case *ast.BasicLit:
return nil
case *ast.Ident:
return e
case *ast.SelectorExpr:
return e
default:
return nil
}
}

func isBenchmark(expr ast.Expr) bool {
selectorExpr, ok := expr.(*ast.SelectorExpr)
if !ok {
Expand All @@ -246,33 +276,51 @@ func isBenchmark(expr ast.Expr) bool {
return false
}

func identEqual(a, b ast.Expr) bool {
if a == nil || b == nil {
return false
}

switch aT := a.(type) {
case *ast.Ident:
identB, ok := b.(*ast.Ident)
if !ok {
return false
}

return aT.Name == identB.Name
case *ast.SelectorExpr:
selectorB, ok := b.(*ast.SelectorExpr)
if !ok {
return false
}

return identEqual(aT.Sel, selectorB.Sel) && identEqual(aT.X, selectorB.X)
case *ast.IndexExpr:
return identEqual(aT.X, b)
default:
return false
}
}

type bodyChecker struct {
initIdent *ast.Ident
nExpr ast.Expr
modified bool
}

func (b *bodyChecker) check(n ast.Node) bool {
switch stmt := n.(type) {
case *ast.AssignStmt:
for _, lhs := range stmt.Lhs {
ident, ok := lhs.(*ast.Ident)
if !ok {
continue
}

if b.initIdent.Name == ident.Name {
if identEqual(lhs, b.initIdent) || identEqual(lhs, b.nExpr) {
b.modified = true

return false
}
}
case *ast.IncDecStmt:
ident, ok := stmt.X.(*ast.Ident)
if !ok {
return true
}

if b.initIdent.Name == ident.Name {
if identEqual(stmt.X, b.initIdent) || identEqual(stmt.X, b.nExpr) {
b.modified = true

return false
Expand Down
52 changes: 52 additions & 0 deletions testdata/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,4 +134,56 @@ func main() {

for i := 0; b.N >= i; i++ {
}

var n int
for i := 0; i < n; i++ {
n--
}

for i := 0; i < n; i++ {
n++
}

// Example from https://github.com/ckaznocha/intrange/issues/12
var what string
for i := 0; i < len(what); i++ {
if what[i] == 'v' && i+1 < len(what) && what[i+1] >= '0' && what[i+1] <= '9' {
what = what[:i] + what[i+1:]
}
}

for i := 0; i < len(what); i++ { // want `for loop can be changed to use an integer range \(Go 1\.22\+\)`
}

var t struct{ n int }
for i := 0; i < t.n; i++ { // want `for loop can be changed to use an integer range \(Go 1\.22\+\)`
}

for i := 0; i < t.n; i++ {
t.n++
}

var s []int
for i := 0; i < len(s); i++ { // want `for loop can be changed to use an integer range \(Go 1\.22\+\)`
}

for i := 0; i < len(s); i++ {
s = append(s, 4)
}

var m map[int]int
for i := 0; i < len(m); i++ { // want `for loop can be changed to use an integer range \(Go 1\.22\+\)`
}

for i := 0; i < len(m); i++ {
m[4] = 4
}

var t2 struct{ m map[int]int }
for i := 0; i < len(t2.m); i++ { // want `for loop can be changed to use an integer range \(Go 1\.22\+\)`
}

for i := 0; i < len(t2.m); i++ {
t2.m[4] = 4
}
}

0 comments on commit 2d0a2a8

Please sign in to comment.