class RuboCop::Cop::Performance::MapCompact

In Ruby 2.7, `Enumerable#filter_map` has been added.

This cop identifies places where `map { … }.compact` can be replaced by `filter_map`. It is marked as unsafe auto-correction by default because `map { … }.compact` that is not compatible with `filter_map`.

source,ruby

true, false, nil].compact #=> [true, false
true, false, nil].filter_map(&:itself) #=> [true

@example

# bad
ary.map(&:foo).compact
ary.collect(&:foo).compact

# good
ary.filter_map(&:foo)
ary.map(&:foo).compact!
ary.compact.map(&:foo)

Constants

MSG
RESTRICT_ON_SEND

Public Instance Methods

on_send(node) click to toggle source
# File lib/rubocop/cop/performance/map_compact.rb, line 51
def on_send(node)
  return unless (map_node = map_compact(node))

  compact_loc = node.loc
  range = range_between(map_node.loc.selector.begin_pos, compact_loc.selector.end_pos)

  add_offense(range) do |corrector|
    corrector.replace(map_node.loc.selector, 'filter_map')
    remove_compact_method(corrector, node)
  end
end

Private Instance Methods

invoke_method_after_map_compact_on_same_line?(compact_node, chained_method) click to toggle source
# File lib/rubocop/cop/performance/map_compact.rb, line 79
def invoke_method_after_map_compact_on_same_line?(compact_node, chained_method)
  compact_node.loc.selector.line == chained_method.loc.selector.line
end
remove_compact_method(corrector, compact_node) click to toggle source
# File lib/rubocop/cop/performance/map_compact.rb, line 65
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) && chained_method.dot? &&
     !invoke_method_after_map_compact_on_same_line?(compact_node, chained_method)
    compact_method_range = range_by_whole_lines(compact_method_range, include_final_newline: true)
  else
    corrector.remove(compact_node.loc.dot)
  end

  corrector.remove(compact_method_range)
end