Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new Style/RedundantAssignment cop #8235

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -6,6 +6,7 @@

* [#7868](https://github.com/rubocop-hq/rubocop/pull/7868): `Cop::Base` is the new recommended base class for cops. ([@marcandre][])
* [#7458](https://github.com/rubocop-hq/rubocop/issues/7458): Add new `AsciiConstants` option for `Naming/AsciiIdentifiers`. ([@fatkodima][])
* [#7373](https://github.com/rubocop-hq/rubocop/issues/7373): Add new `Style/RedundantAssignment` cop. ([@fatkodima][])
* [#8213](https://github.com/rubocop-hq/rubocop/pull/8213): Permit to specify TargetRubyVersion 2.8 (experimental). ([@koic][])
* [#8164](https://github.com/rubocop-hq/rubocop/pull/8164): Support auto-correction for `Lint/InterpolationCheck`. ([@koic][])
* [#8223](https://github.com/rubocop-hq/rubocop/pull/8223): Support auto-correction for `Style/IfUnlessModifierOfIfUnless`. ([@koic][])
Expand Down
5 changes: 5 additions & 0 deletions config/default.yml
Expand Up @@ -3594,6 +3594,11 @@ Style/RandomWithOffset:
Enabled: true
VersionAdded: '0.52'

Style/RedundantAssignment:
Description: 'Checks for redundant assignment before returning.'
Enabled: 'pending'
VersionAdded: '0.87'

Style/RedundantBegin:
Description: "Don't use begin blocks when they are not needed."
StyleGuide: '#begin-implicit'
Expand Down
1 change: 1 addition & 0 deletions docs/modules/ROOT/pages/cops.adoc
Expand Up @@ -430,6 +430,7 @@ In the following section you find all available cops:
* xref:cops_style.adoc#styleproc[Style/Proc]
* xref:cops_style.adoc#styleraiseargs[Style/RaiseArgs]
* xref:cops_style.adoc#stylerandomwithoffset[Style/RandomWithOffset]
* xref:cops_style.adoc#styleredundantassignment[Style/RedundantAssignment]
* xref:cops_style.adoc#styleredundantbegin[Style/RedundantBegin]
* xref:cops_style.adoc#styleredundantcapitalw[Style/RedundantCapitalW]
* xref:cops_style.adoc#styleredundantcondition[Style/RedundantCondition]
Expand Down
50 changes: 50 additions & 0 deletions docs/modules/ROOT/pages/cops_style.adoc
Expand Up @@ -6812,6 +6812,56 @@ rand(1...7)

* https://rubystyle.guide#random-numbers

== Style/RedundantAssignment

|===
| Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged

| Pending
| Yes
| Yes
| 0.87
| -
|===

This cop checks for redundant assignment before returning.

=== Examples

[source,ruby]
----
# 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
----

== Style/RedundantBegin

|===
Expand Down
1 change: 1 addition & 0 deletions lib/rubocop.rb
Expand Up @@ -429,6 +429,7 @@
require_relative 'rubocop/cop/style/line_end_concatenation'
require_relative 'rubocop/cop/style/method_call_without_args_parentheses'
require_relative 'rubocop/cop/style/method_call_with_args_parentheses'
require_relative 'rubocop/cop/style/redundant_assignment'
require_relative 'rubocop/cop/style/redundant_fetch_block'
require_relative 'rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses'
require_relative 'rubocop/cop/style/method_call_with_args_parentheses/require_parentheses'
Expand Down
117 changes: 117 additions & 0 deletions lib/rubocop/cop/style/redundant_assignment.rb
@@ -0,0 +1,117 @@
# frozen_string_literal: true

module RuboCop
module Cop
module Style
# This cop 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 < Cop
MSG = 'Redundant assignment before returning detected.'

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

def autocorrect(node)
lambda do |corrector|
expression = node.children[1]
corrector.replace(node, expression.source)
corrector.remove(right_sibling_of(node))
end
end

private

def check_branch(node)
return unless node

case node.type
when :case then check_case_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

def check_case_node(node)
node.when_branches.each { |when_node| check_branch(when_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 do |child_node|
check_branch(child_node)
end
end

def check_ensure_node(node)
check_branch(node.body)
end

def check_begin_node(node)
if (assignment = redundant_assignment?(node))
add_offense(assignment)
else
last_expr = node.children.last
check_branch(last_expr)
end
end

def right_sibling_of(node)
siblings_of(node)[node.sibling_index + 1]
end

def siblings_of(node)
node.parent.children
end
end
end
end
end
4 changes: 1 addition & 3 deletions lib/rubocop/name_similarity.rb
Expand Up @@ -22,9 +22,7 @@ def find_similar_names(target_name, names)
names.delete(target_name)

spell_checker = DidYouMean::SpellChecker.new(dictionary: names)
similar_names = spell_checker.correct(target_name)

similar_names
spell_checker.correct(target_name)
end
end
end