diff --git a/rule/cognitive_complexity.go b/rule/cognitive_complexity.go index ecde3882e..b1122d0ab 100644 --- a/rule/cognitive_complexity.go +++ b/rule/cognitive_complexity.go @@ -67,7 +67,9 @@ func (w cognitiveComplexityLinter) lintCognitiveComplexity() { f := w.file for _, decl := range f.AST.Decls { if fn, ok := decl.(*ast.FuncDecl); ok && fn.Body != nil { - v := cognitiveComplexityVisitor{} + v := cognitiveComplexityVisitor{ + name: fn.Name, + } c := v.subTreeComplexity(fn.Body) if c > w.maxComplexity { w.onFailure(lint.Failure{ @@ -82,6 +84,7 @@ func (w cognitiveComplexityLinter) lintCognitiveComplexity() { } type cognitiveComplexityVisitor struct { + name *ast.Ident complexity int nestingLevel int } @@ -125,8 +128,15 @@ func (v *cognitiveComplexityVisitor) Visit(n ast.Node) ast.Visitor { if n.Label != nil { v.complexity++ } + case *ast.CallExpr: + if ident, ok := n.Fun.(*ast.Ident); ok { + if ident.Obj == v.name.Obj && ident.Name == v.name.Name { + // called by same function directly (direct recursion) + v.complexity++ + return nil + } + } } - // TODO handle (at least) direct recursion return v } diff --git a/testdata/cognitive_complexity.go b/testdata/cognitive_complexity.go index c20794baa..17fab4ed9 100644 --- a/testdata/cognitive_complexity.go +++ b/testdata/cognitive_complexity.go @@ -281,3 +281,13 @@ func (m *Migrator) MigrateIfNeeded(target *EtcdVersionPair) error { // MATCH /fu // no regression test for issue #451 func myFunc() + +// Recursive functions +func Walk(t *Tree, ch chan int) { // MATCH /function Walk has cognitive complexity 3 (> max enabled 0)/ + if t == nil { // +1 + return + } + Walk(t.Left, ch) // +1 + ch <- t.Value + Walk(t.Right, ch) // +1 +}