src

Go monorepo.
git clone git://code.dwrz.net/src
Log | Files | Refs

st1006.go (2281B)


      1 package st1006
      2 
      3 import (
      4 	"go/types"
      5 
      6 	"honnef.co/go/tools/analysis/facts/generated"
      7 	"honnef.co/go/tools/analysis/lint"
      8 	"honnef.co/go/tools/analysis/report"
      9 	"honnef.co/go/tools/go/types/typeutil"
     10 	"honnef.co/go/tools/internal/passes/buildir"
     11 
     12 	"golang.org/x/tools/go/analysis"
     13 )
     14 
     15 var SCAnalyzer = lint.InitializeAnalyzer(&lint.Analyzer{
     16 	Analyzer: &analysis.Analyzer{
     17 		Name:     "ST1006",
     18 		Run:      run,
     19 		Requires: []*analysis.Analyzer{buildir.Analyzer, generated.Analyzer},
     20 	},
     21 	Doc: &lint.RawDocumentation{
     22 		Title: `Poorly chosen receiver name`,
     23 		Text: `Quoting Go Code Review Comments:
     24 
     25 > The name of a method's receiver should be a reflection of its
     26 > identity; often a one or two letter abbreviation of its type
     27 > suffices (such as "c" or "cl" for "Client"). Don't use generic
     28 > names such as "me", "this" or "self", identifiers typical of
     29 > object-oriented languages that place more emphasis on methods as
     30 > opposed to functions. The name need not be as descriptive as that
     31 > of a method argument, as its role is obvious and serves no
     32 > documentary purpose. It can be very short as it will appear on
     33 > almost every line of every method of the type; familiarity admits
     34 > brevity. Be consistent, too: if you call the receiver "c" in one
     35 > method, don't call it "cl" in another.`,
     36 		Since:   "2019.1",
     37 		MergeIf: lint.MergeIfAny,
     38 	},
     39 })
     40 
     41 var Analyzer = SCAnalyzer.Analyzer
     42 
     43 func run(pass *analysis.Pass) (any, error) {
     44 	irpkg := pass.ResultOf[buildir.Analyzer].(*buildir.IR).Pkg
     45 	for _, m := range irpkg.Members {
     46 		if T, ok := m.Object().(*types.TypeName); ok && !T.IsAlias() {
     47 			ms := typeutil.IntuitiveMethodSet(T.Type(), nil)
     48 			for _, sel := range ms {
     49 				fn := sel.Obj().(*types.Func)
     50 				recv := fn.Type().(*types.Signature).Recv()
     51 				if typeutil.Dereference(recv.Type()) != T.Type() {
     52 					// skip embedded methods
     53 					continue
     54 				}
     55 				if recv.Name() == "self" || recv.Name() == "this" {
     56 					report.Report(pass, recv, `receiver name should be a reflection of its identity; don't use generic names such as "this" or "self"`, report.FilterGenerated())
     57 				}
     58 				if recv.Name() == "_" {
     59 					report.Report(pass, recv, "receiver name should not be an underscore, omit the name if it is unused", report.FilterGenerated())
     60 				}
     61 			}
     62 		}
     63 	}
     64 	return nil, nil
     65 }