Skip to content

Commit

Permalink
Implement Style/SlicingWithRange cop
Browse files Browse the repository at this point in the history
Under Ruby >= 2.6, proposes to change ary[x..-1] to ary[x..].
Supports autocorrect.
  • Loading branch information
zverok authored and bbatsov committed May 10, 2020
1 parent ff3d4ea commit 0c3d278
Show file tree
Hide file tree
Showing 7 changed files with 123 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -4,6 +4,7 @@

### New features

* [#7921](https://github.com/rubocop-hq/rubocop/pull/7921): Add [Style/SlicingWithRange] cop. ([@zverok][])
* [#7895](https://github.com/rubocop-hq/rubocop/pull/7895): Include `.simplecov` file by default. ([@robotdana][])
* [#7916](https://github.com/rubocop-hq/rubocop/pull/7916): Support autocorrection for `Lint/AmbiguousRegexpLiteral`. ([@koic][])
* [#7917](https://github.com/rubocop-hq/rubocop/pull/7917): Support autocorrection for `Lint/UselessAccessModifier`. ([@koic][])
Expand Down
6 changes: 6 additions & 0 deletions config/default.yml
Expand Up @@ -3735,6 +3735,12 @@ Style/SingleLineMethods:
VersionChanged: '0.19'
AllowIfMethodIsEmpty: true

Style/SlicingWithRange:
Description: 'Checks array slicing is done with endless ranges when suitable.'
Enabled: pending
VersionAdded: '0.83'
Safe: false

Style/SpecialGlobalVars:
Description: 'Avoid Perl-style global variables.'
StyleGuide: '#no-cryptic-perlisms'
Expand Down
1 change: 1 addition & 0 deletions lib/rubocop.rb
Expand Up @@ -542,6 +542,7 @@
require_relative 'rubocop/cop/style/signal_exception'
require_relative 'rubocop/cop/style/single_line_block_params'
require_relative 'rubocop/cop/style/single_line_methods'
require_relative 'rubocop/cop/style/slicing_with_range'
require_relative 'rubocop/cop/style/special_global_vars'
require_relative 'rubocop/cop/style/stabby_lambda_parentheses'
require_relative 'rubocop/cop/style/stderr_puts'
Expand Down
39 changes: 39 additions & 0 deletions lib/rubocop/cop/style/slicing_with_range.rb
@@ -0,0 +1,39 @@
# frozen_string_literal: true

module RuboCop
module Cop
module Style
# This cop checks that arrays are sliced with endless ranges instead of
# `ary[start..-1]` on Ruby 2.6+.
#
# @example
# # bad
# items[1..-1]
#
# # good
# items[1..]
class SlicingWithRange < Cop
extend TargetRubyVersion

minimum_target_ruby_version 2.6

MSG = 'Prefer ary[n..] over ary[n..-1].'

def_node_matcher :range_till_minus_one?, '(irange (int _) (int -1))'

def on_send(node)
return unless node.method?(:[]) && node.arguments.count == 1
return unless range_till_minus_one?(node.arguments.first)

add_offense(node.arguments.first)
end

def autocorrect(node)
lambda do |corrector|
corrector.remove(node.end)
end
end
end
end
end
end
1 change: 1 addition & 0 deletions manual/cops.md
Expand Up @@ -449,6 +449,7 @@ In the following section you find all available cops:
* [Style/SignalException](cops_style.md#stylesignalexception)
* [Style/SingleLineBlockParams](cops_style.md#stylesinglelineblockparams)
* [Style/SingleLineMethods](cops_style.md#stylesinglelinemethods)
* [Style/SlicingWithRange](cops_style.md#styleslicingwithrange)
* [Style/SpecialGlobalVars](cops_style.md#stylespecialglobalvars)
* [Style/StabbyLambdaParentheses](cops_style.md#stylestabbylambdaparentheses)
* [Style/StderrPuts](cops_style.md#stylestderrputs)
Expand Down
23 changes: 23 additions & 0 deletions manual/cops_style.md
Expand Up @@ -6609,6 +6609,29 @@ AllowIfMethodIsEmpty | `true` | Boolean
* [https://rubystyle.guide#no-single-line-methods](https://rubystyle.guide#no-single-line-methods)
## Style/SlicingWithRange
!!! Note
Required Ruby version: 2.6
Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged
--- | --- | --- | --- | ---
Pending | No | Yes (Unsafe) | 0.83 | -
This cop checks that arrays are sliced with endless ranges instead of
`ary[start..-1]` on Ruby 2.6+.
### Examples
```ruby
# bad
items[1..-1]

# good
items[1..]
```
## Style/SpecialGlobalVars
Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged
Expand Down
52 changes: 52 additions & 0 deletions spec/rubocop/cop/style/slicing_with_range_spec.rb
@@ -0,0 +1,52 @@
# frozen_string_literal: true

RSpec.describe RuboCop::Cop::Style::SlicingWithRange, :config do
subject(:cop) { described_class.new(config) }

context '<= Ruby 2.5', :ruby25 do
it 'reports no offense for array slicing with -1' do
expect_no_offenses(<<~RUBY)
ary[1..-1]
RUBY
end
end

context '>= Ruby 2.6', :ruby26 do
it 'reports an offense for slicing to ..-1' do
expect_offense(<<~RUBY)
ary[1..-1]
^^^^^ Prefer ary[n..] over ary[n..-1].
RUBY

expect_correction(<<~RUBY)
ary[1..]
RUBY
end

it 'reports no offense for excluding end' do
expect_no_offenses(<<~RUBY)
ary[1...-1]
RUBY
end

it 'reports no offense for other methods' do
expect_no_offenses(<<~RUBY)
ary.push(1..-1)
RUBY
end

it 'reports no offense for array with range inside' do
expect_no_offenses(<<~RUBY)
ranges = [1..-1]
RUBY
end
end

context '>= Ruby 2.7', :ruby27 do
it 'reports no offense for startless' do
expect_no_offenses(<<~RUBY)
ary[..-1]
RUBY
end
end
end

0 comments on commit 0c3d278

Please sign in to comment.