diff --git a/analyzer.go b/analyzer.go index d8bd3d8..e80dfc5 100644 --- a/analyzer.go +++ b/analyzer.go @@ -42,22 +42,20 @@ func run(pass *analysis.Pass) (any, error) { var st *structType st, ok = structs[recv.Name] if !ok { - structs[recv.Name] = &structType{starMethods: []*ast.FuncDecl{}, typeMethods: []*ast.FuncDecl{}} + structs[recv.Name] = &structType{recv: recv.Name} st = structs[recv.Name] } if isStar { - st.starMethods = append(st.starMethods, funcDecl) + st.numStarMethod++ } else { - st.typeMethods = append(st.typeMethods, funcDecl) + st.numTypeMethod++ } }) for _, st := range structs { - if len(st.starMethods) > 0 && len(st.typeMethods) > 0 { - for _, typeMethod := range st.typeMethods { - pass.Reportf(typeMethod.Pos(), "receiver type should be a pointer") - } + if st.numStarMethod > 0 && st.numTypeMethod > 0 { + pass.Reportf(pass.Pkg.Scope().Lookup(st.recv).Pos(), "the methods of %q use pointer receiver and non-pointer receiver.", st.recv) } } @@ -65,6 +63,7 @@ func run(pass *analysis.Pass) (any, error) { } type structType struct { - starMethods []*ast.FuncDecl - typeMethods []*ast.FuncDecl + recv string + numStarMethod int + numTypeMethod int } diff --git a/testdata/src/test/rpc.go b/testdata/src/test/rpc.go index 2a4e426..b6e678c 100644 --- a/testdata/src/test/rpc.go +++ b/testdata/src/test/rpc.go @@ -4,7 +4,7 @@ import ( "time" ) -type RPC struct { +type RPC struct { // want `the methods of "RPC" use pointer receiver and non-pointer receiver.` result int done chan struct{} } @@ -15,6 +15,19 @@ func (rpc *RPC) compute() { close(rpc.done) } -func (RPC) version() int { // want "receiver type should be a pointer" +func (RPC) version() int { return 1 // never going to need to change this } + +// Following main function cause data race error +// reference: https://dave.cheney.net/2015/11/18/wednesday-pop-quiz-spot-the-race +// func main() { +// rpc := &RPC{done: make(chan struct{})} +// +// go rpc.compute() // kick off computation in the background +// version := rpc.version() // grab some other information while we're waiting +// <-rpc.done // wait for computation to finish +// result := rpc.result +// +// fmt.Printf("RPC computation complete, result: %d, version: %d\n", result, version) +// }