From 171eaf32d7170edd7944705577878d99dfd9a755 Mon Sep 17 00:00:00 2001 From: fatkodima Date: Wed, 14 Oct 2020 17:47:46 +0300 Subject: [PATCH] Fix an error for `Style/StringConcatenation` when correcting nested concatenable parts --- CHANGELOG.md | 4 ++++ lib/rubocop/cop/style/string_concatenation.rb | 14 +++++++++++++- .../rubocop/cop/style/string_concatenation_spec.rb | 12 ++++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b09e1597ec..3551215a559 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## master (unreleased) +### Bug fixes + +* [#8892](https://github.com/rubocop-hq/rubocop/issues/8892): Fix an error for `Style/StringConcatenation` when correcting nested concatenable parts. ([@fatkodima][]) + ## 0.93.1 (2020-10-12) ### Bug fixes diff --git a/lib/rubocop/cop/style/string_concatenation.rb b/lib/rubocop/cop/style/string_concatenation.rb index 8f33df333d9..dae12524997 100644 --- a/lib/rubocop/cop/style/string_concatenation.rb +++ b/lib/rubocop/cop/style/string_concatenation.rb @@ -33,6 +33,10 @@ class StringConcatenation < Base } PATTERN + def on_new_investigation + @corrected_nodes = nil + end + def on_send(node) return unless string_concatenation?(node) @@ -42,8 +46,12 @@ def on_send(node) collect_parts(topmost_plus_node, parts) add_offense(topmost_plus_node) do |corrector| - if parts.none? { |part| uncorrectable?(part) } + correctable_parts = parts.none? { |part| uncorrectable?(part) } + if correctable_parts && !corrected_ancestor?(topmost_plus_node) corrector.replace(topmost_plus_node, replacement(parts)) + + @corrected_nodes ||= Set.new.compare_by_identity + @corrected_nodes.add(topmost_plus_node) end end end @@ -80,6 +88,10 @@ def uncorrectable?(part) part.each_descendant(:block).any? end + def corrected_ancestor?(node) + node.each_ancestor(:send).any? { |ancestor| @corrected_nodes&.include?(ancestor) } + end + def replacement(parts) interpolated_parts = parts.map do |part| diff --git a/spec/rubocop/cop/style/string_concatenation_spec.rb b/spec/rubocop/cop/style/string_concatenation_spec.rb index 85207e6dcd2..189348765f0 100644 --- a/spec/rubocop/cop/style/string_concatenation_spec.rb +++ b/spec/rubocop/cop/style/string_concatenation_spec.rb @@ -36,6 +36,18 @@ RUBY end + it 'correctly handles nested concatenable parts' do + expect_offense(<<~RUBY) + (user.vip? ? greeting + ', ' : '') + user.name + ' <' + user.email + '>' + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer string interpolation to string concatenation. + ^^^^^^^^^^^^^^^ Prefer string interpolation to string concatenation. + RUBY + + expect_correction(<<~RUBY) + "\#{(user.vip? ? "\#{greeting}, " : '')}\#{user.name} <\#{user.email}>" + RUBY + end + it 'does not register an offense when using `+` with all non string arguments' do expect_no_offenses(<<~RUBY) user.name + user.email