x/tools: run slicesbackward analyzer I renamed the loop vars in most cases, which suggests the analyzer could use a better heuristic for the name. For example, use the LHS of a following y := x or switch y := x.(type) statement, or use the singular of the range operand if its name is a plural. I also manually fixed one error due to golang/go#78629 Change-Id: I32b5f08f1adcac8761ebd8984f4bde28a05af0fd Reviewed-on: https://go-review.googlesource.com/c/tools/+/765305 Auto-Submit: Alan Donovan <adonovan@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Madeline Kalil <mkalil@google.com>
diff --git a/go/analysis/passes/httpresponse/httpresponse.go b/go/analysis/passes/httpresponse/httpresponse.go index 37ecb65..22539de 100644 --- a/go/analysis/passes/httpresponse/httpresponse.go +++ b/go/analysis/passes/httpresponse/httpresponse.go
@@ -9,6 +9,7 @@ import ( "go/ast" "go/types" + "slices" "golang.org/x/tools/go/analysis" "golang.org/x/tools/go/analysis/passes/inspect" @@ -144,8 +145,8 @@ // node, along with the number of call expressions encountered. func restOfBlock(stack []ast.Node) ([]ast.Stmt, int) { var ncalls int - for i := len(stack) - 1; i >= 0; i-- { - if b, ok := stack[i].(*ast.BlockStmt); ok { + for i, n := range slices.Backward(stack) { + if b, ok := n.(*ast.BlockStmt); ok { for j, v := range b.List { if v == stack[i+1] { return b.List[j:], ncalls @@ -154,7 +155,7 @@ break } - if _, ok := stack[i].(*ast.CallExpr); ok { + if _, ok := n.(*ast.CallExpr); ok { ncalls++ } }
diff --git a/go/callgraph/vta/propagation.go b/go/callgraph/vta/propagation.go index a96f82d..33ec246 100644 --- a/go/callgraph/vta/propagation.go +++ b/go/callgraph/vta/propagation.go
@@ -155,9 +155,9 @@ sccToTypes[sccID] = &typeSet } - for i := len(sccs) - 1; i >= 0; i-- { + for i, scc := range slices.Backward(sccs) { nextSccs := make(map[int]empty) - for _, n := range sccs[i] { + for _, n := range scc { for succ := range graph.successors(n) { nextSccs[idxToSccID[succ]] = empty{} }
diff --git a/gopls/internal/analysis/infertypeargs/infertypeargs.go b/gopls/internal/analysis/infertypeargs/infertypeargs.go index 0ce43e6..5a22aef 100644 --- a/gopls/internal/analysis/infertypeargs/infertypeargs.go +++ b/gopls/internal/analysis/infertypeargs/infertypeargs.go
@@ -8,6 +8,7 @@ "go/ast" "go/token" "go/types" + "slices" "golang.org/x/tools/go/analysis" "golang.org/x/tools/go/analysis/passes/inspect" @@ -74,7 +75,7 @@ // Start removing argument expressions from the right, and check if we can // still infer the call expression. required := len(indices) // number of type expressions that are required - for i := len(indices) - 1; i >= 0; i-- { + for i := range slices.Backward(indices) { var fun ast.Expr if i == 0 { // No longer an index expression: just use the parameterized operand.
diff --git a/gopls/internal/cache/check.go b/gopls/internal/cache/check.go index a35758c..0bd7366 100644 --- a/gopls/internal/cache/check.go +++ b/gopls/internal/cache/check.go
@@ -17,6 +17,7 @@ "go/types" "regexp" "runtime" + "slices" "sort" "strings" "sync" @@ -1866,8 +1867,7 @@ // we reach the workspace. var errors []*Diagnostic for _, depErr := range relevantErrors { - for i := len(depErr.ImportStack) - 1; i >= 0; i-- { - item := depErr.ImportStack[i] + for _, item := range slices.Backward(depErr.ImportStack) { if snapshot.IsWorkspacePackage(PackageID(item)) { break } @@ -1905,8 +1905,7 @@ // Add a diagnostic to the module that contained the lowest-level import of // the missing package. for _, depErr := range relevantErrors { - for i := len(depErr.ImportStack) - 1; i >= 0; i-- { - item := depErr.ImportStack[i] + for _, item := range slices.Backward(depErr.ImportStack) { mp := snapshot.Metadata(PackageID(item)) if mp == nil || mp.Module == nil { continue
diff --git a/gopls/internal/cache/mod.go b/gopls/internal/cache/mod.go index 940c5e0..26e6149 100644 --- a/gopls/internal/cache/mod.go +++ b/gopls/internal/cache/mod.go
@@ -9,6 +9,7 @@ "errors" "fmt" "regexp" + "slices" "strings" "golang.org/x/mod/modfile" @@ -380,8 +381,8 @@ var reference *modfile.Line matches := moduleVersionInErrorRe.FindAllStringSubmatch(goCmdError, -1) - for i := len(matches) - 1; i >= 0; i-- { - ver := module.Version{Path: matches[i][1], Version: matches[i][2]} + for _, match := range slices.Backward(matches) { + ver := module.Version{Path: match[1], Version: match[2]} if err := module.Check(ver.Path, ver.Version); err != nil { continue } @@ -412,8 +413,8 @@ func (s *Snapshot) goCommandDiagnostic(pm *ParsedModule, loc protocol.Location, goCmdError string) (*Diagnostic, error) { matches := moduleVersionInErrorRe.FindAllStringSubmatch(goCmdError, -1) var innermost *module.Version - for i := len(matches) - 1; i >= 0; i-- { - ver := module.Version{Path: matches[i][1], Version: matches[i][2]} + for _, match := range slices.Backward(matches) { + ver := module.Version{Path: match[1], Version: match[2]} if err := module.Check(ver.Path, ver.Version); err != nil { continue }
diff --git a/gopls/internal/cmd/semantictokens.go b/gopls/internal/cmd/semantictokens.go index 55182f3..6dd0052 100644 --- a/gopls/internal/cmd/semantictokens.go +++ b/gopls/internal/cmd/semantictokens.go
@@ -11,6 +11,7 @@ "fmt" "log" "os" + "slices" "unicode/utf8" "golang.org/x/tools/gopls/internal/protocol" @@ -148,9 +149,8 @@ return nil } lines := bytes.Split(file.mapper.Content, []byte{'\n'}) - for i := len(marks) - 1; i >= 0; i-- { - mx := marks[i] - markLine(mx, lines) + for _, mark := range slices.Backward(marks) { + markLine(mark, lines) } os.Stdout.Write(bytes.Join(lines, []byte{'\n'})) return nil
diff --git a/gopls/internal/golang/completion/util.go b/gopls/internal/golang/completion/util.go index 10d6325..0b07129 100644 --- a/gopls/internal/golang/completion/util.go +++ b/gopls/internal/golang/completion/util.go
@@ -8,6 +8,7 @@ "go/ast" "go/token" "go/types" + "slices" "golang.org/x/tools/go/types/typeutil" "golang.org/x/tools/gopls/internal/golang" @@ -268,9 +269,9 @@ } } - for i := len(blockLines) - 1; i >= 0; i-- { - if blockLines[i].End() < pos { - return blockLines[i] + for _, stmt := range slices.Backward(blockLines) { + if stmt.End() < pos { + return stmt } }
diff --git a/gopls/internal/golang/hover.go b/gopls/internal/golang/hover.go index 65618fc..31942fd 100644 --- a/gopls/internal/golang/hover.go +++ b/gopls/internal/golang/hover.go
@@ -1687,8 +1687,8 @@ switch n := n.(type) { case *ast.Field: findEnclosingDeclAndSpec := func() { - for i := len(stack) - 1; i >= 0; i-- { - switch n := stack[i].(type) { + for _, n := range slices.Backward(stack) { + switch n := n.(type) { case ast.Spec: spec = n case ast.Decl:
diff --git a/gopls/internal/golang/semtok.go b/gopls/internal/golang/semtok.go index 35506a2..2c8c7d5 100644 --- a/gopls/internal/golang/semtok.go +++ b/gopls/internal/golang/semtok.go
@@ -321,8 +321,7 @@ // strStack converts the stack to a string, for debugging and error messages. func (tv *tokenVisitor) strStack() string { msg := []string{"["} - for i := len(tv.stack) - 1; i >= 0; i-- { - n := tv.stack[i] + for _, n := range slices.Backward(tv.stack) { msg = append(msg, strings.TrimPrefix(fmt.Sprintf("%T", n), "*ast.")) } if len(tv.stack) > 0 {
diff --git a/gopls/internal/server/general.go b/gopls/internal/server/general.go index 2f05b00..831ab85 100644 --- a/gopls/internal/server/general.go +++ b/gopls/internal/server/general.go
@@ -16,6 +16,7 @@ "os" "path" "path/filepath" + "slices" "sort" "strings" "sync" @@ -301,9 +302,9 @@ // // Copied from the testenv package. func go1Point() int { - for i := len(build.Default.ReleaseTags) - 1; i >= 0; i-- { + for _, tag := range slices.Backward(build.Default.ReleaseTags) { var version int - if _, err := fmt.Sscanf(build.Default.ReleaseTags[i], "go1.%d", &version); err != nil { + if _, err := fmt.Sscanf(tag, "go1.%d", &version); err != nil { continue } return version
diff --git a/internal/bisect/bisect.go b/internal/bisect/bisect.go index 7b1d112..04da97e 100644 --- a/internal/bisect/bisect.go +++ b/internal/bisect/bisect.go
@@ -285,6 +285,7 @@ if m == nil { return true } + // Don't use slices.Backward here (no imports). for i := len(m.list) - 1; i >= 0; i-- { c := &m.list[i] if id&c.mask == c.bits { @@ -299,6 +300,7 @@ if m == nil { return false } + // Don't use slices.Backward here (no imports). for i := len(m.list) - 1; i >= 0; i-- { c := &m.list[i] if id&c.mask == c.bits {
diff --git a/internal/excfg/excfg.go b/internal/excfg/excfg.go index f312c02..135f6ac 100644 --- a/internal/excfg/excfg.go +++ b/internal/excfg/excfg.go
@@ -151,8 +151,7 @@ // // We do this backwards so that successor blocks are usually already visited // and we can link them up eagerly. - for i := len(cfg.Blocks) - 1; i >= 0; i-- { - b := cfg.Blocks[i] + for _, b := range slices.Backward(cfg.Blocks) { if b.Live { eb.visitBlock(b) } @@ -265,9 +264,8 @@ next = eb.entry[cb.Succs[0].Index] } isIf := len(cb.Succs) == 2 - for ni := len(cb.Nodes) - 1; ni >= 0; ni-- { + for _, node := range slices.Backward(cb.Nodes) { eb.assertReverse() - node := cb.Nodes[ni] if isIf { next = eb.visitCond(node.(ast.Expr), next, eb.entry[cb.Succs[1].Index])
diff --git a/internal/gocommand/version.go b/internal/gocommand/version.go index cce290c..d82f13a 100644 --- a/internal/gocommand/version.go +++ b/internal/gocommand/version.go
@@ -8,6 +8,7 @@ "context" "fmt" "regexp" + "slices" "strings" ) @@ -41,9 +42,9 @@ } // Split up "[go1.1 go1.15]" and return highest go1.X value. tags := strings.Fields(stdout[1 : len(stdout)-2]) - for i := len(tags) - 1; i >= 0; i-- { + for _, tag := range slices.Backward(tags) { var version int - if _, err := fmt.Sscanf(tags[i], "go1.%d", &version); err != nil { + if _, err := fmt.Sscanf(tag, "go1.%d", &version); err != nil { continue } return version, nil
diff --git a/internal/refactor/inline/inline.go b/internal/refactor/inline/inline.go index 6a31d3b..cbcf7b3 100644 --- a/internal/refactor/inline/inline.go +++ b/internal/refactor/inline/inline.go
@@ -2022,8 +2022,7 @@ return string("RW"[btoi(effects)]) + i } removed := false - for i := len(args) - 1; i >= 0; i-- { - argi := args[i] + for i, argi := range slices.Backward(args) { if sg.has(argi) && !argi.pure { // i is not bound: check whether it must be bound due to hazards. idx := slices.Index(effects, i)
diff --git a/internal/testenv/testenv.go b/internal/testenv/testenv.go index 2bea513..b02de15 100644 --- a/internal/testenv/testenv.go +++ b/internal/testenv/testenv.go
@@ -18,6 +18,7 @@ "path/filepath" "runtime" "runtime/debug" + "slices" "strings" "sync" "testing" @@ -330,9 +331,9 @@ // Go1Point returns the x in Go 1.x. func Go1Point() int { - for i := len(build.Default.ReleaseTags) - 1; i >= 0; i-- { + for _, tag := range slices.Backward(build.Default.ReleaseTags) { var version int - if _, err := fmt.Sscanf(build.Default.ReleaseTags[i], "go1.%d", &version); err != nil { + if _, err := fmt.Sscanf(tag, "go1.%d", &version); err != nil { continue } return version