aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/raeperd/recvcheck/analyzer.go
diff options
context:
space:
mode:
authorTaras Madan <tarasmadan@google.com>2024-11-11 11:41:38 +0100
committerTaras Madan <tarasmadan@google.com>2024-11-11 11:10:48 +0000
commit27e76fae2ee2d84dc7db63af1d9ed7358ba35b7a (patch)
treeed19c0e35e272b3c4cc5a2f2c595e035b2428337 /vendor/github.com/raeperd/recvcheck/analyzer.go
parent621e84e063b0e15b23e17780338627c509e1b9e8 (diff)
vendor: update
Diffstat (limited to 'vendor/github.com/raeperd/recvcheck/analyzer.go')
-rw-r--r--vendor/github.com/raeperd/recvcheck/analyzer.go69
1 files changed, 69 insertions, 0 deletions
diff --git a/vendor/github.com/raeperd/recvcheck/analyzer.go b/vendor/github.com/raeperd/recvcheck/analyzer.go
new file mode 100644
index 000000000..e80dfc577
--- /dev/null
+++ b/vendor/github.com/raeperd/recvcheck/analyzer.go
@@ -0,0 +1,69 @@
+package recvcheck
+
+import (
+ "go/ast"
+
+ "golang.org/x/tools/go/analysis"
+ "golang.org/x/tools/go/analysis/passes/inspect"
+ "golang.org/x/tools/go/ast/inspector"
+)
+
+var Analyzer = &analysis.Analyzer{
+ Name: "recvcheck",
+ Doc: "checks for receiver type consistency",
+ Run: run,
+ Requires: []*analysis.Analyzer{inspect.Analyzer},
+}
+
+func run(pass *analysis.Pass) (any, error) {
+ inspector := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
+
+ structs := map[string]*structType{}
+ inspector.Preorder([]ast.Node{(*ast.FuncDecl)(nil)}, func(n ast.Node) {
+ funcDecl, ok := n.(*ast.FuncDecl)
+ if !ok || funcDecl.Recv == nil || len(funcDecl.Recv.List) != 1 {
+ return
+ }
+
+ var recv *ast.Ident
+ var isStar bool
+ switch recvType := funcDecl.Recv.List[0].Type.(type) {
+ case *ast.StarExpr:
+ isStar = true
+ if recv, ok = recvType.X.(*ast.Ident); !ok {
+ return
+ }
+ case *ast.Ident:
+ recv = recvType
+ default:
+ return
+ }
+
+ var st *structType
+ st, ok = structs[recv.Name]
+ if !ok {
+ structs[recv.Name] = &structType{recv: recv.Name}
+ st = structs[recv.Name]
+ }
+
+ if isStar {
+ st.numStarMethod++
+ } else {
+ st.numTypeMethod++
+ }
+ })
+
+ for _, st := range structs {
+ 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)
+ }
+ }
+
+ return nil, nil
+}
+
+type structType struct {
+ recv string
+ numStarMethod int
+ numTypeMethod int
+}