github.com/songshiyun/revive@v1.1.5-0.20220323112655-f8433a19b3c5/rule/constant-logical-expr.go (about) 1 package rule 2 3 import ( 4 "go/ast" 5 "go/token" 6 7 "github.com/songshiyun/revive/lint" 8 ) 9 10 // ConstantLogicalExprRule warns on constant logical expressions. 11 type ConstantLogicalExprRule struct{} 12 13 // Apply applies the rule to given file. 14 func (r *ConstantLogicalExprRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure { 15 var failures []lint.Failure 16 17 onFailure := func(failure lint.Failure) { 18 failures = append(failures, failure) 19 } 20 21 astFile := file.AST 22 w := &lintConstantLogicalExpr{astFile, onFailure} 23 ast.Walk(w, astFile) 24 return failures 25 } 26 27 // Name returns the rule name. 28 func (r *ConstantLogicalExprRule) Name() string { 29 return "constant-logical-expr" 30 } 31 32 type lintConstantLogicalExpr struct { 33 file *ast.File 34 onFailure func(lint.Failure) 35 } 36 37 func (w *lintConstantLogicalExpr) Visit(node ast.Node) ast.Visitor { 38 switch n := node.(type) { 39 case *ast.BinaryExpr: 40 if !w.isOperatorWithLogicalResult(n.Op) { 41 return w 42 } 43 44 if gofmt(n.X) != gofmt(n.Y) { // check if subexpressions are the same 45 return w 46 } 47 48 // Handles cases like: a <= a, a == a, a >= a 49 if w.isEqualityOperator(n.Op) { 50 w.newFailure(n, "expression always evaluates to true") 51 return w 52 } 53 54 // Handles cases like: a < a, a > a, a != a 55 if w.isInequalityOperator(n.Op) { 56 w.newFailure(n, "expression always evaluates to false") 57 return w 58 } 59 60 w.newFailure(n, "left and right hand-side sub-expressions are the same") 61 } 62 63 return w 64 } 65 66 func (w *lintConstantLogicalExpr) isOperatorWithLogicalResult(t token.Token) bool { 67 switch t { 68 case token.LAND, token.LOR, token.EQL, token.LSS, token.GTR, token.NEQ, token.LEQ, token.GEQ: 69 return true 70 } 71 72 return false 73 } 74 75 func (w *lintConstantLogicalExpr) isEqualityOperator(t token.Token) bool { 76 switch t { 77 case token.EQL, token.LEQ, token.GEQ: 78 return true 79 } 80 81 return false 82 } 83 84 func (w *lintConstantLogicalExpr) isInequalityOperator(t token.Token) bool { 85 switch t { 86 case token.LSS, token.GTR, token.NEQ: 87 return true 88 } 89 90 return false 91 } 92 93 func (w lintConstantLogicalExpr) newFailure(node ast.Node, msg string) { 94 w.onFailure(lint.Failure{ 95 Confidence: 1, 96 Node: node, 97 Category: "logic", 98 Failure: msg, 99 }) 100 }