forked from rubocop/rubocop
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
7 changed files
with
257 additions
and
11 deletions.
There are no files selected for viewing
1 change: 1 addition & 0 deletions
1
changelog/new_add_new_lint_numeric_operation_with_constant_result_cop.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
* [#11191](https://github.com/rubocop/rubocop/issues/11191): Add new `Lint/BinaryOperatorWithIdenticalOperands` cop. ([@zopolis4][]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
106 changes: 106 additions & 0 deletions
106
lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
# frozen_string_literal: true | ||
|
||
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. | ||
# 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. | ||
# Similar numeric operations that are leftover from debugging or mistakes | ||
# are handled by Lint/UselessNumericOperation. | ||
# | ||
# @example | ||
# | ||
# # bad | ||
# x - x | ||
# x * 0 | ||
# x % 1 | ||
# x % x | ||
# | ||
# # good | ||
# 0 | ||
# | ||
# # bad | ||
# x -= x | ||
# x *= 0 | ||
# x %= 1 | ||
# x %= x | ||
# | ||
# # good | ||
# x = 0 | ||
# | ||
# # bad | ||
# x / x | ||
# x ** 0 | ||
# | ||
# # good | ||
# 1 | ||
# | ||
# # bad | ||
# x /= x | ||
# x **= 0 | ||
# | ||
# # good | ||
# x = 1 | ||
# | ||
class NumericOperationWithConstantResult < Base | ||
extend AutoCorrector | ||
MSG = 'Numeric operation with a constant result detected.' | ||
RESTRICT_ON_SEND = %i[- * / % **].freeze | ||
|
||
# @!method operation_with_constant_result?(node) | ||
def_node_matcher :operation_with_constant_result?, | ||
'(send (send nil? $_) $_ ({int | send nil?} $_))' | ||
|
||
# @!method abbreviated_assignment_with_constant_result?(node) | ||
def_node_matcher :abbreviated_assignment_with_constant_result?, | ||
'(op-asgn (lvasgn $_) $_ ({int | lvar} $_))' | ||
|
||
def on_send(node) | ||
return unless operation_with_constant_result?(node) | ||
|
||
variable, operation, number = operation_with_constant_result?(node) | ||
result = constant_result?(variable, operation, number) | ||
return unless result | ||
|
||
add_offense(node) do |corrector| | ||
corrector.replace(node, result.to_s) | ||
end | ||
end | ||
|
||
def on_op_asgn(node) | ||
return unless abbreviated_assignment_with_constant_result?(node) | ||
|
||
variable, operation, number = abbreviated_assignment_with_constant_result?(node) | ||
result = constant_result?(variable, operation, number) | ||
return unless result | ||
|
||
add_offense(node) do |corrector| | ||
corrector.replace(node, "#{variable} = #{result}") | ||
end | ||
end | ||
|
||
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 | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
135 changes: 135 additions & 0 deletions
135
spec/rubocop/cop/lint/numeric_operation_with_constant_result_spec.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
# 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 | ||
^^^^^ Numeric operation with a constant result detected. | ||
RUBY | ||
|
||
expect_correction(<<~RUBY) | ||
0 | ||
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 | ||
^^^^^ Numeric operation with a constant result detected. | ||
RUBY | ||
|
||
expect_correction(<<~RUBY) | ||
1 | ||
RUBY | ||
end | ||
|
||
it 'registers an offense when a variable is raised to the power of 0' do | ||
expect_offense(<<~RUBY) | ||
x ** 0 | ||
^^^^^^ Numeric operation with a constant result detected. | ||
RUBY | ||
|
||
expect_correction(<<~RUBY) | ||
1 | ||
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 | ||
^^^^^^ 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 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 | ||
^^^^^^ Numeric operation with a constant result detected. | ||
RUBY | ||
|
||
expect_correction(<<~RUBY) | ||
x = 1 | ||
RUBY | ||
end | ||
|
||
it 'egisters an offense when a variable is raised to the power of 0 via abbreviated assignment' do | ||
expect_offense(<<~RUBY) | ||
x **= 0 | ||
^^^^^^^ Numeric operation with a constant result detected. | ||
RUBY | ||
|
||
expect_correction(<<~RUBY) | ||
x = 1 | ||
RUBY | ||
end | ||
end |