Skip to content

Commit f0bc51b

Browse files
committed
Add new Performance/BigDecimalWithNumericArgument cop
1 parent bb3cf35 commit f0bc51b

File tree

7 files changed

+114
-0
lines changed

7 files changed

+114
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
### New features
66

7+
* [#129](https://github.com/rubocop-hq/rubocop-performance/pull/129): Add new `Performance/BigDecimalWithNumericArgument` cop. ([@fatkodima][])
78
* [#81](https://github.com/rubocop-hq/rubocop-performance/issues/81): Add new `Performance/StringInclude` cop. ([@fatkodima][])
89
* [#123](https://github.com/rubocop-hq/rubocop-performance/pull/123): Add new `Performance/AncestorsInclude` cop. ([@fatkodima][])
910
* [#125](https://github.com/rubocop-hq/rubocop-performance/pull/125): Support `Range#member?` method for `Performance/RangeInclude` cop. ([@fatkodima][])

config/default.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ Performance/AncestorsInclude:
66
Enabled: true
77
VersionAdded: '1.7'
88

9+
Performance/BigDecimalWithNumericArgument:
10+
Description: 'Convert numeric argument to string before passing to BigDecimal.'
11+
Enabled: true
12+
VersionAdded: '1.7'
13+
914
Performance/BindCall:
1015
Description: 'Use `bind_call(obj, args, ...)` instead of `bind(obj).call(args, ...)`.'
1116
Enabled: true

docs/modules/ROOT/pages/cops.adoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
= Department xref:cops_performance.adoc[Performance]
44

55
* xref:cops_performance.adoc#performanceancestorsinclude[Performance/AncestorsInclude]
6+
* xref:cops_performance.adoc#performancebigdecimalwithnumericargument[Performance/BigDecimalWithNumericArgument]
67
* xref:cops_performance.adoc#performancebindcall[Performance/BindCall]
78
* xref:cops_performance.adoc#performancecaller[Performance/Caller]
89
* xref:cops_performance.adoc#performancecasewhensplat[Performance/CaseWhenSplat]

docs/modules/ROOT/pages/cops_performance.adoc

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,36 @@ A <= B
3030

3131
* https://github.com/JuanitoFatas/fast-ruby#ancestorsinclude-vs--code
3232

33+
== Performance/BigDecimalWithNumericArgument
34+
35+
|===
36+
| Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged
37+
38+
| Enabled
39+
| Yes
40+
| Yes
41+
| 1.7
42+
| -
43+
|===
44+
45+
This cop identifies places where numeric argument to BigDecimal should be
46+
converted to string. Initializing from String is faster
47+
than from Numeric for BigDecimal.
48+
49+
BigDecimal(1, 2)
50+
BigDecimal(1.2, 3, exception: true)
51+
52+
# good
53+
BigDecimal('1', 2)
54+
BigDecimal('1.2', 3, exception: true)
55+
56+
=== Examples
57+
58+
[source,ruby]
59+
----
60+
# bad
61+
----
62+
3363
== Performance/BindCall
3464

3565
NOTE: Required Ruby version: 2.7
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# frozen_string_literal: true
2+
3+
module RuboCop
4+
module Cop
5+
module Performance
6+
# This cop identifies places where numeric argument to BigDecimal should be
7+
# converted to string. Initializing from String is faster
8+
# than from Numeric for BigDecimal.
9+
#
10+
# @example
11+
#
12+
# # bad
13+
# BigDecimal(1, 2)
14+
# BigDecimal(1.2, 3, exception: true)
15+
#
16+
# # good
17+
# BigDecimal('1', 2)
18+
# BigDecimal('1.2', 3, exception: true)
19+
#
20+
class BigDecimalWithNumericArgument < Cop
21+
MSG = 'Convert numeric argument to string before passing to `BigDecimal`.'
22+
23+
def_node_matcher :big_decimal_with_numeric_argument?, <<~PATTERN
24+
(send nil? :BigDecimal $numeric_type? ...)
25+
PATTERN
26+
27+
def on_send(node)
28+
big_decimal_with_numeric_argument?(node) do |numeric|
29+
add_offense(node, location: numeric.source_range)
30+
end
31+
end
32+
33+
def autocorrect(node)
34+
big_decimal_with_numeric_argument?(node) do |numeric|
35+
lambda do |corrector|
36+
corrector.wrap(numeric, "'", "'")
37+
end
38+
end
39+
end
40+
end
41+
end
42+
end
43+
end

lib/rubocop/cop/performance_cops.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
require_relative 'mixin/regexp_metacharacter'
44

55
require_relative 'performance/ancestors_include'
6+
require_relative 'performance/big_decimal_with_numeric_argument'
67
require_relative 'performance/bind_call'
78
require_relative 'performance/caller'
89
require_relative 'performance/case_when_splat'
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# frozen_string_literal: true
2+
3+
RSpec.describe RuboCop::Cop::Performance::BigDecimalWithNumericArgument do
4+
subject(:cop) { described_class.new }
5+
6+
it 'registers an offense and corrects when using `BigDecimal` with integer' do
7+
expect_offense(<<~RUBY)
8+
BigDecimal(1)
9+
^ Convert numeric argument to string before passing to `BigDecimal`.
10+
RUBY
11+
12+
expect_correction(<<~RUBY)
13+
BigDecimal('1')
14+
RUBY
15+
end
16+
17+
it 'registers an offense and corrects when using `BigDecimal` with float' do
18+
expect_offense(<<~RUBY)
19+
BigDecimal(1.5, 2, exception: true)
20+
^^^ Convert numeric argument to string before passing to `BigDecimal`.
21+
RUBY
22+
23+
expect_correction(<<~RUBY)
24+
BigDecimal('1.5', 2, exception: true)
25+
RUBY
26+
end
27+
28+
it 'does not register an offense when using `BigDecimal` with string' do
29+
expect_no_offenses(<<~RUBY)
30+
BigDecimal('1')
31+
RUBY
32+
end
33+
end

0 commit comments

Comments
 (0)