github.com/amarpal/go-tools@v0.0.0-20240422043104-40142f59f616/stylecheck/st1016/st1016.go (about) 1 package st1016 2 3 import ( 4 "fmt" 5 "go/types" 6 "sort" 7 "strings" 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/lint" 12 "github.com/amarpal/go-tools/analysis/report" 13 "github.com/amarpal/go-tools/go/types/typeutil" 14 "github.com/amarpal/go-tools/internal/passes/buildir" 15 16 "golang.org/x/tools/go/analysis" 17 ) 18 19 var SCAnalyzer = lint.InitializeAnalyzer(&lint.Analyzer{ 20 Analyzer: &analysis.Analyzer{ 21 Name: "ST1016", 22 Run: run, 23 Requires: []*analysis.Analyzer{buildir.Analyzer, generated.Analyzer}, 24 }, 25 Doc: &lint.Documentation{ 26 Title: `Use consistent method receiver names`, 27 Since: "2019.1", 28 NonDefault: true, 29 MergeIf: lint.MergeIfAny, 30 }, 31 }) 32 33 var Analyzer = SCAnalyzer.Analyzer 34 35 func run(pass *analysis.Pass) (interface{}, error) { 36 irpkg := pass.ResultOf[buildir.Analyzer].(*buildir.IR).Pkg 37 for _, m := range irpkg.Members { 38 names := map[string]int{} 39 40 var firstFn *types.Func 41 if T, ok := m.Object().(*types.TypeName); ok && !T.IsAlias() { 42 ms := typeutil.IntuitiveMethodSet(T.Type(), nil) 43 for _, sel := range ms { 44 fn := sel.Obj().(*types.Func) 45 recv := fn.Type().(*types.Signature).Recv() 46 if code.IsGenerated(pass, recv.Pos()) { 47 // Don't concern ourselves with methods in generated code 48 continue 49 } 50 if typeutil.Dereference(recv.Type()) != T.Type() { 51 // skip embedded methods 52 continue 53 } 54 if firstFn == nil { 55 firstFn = fn 56 } 57 if recv.Name() != "" && recv.Name() != "_" { 58 names[recv.Name()]++ 59 } 60 } 61 } 62 63 if len(names) > 1 { 64 var seen []string 65 for name, count := range names { 66 seen = append(seen, fmt.Sprintf("%dx %q", count, name)) 67 } 68 sort.Strings(seen) 69 70 report.Report(pass, firstFn, fmt.Sprintf("methods on the same type should have the same receiver name (seen %s)", strings.Join(seen, ", "))) 71 } 72 } 73 return nil, nil 74 }