66 lines
		
	
	
		
			1.8 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			66 lines
		
	
	
		
			1.8 KiB
		
	
	
	
		
			Go
		
	
	
	
| // 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
 | |
| 
 | |
| // 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"
 | |
| )
 | |
| 
 | |
| var Analyzer = &analysis.Analyzer{
 | |
| 	Name: "assign",
 | |
| 	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.`,
 | |
| 	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
 | |
| }
 |