Skip to content

Commit

Permalink
[Fix rubocop#313] Fix a false negative for `Performance/RedundantStri…
Browse files Browse the repository at this point in the history
…ngChars`

Fixes rubocop#313.

This PR fixes a false negative for `Performance/RedundantStringChars`
when using `str.chars.last` without argument.

Report rubocop#249 has `str.chars.last(2)` argument. rubocop#250 mistakenly changed
even without arguments `str.chars.last`.
  • Loading branch information
koic committed Nov 21, 2022
1 parent 3f4d8dd commit 1fbe937
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 5 deletions.
@@ -0,0 +1 @@
* [#313](https://github.com/rubocop/rubocop-performance/issues/313): Fix a false negative for `Performance/RedundantStringChars` when using `str.chars.last` without argument. ([@koic][])
10 changes: 7 additions & 3 deletions lib/rubocop/cop/performance/redundant_string_chars.rb
Expand Up @@ -9,6 +9,7 @@ module Performance
# # bad
# str.chars[0..2]
# str.chars.slice(0..2)
# str.chars.last
#
# # good
# str[0..2].chars
Expand All @@ -20,6 +21,7 @@ module Performance
# # good
# str[0]
# str[0...2].chars
# str[-1]
#
# # bad
# str.chars.take(2)
Expand All @@ -33,9 +35,8 @@ module Performance
# str.size
# str.empty?
#
# # For example, if the receiver is a blank string, it will be incompatible.
# # For example, if the receiver is an empty string, it will be incompatible.
# # If a negative value is specified for the receiver, `nil` is returned.
# str.chars.last # Incompatible with `str[-1]`.
# str.chars.last(2) # Incompatible with `str[-2..-1].chars`.
# str.chars.drop(2) # Incompatible with `str[2..-1].chars`.
#
Expand All @@ -44,14 +45,15 @@ class RedundantStringChars < Base
extend AutoCorrector

MSG = 'Use `%<good_method>s` instead of `%<bad_method>s`.'
RESTRICT_ON_SEND = %i[[] slice first take length size empty?].freeze
RESTRICT_ON_SEND = %i[[] slice first last take length size empty?].freeze

def_node_matcher :redundant_chars_call?, <<~PATTERN
(send $(send _ :chars) $_ $...)
PATTERN

def on_send(node)
return unless (receiver, method, args = redundant_chars_call?(node))
return if method == :last && !args.empty?

range = offense_range(receiver, node)
message = build_message(method, args)
Expand Down Expand Up @@ -86,6 +88,8 @@ def build_good_method(method, args)
"[#{build_call_args(args)}].chars"
when :[], :first
build_good_method_for_brackets_or_first_method(method, args)
when :last
'[-1]'
when :take
"[0...#{args.first.source}].chars"
else
Expand Down
9 changes: 7 additions & 2 deletions spec/rubocop/cop/performance/redundant_string_chars_spec.rb
Expand Up @@ -67,9 +67,14 @@
RUBY
end

it 'does not register an offense when using `str.chars.last`' do
expect_no_offenses(<<~RUBY)
it 'registers an offense and corrects when using `str.chars.last`' do
expect_offense(<<~RUBY)
str.chars.last
^^^^^^^^^^ Use `[-1]` instead of `chars.last`.
RUBY

expect_correction(<<~RUBY)
str[-1]
RUBY
end

Expand Down

0 comments on commit 1fbe937

Please sign in to comment.