class RuboCop::Cop::Performance::CollectionLiteralInLoop
This cop identifies places where Array and Hash literals are used within loops. It is better to extract them into a local variable or constant to avoid unnecessary allocations on each iteration.
You can set the minimum number of elements to consider an offense with `MinSize`.
@example
# bad users.select do |user| %i[superadmin admin].include?(user.role) end # good admin_roles = %i[superadmin admin] users.select do |user| admin_roles.include?(user.role) end # good ADMIN_ROLES = %i[superadmin admin] ... users.select do |user| ADMIN_ROLES.include?(user.role) end
Constants
- ARRAY_METHODS
- ENUMERABLE_METHOD_NAMES
- HASH_METHODS
- LOOP_TYPES
- MSG
- NONMUTATING_ARRAY_METHODS
- NONMUTATING_HASH_METHODS
- POST_CONDITION_LOOP_TYPES
Public Instance Methods
on_send(node)
click to toggle source
# File lib/rubocop/cop/performance/collection_literal_in_loop.rb, line 80 def on_send(node) receiver, method, = *node.children return unless check_literal?(receiver, method) && parent_is_loop?(receiver) message = format(MSG, literal_class: literal_class(receiver)) add_offense(receiver, message: message) end
Private Instance Methods
check_literal?(node, method)
click to toggle source
# File lib/rubocop/cop/performance/collection_literal_in_loop.rb, line 90 def check_literal?(node, method) !node.nil? && nonmutable_method_of_array_or_hash?(node, method) && node.children.size >= min_size && node.recursive_basic_literal? end
enumerable_method?(method_name)
click to toggle source
# File lib/rubocop/cop/performance/collection_literal_in_loop.rb, line 130 def enumerable_method?(method_name) ENUMERABLE_METHOD_NAMES.include?(method_name) end
keyword_loop?(type)
click to toggle source
# File lib/rubocop/cop/performance/collection_literal_in_loop.rb, line 112 def keyword_loop?(type) LOOP_TYPES.include?(type) end
literal_class(node)
click to toggle source
# File lib/rubocop/cop/performance/collection_literal_in_loop.rb, line 122 def literal_class(node) if node.array_type? 'Array' elsif node.hash_type? 'Hash' end end
loop?(ancestor, node)
click to toggle source
# File lib/rubocop/cop/performance/collection_literal_in_loop.rb, line 106 def loop?(ancestor, node) keyword_loop?(ancestor.type) || kernel_loop?(ancestor) || node_within_enumerable_loop?(node, ancestor) end
min_size()
click to toggle source
# File lib/rubocop/cop/performance/collection_literal_in_loop.rb, line 134 def min_size Integer(cop_config['MinSize'] || 1) end
node_within_enumerable_loop?(node, ancestor)
click to toggle source
# File lib/rubocop/cop/performance/collection_literal_in_loop.rb, line 116 def node_within_enumerable_loop?(node, ancestor) enumerable_loop?(ancestor) do |receiver| receiver != node && !receiver&.descendants&.include?(node) end end
nonmutable_method_of_array_or_hash?(node, method)
click to toggle source
# File lib/rubocop/cop/performance/collection_literal_in_loop.rb, line 97 def nonmutable_method_of_array_or_hash?(node, method) (node.array_type? && ARRAY_METHODS.include?(method)) || (node.hash_type? && HASH_METHODS.include?(method)) end
parent_is_loop?(node)
click to toggle source
# File lib/rubocop/cop/performance/collection_literal_in_loop.rb, line 102 def parent_is_loop?(node) node.each_ancestor.any? { |ancestor| loop?(ancestor, node) } end