diff --git a/lib/rubocop/cop/performance/redundant_split_regexp_argument.rb b/lib/rubocop/cop/performance/redundant_split_regexp_argument.rb index 74a2c5bdd0..e6a77a1df4 100644 --- a/lib/rubocop/cop/performance/redundant_split_regexp_argument.rb +++ b/lib/rubocop/cop/performance/redundant_split_regexp_argument.rb @@ -18,7 +18,7 @@ class RedundantSplitRegexpArgument < Base MSG = 'Use string as argument instead of regexp.' RESTRICT_ON_SEND = %i[split].freeze DETERMINISTIC_REGEX = /\A(?:#{LITERAL_REGEX})+\Z/.freeze - STR_SPECIAL_CHARS = %w[\n \" \' \\ \t \b \f \r].freeze + STR_SPECIAL_CHARS = %w[\n \" \' \\\\ \t \b \f \r].freeze def_node_matcher :split_call_with_regexp?, <<~PATTERN {(send !nil? :split {regexp})} @@ -40,11 +40,27 @@ def determinist_regexp?(first_argument) end def autocorrect(corrector, node) - new_argument = node.first_argument.source[1..-2] - new_argument.delete!('\\') unless STR_SPECIAL_CHARS.include?(new_argument) + new_argument = replacement(node) corrector.replace(node.first_argument, "\"#{new_argument}\"") end + + def replacement(node) + regexp_content = node.first_argument.content + stack = [] + chars = regexp_content.chars.each_with_object([]) do |char, strings| + if stack.empty? && char == '\\' + stack.push(char) + else + strings << "#{stack.pop}#{char}" + end + end + chars.map do |char| + char = char.dup + char.delete!('\\') unless STR_SPECIAL_CHARS.include?(char) + char + end.join + end end end end diff --git a/spec/rubocop/cop/performance/redundant_split_regexp_argument_spec.rb b/spec/rubocop/cop/performance/redundant_split_regexp_argument_spec.rb index 01575f8c12..556fac454d 100644 --- a/spec/rubocop/cop/performance/redundant_split_regexp_argument_spec.rb +++ b/spec/rubocop/cop/performance/redundant_split_regexp_argument_spec.rb @@ -37,6 +37,39 @@ RUBY end + it 'registers an offense when the method is split and corrects correctly consecutive special string chars' do + expect_offense(<<~RUBY) + "foo\\n\\nbar\\n\\nbaz\\n\\n".split(/\\n\\n/) + ^^^^^^ Use string as argument instead of regexp. + RUBY + + expect_correction(<<~RUBY) + "foo\\n\\nbar\\n\\nbaz\\n\\n".split("\\n\\n") + RUBY + end + + it 'registers an offense when the method is split and corrects correctly consecutive backslash escape chars' do + expect_offense(<<~RUBY) + "foo\\\\\\.bar".split(/\\\\\\./) + ^^^^^^ Use string as argument instead of regexp. + RUBY + + expect_correction(<<~RUBY) + "foo\\\\\\.bar".split("\\\\\.") + RUBY + end + + it 'registers an offense when the method is split and corrects correctly complex special string chars' do + expect_offense(<<~RUBY) + "foo\\nbar\\nbaz\\n".split(/foo\\n\\.\\n/) + ^^^^^^^^^^^ Use string as argument instead of regexp. + RUBY + + expect_correction(<<~RUBY) + "foo\\nbar\\nbaz\\n".split("foo\\n.\\n") + RUBY + end + it 'registers an offense when the method is split' do expect_offense(<<~RUBY) 'a,b,c'.split(/,/)