diff --git a/CHANGELOG.md b/CHANGELOG.md index 977f3ec2e4..d77a6c97e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## master (unreleased) +### Bug fixes + +* [#247](https://github.com/rubocop/rubocop-performance/issues/247): Fix an incorrect auto-correct for `Performance/MapCompact` when using multi-line trailing dot method calls. ([@koic][]) + ### Changes * [#245](https://github.com/rubocop/rubocop-performance/issues/245): Mark `Performance/DeletePrefix` and `Performance/DeleteSuffix` as unsafe. ([@koic][]) diff --git a/lib/rubocop/cop/performance/map_compact.rb b/lib/rubocop/cop/performance/map_compact.rb index 8923ed5422..705c723da7 100644 --- a/lib/rubocop/cop/performance/map_compact.rb +++ b/lib/rubocop/cop/performance/map_compact.rb @@ -56,23 +56,24 @@ def on_send(node) add_offense(range) do |corrector| corrector.replace(map_node.loc.selector, 'filter_map') - corrector.remove(compact_loc.dot) - corrector.remove(compact_method_range(node)) + remove_compact_method(corrector, node) end end private - def compact_method_range(compact_node) + def remove_compact_method(corrector, compact_node) chained_method = compact_node.parent compact_method_range = compact_node.loc.selector if compact_node.multiline? && chained_method&.loc.respond_to?(:selector) && !invoke_method_after_map_compact_on_same_line?(compact_node, chained_method) - range_by_whole_lines(compact_method_range, include_final_newline: true) + compact_method_range = range_by_whole_lines(compact_method_range, include_final_newline: true) else - compact_method_range + corrector.remove(compact_node.loc.dot) end + + corrector.remove(compact_method_range) end def invoke_method_after_map_compact_on_same_line?(compact_node, chained_method) diff --git a/spec/rubocop/cop/performance/map_compact_spec.rb b/spec/rubocop/cop/performance/map_compact_spec.rb index 5602bc9e20..cd9bc9e4a6 100644 --- a/spec/rubocop/cop/performance/map_compact_spec.rb +++ b/spec/rubocop/cop/performance/map_compact_spec.rb @@ -73,6 +73,22 @@ RUBY end + it 'registers an offense when using `map.compact.first` with multi-line trailing dot method calls' do + expect_offense(<<~RUBY) + collection. + map { |item| item.do_something }. + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `filter_map` instead. + compact. + first + RUBY + + expect_correction(<<~RUBY) + collection. + filter_map { |item| item.do_something }. + first + RUBY + end + it 'registers an offense when using `map.compact.first` and there is a line break after `map.compact`' do expect_offense(<<~RUBY) collection.map { |item| item.do_something }.compact