Home | History | Annotate | Download | only in vet
      1 // Copyright 2013 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 /*
      6 This file contains the code to check for useless assignments.
      7 */
      8 
      9 package main
     10 
     11 import (
     12 	"go/ast"
     13 	"go/token"
     14 	"reflect"
     15 )
     16 
     17 func init() {
     18 	register("assign",
     19 		"check for useless assignments",
     20 		checkAssignStmt,
     21 		assignStmt)
     22 }
     23 
     24 // TODO: should also check for assignments to struct fields inside methods
     25 // that are on T instead of *T.
     26 
     27 // checkAssignStmt checks for assignments of the form "<expr> = <expr>".
     28 // These are almost always useless, and even when they aren't they are usually a mistake.
     29 func checkAssignStmt(f *File, node ast.Node) {
     30 	stmt := node.(*ast.AssignStmt)
     31 	if stmt.Tok != token.ASSIGN {
     32 		return // ignore :=
     33 	}
     34 	if len(stmt.Lhs) != len(stmt.Rhs) {
     35 		// If LHS and RHS have different cardinality, they can't be the same.
     36 		return
     37 	}
     38 	for i, lhs := range stmt.Lhs {
     39 		rhs := stmt.Rhs[i]
     40 		if hasSideEffects(lhs) || hasSideEffects(rhs) {
     41 			continue // expressions may not be equal
     42 		}
     43 		if reflect.TypeOf(lhs) != reflect.TypeOf(rhs) {
     44 			continue // short-circuit the heavy-weight gofmt check
     45 		}
     46 		le := f.gofmt(lhs)
     47 		re := f.gofmt(rhs)
     48 		if le == re {
     49 			f.Badf(stmt.Pos(), "self-assignment of %s to %s", re, le)
     50 		}
     51 	}
     52 }
     53