Check for inconsistent receiver names.
diff --git a/lint.go b/lint.go
index cbd2ec4..6980517 100644
--- a/lint.go
+++ b/lint.go
@@ -104,7 +104,7 @@
return true
}
// TODO(dsymonds): We could check the signature to be more precise.
- recv := receiverName(fn)
+ recv := receiverType(fn)
if i, ok := nmap[fn.Name.Name]; ok {
has[recv] |= i
}
@@ -477,7 +477,7 @@
if fn.Recv != nil {
// method
kind = "method"
- recv := receiverName(fn)
+ recv := receiverType(fn)
if !ast.IsExported(recv) {
// receiver is unexported
return
@@ -700,23 +700,35 @@
"self": true,
}
-// lintReceiverNames examines receiver names. It complains about names such as "this".
+// lintReceiverNames examines receiver names. It complains about inconsistent
+// names used for the same type and names such as "this".
func (f *file) lintReceiverNames() {
+ typeReceiver := map[string]string{}
f.walk(func(n ast.Node) bool {
fn, ok := n.(*ast.FuncDecl)
if !ok || fn.Recv == nil {
return true
}
names := fn.Recv.List[0].Names
- if len(names) < 1 || !badReceiverNames[names[0].Name] {
+ if len(names) < 1 {
return true
}
- f.errorf(n, 1, `receiver name should be a reflection of its identity; don't use generic names such as "me", "this", or "self"`)
+ name := names[0].Name
+ if badReceiverNames[name] {
+ f.errorf(n, 1, `receiver name should be a reflection of its identity; don't use generic names such as "me", "this", or "self"`)
+ return true
+ }
+ recv := receiverType(fn)
+ if prev, ok := typeReceiver[recv]; ok && prev != name {
+ f.errorf(n, 1, "receiver name %s should be consistent with previous receiver name %s for %s", name, prev, recv)
+ return true
+ }
+ typeReceiver[recv] = name
return true
})
}
-func receiverName(fn *ast.FuncDecl) string {
+func receiverType(fn *ast.FuncDecl) string {
switch e := fn.Recv.List[0].Type.(type) {
case *ast.Ident:
return e.Name
diff --git a/testdata/receiver-names.go b/testdata/receiver-names.go
index a4fcac7..58f567d 100644
--- a/testdata/receiver-names.go
+++ b/testdata/receiver-names.go
@@ -16,3 +16,23 @@
func (foo) f4() {
}
+
+type bar struct{}
+
+func (b bar) f1() {
+}
+
+func (b bar) f2() {
+}
+
+func (a bar) f3() { // MATCH /receiver name a should be consistent with previous receiver name b for bar/
+}
+
+func (a *bar) f4() { // MATCH /receiver name a should be consistent with previous receiver name b for bar/
+}
+
+func (b *bar) f5() {
+}
+
+func (bar) f6() {
+}