@@ -99,10 +99,13 @@ func checkForStmt(pass *analysis.Pass, forStmt *ast.ForStmt) {
99
99
return
100
100
}
101
101
102
- var operand ast.Expr
102
+ var (
103
+ operand ast.Expr
104
+ hasEquivalentOperator bool
105
+ )
103
106
104
107
switch cond .Op {
105
- case token .LSS : // ;i < n;
108
+ case token .LSS , token . LEQ : // ;i < n; || ;i <= n;
106
109
x , ok := cond .X .(* ast.Ident )
107
110
if ! ok {
108
111
return
@@ -112,8 +115,9 @@ func checkForStmt(pass *analysis.Pass, forStmt *ast.ForStmt) {
112
115
return
113
116
}
114
117
118
+ hasEquivalentOperator = cond .Op == token .LEQ
115
119
operand = cond .Y
116
- case token .GTR : // ;n > i;
120
+ case token .GTR , token . GEQ : // ;n > i; || ;n >= i;
117
121
y , ok := cond .Y .(* ast.Ident )
118
122
if ! ok {
119
123
return
@@ -123,6 +127,7 @@ func checkForStmt(pass *analysis.Pass, forStmt *ast.ForStmt) {
123
127
return
124
128
}
125
129
130
+ hasEquivalentOperator = cond .Op == token .GEQ
126
131
operand = cond .X
127
132
default :
128
133
return
@@ -240,7 +245,18 @@ func checkForStmt(pass *analysis.Pass, forStmt *ast.ForStmt) {
240
245
return
241
246
}
242
247
243
- rangeX := operandToString (pass , initIdent , operand )
248
+ operandIsNumberLit := isNumberLit (operand )
249
+
250
+ if hasEquivalentOperator && ! operandIsNumberLit {
251
+ return
252
+ }
253
+
254
+ rangeX := operandToString (
255
+ pass ,
256
+ initIdent ,
257
+ operand ,
258
+ hasEquivalentOperator && operandIsNumberLit ,
259
+ )
244
260
245
261
var replacement string
246
262
if bc .accessed {
@@ -387,7 +403,10 @@ func findNExpr(expr ast.Expr) ast.Expr {
387
403
}
388
404
}
389
405
390
- func recursiveOperandToString (expr ast.Expr ) string {
406
+ func recursiveOperandToString (
407
+ expr ast.Expr ,
408
+ incrementInt bool ,
409
+ ) string {
391
410
switch e := expr .(type ) {
392
411
case * ast.CallExpr :
393
412
args := ""
@@ -397,20 +416,29 @@ func recursiveOperandToString(expr ast.Expr) string {
397
416
args += ", "
398
417
}
399
418
400
- args += recursiveOperandToString (v )
419
+ args += recursiveOperandToString (v , incrementInt && len ( e . Args ) == 1 )
401
420
}
402
421
403
- return recursiveOperandToString (e .Fun ) + "(" + args + ")"
422
+ return recursiveOperandToString (e .Fun , false ) + "(" + args + ")"
404
423
case * ast.BasicLit :
424
+ if incrementInt && e .Kind == token .INT {
425
+ v , err := strconv .Atoi (e .Value )
426
+ if err == nil {
427
+ return strconv .Itoa (v + 1 )
428
+ }
429
+
430
+ return e .Value
431
+ }
432
+
405
433
return e .Value
406
434
case * ast.Ident :
407
435
return e .Name
408
436
case * ast.SelectorExpr :
409
- return recursiveOperandToString (e .X ) + "." + recursiveOperandToString (e .Sel )
437
+ return recursiveOperandToString (e .X , false ) + "." + recursiveOperandToString (e .Sel , false )
410
438
case * ast.IndexExpr :
411
- return recursiveOperandToString (e .X ) + "[" + recursiveOperandToString (e .Index ) + "]"
439
+ return recursiveOperandToString (e .X , false ) + "[" + recursiveOperandToString (e .Index , false ) + "]"
412
440
case * ast.BinaryExpr :
413
- return recursiveOperandToString (e .X ) + " " + e .Op .String () + " " + recursiveOperandToString (e .Y )
441
+ return recursiveOperandToString (e .X , false ) + " " + e .Op .String () + " " + recursiveOperandToString (e .Y , false )
414
442
default :
415
443
return ""
416
444
}
@@ -487,6 +515,46 @@ func (b *bodyChecker) check(n ast.Node) bool {
487
515
return true
488
516
}
489
517
518
+ func isNumberLit (exp ast.Expr ) bool {
519
+ switch lit := exp .(type ) {
520
+ case * ast.BasicLit :
521
+ if lit .Kind == token .INT {
522
+ return true
523
+ }
524
+
525
+ return false
526
+ case * ast.CallExpr :
527
+ switch fun := lit .Fun .(type ) {
528
+ case * ast.Ident :
529
+ switch fun .Name {
530
+ case
531
+ "int" ,
532
+ "int8" ,
533
+ "int16" ,
534
+ "int32" ,
535
+ "int64" ,
536
+ "uint" ,
537
+ "uint8" ,
538
+ "uint16" ,
539
+ "uint32" ,
540
+ "uint64" :
541
+ default :
542
+ return false
543
+ }
544
+ default :
545
+ return false
546
+ }
547
+
548
+ if len (lit .Args ) != 1 {
549
+ return false
550
+ }
551
+
552
+ return isNumberLit (lit .Args [0 ])
553
+ default :
554
+ return false
555
+ }
556
+ }
557
+
490
558
func compareNumberLit (exp ast.Expr , val int ) bool {
491
559
switch lit := exp .(type ) {
492
560
case * ast.BasicLit :
@@ -534,8 +602,13 @@ func compareNumberLit(exp ast.Expr, val int) bool {
534
602
}
535
603
}
536
604
537
- func operandToString (pass * analysis.Pass , i * ast.Ident , operand ast.Expr ) string {
538
- s := recursiveOperandToString (operand )
605
+ func operandToString (
606
+ pass * analysis.Pass ,
607
+ i * ast.Ident ,
608
+ operand ast.Expr ,
609
+ increment bool ,
610
+ ) string {
611
+ s := recursiveOperandToString (operand , increment )
539
612
t := pass .TypesInfo .TypeOf (i )
540
613
541
614
if t == types .Typ [types .Int ] {
0 commit comments