Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
## Summary This PR adds new `Style/StringChars` cop. The cop checks for uses of `String#split` with empty string or regexp literal argument. ```ruby # bad string.split(//) string.split('') # good string.chars ``` Since Ruby 2.0, the behavior of `String#chars` and `String#split(//)` is the same. ### Ruby 1.9 and lower ```console % ruby -ve "p 'foo'.split(//)" ruby 1.9.3p551 (2014-11-13 revision 48407) [x86_64-darwin13.0.2] ["f", "o", "o"] % ruby -ve "p 'foo'.chars" ruby 1.9.3p551 (2014-11-13 revision 48407) [x86_64-darwin13.0.2] #<Enumerator: "foo":chars> ``` ### Ruby 2.0 and higher ```console % ruby -ve "p 'foo'.split(//)" ruby 2.0.0p648 (2015-12-16 revision 53162) [x86_64-darwin13.0.2] ["f", "o", "o"] % ruby -ve "p 'foo'.chars" ruby 2.0.0p648 (2015-12-16 revision 53162) [x86_64-darwin13.0.2] ["f", "o", "o"] ``` Writing `String#chars` would pretty express the intent of the code. ## Additional Information This cop is intended to use `String#chars` method that express readable code. And it has a different purpose than `Performance/RedundantSplitRegexpArgument` cop. https://docs.rubocop.org/rubocop-performance/cops_performance.html#performanceredundantsplitregexpargument Therefore, it will be added as a new `Style` cop.
- Loading branch information
Showing
8 changed files
with
103 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
* [#9615](https://github.com/rubocop/rubocop/pull/9615): Add new `Style/StringChars` cop. ([@koic][]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
# frozen_string_literal: true | ||
|
||
module RuboCop | ||
module Cop | ||
module Style | ||
# Checks for uses of `String#split` with empty string or regexp literal argument. | ||
# | ||
# This cop is marked as unsafe. But probably it's quite unlikely that some other class would | ||
# define a `split` method that takes exactly the same arguments. | ||
# | ||
# @example | ||
# # bad | ||
# string.split(//) | ||
# string.split('') | ||
# | ||
# # good | ||
# string.chars | ||
# | ||
class StringChars < Base | ||
extend AutoCorrector | ||
|
||
MSG = 'Use `chars` instead of `%<current>s`.' | ||
RESTRICT_ON_SEND = %i[split].freeze | ||
BAD_ARGUMENTS = %w[// '' ""].freeze | ||
|
||
def on_send(node) | ||
return unless node.arguments.one? && BAD_ARGUMENTS.include?(node.first_argument.source) | ||
|
||
range = node.loc.selector.begin.join(node.loc.end) | ||
|
||
add_offense(range, message: format(MSG, current: range.source)) do |corrector| | ||
corrector.replace(range, 'chars') | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
# frozen_string_literal: true | ||
|
||
RSpec.describe RuboCop::Cop::Style::StringChars, :config do | ||
it 'registers and corrects an offense when using `split(//)`' do | ||
expect_offense(<<~RUBY) | ||
string.split(//) | ||
^^^^^^^^^ Use `chars` instead of `split(//)`. | ||
RUBY | ||
|
||
expect_correction(<<~RUBY) | ||
string.chars | ||
RUBY | ||
end | ||
|
||
it "registers and corrects an offense when using `split('')`" do | ||
expect_offense(<<~RUBY) | ||
string.split('') | ||
^^^^^^^^^ Use `chars` instead of `split('')`. | ||
RUBY | ||
|
||
expect_correction(<<~RUBY) | ||
string.chars | ||
RUBY | ||
end | ||
|
||
it 'registers and corrects an offense when using `split("")`' do | ||
expect_offense(<<~RUBY) | ||
string.split("") | ||
^^^^^^^^^ Use `chars` instead of `split("")`. | ||
RUBY | ||
|
||
expect_correction(<<~RUBY) | ||
string.chars | ||
RUBY | ||
end | ||
|
||
it 'does not register an offense when using `chars`' do | ||
expect_no_offenses(<<~RUBY) | ||
string.chars | ||
RUBY | ||
end | ||
|
||
it 'does not register an offense when using `split(/ /)`' do | ||
expect_no_offenses(<<~RUBY) | ||
string.split(/ /) | ||
RUBY | ||
end | ||
|
||
it 'does not register an offense when using `split`' do | ||
expect_no_offenses(<<~RUBY) | ||
string.split | ||
RUBY | ||
end | ||
end |