class RuboCop::Cop::Style::UnlessLogicalOperators

return unless a?
return unless a
# good
return unless a and b
return unless a or b
return unless a && b
return unless a || b
# bad
@example EnforcedStyle: forbid_logical_operators
return unless a?
return unless a or b or c
return unless a and b and c
return unless a || b || c
return unless a && b && c
# good
return unless a || b and c
return unless a && b or c
return unless a || b or c
return unless a && b and c
return unless a && b || c
return unless a || b && c
# bad
@example EnforcedStyle: forbid_mixed_logical_operators (default)
there is only one condition in the expression.
This makes it even more easy to read the ‘unless` condition as
`forbid_logical_operators` style forbids any use of logical operator.
in order for the expression to be truthy or falsey.
because either all conditions need to be met or any condition need to be met
of logical operators. This makes the `unless` condition easier to read
`forbid_mixed_logical_operators` style forbids the use of more than one type
- `forbid_logical_operators`
- `forbid_mixed_logical_operators` (default)
This cop supports two styles:
to read and understand.
It discourages such code, as the condition becomes more difficult
Checks for the use of logical operators in an `unless` condition.

def mixed_logical_operator?(node)

def mixed_logical_operator?(node)
  or_with_and?(node) ||
    and_with_or?(node) ||
    mixed_precedence_and?(node) ||
    mixed_precedence_or?(node)
end

def mixed_precedence_and?(node)

def mixed_precedence_and?(node)
  and_sources = node.condition.each_descendant(:and).map(&:operator)
  and_sources << node.condition.operator if node.condition.and_type?
  !(and_sources.all?('&&') || and_sources.all?('and'))
end

def mixed_precedence_or?(node)

def mixed_precedence_or?(node)
  or_sources = node.condition.each_descendant(:or).map(&:operator)
  or_sources << node.condition.operator if node.condition.or_type?
  !(or_sources.all?('||') || or_sources.all?('or'))
end

def on_if(node)

def on_if(node)
  return unless node.unless?
  if style == :forbid_mixed_logical_operators && mixed_logical_operator?(node)
    add_offense(node, message: FORBID_MIXED_LOGICAL_OPERATORS)
  elsif style == :forbid_logical_operators && logical_operator?(node)
    add_offense(node, message: FORBID_LOGICAL_OPERATORS)
  end
end