github.com/amarpal/go-tools@v0.0.0-20240422043104-40142f59f616/staticcheck/sa4018/sa4018.go (about) 1 package sa4018 2 3 import ( 4 "fmt" 5 "go/ast" 6 "go/token" 7 "reflect" 8 9 "github.com/amarpal/go-tools/analysis/code" 10 "github.com/amarpal/go-tools/analysis/facts/generated" 11 "github.com/amarpal/go-tools/analysis/facts/purity" 12 "github.com/amarpal/go-tools/analysis/lint" 13 "github.com/amarpal/go-tools/analysis/report" 14 15 "golang.org/x/tools/go/analysis" 16 "golang.org/x/tools/go/analysis/passes/inspect" 17 ) 18 19 var SCAnalyzer = lint.InitializeAnalyzer(&lint.Analyzer{ 20 Analyzer: &analysis.Analyzer{ 21 Name: "SA4018", 22 Run: run, 23 Requires: []*analysis.Analyzer{inspect.Analyzer, generated.Analyzer, purity.Analyzer}, 24 }, 25 Doc: &lint.Documentation{ 26 Title: `Self-assignment of variables`, 27 Since: "2017.1", 28 Severity: lint.SeverityWarning, 29 MergeIf: lint.MergeIfAny, 30 }, 31 }) 32 33 var Analyzer = SCAnalyzer.Analyzer 34 35 func run(pass *analysis.Pass) (interface{}, error) { 36 pure := pass.ResultOf[purity.Analyzer].(purity.Result) 37 38 fn := func(node ast.Node) { 39 assign := node.(*ast.AssignStmt) 40 if assign.Tok != token.ASSIGN || len(assign.Lhs) != len(assign.Rhs) { 41 return 42 } 43 for i, lhs := range assign.Lhs { 44 rhs := assign.Rhs[i] 45 if reflect.TypeOf(lhs) != reflect.TypeOf(rhs) { 46 continue 47 } 48 if code.MayHaveSideEffects(pass, lhs, pure) || code.MayHaveSideEffects(pass, rhs, pure) { 49 continue 50 } 51 52 rlh := report.Render(pass, lhs) 53 rrh := report.Render(pass, rhs) 54 if rlh == rrh { 55 report.Report(pass, assign, fmt.Sprintf("self-assignment of %s to %s", rrh, rlh), report.FilterGenerated()) 56 } 57 } 58 } 59 code.Preorder(pass, fn, (*ast.AssignStmt)(nil)) 60 return nil, nil 61 }