Skip to content

Commit

Permalink
Support autocorrect for Lint/Loop cop
Browse files Browse the repository at this point in the history
  • Loading branch information
fatkodima committed Aug 5, 2020
1 parent c29441f commit 714b13d
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 8 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -13,6 +13,7 @@
* [#8432](https://github.com/rubocop-hq/rubocop/pull/8432): Add new `Lint/FloatComparison` cop. ([@fatkodima][])
* [#8376](https://github.com/rubocop-hq/rubocop/pull/8376): Add new `Lint/MissingSuper` cop. ([@fatkodima][])
* [#8415](https://github.com/rubocop-hq/rubocop/pull/8415): Add new `Style/ExplicitBlockArgument` cop. ([@fatkodima][])
* [#8383](https://github.com/rubocop-hq/rubocop/pull/8383): Support autocorrect for `Lint/Loop` cop. ([@fatkodima][])
* [#8339](https://github.com/rubocop-hq/rubocop/pull/8339): Add `Config#for_badge` as an efficient way to get a cop's config merged with its department's. ([@marcandre][])
* [#5067](https://github.com/rubocop-hq/rubocop/issues/5067): Add new `Style/StringConcatenation` cop. ([@fatkodima][])
* [#7425](https://github.com/rubocop-hq/rubocop/pull/7425): Add new `Lint/TopLevelReturnWithArgument` cop. ([@iamravitejag][])
Expand Down
1 change: 1 addition & 0 deletions config/default.yml
Expand Up @@ -1559,6 +1559,7 @@ Lint/Loop:
StyleGuide: '#loop-with-break'
Enabled: true
VersionAdded: '0.9'
VersionChanged: '0.89'

Lint/MissingCopEnableDirective:
Description: 'Checks for a `# rubocop:enable` after `# rubocop:disable`.'
Expand Down
4 changes: 2 additions & 2 deletions docs/modules/ROOT/pages/cops_lint.adoc
Expand Up @@ -1711,9 +1711,9 @@ This cop checks for interpolated literals.

| Enabled
| Yes
| No
| Yes
| 0.9
| -
| 0.89
|===

This cop checks for uses of `begin...end while/until something`.
Expand Down
23 changes: 22 additions & 1 deletion lib/rubocop/cop/lint/loop.rb
Expand Up @@ -43,6 +43,8 @@ module Lint
# break if some_condition
# end
class Loop < Base
extend AutoCorrector

MSG = 'Use `Kernel#loop` with `break` rather than ' \
'`begin/end/until`(or `while`).'

Expand All @@ -57,7 +59,26 @@ def on_until_post(node)
private

def register_offense(node)
add_offense(node.loc.keyword)
body = node.body

add_offense(node.loc.keyword) do |corrector|
corrector.replace(body.loc.begin, 'loop do')
corrector.remove(keyword_and_condition_range(node))
corrector.insert_before(body.loc.end, build_break_line(node))
end
end

def keyword_and_condition_range(node)
node.body.loc.end.end.join(node.source_range.end)
end

def build_break_line(node)
conditional_keyword = node.while_post_type? ? 'unless' : 'if'
"break #{conditional_keyword} #{node.condition.source}\n#{indent(node)}"
end

def indent(node)
' ' * node.loc.column
end
end
end
Expand Down
28 changes: 23 additions & 5 deletions spec/rubocop/cop/lint/loop_spec.rb
Expand Up @@ -3,17 +3,35 @@
RSpec.describe RuboCop::Cop::Lint::Loop do
subject(:cop) { described_class.new }

it 'registers an offense for begin/end/while' do
it 'registers an offense and corrects for begin/end/while' do
expect_offense(<<~RUBY)
begin something; top; end while test
^^^^^ Use `Kernel#loop` with `break` rather than `begin/end/until`(or `while`).
begin
something
end while test
^^^^^ Use `Kernel#loop` with `break` rather than `begin/end/until`(or `while`).
RUBY

expect_correction(<<~RUBY)
loop do
something
break unless test
end
RUBY
end

it 'registers an offense for begin/end/until' do
expect_offense(<<~RUBY)
begin something; top; end until test
^^^^^ Use `Kernel#loop` with `break` rather than `begin/end/until`(or `while`).
begin
something
end until test
^^^^^ Use `Kernel#loop` with `break` rather than `begin/end/until`(or `while`).
RUBY

expect_correction(<<~RUBY)
loop do
something
break if test
end
RUBY
end

Expand Down

0 comments on commit 714b13d

Please sign in to comment.