Skip to content

Commit

Permalink
[Fix #3981] Allow NumericLiterals to be less strict
Browse files Browse the repository at this point in the history
This introduces a new configuration option for `Style/NumericLiteral`
called `Strict`, which requires numbers to have a group of 3 digits at
end. The cop was changed in 0.47.0 for this behavior, but it's a common
practise to specify monetary amounts in cents and then it's useful to
group the cents separately (e.g. $123,456.78 as `Money.new(123_456_78)`
instead of `Money.new(12_345_678)`). So this commit makes the behavior
configurable and reverts the default to the behavior before the 0.47.0
release.
  • Loading branch information
iGEL authored and bbatsov committed Feb 21, 2017
1 parent 380a807 commit 7796c09
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 4 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

### New features

* [#4045](https://github.com/bbatsov/rubocop/pull/4045): Add new configuration `Strict` for `Style/NumericLiteral` to make the change to this cop in 0.47.0 configurable. ([@iGEL][])
* [#3893](https://github.com/bbatsov/rubocop/issues/3893): Add a new configuration, `IncludeActiveSupportAliases`, to `Performance/DoublStartEndWith`. This configuration will check for ActiveSupport's `starts_with?` and `ends_with?`. ([@rrosenblum][])
* [#3889](https://github.com/bbatsov/rubocop/pull/3889): Add new `Style/EmptyLineAfterMagicComment` cop. ([@backus][])
* [#3800](https://github.com/bbatsov/rubocop/issues/3800): Make `Style/EndOfLine` configurable with `lf`, `crlf`, and `native` (default) styles. ([@jonas054][])
Expand Down
28 changes: 25 additions & 3 deletions lib/rubocop/cop/style/numeric_literals.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,33 @@ module Cop
module Style
# This cop checks for big numeric literals without _ between groups
# of digits in them.
#
# @example
#
# # bad
#
# 1000000
# 1_00_000
# 1_0000
#
# # good
#
# 1_000_000
# 1000
#
# # good unless Strict is set
#
# 10_000_00 # typical representation of $10,000 in cents
#
class NumericLiterals < Cop
# The parameter is called MinDigits (meaning the minimum number of
# digits for which an offense can be registered), but essentially it's
# a Max parameter (the maximum number of something that's allowed).
include ConfigurableMax
include IntegerNode

MSG = 'Separate every 3 digits in the integer portion of a number ' \
'with underscores(_).'.freeze
MSG = 'Use underscores(_) as decimal mark and ' \
'separate every 3 digits with them.'.freeze

def on_int(node)
check(node)
Expand All @@ -39,13 +57,17 @@ def check(node)
case int
when /^\d+$/
add_offense(node, :expression) { self.max = int.size + 1 }
when /\d{4}/, /_\d{1,2}(_|$)/
when /\d{4}/, short_group_regex
add_offense(node, :expression) do
self.config_to_allow_offenses = { 'Enabled' => false }
end
end
end

def short_group_regex
cop_config['Strict'] ? /_\d{1,2}(_|$)/ : /_\d{1,2}_/
end

def autocorrect(node)
lambda do |corrector|
corrector.replace(node.source_range, format_number(node))
Expand Down
19 changes: 19 additions & 0 deletions manual/cops_style.md
Original file line number Diff line number Diff line change
Expand Up @@ -3884,6 +3884,25 @@ Enabled | Yes
This cop checks for big numeric literals without _ between groups
of digits in them.

### Example

```ruby
# bad

1000000
1_00_000
1_0000

# good

1_000_000
1000

# good unless Strict is set

10_000_00 # typical representation of $10,000 in cents
```

### Important attributes

Attribute | Value
Expand Down
24 changes: 23 additions & 1 deletion spec/rubocop/cop/style/numeric_literals_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,15 @@
expect(cop.config_to_allow_offenses).to eq('MinDigits' => 7)
end

it 'accepts integers with less than three places at the end' do
inspect_source(cop, ['a = 123_456_789_00',
'b = 819_2'])
expect(cop.offenses).to be_empty
end

it 'registers an offense for an integer with misplaced underscore' do
inspect_source(cop, ['a = 123_456_78_90_00',
'b = 819_2'])
'b = 1_8192'])
expect(cop.offenses.size).to eq(2)
expect(cop.config_to_allow_offenses).to eq('Enabled' => false)
end
Expand Down Expand Up @@ -78,4 +84,20 @@
corrected = autocorrect_source(cop, ['a = -123456.78'])
expect(corrected).to eq 'a = -123_456.78'
end

context 'strict' do
let(:cop_config) do
{
'MinDigits' => 5,
'Strict' => true
}
end

it 'registers an offense for an integer with misplaced underscore' do
inspect_source(cop, ['a = 123_456_78_90_00',
'b = 81_92'])
expect(cop.offenses.size).to eq(2)
expect(cop.config_to_allow_offenses).to eq('Enabled' => false)
end
end
end

0 comments on commit 7796c09

Please sign in to comment.