Class: RuboCop::Cop::Style::MapIntoArray

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

Overview

Checks for usages of ‘each` with `<<`, `push`, or `append` which can be replaced by `map`.

If ‘PreferredMethods` is configured for `map` in `Style/CollectionMethods`, this cop uses the specified method for replacement.

NOTE: The return value of ‘Enumerable#each` is `self`, whereas the return value of `Enumerable#map` is an `Array`. They are not autocorrected when a return value could be used because these types differ.

NOTE: It only detects when the mapping destination is a local variable initialized as an empty array and referred to only by the pushing operation. This is because, if not, it’s challenging to statically guarantee that the mapping destination variable remains an empty array:

source,ruby

ret = [] src.each { |e| ret << e * 2 } # ‘<<` method may mutate `ret`

dest = [] src.each { |e| dest << transform(e, dest) } # ‘transform` method may mutate `dest`


Examples:

# bad
dest = []
src.each { |e| dest << e * 2 }
dest

# good
dest = src.map { |e| e * 2 }

# good - contains another operation
dest = []
src.each { |e| dest << e * 2; puts e }
dest

Constant Summary collapse

MSG =
'Use `%<new_method_name>s` instead of `each` to map elements into an array.'

Constants inherited from Base

Base::RESTRICT_ON_SEND

Instance Attribute Summary

Attributes inherited from Base

#config, #processed_source

Class Method Summary collapse

Instance Method Summary collapse

Methods included from AutoCorrector

support_autocorrect?

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, lint?, match?, #message, #offenses, #on_investigation_end, #on_new_investigation, #on_other_file, #parse, #parser_engine, #ready, #relevant_file?, requires_gem, 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

Class Method Details

.joining_forcesObject



71
72
73
# File 'lib/rubocop/cop/style/map_into_array.rb', line 71

def self.joining_forces
  VariableForce
end

Instance Method Details

#after_leaving_scope(scope, _variable_table) ⇒ Object



75
76
77
# File 'lib/rubocop/cop/style/map_into_array.rb', line 75

def after_leaving_scope(scope, _variable_table)
  (@scopes ||= []) << scope
end

#each_block_with_push?(node) ⇒ Object



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

def_node_matcher :each_block_with_push?, <<-PATTERN
  [
    ^({begin kwbegin} ...)
    ({block numblock} (send _ :each) _
      (send (lvar _) {:<< :push :append} _))
  ]
PATTERN

#empty_array_asgn?(node) ⇒ Object



66
# File 'lib/rubocop/cop/style/map_into_array.rb', line 66

def_node_matcher :empty_array_asgn?, '(lvasgn _ (array))'

#lvar_ref?(node, name) ⇒ Object



69
# File 'lib/rubocop/cop/style/map_into_array.rb', line 69

def_node_matcher :lvar_ref?, '(lvar %1)'

#on_block(node) ⇒ Object Also known as: on_numblock



79
80
81
82
83
84
85
86
87
88
# File 'lib/rubocop/cop/style/map_into_array.rb', line 79

def on_block(node)
  return unless each_block_with_push?(node)

  dest_var = find_dest_var(node)
  return unless (asgn = find_closest_assignment(node, dest_var))
  return unless empty_array_asgn?(asgn)
  return unless dest_used_only_for_mapping?(node, dest_var, asgn)

  register_offense(node, dest_var, asgn)
end