Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add analysis.SuggestedFix for range over int #34

Merged
merged 1 commit into from
Nov 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 53 additions & 1 deletion intrange.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"go/token"
"go/types"
"strconv"
"strings"

"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/analysis/passes/inspect"
Expand Down Expand Up @@ -97,7 +98,10 @@ func checkForStmt(pass *analysis.Pass, forStmt *ast.ForStmt) {
return
}

var nExpr ast.Expr
var (
nExpr ast.Expr
nStr string
)

switch cond.Op {
case token.LSS: // ;i < n;
Expand All @@ -106,6 +110,7 @@ func checkForStmt(pass *analysis.Pass, forStmt *ast.ForStmt) {
}

nExpr = findNExpr(cond.Y)
nStr = findNStr(cond.Y)

x, ok := cond.X.(*ast.Ident)
if !ok {
Expand All @@ -121,6 +126,7 @@ func checkForStmt(pass *analysis.Pass, forStmt *ast.ForStmt) {
}

nExpr = findNExpr(cond.X)
nStr = findNStr(cond.X)

y, ok := cond.Y.(*ast.Ident)
if !ok {
Expand Down Expand Up @@ -237,9 +243,23 @@ func checkForStmt(pass *analysis.Pass, forStmt *ast.ForStmt) {
return
}

nStr = castNStr(pass, initIdent, nStr)

pass.Report(analysis.Diagnostic{
Pos: forStmt.Pos(),
Message: msg,
SuggestedFixes: []analysis.SuggestedFix{
{
Message: fmt.Sprintf("Replace loop with `%s := range %s`", initIdent.Name, nStr),
TextEdits: []analysis.TextEdit{
{
Pos: forStmt.Init.Pos(),
End: forStmt.Post.End(),
NewText: []byte(fmt.Sprintf("%s := range %s", initIdent.Name, nStr)),
},
},
},
},
})
}

Expand Down Expand Up @@ -363,6 +383,27 @@ func findNExpr(expr ast.Expr) ast.Expr {
}
}

func findNStr(expr ast.Expr) string {
switch e := expr.(type) {
case *ast.CallExpr:
args := make([]string, len(e.Args))
for i, v := range e.Args {
args[i] = findNStr(v)
}
return findNStr(e.Fun) + "(" + strings.Join(args, ", ") + ")"
case *ast.BasicLit:
return e.Value
case *ast.Ident:
return e.String()
case *ast.SelectorExpr:
return findNStr(e.X) + "." + findNStr(e.Sel)
case *ast.IndexExpr:
return findNStr(e.X) + "[" + findNStr(e.Index) + "]"
default:
return ""
}
}

func isBenchmark(expr ast.Expr) bool {
selectorExpr, ok := expr.(*ast.SelectorExpr)
if !ok {
Expand Down Expand Up @@ -497,3 +538,14 @@ func compareNumberLit(exp ast.Expr, val int) bool {
return false
}
}

func castNStr(pass *analysis.Pass, i *ast.Ident, n string) string {
initType := pass.TypesInfo.TypeOf(i).String()
if initType == "int" {
return n
}
if _, err := strconv.Atoi(n); err != nil {
return n
}
return initType + "(" + n + ")"
}
82 changes: 41 additions & 41 deletions testdata/main.go.golden
Original file line number Diff line number Diff line change
Expand Up @@ -25,55 +25,55 @@ func main() {
i = i + 1
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

const x = 10
Expand All @@ -84,52 +84,52 @@ func main() {
for i := 0; i < x; i += 2 {
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

var b *testing.B
Expand All @@ -156,35 +156,35 @@ func main() {
}
}

for i := 0; i < len(what); i++ { // want `for loop can be changed to use an integer range \(Go 1\.22\+\)`
for i := range len(what) { // 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 := range t.n { // 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 := range len(s) { // 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 := range len(m) { // 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 := range len(t2.m) { // want `for loop can be changed to use an integer range \(Go 1\.22\+\)`
}

for i := 0; i < len(t2.m); i++ {
Expand All @@ -194,13 +194,13 @@ func main() {

// https://github.com/ckaznocha/intrange/issues/16
func issue16(service protoreflect.ServiceDescriptor) {
for i := 0; i < service.Methods().Len(); i++ { // want `for loop can be changed to use an integer range \(Go 1\.22\+\)`
for i := range service.Methods().Len() { // want `for loop can be changed to use an integer range \(Go 1\.22\+\)`
print(i)
}
}

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

Expand All @@ -214,7 +214,7 @@ func opReEval_IndexExpressions_ArrayLike(n []int) {
}

func opReEval_IndexExpressions_Map(n map[string]int) {
for i := 0; i < n["N"]; i++ { // want `for loop can be changed to use an integer range \(Go 1\.22\+\)`
for i := range n["N"] { // want `for loop can be changed to use an integer range \(Go 1\.22\+\)`
print(i)
}

Expand Down