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
255 additions
and
10 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
104 changes: 104 additions & 0 deletions
104
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,104 @@ | ||
# 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. | ||
# Addiionally, 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. | ||
# | ||
# @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 = 'Do not apply numeric operations with constant results to variables.' | ||
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 | ||
^^^^^ Do not apply numeric operations with constant results to variables. | ||
RUBY | ||
|
||
expect_correction(<<~RUBY) | ||
0 | ||
RUBY | ||
end | ||
|
||
it 'registers an offense when a variable is multiplied by 0' do | ||
expect_offense(<<~RUBY) | ||
x * 0 | ||
^^^^^ Do not apply numeric operations with constant results to variables. | ||
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 | ||
^^^^^ Do not apply numeric operations with constant results to variables. | ||
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 | ||
^^^^^ Do not apply numeric operations with constant results to variables. | ||
RUBY | ||
|
||
expect_correction(<<~RUBY) | ||
0 | ||
RUBY | ||
end | ||
|
||
it 'registers an offense when a variable is divided by itself' do | ||
expect_offense(<<~RUBY) | ||
x / x | ||
^^^^^ Do not apply numeric operations with constant results to variables. | ||
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 | ||
^^^^^^ Do not apply numeric operations with constant results to variables. | ||
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 | ||
^^^^^^ Do not apply numeric operations with constant results to variables. | ||
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 | ||
^^^^^^ Do not apply numeric operations with constant results to variables. | ||
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 | ||
^^^^^^ Do not apply numeric operations with constant results to variables. | ||
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 | ||
^^^^^^ Do not apply numeric operations with constant results to variables. | ||
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 | ||
^^^^^^ Do not apply numeric operations with constant results to variables. | ||
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 | ||
^^^^^^^ Do not apply numeric operations with constant results to variables. | ||
RUBY | ||
|
||
expect_correction(<<~RUBY) | ||
x = 1 | ||
RUBY | ||
end | ||
end |