class RuboCop::Cop::Style::MapCompactWithConditionalBlock
Prefer ‘select` or `reject` over `map { … }.compact`. This cop also handles `filter_map { … }`, similar to `map { … }.compact`.
@example
# bad array.map { |e| some_condition? ? e : next }.compact # bad array.filter_map { |e| some_condition? ? e : next } # bad array.map do |e| if some_condition? e else next end end.compact # bad array.map do |e| next if some_condition? e end.compact # bad array.map do |e| e if some_condition? end.compact # good array.select { |e| some_condition? } # good array.reject { |e| some_condition? }
Constants
- MSG
- RESTRICT_ON_SEND
Public Instance Methods
on_send(node)
click to toggle source
# File lib/rubocop/cop/style/map_compact_with_conditional_block.rb, line 76 def on_send(node) map_candidate = node.children.first if (block_argument, condition, return_value = conditional_block(map_candidate)) return unless node.method?(:compact) && node.arguments.empty? range = map_with_compact_range(node) elsif (block_argument, condition, return_value = conditional_block(node.parent)) return unless node.method?(:filter_map) range = filter_map_range(node) else return end inspect(node, block_argument, condition, return_value, range) end
Also aliased as: on_csend
Private Instance Methods
current(node)
click to toggle source
# File lib/rubocop/cop/style/map_compact_with_conditional_block.rb, line 148 def current(node) if node.method?(:compact) map_or_filter_map_method = node.children.first "#{map_or_filter_map_method.method_name} { ... }.compact" else 'filter_map { ... }' end end
filter_map_range(node)
click to toggle source
# File lib/rubocop/cop/style/map_compact_with_conditional_block.rb, line 162 def filter_map_range(node) node.loc.selector.join(node.parent.source_range.end) end
inspect(node, block_argument_node, condition_node, return_value_node, range)
click to toggle source
# File lib/rubocop/cop/style/map_compact_with_conditional_block.rb, line 96 def inspect(node, block_argument_node, condition_node, return_value_node, range) 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' current = current(node) add_offense(range, message: format(MSG, current: current, method: method)) do |corrector| return if part_of_ignored_node?(node) || ignored_node?(node) corrector.replace( range, "#{method} { |#{block_argument_node.source}| #{condition_node.source} }" ) ignore_node(node) end end
map_with_compact_range(node)
click to toggle source
# File lib/rubocop/cop/style/map_compact_with_conditional_block.rb, line 158 def map_with_compact_range(node) node.receiver.send_node.loc.selector.begin.join(node.source_range.end) end
returns_block_argument?(block_argument_node, return_value_node)
click to toggle source
# File lib/rubocop/cop/style/map_compact_with_conditional_block.rb, line 114 def returns_block_argument?(block_argument_node, return_value_node) block_argument_node.name == return_value_node.children.first end
truthy_branch?(node)
click to toggle source
# File lib/rubocop/cop/style/map_compact_with_conditional_block.rb, line 118 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
truthy_branch_for_guard?(node)
click to toggle source
# File lib/rubocop/cop/style/map_compact_with_conditional_block.rb, line 138 def truthy_branch_for_guard?(node) if_node = node.left_sibling if if_node.if? if_node.if_branch.arguments.any? else if_node.if_branch.arguments.none? end end
truthy_branch_for_if?(node)
click to toggle source
# File lib/rubocop/cop/style/map_compact_with_conditional_block.rb, line 128 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