You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

constant-logical-expr.go 1.9KB

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