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.reject { |e| e.nil? }
array.select { |e| !e.nil? }
array.filter { |e| !e.nil? }
array.grep_v(nil)
array.grep_v(NilClass)

# good
array.compact

# bad
hash.reject!(&:nil?)
hash.reject! { |k, v| v.nil? }
hash.select! { |k, v| !v.nil? }
hash.filter! { |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 reject! select select! filter filter! grep_v].freeze
TO_ENUM_METHODS =
%i[to_enum lazy].freeze
FILTER_METHODS =
%i[filter filter!].freeze

Constants included from RangeHelp

RangeHelp::BYTE_ORDER_MARK, RangeHelp::NOT_GIVEN

Instance Attribute Summary

Attributes inherited from Base

#config, #processed_source

Instance Method Summary collapse

Methods included from AutoCorrector

support_autocorrect?

Methods included from TargetRubyVersion

maximum_target_ruby_version, minimum_target_ruby_version, required_maximum_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, #always_autocorrect?, autocorrect_incompatible_with, badge, #begin_investigation, #callbacks_needed, callbacks_needed, #config_to_allow_offenses, #config_to_allow_offenses=, #contextual_autocorrect?, #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, #parser_engine, #ready, #relevant_file?, requires_gem, #string_literals_frozen_by_default?, support_autocorrect?, support_multiple_source?, #target_gem_version, #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

#grep_v_with_nil?(node) ⇒ Object



86
87
88
# File 'lib/rubocop/cop/style/collection_compact.rb', line 86

def_node_matcher :grep_v_with_nil?, <<~PATTERN
  (send _ :grep_v {(nil) (const {nil? cbase} :NilClass)})
PATTERN

#on_send(node) ⇒ Object Also known as: on_csend



90
91
92
93
94
95
96
97
98
99
100
# File 'lib/rubocop/cop/style/collection_compact.rb', line 90

def on_send(node)
  return if target_ruby_version < 2.6 && FILTER_METHODS.include?(node.method_name)
  return unless (range = offense_range(node))
  return if allowed_receiver?(node.receiver)
  return if target_ruby_version <= 3.0 && to_enum_method?(node)

  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



65
66
67
68
69
70
71
72
# File 'lib/rubocop/cop/style/collection_compact.rb', line 65

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

#reject_method_with_block_pass?(node) ⇒ Object



58
59
60
61
62
# File 'lib/rubocop/cop/style/collection_compact.rb', line 58

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

#select_method?(node) ⇒ Object



75
76
77
78
79
80
81
82
83
# File 'lib/rubocop/cop/style/collection_compact.rb', line 75

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