Class: RuboCop::Cop::Style::CollectionCompact

Inherits:
Base
  • Object
show all
Extended by:
AutoCorrector, TargetRubyVersion
Includes:
AllowedReceivers, RangeHelp
Defined in:
lib/rubocop/cop/style/collection_compact.rb

Overview

Checks for places where custom logic on rejection nils from arrays and hashes can be replaced with {Array,Hash}#{compact,compact!}.

Examples:

# bad
array.reject(&:nil?)
array.delete_if(&:nil?)
array.reject { |e| e.nil? }
array.delete_if { |e| e.nil? }
array.select { |e| !e.nil? }

# good
array.compact

# bad
hash.reject!(&:nil?)
hash.reject! { |k, v| v.nil? }
hash.select! { |k, v| !v.nil? }

# good
hash.compact!

AllowedReceivers: ['params']

# good
params.reject(&:nil?)

Cop Safety Information:

  • It is unsafe by default because false positives may occur in the nil check of block arguments to the receiver object. Additionally, we can’t know the type of the receiver object for sure, which may result in false positives as well.

    For example, [[1, 2], [3, nil]].reject { |first, second| second.nil? } and [[1, 2], [3, nil]].compact are not compatible. This will work fine when the receiver is a hash object.

Constant Summary collapse

MSG =
'Use `%<good>s` instead of `%<bad>s`.'
RESTRICT_ON_SEND =
%i[reject delete_if reject! select select!].freeze
TO_ENUM_METHODS =
%i[to_enum lazy].freeze

Instance Attribute Summary

Attributes inherited from Base

#config, #processed_source

Instance Method Summary collapse

Methods included from AutoCorrector

support_autocorrect?

Methods included from TargetRubyVersion

minimum_target_ruby_version, required_minimum_ruby_version, support_target_ruby_version?

Methods included from AllowedReceivers

#allowed_receiver?, #allowed_receivers, #receiver_name

Methods inherited from Base

#active_support_extensions_enabled?, #add_global_offense, #add_offense, autocorrect_incompatible_with, badge, #begin_investigation, callbacks_needed, #callbacks_needed, #config_to_allow_offenses, #config_to_allow_offenses=, #cop_config, cop_name, #cop_name, department, documentation_url, exclude_from_registry, #excluded_file?, #external_dependency_checksum, inherited, #initialize, #inspect, joining_forces, lint?, match?, #message, #offenses, #on_investigation_end, #on_new_investigation, #on_other_file, #parse, #ready, #relevant_file?, support_autocorrect?, support_multiple_source?, #target_rails_version, #target_ruby_version

Methods included from ExcludeLimit

#exclude_limit

Methods included from AutocorrectLogic

#autocorrect?, #autocorrect_enabled?, #autocorrect_requested?, #autocorrect_with_disable_uncorrectable?, #correctable?, #disable_uncorrectable?, #safe_autocorrect?

Methods included from IgnoredNode

#ignore_node, #ignored_node?, #part_of_ignored_node?

Methods included from Util

silence_warnings

Constructor Details

This class inherits a constructor from RuboCop::Cop::Base

Instance Method Details

#on_send(node) ⇒ Object



82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/rubocop/cop/style/collection_compact.rb', line 82

def on_send(node)
  return unless (range = offense_range(node))
  return if allowed_receiver?(node.receiver)
  if (target_ruby_version <= 3.0 || node.method?(:delete_if)) && to_enum_method?(node)
    return
  end

  good = good_method_name(node)
  message = format(MSG, good: good, bad: range.source)

  add_offense(range, message: message) { |corrector| corrector.replace(range, good) }
end

#reject_method?(node) ⇒ Object



62
63
64
65
66
67
68
69
# File 'lib/rubocop/cop/style/collection_compact.rb', line 62

def_node_matcher :reject_method?, <<~PATTERN
  (block
    (send
      !nil? {:reject :delete_if :reject!})
    $(args ...)
    (send
      $(lvar _) :nil?))
PATTERN

#reject_method_with_block_pass?(node) ⇒ Object



55
56
57
58
59
# File 'lib/rubocop/cop/style/collection_compact.rb', line 55

def_node_matcher :reject_method_with_block_pass?, <<~PATTERN
  (send !nil? {:reject :delete_if :reject!}
    (block_pass
      (sym :nil?)))
PATTERN

#select_method?(node) ⇒ Object



72
73
74
75
76
77
78
79
80
# File 'lib/rubocop/cop/style/collection_compact.rb', line 72

def_node_matcher :select_method?, <<~PATTERN
  (block
    (send
      !nil? {:select :select!})
    $(args ...)
    (send
      (send
        $(lvar _) :nil?) :!))
PATTERN