From bf94da4667789c94296c32cb038e5238d314157b Mon Sep 17 00:00:00 2001 From: Ivan Ivanov Date: Sun, 1 May 2022 20:07:12 +0300 Subject: [PATCH] Fix gocognit output when a function has generic receiver type recvString func in gocognit returns BADRECV when the function's receiver is a generic type. Implement recvString in two variants in order to keep the code compatible with go versions less than 1.18 --- gocognit.go | 12 ------------ recv.go | 30 ++++++++++++++++++++++++++++++ recv_pre118.go | 20 ++++++++++++++++++++ 3 files changed, 50 insertions(+), 12 deletions(-) create mode 100644 recv.go create mode 100644 recv_pre118.go diff --git a/gocognit.go b/gocognit.go index 418c163..1d539ee 100644 --- a/gocognit.go +++ b/gocognit.go @@ -49,18 +49,6 @@ func funcName(fn *ast.FuncDecl) string { return fn.Name.Name } -// recvString returns a string representation of recv of the -// form "T", "*T", or "BADRECV" (if not a proper receiver type). -func recvString(recv ast.Expr) string { - switch t := recv.(type) { - case *ast.Ident: - return t.Name - case *ast.StarExpr: - return "*" + recvString(t.X) - } - return "BADRECV" -} - // Complexity calculates the cognitive complexity of a function. func Complexity(fn *ast.FuncDecl) int { v := complexityVisitor{ diff --git a/recv.go b/recv.go new file mode 100644 index 0000000..b2e8b6a --- /dev/null +++ b/recv.go @@ -0,0 +1,30 @@ +//go:build go1.18 +// +build go1.18 + +package gocognit + +import ( + "go/ast" + "strings" +) + +// recvString returns a string representation of recv of the +// form "T", "*T", Type[T], Type[T, V], or "BADRECV" (if not a proper receiver type). +func recvString(recv ast.Expr) string { + switch t := recv.(type) { + case *ast.Ident: + return t.Name + case *ast.StarExpr: + return "*" + recvString(t.X) + case *ast.IndexExpr: + return recvString(t.X) + "[" + recvString(t.Index) + "]" + case *ast.IndexListExpr: + targs := make([]string, len(t.Indices)) + for i, exp := range t.Indices { + targs[i] = recvString(exp) + } + + return recvString(t.X) + "[" + strings.Join(targs, ", ") + "]" + } + return "BADRECV" +} diff --git a/recv_pre118.go b/recv_pre118.go new file mode 100644 index 0000000..9e0ebfd --- /dev/null +++ b/recv_pre118.go @@ -0,0 +1,20 @@ +//go:build !go1.18 +// +build !go1.18 + +package gocognit + +import ( + "go/ast" +) + +// recvString returns a string representation of recv of the +// form "T", "*T", or "BADRECV" (if not a proper receiver type). +func recvString(recv ast.Expr) string { + switch t := recv.(type) { + case *ast.Ident: + return t.Name + case *ast.StarExpr: + return "*" + recvString(t.X) + } + return "BADRECV" +}