class RuboCop::Cop::Style::NegatedIfElseCondition

Checks for uses of ‘if-else` and ternary operators with a negated condition which can be simplified by inverting condition and swapping branches.

@example

# bad
if !x
  do_something
else
  do_something_else
end

# good
if x
  do_something_else
else
  do_something
end

# bad
!x ? do_something : do_something_else

# good
x ? do_something_else : do_something

Constants

MSG
NEGATED_EQUALITY_METHODS

Public Class Methods

autocorrect_incompatible_with() click to toggle source
# File lib/rubocop/cop/style/negated_if_else_condition.rb, line 41
def self.autocorrect_incompatible_with
  [Style::InverseMethods, Style::Not]
end

Public Instance Methods

on_if(node) click to toggle source
# File lib/rubocop/cop/style/negated_if_else_condition.rb, line 49
def on_if(node)
  return unless if_else?(node)

  condition = unwrap_begin_nodes(node.condition)

  return if double_negation?(condition) || !negated_condition?(condition)

  type = node.ternary? ? 'ternary' : 'if-else'
  add_offense(node, message: format(MSG, type: type)) do |corrector|
    unless corrected_ancestor?(node)
      correct_negated_condition(corrector, condition)
      swap_branches(corrector, node)

      @corrected_nodes ||= Set.new.compare_by_identity
      @corrected_nodes.add(node)
    end
  end
end
on_new_investigation() click to toggle source
# File lib/rubocop/cop/style/negated_if_else_condition.rb, line 45
def on_new_investigation
  @corrected_nodes = nil
end

Private Instance Methods

correct_negated_condition(corrector, node) click to toggle source
# File lib/rubocop/cop/style/negated_if_else_condition.rb, line 89
def correct_negated_condition(corrector, node)
  receiver, method_name, rhs = *node
  replacement =
    if node.negation_method?
      receiver.source
    else
      inverted_method = method_name.to_s.sub('!', '=')
      "#{receiver.source} #{inverted_method} #{rhs.source}"
    end

  corrector.replace(node, replacement)
end
corrected_ancestor?(node) click to toggle source
# File lib/rubocop/cop/style/negated_if_else_condition.rb, line 85
def corrected_ancestor?(node)
  node.each_ancestor(:if).any? { |ancestor| @corrected_nodes&.include?(ancestor) }
end
else_range(node) click to toggle source

Collect the entire else branch, including whitespace and comments

# File lib/rubocop/cop/style/negated_if_else_condition.rb, line 124
def else_range(node)
  if node.ternary?
    node.else_branch
  else
    range_between(node.loc.else.end_pos, node.loc.end.begin_pos)
  end
end
if_else?(node) click to toggle source
# File lib/rubocop/cop/style/negated_if_else_condition.rb, line 70
def if_else?(node)
  else_branch = node.else_branch
  !node.elsif? && else_branch && (!else_branch.if_type? || !else_branch.elsif?)
end
if_range(node) click to toggle source

Collect the entire if branch, including whitespace and comments

# File lib/rubocop/cop/style/negated_if_else_condition.rb, line 115
def if_range(node)
  if node.ternary?
    node.if_branch
  else
    range_between(node.condition.loc.expression.end_pos, node.loc.else.begin_pos)
  end
end
negated_condition?(node) click to toggle source
# File lib/rubocop/cop/style/negated_if_else_condition.rb, line 80
def negated_condition?(node)
  node.send_type? &&
    (node.negation_method? || NEGATED_EQUALITY_METHODS.include?(node.method_name))
end
swap_branches(corrector, node) click to toggle source
# File lib/rubocop/cop/style/negated_if_else_condition.rb, line 102
def swap_branches(corrector, node)
  if node.if_branch.nil?
    corrector.remove(range_by_whole_lines(node.loc.else, include_final_newline: true))
  else
    if_range = if_range(node)
    else_range = else_range(node)

    corrector.replace(if_range, else_range.source)
    corrector.replace(else_range, if_range.source)
  end
end
unwrap_begin_nodes(node) click to toggle source
# File lib/rubocop/cop/style/negated_if_else_condition.rb, line 75
def unwrap_begin_nodes(node)
  node = node.children.first while node.begin_type? || node.kwbegin_type?
  node
end