lib/rubocop/cop/style/redundant_assignment.rb
# frozen_string_literal: true
module RuboCop
module Cop
module Style
# Checks for redundant assignment before returning.
#
# @example
# # bad
# def test
# x = foo
# x
# end
#
# # bad
# def test
# if x
# z = foo
# z
# elsif y
# z = bar
# z
# end
# end
#
# # good
# def test
# foo
# end
#
# # good
# def test
# if x
# foo
# elsif y
# bar
# end
# end
#
class RedundantAssignment < Base
extend AutoCorrector
MSG = 'Redundant assignment before returning detected.'
# @!method redundant_assignment?(node)
def_node_matcher :redundant_assignment?, <<~PATTERN
(... $(lvasgn _name _expression) (lvar _name))
PATTERN
def on_def(node)
check_branch(node.body)
end
alias on_defs on_def
private
# rubocop:disable Metrics/CyclomaticComplexity
def check_branch(node)
return unless node
case node.type
when :case then check_case_node(node)
when :case_match then check_case_match_node(node)
when :if then check_if_node(node)
when :rescue, :resbody
check_rescue_node(node)
when :ensure then check_ensure_node(node)
when :begin, :kwbegin
check_begin_node(node)
end
end
# rubocop:enable Metrics/CyclomaticComplexity
def check_case_node(node)
node.when_branches.each { |when_node| check_branch(when_node.body) }
check_branch(node.else_branch)
end
def check_case_match_node(node)
node.in_pattern_branches.each { |in_pattern_node| check_branch(in_pattern_node.body) }
check_branch(node.else_branch)
end
def check_if_node(node)
return if node.modifier_form? || node.ternary?
check_branch(node.if_branch)
check_branch(node.else_branch)
end
def check_rescue_node(node)
node.child_nodes.each { |child_node| check_branch(child_node) }
end
def check_ensure_node(node)
check_branch(node.body)
end
def check_begin_node(node)
if (assignment = redundant_assignment?(node))
add_offense(assignment) do |corrector|
expression = assignment.children[1]
corrector.replace(assignment, expression.source)
corrector.remove(assignment.right_sibling)
end
else
last_expr = node.children.last
check_branch(last_expr)
end
end
end
end
end
end