Skip to content

Commit

Permalink
Auto-correct dstr nodes in StringConcatenation
Browse files Browse the repository at this point in the history
The cop documentation says that complex cases are skipped in auto-correction,
but the concatenation of strings where at least one has interpolation isn't
really that complex. I think we can safely add auto-correction in those cases.
  • Loading branch information
jonas054 committed Apr 6, 2021
1 parent 32bd7c2 commit c840536
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 17 deletions.
6 changes: 0 additions & 6 deletions lib/rubocop/cop/mixin/percent_literal.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,6 @@ def begin_source(node)
def type(node)
node.loc.begin.source[0..-2]
end

# A range containing only the contents of the percent literal (e.g. in
# %i{1 2 3} this will be the range covering '1 2 3' only)
def contents_range(node)
range_between(node.loc.begin.end_pos, node.loc.end.begin_pos)
end
end
end
end
6 changes: 6 additions & 0 deletions lib/rubocop/cop/mixin/range_help.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ def source_range(source_buffer, line_number, column, length = 1)
Parser::Source::Range.new(source_buffer, begin_pos, end_pos)
end

# A range containing only the contents of a literal with delimiters (e.g. in
# `%i{1 2 3}` this will be the range covering `1 2 3` only).
def contents_range(node)
range_between(node.loc.begin.end_pos, node.loc.end.begin_pos)
end

def range_between(start_pos, end_pos)
Parser::Source::Range.new(processed_source.buffer, start_pos, end_pos)
end
Expand Down
14 changes: 7 additions & 7 deletions lib/rubocop/cop/style/string_concatenation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ module Style
#
class StringConcatenation < Base
include Util
include RangeHelp
extend AutoCorrector

MSG = 'Prefer string interpolation to string concatenation.'
Expand Down Expand Up @@ -103,7 +104,6 @@ def plus_node?(node)

def uncorrectable?(part)
part.multiline? ||
part.dstr_type? ||
(part.str_type? && part.heredoc?) ||
part.each_descendant(:block).any?
end
Expand All @@ -115,12 +115,12 @@ def corrected_ancestor?(node)
def replacement(parts)
interpolated_parts =
parts.map do |part|
if part.str_type?
if single_quoted?(part)
part.value.gsub(/(\\|")/, '\\\\\&')
else
part.value.inspect[1..-2]
end
case part.type
when :str
value = part.value
single_quoted?(part) ? value.gsub(/(\\|")/, '\\\\\&') : value.inspect[1..-2]
when :dstr
contents_range(part).source
else
"\#{#{part.source}}"
end
Expand Down
10 changes: 6 additions & 4 deletions spec/rubocop/cop/style/string_concatenation_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -109,13 +109,15 @@
end

context 'nested interpolation' do
it 'registers an offense but does not correct' do
expect_offense(<<~RUBY)
"foo" + "bar: \#{baz}"
it 'registers an offense and corrects' do
expect_offense(<<~'RUBY')
"foo" + "bar: #{baz}"
^^^^^^^^^^^^^^^^^^^^^ Prefer string interpolation to string concatenation.
RUBY

expect_no_corrections
expect_correction(<<~'RUBY')
"foobar: #{baz}"
RUBY
end
end

Expand Down

0 comments on commit c840536

Please sign in to comment.