1
0
mirror of https://github.com/mgechev/revive.git synced 2025-11-23 22:04:49 +02:00

fixes computation of complexity of Bool exprs

This commit is contained in:
chavacava
2019-12-16 23:02:12 +01:00
parent 0cdcc25bc7
commit e63e7cbd3d

View File

@@ -6,6 +6,7 @@ import (
"go/token" "go/token"
"github.com/mgechev/revive/lint" "github.com/mgechev/revive/lint"
"golang.org/x/tools/go/ast/astutil"
) )
// CognitiveComplexityRule lints given else constructs. // CognitiveComplexityRule lints given else constructs.
@@ -133,28 +134,65 @@ func (v *cognitiveComplexityVisitor) walk(complexityIncrement int, targets ...as
} }
func (cognitiveComplexityVisitor) binExpComplexity(n *ast.BinaryExpr) int { func (cognitiveComplexityVisitor) binExpComplexity(n *ast.BinaryExpr) int {
calculator := binExprComplexityCalculator{complexity: 0} calculator := binExprComplexityCalculator{currentOp: []token.Token{}}
ast.Walk(&calculator, n)
astutil.Apply(n, calculator.pre(), calculator.post())
return calculator.complexity return calculator.complexity
} }
type binExprComplexityCalculator struct { type binExprComplexityCalculator struct {
complexity int complexity int
currentOp token.Token currentOp []token.Token // stack of bool operators
subexpStarted bool
} }
func (v *binExprComplexityCalculator) Visit(n ast.Node) ast.Visitor { func (becc *binExprComplexityCalculator) pre() astutil.ApplyFunc {
switch n := n.(type) { return func(c *astutil.Cursor) bool {
case *ast.BinaryExpr: switch n := c.Node().(type) {
isLogicOp := n.Op == token.LAND || n.Op == token.LOR case *ast.BinaryExpr:
if isLogicOp && n.Op != v.currentOp { isBoolOp := n.Op == token.LAND || n.Op == token.LOR
v.complexity++ if !isBoolOp {
v.currentOp = n.Op break
}
ops := len(becc.currentOp)
// if
// is the first boolop in the expression OR
// is the first boolop inside a subexpression (...) OR
// is not the same to the previous one
// then
// increment complexity
if ops == 0 || becc.subexpStarted || n.Op != becc.currentOp[ops-1] {
becc.complexity++
becc.subexpStarted = false
}
becc.currentOp = append(becc.currentOp, n.Op)
case *ast.ParenExpr:
becc.subexpStarted = true
} }
case *ast.ParenExpr:
v.complexity++
}
return v return true
}
}
func (becc *binExprComplexityCalculator) post() astutil.ApplyFunc {
return func(c *astutil.Cursor) bool {
switch n := c.Node().(type) {
case *ast.BinaryExpr:
isBoolOp := n.Op == token.LAND || n.Op == token.LOR
if !isBoolOp {
break
}
ops := len(becc.currentOp)
if ops > 0 {
becc.currentOp = becc.currentOp[:ops-1]
}
case *ast.ParenExpr:
becc.subexpStarted = false
}
return true
}
} }