diff --git a/cmd/gocognit/main.go b/cmd/gocognit/main.go index 7478496..469c3b2 100644 --- a/cmd/gocognit/main.go +++ b/cmd/gocognit/main.go @@ -111,6 +111,7 @@ func main() { jsonEncode bool ignoreExpr string ) + flag.IntVar(&over, "over", defaultOverFlagVal, "show functions with complexity > N only") flag.IntVar(&top, "top", defaultTopFlagVal, "show the top N most complex functions only") flag.BoolVar(&avg, "avg", false, "show the average complexity") @@ -121,9 +122,11 @@ func main() { log.SetFlags(0) log.SetPrefix("gocognit: ") + flag.Usage = usage flag.Parse() args := flag.Args() + if len(args) == 0 { usage() } @@ -146,12 +149,14 @@ func main() { } filteredStats := filterStats(stats, ignoreRegexp, top, over) + var written int if jsonEncode { written, err = writeJSONStats(os.Stdout, filteredStats) } else { written, err = writeTextStats(os.Stdout, filteredStats, tmpl) } + if err != nil { log.Fatal(err) } @@ -175,6 +180,7 @@ func analyzePath(path string, includeTests bool) ([]gocognit.Stat, error) { func analyze(paths []string, includeTests bool) (stats []gocognit.Stat, err error) { var out []gocognit.Stat + for _, path := range paths { stats, err := analyzePath(path, includeTests) if err != nil { @@ -189,11 +195,13 @@ func analyze(paths []string, includeTests bool) (stats []gocognit.Stat, err erro func isDir(filename string) bool { fi, err := os.Stat(filename) + return err == nil && fi.IsDir() } func analyzeFile(fname string, stats []gocognit.Stat) ([]gocognit.Stat, error) { fset := token.NewFileSet() + f, err := parser.ParseFile(fset, fname, nil, parser.ParseComments) if err != nil { return nil, err @@ -240,6 +248,7 @@ func writeTextStats(w io.Writer, stats []gocognit.Stat, tmpl *template.Template) if err := tmpl.Execute(w, stat); err != nil { return i, err } + fmt.Fprintln(w) } @@ -266,6 +275,7 @@ func prepareRegexp(expr string) (*regexp.Regexp, error) { func filterStats(sortedStats []gocognit.Stat, ignoreRegexp *regexp.Regexp, top, over int) []gocognit.Stat { var filtered []gocognit.Stat + i := 0 for _, stat := range sortedStats { if i == top { @@ -296,6 +306,7 @@ func average(stats []gocognit.Stat) float64 { for _, s := range stats { total += s.Complexity } + return float64(total) / float64(len(stats)) } diff --git a/doc.go b/doc.go index ae3d0a2..797b192 100644 --- a/doc.go +++ b/doc.go @@ -1,2 +1,3 @@ -// Package gocognit defines Analyzer other utilities to checks and calculate the complexity of function based on "cognitive complexity" methods. +// Package gocognit defines Analyzer other utilities to checks and calculate +// the complexity of function based on "cognitive complexity" methods. package gocognit diff --git a/gocognit.go b/gocognit.go index 2bba2eb..dd8dfa2 100644 --- a/gocognit.go +++ b/gocognit.go @@ -39,6 +39,7 @@ func ComplexityStats(f *ast.File, fset *token.FileSet, stats []Stat) []Stat { }) } } + return stats } @@ -66,9 +67,11 @@ func funcName(fn *ast.FuncDecl) string { if fn.Recv != nil { if fn.Recv.NumFields() > 0 { typ := fn.Recv.List[0].Type + return fmt.Sprintf("(%s).%s", recvString(typ), fn.Name) } } + return fn.Name.Name } @@ -79,6 +82,7 @@ func Complexity(fn *ast.FuncDecl) int { } ast.Walk(&v, fn) + return v.complexity } @@ -162,6 +166,7 @@ func (v *complexityVisitor) Visit(n ast.Node) ast.Visitor { case *ast.CallExpr: return v.visitCallExpr(n) } + return v } @@ -209,6 +214,7 @@ func (v *complexityVisitor) visitSwitchStmt(n *ast.SwitchStmt) ast.Visitor { v.incNesting() ast.Walk(v, n.Body) v.decNesting() + return nil } @@ -226,6 +232,7 @@ func (v *complexityVisitor) visitTypeSwitchStmt(n *ast.TypeSwitchStmt) ast.Visit v.incNesting() ast.Walk(v, n.Body) v.decNesting() + return nil } @@ -235,6 +242,7 @@ func (v *complexityVisitor) visitSelectStmt(n *ast.SelectStmt) ast.Visitor { v.incNesting() ast.Walk(v, n.Body) v.decNesting() + return nil } @@ -256,6 +264,7 @@ func (v *complexityVisitor) visitForStmt(n *ast.ForStmt) ast.Visitor { v.incNesting() ast.Walk(v, n.Body) v.decNesting() + return nil } @@ -275,6 +284,7 @@ func (v *complexityVisitor) visitRangeStmt(n *ast.RangeStmt) ast.Visitor { v.incNesting() ast.Walk(v, n.Body) v.decNesting() + return nil } @@ -302,10 +312,12 @@ func (v *complexityVisitor) visitBinaryExpr(n *ast.BinaryExpr) ast.Visitor { for _, op := range ops { if lastOp != op { v.incComplexity() + lastOp = op } } } + return v } @@ -317,11 +329,13 @@ func (v *complexityVisitor) visitCallExpr(n *ast.CallExpr) ast.Visitor { v.incComplexity() } } + return v } func (v *complexityVisitor) collectBinaryOps(exp ast.Expr) []token.Token { v.markCalculated(exp) + if exp, ok := exp.(*ast.BinaryExpr); ok { return mergeBinaryOps(v.collectBinaryOps(exp.X), exp.Op, v.collectBinaryOps(exp.Y)) } @@ -339,9 +353,11 @@ func (v *complexityVisitor) incIfComplexity(n *ast.IfStmt) { func mergeBinaryOps(x []token.Token, op token.Token, y []token.Token) []token.Token { var out []token.Token out = append(out, x...) + if isBinaryLogicalOp(op) { out = append(out, op) } + out = append(out, y...) return out } diff --git a/recv.go b/recv.go index 2f20d84..eaf3c97 100644 --- a/recv.go +++ b/recv.go @@ -20,5 +20,6 @@ func recvString(recv ast.Expr) string { case *ast.IndexListExpr: return recvString(t.X) } + return "BADRECV" } diff --git a/recv_pre118.go b/recv_pre118.go index 9e0ebfd..a47ba1b 100644 --- a/recv_pre118.go +++ b/recv_pre118.go @@ -16,5 +16,6 @@ func recvString(recv ast.Expr) string { case *ast.StarExpr: return "*" + recvString(t.X) } + return "BADRECV" }