Skip to content

Commit

Permalink
Properly auto-correct percent arrays in CaseWhenSplat
Browse files Browse the repository at this point in the history
  • Loading branch information
rrosenblum committed Sep 17, 2015
1 parent ae6fe94 commit 8eedad3
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
* [#2240](https://github.com/bbatsov/rubocop/pull/2240): `Lint/UnneededDisable` should not report non-`Lint` `rubocop:disable` comments when running `rubocop --lint`. ([@jonas054][])
* [#2121](https://github.com/bbatsov/rubocop/issues/2121): Allow space before values in hash literals in `Style/ExtraSpacing` to avoid correction conflict. ([@jonas054][])
* [#2241](https://github.com/bbatsov/rubocop/issues/2241): Read cache in binary format. ([@jonas054][])
* [#2247](https://github.com/bbatsov/rubocop/issues/2247): Fix auto-correct of `Performance/CaseWhenSplat` for percent arrays (`%w`, `%W`, `%i`, and `%I`). ([@rrosenblum][])

### Changes

Expand Down
34 changes: 31 additions & 3 deletions lib/rubocop/cop/performance/case_when_splat.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ class CaseWhenSplat < Cop
MSG = 'Place `when` conditions with a splat ' \
'at the end of the `when` branches.'.freeze
ARRAY_MSG = 'Do not expand array literals in `when` conditions.'.freeze
OPEN_BRACKET = '['.freeze
PERCENT_W = '%w'.freeze
PERCENT_CAPITAL_W = '%W'.freeze
PERCENT_I = '%i'.freeze
PERCENT_CAPITAL_I = '%I'.freeze

def on_case(node)
_case_branch, *when_branches, _else_branch = *node
Expand Down Expand Up @@ -104,9 +109,16 @@ def error_condition?(condition)

def correct_array_literal(condition, variable)
lambda do |corrector|
corrector.remove(condition.loc.operator)
corrector.remove(variable.loc.begin)
corrector.remove(variable.loc.end)
array_start = variable.loc.begin.source

if array_start.start_with?(OPEN_BRACKET)
corrector.remove(condition.loc.operator)
corrector.remove(variable.loc.begin)
corrector.remove(variable.loc.end)
else
corrector.replace(condition.loc.expression,
expand_percent_array(variable))
end
end
end

Expand All @@ -126,6 +138,22 @@ def reorder_splat_condition(node)
correction)
end
end

def expand_percent_array(array)
array_start = array.loc.begin.source
elements = *array
elements = elements.map { |e| e.loc.expression.source }

if array_start.start_with?(PERCENT_W)
"'#{elements.join("', '")}'"
elsif array_start.start_with?(PERCENT_CAPITAL_W)
%("#{elements.join('", "')}")
elsif array_start.start_with?(PERCENT_I)
":#{elements.join(', :')}"
elsif array_start.start_with?(PERCENT_CAPITAL_I)
%(:"#{elements.join('", :"')}")
end
end
end
end
end
Expand Down
86 changes: 86 additions & 0 deletions spec/rubocop/cop/performance/case_when_splat_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -298,5 +298,91 @@
' bar',
'end'].join("\n"))
end

it 'corrects splat on array literals using %w' do
new_source = autocorrect_source(cop, ['case foo',
'when *%w(first second)',
' baz',
'end'])

expect(new_source).to eq(['case foo',
"when 'first', 'second'",
' baz',
'end'].join("\n"))
end

it 'corrects splat on array literals using %W' do
new_source = autocorrect_source(cop, ['case foo',
'when *%W(#{first} #{second})',
' baz',
'end'])

expect(new_source).to eq(['case foo',
'when "#{first}", "#{second}"',
' baz',
'end'].join("\n"))
end

context 'ruby >= 2.0', ruby_greater_than_or_equal: 2.0 do
it 'corrects splat on array literals using %i' do
new_source = autocorrect_source(cop, ['case foo',
'when *%i(first second)',
' baz',
'end'])

expect(new_source).to eq(['case foo',
'when :first, :second',
' baz',
'end'].join("\n"))
end

it 'corrects splat on array literals using %I' do
new_source = autocorrect_source(cop, ['case foo',
'when *%I(#{first} #{second})',
' baz',
'end'])

expect(new_source).to eq(['case foo',
'when :"#{first}", :"#{second}"',
' baz',
'end'].join("\n"))
end

it 'corrects everything at once' do
new_source = autocorrect_source(cop, ['case foo',
'when *bar',
' 1',
'when baz',
' 2',
"when *['a', 'b']",
' 3',
'when *%w(c d)',
' 4',
'when *%W(#{e} #{f})',
' 5',
'when *%i(g h)',
' 6',
'when *%I(#{i} #{j})',
' 7',
'end'])

expect(new_source).to eq(['case foo',
'when baz',
' 2',
"when 'a', 'b'",
' 3',
"when 'c', 'd'",
' 4',
'when "#{e}", "#{f}"',
' 5',
'when :g, :h',
' 6',
'when :"#{i}", :"#{j}"',
' 7',
'when *bar',
' 1',
'end'].join("\n"))
end
end
end
end

0 comments on commit 8eedad3

Please sign in to comment.