github.com/jhump/golang-x-tools@v0.0.0-20220218190644-4958d6d39439/go/analysis/passes/assign/assign.go (about) 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 // Package assign defines an Analyzer that detects useless assignments. 6 package assign 7 8 // TODO(adonovan): check also for assignments to struct fields inside 9 // methods that are on T instead of *T. 10 11 import ( 12 "fmt" 13 "go/ast" 14 "go/token" 15 "reflect" 16 17 "github.com/jhump/golang-x-tools/go/analysis" 18 "github.com/jhump/golang-x-tools/go/analysis/passes/inspect" 19 "github.com/jhump/golang-x-tools/go/analysis/passes/internal/analysisutil" 20 "github.com/jhump/golang-x-tools/go/ast/inspector" 21 ) 22 23 const Doc = `check for useless assignments 24 25 This checker reports assignments of the form x = x or a[i] = a[i]. 26 These are almost always useless, and even when they aren't they are 27 usually a mistake.` 28 29 var Analyzer = &analysis.Analyzer{ 30 Name: "assign", 31 Doc: Doc, 32 Requires: []*analysis.Analyzer{inspect.Analyzer}, 33 Run: run, 34 } 35 36 func run(pass *analysis.Pass) (interface{}, error) { 37 inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) 38 39 nodeFilter := []ast.Node{ 40 (*ast.AssignStmt)(nil), 41 } 42 inspect.Preorder(nodeFilter, func(n ast.Node) { 43 stmt := n.(*ast.AssignStmt) 44 if stmt.Tok != token.ASSIGN { 45 return // ignore := 46 } 47 if len(stmt.Lhs) != len(stmt.Rhs) { 48 // If LHS and RHS have different cardinality, they can't be the same. 49 return 50 } 51 for i, lhs := range stmt.Lhs { 52 rhs := stmt.Rhs[i] 53 if analysisutil.HasSideEffects(pass.TypesInfo, lhs) || 54 analysisutil.HasSideEffects(pass.TypesInfo, rhs) { 55 continue // expressions may not be equal 56 } 57 if reflect.TypeOf(lhs) != reflect.TypeOf(rhs) { 58 continue // short-circuit the heavy-weight gofmt check 59 } 60 le := analysisutil.Format(pass.Fset, lhs) 61 re := analysisutil.Format(pass.Fset, rhs) 62 if le == re { 63 pass.Report(analysis.Diagnostic{ 64 Pos: stmt.Pos(), Message: fmt.Sprintf("self-assignment of %s to %s", re, le), 65 SuggestedFixes: []analysis.SuggestedFix{ 66 {Message: "Remove", TextEdits: []analysis.TextEdit{ 67 {Pos: stmt.Pos(), End: stmt.End(), NewText: []byte{}}, 68 }}, 69 }, 70 }) 71 } 72 } 73 }) 74 75 return nil, nil 76 }