github.com/Johnny2210/revive@v1.0.8-0.20210625134200-febf37ccd0f5/rule/constant-logical-expr.go (about)

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