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
 | 
						|
}
 |