class RuboCop::Cop::Style::MapCompactWithConditionalBlock
array.reject { |e| some_condition? }
# good
array.select { |e| some_condition? }
# good
end.compact
e if some_condition?
array.map do |e|
# bad
end.compact
e
next if some_condition?
array.map do |e|
# bad
end.compact
end
next
else
e
if some_condition?
array.map do |e|
# bad
array.map { |e| some_condition? ? e : next }.compact
# bad
@example
Prefer ‘select` or `reject` over `map { … }.compact`.
def on_send(node)
def on_send(node) map_and_compact?(node) do |block_argument_node, condition_node, return_value_node| return unless returns_block_argument?(block_argument_node, return_value_node) return if condition_node.parent.elsif? method = truthy_branch?(return_value_node) ? 'select' : 'reject' range = range(node) add_offense(range, message: format(MSG, method: method)) do |corrector| corrector.replace( range, "#{method} { |#{block_argument_node.source}| #{condition_node.source} }" ) end end end
def range(node)
def range(node) buffer = node.source_range.source_buffer map_node = node.receiver.send_node begin_pos = map_node.loc.selector.begin_pos end_pos = node.source_range.end_pos Parser::Source::Range.new(buffer, begin_pos, end_pos) end
def returns_block_argument?(block_argument_node, return_value_node)
def returns_block_argument?(block_argument_node, return_value_node) block_argument_node.name == return_value_node.children.first end
def truthy_branch?(node)
def truthy_branch?(node) if node.parent.begin_type? truthy_branch_for_guard?(node) elsif node.parent.next_type? truthy_branch_for_if?(node.parent) else truthy_branch_for_if?(node) end end
def truthy_branch_for_guard?(node)
def truthy_branch_for_guard?(node) if_node = node.left_sibling if if_node.if? || if_node.ternary? if_node.else_branch.nil? elsif if_node.unless? if_node.if_branch.nil? end end
def truthy_branch_for_if?(node)
def truthy_branch_for_if?(node) if_node = node.parent if if_node.if? || if_node.ternary? if_node.if_branch == node elsif if_node.unless? if_node.else_branch == node end end