class RuboCop::Cop::Style::IfWithBooleanLiteralBranches

Checks for redundant `if` with boolean literal branches. It checks only conditions to return boolean value (`true` or `false`) for safe detection. The conditions to be checked are comparison methods, predicate methods, and double negative. `nonzero?` method is allowed by default. These are customizable with `AllowedMethods` option.

@safety

Autocorrection is unsafe because there is no guarantee that all predicate methods
will return a boolean value. Those methods can be allowed with `AllowedMethods` config.

@example

# bad
if foo == bar
  true
else
  false
end

# bad
foo == bar ? true : false

# good
foo == bar

@example

# bad
if foo.do_something?
  true
else
  false
end

# good (but potentially an unsafe correction)
foo.do_something?

@example AllowedMethods: ['nonzero?'] (default)

# good
num.nonzero? ? true : false

Constants

MSG
MSG_FOR_ELSIF

Public Instance Methods

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

  condition = node.condition
  range, keyword = offense_range_with_keyword(node, condition)

  add_offense(range, message: message(node, keyword)) do |corrector|
    replacement = replacement_condition(node, condition)

    if node.elsif?
      corrector.insert_before(node, "else\n")
      corrector.replace(node, "#{indent(node.if_branch)}#{replacement}")
    else
      corrector.replace(node, replacement)
    end
  end
end

Private Instance Methods

assume_boolean_value?(condition) click to toggle source
# File lib/rubocop/cop/style/if_with_boolean_literal_branches.rb, line 109
def assume_boolean_value?(condition)
  return false unless condition.send_type?
  return false if allowed_method?(condition.method_name)

  condition.comparison_method? || condition.predicate_method? || double_negative?(condition)
end
message(node, keyword) click to toggle source
# File lib/rubocop/cop/style/if_with_boolean_literal_branches.rb, line 91
def message(node, keyword)
  message_template = node.elsif? ? MSG_FOR_ELSIF : MSG

  format(message_template, keyword: keyword)
end
offense_range_with_keyword(node, condition) click to toggle source
# File lib/rubocop/cop/style/if_with_boolean_literal_branches.rb, line 79
def offense_range_with_keyword(node, condition)
  if node.ternary?
    range = condition.source_range.end.join(node.source_range.end)

    [range, 'ternary operator']
  else
    keyword = node.loc.keyword

    [keyword, "`#{keyword.source}`"]
  end
end
opposite_condition?(node) click to toggle source
# File lib/rubocop/cop/style/if_with_boolean_literal_branches.rb, line 126
def opposite_condition?(node)
  (!node.unless? && node.if_branch.false_type?) ||
    (node.unless? && node.if_branch.true_type?)
end
replacement_condition(node, condition) click to toggle source
# File lib/rubocop/cop/style/if_with_boolean_literal_branches.rb, line 116
def replacement_condition(node, condition)
  bang = '!' if opposite_condition?(node)

  if bang && require_parentheses?(condition)
    "#{bang}(#{condition.source})"
  else
    "#{bang}#{condition.source}"
  end
end
require_parentheses?(condition) click to toggle source
# File lib/rubocop/cop/style/if_with_boolean_literal_branches.rb, line 131
def require_parentheses?(condition)
  condition.and_type? || condition.or_type? ||
    (condition.send_type? && condition.comparison_method?)
end
return_boolean_value?(condition) click to toggle source
# File lib/rubocop/cop/style/if_with_boolean_literal_branches.rb, line 97
def return_boolean_value?(condition)
  if condition.begin_type?
    return_boolean_value?(condition.children.first)
  elsif condition.or_type?
    return_boolean_value?(condition.lhs) && return_boolean_value?(condition.rhs)
  elsif condition.and_type?
    return_boolean_value?(condition.rhs)
  else
    assume_boolean_value?(condition)
  end
end