diff --git a/changelog/fix_incorrect_autocorrect_for_performance_redundant_string_chars.md b/changelog/fix_incorrect_autocorrect_for_performance_redundant_string_chars.md new file mode 100644 index 0000000..f29d3ab --- /dev/null +++ b/changelog/fix_incorrect_autocorrect_for_performance_redundant_string_chars.md @@ -0,0 +1 @@ +* [#273](https://github.com/rubocop/rubocop-performance/pull/273): Fix an incorrect autocorrect for `Performance/RedundantStringChars` when using `str.chars[0]`. ([@koic][]) diff --git a/lib/rubocop/cop/performance/redundant_string_chars.rb b/lib/rubocop/cop/performance/redundant_string_chars.rb index 20d9bc0..d0d4972 100644 --- a/lib/rubocop/cop/performance/redundant_string_chars.rb +++ b/lib/rubocop/cop/performance/redundant_string_chars.rb @@ -82,14 +82,10 @@ def build_message(method, args) def build_good_method(method, args) case method - when :[], :slice + when :slice "[#{build_call_args(args)}].chars" - when :first - if args.any? - "[0...#{args.first.source}].chars" - else - '[0]' - end + when :[], :first + build_good_method_for_brackets_or_first_method(method, args) when :take "[0...#{args.first.source}].chars" else @@ -97,6 +93,18 @@ def build_good_method(method, args) end end + def build_good_method_for_brackets_or_first_method(method, args) + first_arg = args.first + + if first_arg&.range_type? + "[#{build_call_args(args)}].chars" + elsif method == :first && args.any? + "[0...#{args.first.source}].chars" + else + first_arg ? "[#{first_arg.source}]" : '[0]' + end + end + def build_bad_method(method, args) case method when :[] diff --git a/spec/rubocop/cop/performance/redundant_string_chars_spec.rb b/spec/rubocop/cop/performance/redundant_string_chars_spec.rb index df25663..a520811 100644 --- a/spec/rubocop/cop/performance/redundant_string_chars_spec.rb +++ b/spec/rubocop/cop/performance/redundant_string_chars_spec.rb @@ -34,6 +34,28 @@ RUBY end + it 'registers an offense and corrects when using `str.chars[0]`' do + expect_offense(<<~RUBY) + str.chars[0] + ^^^^^^^^ Use `[0]` instead of `chars[0]`. + RUBY + + expect_correction(<<~RUBY) + str[0] + RUBY + end + + it 'registers an offense and corrects when using `str.chars[42]`' do + expect_offense(<<~RUBY) + str.chars[42] + ^^^^^^^^^ Use `[42]` instead of `chars[42]`. + RUBY + + expect_correction(<<~RUBY) + str[42] + RUBY + end + it 'registers an offense and corrects when using `str.chars.first(2)`' do expect_offense(<<~RUBY) str.chars.first(2)