class RuboCop::Cop::Style::IfWithBooleanLiteralBranches
num.nonzero? ? true : false
# good
@example AllowedMethods: [‘nonzero?’]
foo == bar
# good
foo == bar ? true : false
# bad
end
false
else
true
if foo == bar
# bad
@example
will return boolean value. Those methods can be allowed with ‘AllowedMethods` config.
However, auto-correction is unsafe because there is no guarantee that all predicate methods
The conditions to be checked are comparison methods, predicate methods, and double negative.
It checks only conditions to return boolean value (`true` or `false`) for safe detection.
This cop checks for redundant `if` with boolean literal branches.
def assume_boolean_value?(condition)
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
def message(node, keyword)
def message(node, keyword) message_template = node.elsif? ? MSG_FOR_ELSIF : MSG format(message_template, keyword: keyword) end
def offense_range_with_keyword(node, condition)
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
def on_if(node)
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
def opposite_condition?(node)
def opposite_condition?(node) !node.unless? && node.if_branch.false_type? || node.unless? && node.if_branch.true_type? end
def replacement_condition(node, condition)
def replacement_condition(node, condition) bang = '!' if opposite_condition?(node) if bang && require_parentheses?(condition) "#{bang}(#{condition.source})" else "#{bang}#{condition.source}" end end
def require_parentheses?(condition)
def require_parentheses?(condition) condition.and_type? || condition.or_type? || condition.send_type? && condition.comparison_method? end
def return_boolean_value?(condition)
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