Skip to content

Commit

Permalink
[Fix rubocop#13557] Fix false positives for `Lint/NumericOperationWit…
Browse files Browse the repository at this point in the history
…hConstantResult`

Subtracting could happen with an array
Modulo is also the string format operator
  • Loading branch information
Earlopain committed Dec 13, 2024
1 parent 4618790 commit da96c63
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 80 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* [#13557](https://github.com/rubocop/rubocop/issues/13557): Fix false positives for `Lint/NumericOperationWithConstantResult`. ([@earlopain][])
20 changes: 6 additions & 14 deletions lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,27 @@ module RuboCop
module Cop
module Lint
# Certain numeric operations have a constant result, usually 0 or 1.
# Subtracting a number from itself or multiplying it by 0 will always return 0.
# Additionally, a variable modulo 0 or itself will always return 0.
# Multiplying a number by 0 will always return 0.
# Dividing a number by itself or raising it to the power of 0 will always return 1.
# As such, they can be replaced with that result.
# These are probably leftover from debugging, or are mistakes.
# Other numeric operations that are similarly leftover from debugging or mistakes
# are handled by Lint/UselessNumericOperation.
#
# NOTE: This cop doesn't detect offenses for the `-` and `%` operator because it
# can't determine the type of `x`. If `x` is an Array or String, it doesn't perform
# a numeric operation.
#
# @example
#
# # bad
# x - x
# x * 0
# x % 1
# x % x
#
# # good
# 0
#
# # bad
# x -= x
# x *= 0
# x %= 1
# x %= x
#
# # good
# x = 0
Expand All @@ -49,7 +46,7 @@ module Lint
class NumericOperationWithConstantResult < Base
extend AutoCorrector
MSG = 'Numeric operation with a constant result detected.'
RESTRICT_ON_SEND = %i[- * / % **].freeze
RESTRICT_ON_SEND = %i[* / **].freeze

# @!method operation_with_constant_result?(node)
def_node_matcher :operation_with_constant_result?,
Expand Down Expand Up @@ -85,21 +82,16 @@ def on_op_asgn(node)

private

# rubocop :disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
def constant_result?(variable, operation, number)
if number.to_s == '0'
return 0 if operation == :*
return 1 if operation == :**
elsif number.to_s == '1'
return 0 if operation == :%
elsif number == variable
return 0 if %i[- %].include?(operation)
return 1 if operation == :/
end
# If we weren't able to find any matches, return false so we can bail out.
false
end
# rubocop :enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
end
end
end
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,6 @@
# frozen_string_literal: true

RSpec.describe RuboCop::Cop::Lint::NumericOperationWithConstantResult, :config do
it 'registers an offense when a variable is subtracted from itself' do
expect_offense(<<~RUBY)
x - x
^^^^^ Numeric operation with a constant result detected.
RUBY

expect_correction(<<~RUBY)
0
RUBY
end

it 'registers an offense when a variable is multiplied by 0' do
expect_offense(<<~RUBY)
x * 0
Expand All @@ -23,28 +12,6 @@
RUBY
end

it 'registers an offense when the modulo of variable and 1 is taken' do
expect_offense(<<~RUBY)
x % 1
^^^^^ Numeric operation with a constant result detected.
RUBY

expect_correction(<<~RUBY)
0
RUBY
end

it 'registers an offense when the modulo of variable and itself is taken' do
expect_offense(<<~RUBY)
x % x
^^^^^ Numeric operation with a constant result detected.
RUBY

expect_correction(<<~RUBY)
0
RUBY
end

it 'registers an offense when a variable is divided by itself' do
expect_offense(<<~RUBY)
x / x
Expand All @@ -67,17 +34,6 @@
RUBY
end

it 'registers an offense when a variable is subtracted from itself via abbreviated assignment' do
expect_offense(<<~RUBY)
x -= x
^^^^^^ Numeric operation with a constant result detected.
RUBY

expect_correction(<<~RUBY)
x = 0
RUBY
end

it 'registers an offense when a variable is multiplied by 0 via abbreviated assignment' do
expect_offense(<<~RUBY)
x *= 0
Expand All @@ -89,28 +45,6 @@
RUBY
end

it 'registers an offense when the modulo of variable and 1 is taken via abbreviated assignment' do
expect_offense(<<~RUBY)
x %= 1
^^^^^^ Numeric operation with a constant result detected.
RUBY

expect_correction(<<~RUBY)
x = 0
RUBY
end

it 'registers an offense when the modulo of variable and itself is taken via abbreviated assignment' do
expect_offense(<<~RUBY)
x %= x
^^^^^^ Numeric operation with a constant result detected.
RUBY

expect_correction(<<~RUBY)
x = 0
RUBY
end

it 'registers an offense when a variable is divided by itself via abbreviated assignment' do
expect_offense(<<~RUBY)
x /= x
Expand All @@ -132,4 +66,17 @@
x = 1
RUBY
end

[
'x - x',
'x -= x',
'x % x',
'x %= x',
'x % 1',
'x %= 1'
].each do |expression|
it "registers no offense for `#{expression}`" do
expect_no_offenses(expression)
end
end
end

0 comments on commit da96c63

Please sign in to comment.