| // Copyright 2013 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| // Package assign defines an Analyzer that detects useless assignments. |
| package assign |
| |
| // TODO(adonovan): check also for assignments to struct fields inside |
| // methods that are on T instead of *T. |
| |
| import ( |
| "go/ast" |
| "go/token" |
| "reflect" |
| |
| "golang.org/x/tools/go/analysis" |
| "golang.org/x/tools/go/analysis/passes/inspect" |
| "golang.org/x/tools/go/analysis/passes/internal/analysisutil" |
| "golang.org/x/tools/go/ast/inspector" |
| ) |
| |
| const Doc = `check for useless assignments |
| |
| This checker reports assignments of the form x = x or a[i] = a[i]. |
| These are almost always useless, and even when they aren't they are |
| usually a mistake.` |
| |
| var Analyzer = &analysis.Analyzer{ |
| Name: "assign", |
| Doc: Doc, |
| Requires: []*analysis.Analyzer{inspect.Analyzer}, |
| Run: run, |
| } |
| |
| func run(pass *analysis.Pass) (interface{}, error) { |
| inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) |
| |
| nodeFilter := []ast.Node{ |
| (*ast.AssignStmt)(nil), |
| } |
| inspect.Preorder(nodeFilter, func(n ast.Node) { |
| stmt := n.(*ast.AssignStmt) |
| if stmt.Tok != token.ASSIGN { |
| return // ignore := |
| } |
| if len(stmt.Lhs) != len(stmt.Rhs) { |
| // If LHS and RHS have different cardinality, they can't be the same. |
| return |
| } |
| for i, lhs := range stmt.Lhs { |
| rhs := stmt.Rhs[i] |
| if analysisutil.HasSideEffects(pass.TypesInfo, lhs) || |
| analysisutil.HasSideEffects(pass.TypesInfo, rhs) { |
| continue // expressions may not be equal |
| } |
| if reflect.TypeOf(lhs) != reflect.TypeOf(rhs) { |
| continue // short-circuit the heavy-weight gofmt check |
| } |
| le := analysisutil.Format(pass.Fset, lhs) |
| re := analysisutil.Format(pass.Fset, rhs) |
| if le == re { |
| pass.Reportf(stmt.Pos(), "self-assignment of %s to %s", re, le) |
| } |
| } |
| }) |
| |
| return nil, nil |
| } |