Skip to content

Commit 4be0b43

Browse files
committed
cyclomatic: Update cyclomatic complexity tool to handle SDKv1 roles
1 parent d9e3ad9 commit 4be0b43

File tree

2 files changed

+25
-19
lines changed

2 files changed

+25
-19
lines changed

cyclomatic.go

+15-9
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,12 @@ import (
1414

1515
// This implementation uses PMD implementation as reference and uses the method of
1616
// counting one + one of the following UAST Roles if present on any children:
17-
// If | SwitchCase | For[Each] | [Do]While | TryCatch | Continue | OpBoolean* | Goto
17+
// * Statement, If | Case | For | While | DoWhile | Continue
18+
// * Try, Catch
19+
// * Operator, Boolean
20+
// * Goto
1821
// Important: since some languages allow for code defined
19-
// outside function definitions, this won't check that the Node has the role FunctionDeclarationRole
22+
// outside function definitions, this won't check that the Node has the roles Function, Declaration
2023
// so the user should check that if the intended use is calculating the complexity of a function/method.
2124
// If the children contain more than one function definitions, the value will not be averaged between
2225
// the total number of function declarations but given as a total.
@@ -62,17 +65,20 @@ func cyclomaticComplexity(n *uast.Node) int {
6265
break
6366
}
6467
n := p.Node()
68+
roles := make(map[uast.Role]bool)
6569
for _, r := range n.Roles {
66-
if addsComplexity(r) {
67-
complexity++
68-
}
70+
roles[r] = true
71+
}
72+
if addsComplexity(roles) {
73+
complexity++
6974
}
7075
}
7176
return complexity
7277
}
7378

74-
func addsComplexity(r uast.Role) bool {
75-
return r == uast.If || r == uast.SwitchCase || r == uast.For || r == uast.ForEach ||
76-
r == uast.DoWhile || r == uast.While || r == uast.TryCatch || r == uast.Continue ||
77-
r == uast.OpBooleanAnd || r == uast.OpBooleanOr || r == uast.OpBooleanXor
79+
func addsComplexity(roles map[uast.Role]bool) bool {
80+
return roles[uast.Statement] && (roles[uast.If] || roles[uast.Case] || roles[uast.For] || roles[uast.While] || roles[uast.DoWhile] || roles[uast.Continue]) ||
81+
roles[uast.Try] && roles[uast.Catch] ||
82+
roles[uast.Operator] && roles[uast.Boolean] ||
83+
roles[uast.Goto]
7884
}

cyclomatic_test.go

+10-10
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,19 @@ func TestCyclomaticComplexity(t *testing.T) {
1313
Children: []*uast.Node{
1414
{InternalType: "root"}, // 1 (initial)
1515
// Prefix is the default so it doesnt need any role
16-
{InternalType: "if1", Roles: []uast.Role{uast.If}, Children: []*uast.Node{ // 2 (If)
17-
{InternalType: "if1else1", Roles: []uast.Role{uast.IfElse}, Children: []*uast.Node{ // 0
18-
{InternalType: "if1else1foreach", Roles: []uast.Role{uast.ForEach}, Children: []*uast.Node{ // 3 (ForEach)
19-
{InternalType: "foreach_child1"}, // 0
20-
{InternalType: "foreach_child2_continue", Roles: []uast.Role{uast.Continue}}, // 4 (Continue)
16+
{InternalType: "if1", Roles: []uast.Role{uast.Statement, uast.If}, Children: []*uast.Node{ // 2 (If, Statement)
17+
{InternalType: "if1else1", Roles: []uast.Role{uast.If, uast.Then}, Children: []*uast.Node{ // 0
18+
{InternalType: "if1else1foreach", Roles: []uast.Role{uast.Statement, uast.For, uast.Iterator}, Children: []*uast.Node{ // 3 (For, Statement)
19+
{InternalType: "foreach_child1"}, // 0
20+
{InternalType: "foreach_child2_continue", Roles: []uast.Role{uast.Statement, uast.Continue}}, // 4 (Statement, Continue)
2121
}},
22-
{InternalType: "if1else1if", Roles: []uast.Role{uast.If}, Children: []*uast.Node{ // 5 (If)
23-
{InternalType: "elseif_child1"}, // 0
24-
{InternalType: "opAnd", Roles: []uast.Role{uast.OpBooleanAnd}}, // 6 (OpBooleanAnd)
25-
{InternalType: "elseif_child2"}, // 0
22+
{InternalType: "if1else1if", Roles: []uast.Role{uast.Statement, uast.If}, Children: []*uast.Node{ // 5 (Statement, If)
23+
{InternalType: "elseif_child1"}, // 0
24+
{InternalType: "opAnd", Roles: []uast.Role{uast.Operator, uast.Boolean, uast.And}}, // 6 (Operator, Boolean)
25+
{InternalType: "elseif_child2"}, // 0
2626
}},
2727
}},
28-
{InternalType: "break", Roles: []uast.Role{uast.Break}},
28+
{InternalType: "break", Roles: []uast.Role{uast.Statement, uast.Break}},
2929
},
3030
}}}
3131
require.Equal(cyclomaticComplexity(n), 6)

0 commit comments

Comments
 (0)