Skip to content

Commit

Permalink
Add partial autocorrect support for Lint/LiteralAsCondition
Browse files Browse the repository at this point in the history
  • Loading branch information
Zopolis4 committed Oct 16, 2024
1 parent 6d54052 commit 21cc43e
Show file tree
Hide file tree
Showing 5 changed files with 210 additions and 10 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* [#13117](https://github.com/rubocop/rubocop/issues/13117): Add partial autocorrect support to `Lint/LiteralAsCondition` cop to check for redundant conditions. ([@zopolis4][])
1 change: 1 addition & 0 deletions config/default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2022,6 +2022,7 @@ Lint/LambdaWithoutLiteralBlock:
Lint/LiteralAsCondition:
Description: 'Checks of literals used in conditions.'
Enabled: true
AutoCorrect: contextual
VersionAdded: '0.51'

Lint/LiteralAssignmentInCondition:
Expand Down
100 changes: 93 additions & 7 deletions lib/rubocop/cop/lint/literal_as_condition.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,26 +34,110 @@ module Lint
# end
class LiteralAsCondition < Base
include RangeHelp
extend AutoCorrector

MSG = 'Literal `%<literal>s` appeared as a condition.'

# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
def on_and(node)
if node.lhs.truthy_literal? && node.rhs.truthy_literal?
add_offense(node) do |corrector|
corrector.replace(node, 'true')
end
return
end

if node.lhs.truthy_literal?
add_offense(node.lhs) do |corrector|
corrector.replace(node, node.rhs.source)
end
end

return unless node.rhs.truthy_literal?

add_offense(node.rhs) do |corrector|
corrector.replace(node, node.lhs.source)
end
end
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength

def on_if(node)
check_for_literal(node)
cond = condition(node)

if cond.truthy_literal? || (node.unless? && cond.falsey_literal?)
add_offense(cond) do |corrector|
corrector.replace(node, node.if_branch.source)
end
end

return unless cond.falsey_literal? || (node.unless? && cond.truthy_literal?)

add_offense(cond)
end

def on_while(node)
return if condition(node).true_type?
return if node.condition.source == 'true'

check_for_literal(node)
if node.condition.truthy_literal?
add_offense(node.condition) do |corrector|
corrector.replace(node.condition, 'true')
end
end

return unless node.condition.falsey_literal?

add_offense(node.condition)
end
alias on_while_post on_while

# rubocop:disable Metrics/AbcSize
def on_while_post(node)
return if node.condition.source == 'true'

if node.condition.truthy_literal?
add_offense(node.condition) do |corrector|
corrector.replace(node, node.body.source.sub!('begin', 'while true'))
end
end

return unless node.condition.falsey_literal?

add_offense(node.condition) do |corrector|
corrector.replace(node, node.body.child_nodes.map(&:source).join("\n"))
end
end
# rubocop:enable Metrics/AbcSize

def on_until(node)
return if condition(node).false_type?
return if node.condition.source == 'false'

check_for_literal(node)
if node.condition.falsey_literal?
add_offense(node.condition) do |corrector|
corrector.replace(node.condition, 'false')
end
end

return unless node.condition.truthy_literal?

add_offense(node.condition)
end
alias on_until_post on_until

# rubocop:disable Metrics/AbcSize
def on_until_post(node)
return if node.condition.source == 'false'

if node.condition.falsey_literal?
add_offense(node.condition) do |corrector|
corrector.replace(node, node.body.source.sub!('begin', 'until false'))
end
end

return unless node.condition.truthy_literal?

add_offense(node.condition) do |corrector|
corrector.replace(node, node.body.child_nodes.map(&:source).join("\n"))
end
end
# rubocop:enable Metrics/AbcSize

def on_case(case_node)
if case_node.condition
Expand Down Expand Up @@ -129,6 +213,8 @@ def check_node(node)

def handle_node(node)
if node.literal?
return if node.parent.and_type?

add_offense(node)
elsif %i[send and or begin].include?(node.type)
check_node(node)
Expand Down
4 changes: 2 additions & 2 deletions spec/rubocop/cli/options_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1060,9 +1060,9 @@ def on_send(node)
expect($stdout.string)
.to eq(<<~RESULT)
== example.rb ==
W: 1: 4: Lint/LiteralAsCondition: Literal 0 appeared as a condition.
W: 1: 4: [Correctable] Lint/LiteralAsCondition: Literal 0 appeared as a condition.
1 file inspected, 1 offense detected
1 file inspected, 1 offense detected, 1 offense autocorrectable
RESULT
end
end
Expand Down
114 changes: 113 additions & 1 deletion spec/rubocop/cop/lint/literal_as_condition_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
top
end
RUBY

expect_correction(<<~RUBY)
top
RUBY
end

it "registers an offense for literal #{lit} in while" do
Expand All @@ -18,15 +22,27 @@
top
end
RUBY

expect_correction(<<~RUBY)
while true
top
end
RUBY
end

it "registers an offense for literal #{lit} in post-loop while" do
expect_offense(<<~RUBY, lit: lit)
begin
top
end while(%{lit})
end while %{lit}
^{lit} Literal `#{lit}` appeared as a condition.
RUBY

expect_correction(<<~RUBY)
while true
top
end
RUBY
end

it "registers an offense for literal #{lit} in until" do
Expand All @@ -36,6 +52,8 @@
top
end
RUBY

expect_no_corrections
end

it "registers an offense for literal #{lit} in post-loop until" do
Expand All @@ -45,6 +63,10 @@
end until %{lit}
^{lit} Literal `#{lit}` appeared as a condition.
RUBY

expect_correction(<<~RUBY)
top
RUBY
end

it "registers an offense for literal #{lit} in case" do
Expand All @@ -54,6 +76,8 @@
when x then top
end
RUBY

expect_no_corrections
end

it "registers an offense for literal #{lit} in a when " \
Expand All @@ -64,6 +88,8 @@
^{lit} Literal `#{lit}` appeared as a condition.
end
RUBY

expect_no_corrections
end

it "accepts literal #{lit} in a when of a case with something after case keyword" do
Expand All @@ -90,6 +116,8 @@
in CONST then top
end
RUBY

expect_no_corrections
end

it "accepts literal #{lit} in a when of a case match" do
Expand All @@ -108,6 +136,12 @@
top
end
RUBY

expect_correction(<<~RUBY)
if x
top
end
RUBY
end

it "registers an offense for literal #{lit} in complex cond" do
Expand All @@ -117,6 +151,12 @@
top
end
RUBY

expect_correction(<<~RUBY)
if x && !(a) && y && z
top
end
RUBY
end

it "registers an offense for literal #{lit} in !" do
Expand All @@ -126,6 +166,8 @@
top
end
RUBY

expect_no_corrections
end

it "registers an offense for literal #{lit} in complex !" do
Expand All @@ -135,6 +177,12 @@
top
end
RUBY

expect_correction(<<~RUBY)
if !(x && (y))
top
end
RUBY
end

it "accepts literal #{lit} if it's not an and/or operand" do
Expand All @@ -158,13 +206,17 @@
!%{lit}
^{lit} Literal `#{lit}` appeared as a condition.
RUBY

expect_no_corrections
end

it "registers an offense for `not #{lit}`" do
expect_offense(<<~RUBY, lit: lit)
not(%{lit})
^{lit} Literal `#{lit}` appeared as a condition.
RUBY

expect_no_corrections
end
end

Expand All @@ -191,6 +243,8 @@
when [1, 2, 5] then top
end
RUBY

expect_no_corrections
end

it 'accepts dstr literal in case' do
Expand Down Expand Up @@ -225,6 +279,8 @@
in [1, 2, 5] then top
end
RUBY

expect_no_corrections
end

it 'accepts an offense for case match with a match var' do
Expand Down Expand Up @@ -275,4 +331,60 @@
end until false
RUBY
end

it 'registers an offense for literal nil in unless' do
expect_offense(<<~RUBY)
unless nil
^^^ Literal `nil` appeared as a condition.
top
end
RUBY

expect_correction(<<~RUBY)
top
RUBY
end

it 'registers an offense for literal nil in post-loop while' do
expect_offense(<<~RUBY)
begin
top
end while nil
^^^ Literal `nil` appeared as a condition.
RUBY

expect_correction(<<~RUBY)
top
RUBY
end

it 'registers an offense for literal nil in complex post-loop while' do
expect_offense(<<~RUBY)
begin
top
foo
end while nil
^^^ Literal `nil` appeared as a condition.
RUBY

expect_correction(<<~RUBY)
top
foo
RUBY
end

it 'registers an offense for literal nil in until' do
expect_offense(<<~RUBY)
until nil
^^^ Literal `nil` appeared as a condition.
top
end
RUBY

expect_correction(<<~RUBY)
until false
top
end
RUBY
end
end

0 comments on commit 21cc43e

Please sign in to comment.