Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Style/SlicingWithRange cop #7921

Merged
merged 1 commit into from May 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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 @@ -3733,6 +3733,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