Skip to content

Commit

Permalink
Added support for indirect recursion
Browse files Browse the repository at this point in the history
  • Loading branch information
uudashr committed Jul 14, 2021
1 parent fdaefaf commit f4ff102
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 5 deletions.
6 changes: 5 additions & 1 deletion gocognit.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ func Complexity(fn *ast.FuncDecl) int {
v := complexityVisitor{
name: fn.Name,
}

ast.Walk(&v, fn)
return v.complexity
}
Expand Down Expand Up @@ -300,8 +301,11 @@ func (v *complexityVisitor) visitBinaryExpr(n *ast.BinaryExpr) ast.Visitor {
func (v *complexityVisitor) visitCallExpr(n *ast.CallExpr) ast.Visitor {
if name, ok := n.Fun.(*ast.Ident); ok {
if name.Obj == v.name.Obj && name.Name == v.name.Name {
// called by same function (recursion)
// called by same function directly (direct recursion)
v.incComplexity()
} else if fnDecl, ok := name.Obj.Decl.(*ast.FuncDecl); ok {
// called by same function indirectly (indirect recursion)
ast.Walk(v, fnDecl)
}
}
return v
Expand Down
29 changes: 27 additions & 2 deletions testdata/src/a/a.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ import (
"io"
)

func HelloWorld() string {
return "Hello, World!"
} // total complexity = 0

func SimpleCond(n int) string { // want "cognitive complexity 1 of func SimpleCond is high \\(> 0\\)"
if n == 100 { // +1
return "a hundred"
Expand Down Expand Up @@ -112,14 +116,35 @@ OUT:
return total
} // Cognitive complexity = 7

func Fact(n int) int { // want "cognitive complexity 3 of func Fact is high \\(> 0\\)"
func FactRec(n int) int { // want "cognitive complexity 3 of func FactRec is high \\(> 0\\)"
if n <= 1 { // +1
return 1
} else { // +1
return n * FactRec(n-1) // +1
}
} // total complexity = 3

func FactRecIndirect(n int) int { // want "cognitive complexity 3 of func FactRecIndirect is high \\(> 0\\)"
if n <= 1 { // +1
return 1
} else { // +1
return n * Fact(n-1) // +1
return factRecIndirect0(n) // +0 +1, due to indirect call to FactRecIndirect
}
} // total complexity = 3

func factRecIndirect0(n int) int { // want "cognitive complexity 3 of func factRecIndirect0 is high \\(> 0\\)"
return n * FactRecIndirect(n-1) // +0 +3 due to inderect call to factRecIndirect0
} // total complexity = 3

func FactLoop(n int) int { // want "cognitive complexity 1 of func FactLoop is high \\(> 0\\)"
total := 1
for n > 0 { // +1
total *= n
n--
}
return total
} // total complexity = 1

func DumpVal(w io.Writer, i interface{}) error { // want "cognitive complexity 1 of func DumpVal is high \\(> 0\\)"
switch v := i.(type) { // +1
case int:
Expand Down
29 changes: 27 additions & 2 deletions testdata/src/b/b.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ import (
"io"
)

func HelloWorld() string {
return "Hello, World!"
} // total complexity = 0

func SimpleCond(n int) string {
if n == 100 { // +1
return "a hundred"
Expand Down Expand Up @@ -112,14 +116,35 @@ OUT:
return total
} // Cognitive complexity = 7

func Fact(n int) int {
func FactRec(n int) int {
if n <= 1 { // +1
return 1
} else { // +1
return n * FactRec(n-1) // +1
}
} // total complexity = 3

func FactRecIndirect(n int) int {
if n <= 1 { // +1
return 1
} else { // +1
return n * Fact(n-1) // +1
return factRecIndirect0(n) // +0 +1, due to indirect call to FactRecIndirect
}
} // total complexity = 3

func factRecIndirect0(n int) int {
return n * FactRecIndirect(n-1) // +0 +3 due to inderect call to factRecIndirect0
} // total complexity = 3

func FactLoop(n int) int {
total := 1
for n > 0 { // +1
total *= n
n--
}
return total
} // total complexity = 1

func DumpVal(w io.Writer, i interface{}) error {
switch v := i.(type) { // +1
case int:
Expand Down

0 comments on commit f4ff102

Please sign in to comment.