Skip to content

Commit

Permalink
Support EnforcedStyleForExponentOperator for SpaceAroundOperators cop
Browse files Browse the repository at this point in the history
  • Loading branch information
khiav reoy authored and bbatsov committed Dec 11, 2019
1 parent d54e15c commit 7276872
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 14 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## master (unreleased)

### New features

* [#7559](https://github.com/rubocop-hq/rubocop/pull/7559): Add `EnforcedStyleForExponentOperator` parameter to `Layout/SpaceAroundOperators` cop. ([@khiav223577][])

### Bug fixes

* [#7530](https://github.com/rubocop-hq/rubocop/issues/7530): Typo in `Style/TrivialAccessors`'s `AllowedMethods`. ([@movermeyer][])
Expand Down
4 changes: 4 additions & 0 deletions config/default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1067,6 +1067,10 @@ Layout/SpaceAroundOperators:
# with an operator on the previous or next line, not counting empty lines
# or comment lines.
AllowForAlignment: true
EnforcedStyleForExponentOperator: no_space
SupportedStylesForExponentOperator:
- space
- no_space

Layout/SpaceBeforeBlockBraces:
Description: >-
Expand Down
34 changes: 28 additions & 6 deletions lib/rubocop/cop/layout/space_around_operators.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,33 @@
module RuboCop
module Cop
module Layout
# Checks that operators have space around them, except for **
# which should not have surrounding space.
# Checks that operators have space around them, except for ** which
# should or shouldn't have surrounding space depending on configuration.
#
# @example
# # bad
# total = 3*4
# "apple"+"juice"
# my_number = 38/4
# a ** b
#
# # good
# total = 3 * 4
# "apple" + "juice"
# my_number = 38 / 4
#
# @example EnforcedStyleForExponentOperator: no_space (default)
# # bad
# a ** b
#
# # good
# a**b
#
# @example EnforcedStyleForExponentOperator: space
# # bad
# a**b
#
# # good
# a ** b
class SpaceAroundOperators < Cop
include PrecedingFollowingAlignment
include RangeHelp
Expand Down Expand Up @@ -104,7 +116,7 @@ def on_special_asgn(node)

def autocorrect(range)
lambda do |corrector|
if range.source =~ /\*\*/
if range.source =~ /\*\*/ && !space_around_exponent_operator?
corrector.replace(range, '**')
elsif range.source.end_with?("\n")
corrector.replace(range, " #{range.source.strip}\n")
Expand Down Expand Up @@ -141,8 +153,10 @@ def offense(type, operator, with_space, right_operand)
end

def offense_message(type, operator, with_space, right_operand)
if operator.is?('**')
'Space around operator `**` detected.' unless with_space.is?('**')
if should_not_have_surrounding_space?(operator)
return if with_space.is?(operator.source)

"Space around operator `#{operator.source}` detected."
elsif with_space.source !~ /^\s.*\s$/
"Surrounding space missing for operator `#{operator.source}`."
elsif excess_leading_space?(type, operator, with_space) ||
Expand Down Expand Up @@ -179,6 +193,14 @@ def hash_table_style?
align_hash_cop_config &&
align_hash_cop_config['EnforcedHashRocketStyle'] == 'table'
end

def space_around_exponent_operator?
cop_config['EnforcedStyleForExponentOperator'] == 'space'
end

def should_not_have_surrounding_space?(operator)
operator.is?('**') ? !space_around_exponent_operator? : false
end
end
end
end
Expand Down
23 changes: 20 additions & 3 deletions manual/cops_layout.md
Original file line number Diff line number Diff line change
Expand Up @@ -4034,8 +4034,8 @@ Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChan
--- | --- | --- | --- | ---
Enabled | Yes | Yes | 0.49 | -
Checks that operators have space around them, except for **
which should not have surrounding space.
Checks that operators have space around them, except for ** which
should or shouldn't have surrounding space depending on configuration.
### Examples
Expand All @@ -4044,20 +4044,37 @@ which should not have surrounding space.
total = 3*4
"apple"+"juice"
my_number = 38/4
a ** b

# good
total = 3 * 4
"apple" + "juice"
my_number = 38 / 4
```
#### EnforcedStyleForExponentOperator: no_space (default)
```ruby
# bad
a ** b

# good
a**b
```
#### EnforcedStyleForExponentOperator: space
```ruby
# bad
a**b

# good
a ** b
```
### Configurable attributes
Name | Default value | Configurable values
--- | --- | ---
AllowForAlignment | `true` | Boolean
EnforcedStyleForExponentOperator | `no_space` | `space`, `no_space`
### References
Expand Down
16 changes: 12 additions & 4 deletions spec/rubocop/cli/cli_auto_gen_config_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,9 @@ def f
expect(IO.readlines('.rubocop_todo.yml')[8..-1].map(&:chomp))
.to eq(['# Offense count: 1',
'# Cop supports --auto-correct.',
'# Configuration parameters: AllowForAlignment.',
'# Configuration parameters: AllowForAlignment, ' \
'EnforcedStyleForExponentOperator.',
'# SupportedStylesForExponentOperator: space, no_space',
'Layout/SpaceAroundOperators:',
' Exclude:',
" - 'example1.rb'",
Expand Down Expand Up @@ -589,7 +591,9 @@ def a; end
'',
'# Offense count: 1',
'# Cop supports --auto-correct.',
'# Configuration parameters: AllowForAlignment.',
'# Configuration parameters: AllowForAlignment, ' \
'EnforcedStyleForExponentOperator.',
'# SupportedStylesForExponentOperator: space, no_space',
'Layout/SpaceAroundOperators:',
' Exclude:',
" - 'example1.rb'",
Expand Down Expand Up @@ -686,7 +690,9 @@ def a; end
'',
'# Offense count: 1',
'# Cop supports --auto-correct.',
'# Configuration parameters: AllowForAlignment.',
'# Configuration parameters: AllowForAlignment, ' \
'EnforcedStyleForExponentOperator.',
'# SupportedStylesForExponentOperator: space, no_space',
'Layout/SpaceAroundOperators:',
' Exclude:',
" - 'example1.rb'",
Expand Down Expand Up @@ -889,7 +895,9 @@ def a; end
" - 'example2.rb'",
'',
'# Cop supports --auto-correct.',
'# Configuration parameters: AllowForAlignment.',
'# Configuration parameters: AllowForAlignment, ' \
'EnforcedStyleForExponentOperator.',
'# SupportedStylesForExponentOperator: space, no_space',
'Layout/SpaceAroundOperators:',
' Exclude:',
" - 'example1.rb'",
Expand Down
26 changes: 25 additions & 1 deletion spec/rubocop/cop/layout/space_around_operators_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@
'Layout/ExtraSpacing' => { 'ForceEqualSignAlignment' => true },
'Layout/HashAlignment' => { 'EnforcedHashRocketStyle' => hash_style },
'Layout/SpaceAroundOperators' => {
'AllowForAlignment' => allow_for_alignment
'AllowForAlignment' => allow_for_alignment,
'EnforcedStyleForExponentOperator' => exponent_operator_style
}
)
end
let(:hash_style) { 'key' }
let(:allow_for_alignment) { true }
let(:exponent_operator_style) { nil }

it 'accepts operator surrounded by tabs' do
expect_no_offenses("a\t+\tb")
Expand Down Expand Up @@ -188,6 +190,28 @@ def self.===(other); end
expect_no_offenses('x = a * b**2')
end

context 'when EnforcedStyleForExponentOperator is space' do
let(:exponent_operator_style) { 'space' }

it 'registers an offenses for exponent operator without spaces' do
expect_offense(<<~RUBY)
x = a * b**2
^^ Surrounding space missing for operator `**`.
RUBY
end

it 'auto-corrects a exponent operator without space' do
new_source = autocorrect_source(<<~RUBY)
x = a * b ** 2
y = a * b** 2
RUBY
expect(new_source).to eq(<<~RUBY)
x = a * b ** 2
y = a * b ** 2
RUBY
end
end

it 'accepts unary operators without space' do
expect_no_offenses(<<~RUBY)
[].map(&:size)
Expand Down

0 comments on commit 7276872

Please sign in to comment.