Class: RuboCop::Cop::Performance::CollectionLiteralInLoop
Relationships & Source Files | |
Super Chains via Extension / Inclusion / Inheritance | |
Class Chain:
self,
Base
|
|
Instance Chain:
self,
Base
|
|
Inherits: |
Base
|
Defined in: | lib/rubocop/cop/performance/collection_literal_in_loop.rb |
Overview
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
.
Constant Summary
-
ARRAY_METHODS =
# File 'lib/rubocop/cop/performance/collection_literal_in_loop.rb', line 56(ENUMERABLE_METHOD_NAMES | NONMUTATING_ARRAY_METHODS).to_set.freeze
-
ENUMERABLE_METHOD_NAMES =
# File 'lib/rubocop/cop/performance/collection_literal_in_loop.rb', line 41(Enumerable.instance_methods + [:each]).to_set.freeze
-
HASH_METHODS =
# File 'lib/rubocop/cop/performance/collection_literal_in_loop.rb', line 66(ENUMERABLE_METHOD_NAMES | NONMUTATING_HASH_METHODS).to_set.freeze
-
LOOP_TYPES =
# File 'lib/rubocop/cop/performance/collection_literal_in_loop.rb', line 39(POST_CONDITION_LOOP_TYPES + %i[while until for]).freeze
-
MSG =
# File 'lib/rubocop/cop/performance/collection_literal_in_loop.rb', line 35'Avoid immutable %<literal_class>s literals in loops. ' \ 'It is better to extract it into a local variable or a constant.'
-
NONMUTATING_ARRAY_METHODS =
# File 'lib/rubocop/cop/performance/collection_literal_in_loop.rb', line 42%i[& * + - <=> == [] all? any? assoc at bsearch bsearch_index collect combination compact count cycle deconstruct difference dig drop drop_while each each_index empty? eql? fetch filter find_index first flatten hash include? index inspect intersection join last length map max min minmax none? one? pack permutation product rassoc reject repeated_combination repeated_permutation reverse reverse_each rindex rotate sample select shuffle size slice sort sum take take_while to_a to_ary to_h to_s transpose union uniq values_at zip |].freeze
-
NONMUTATING_HASH_METHODS =
# File 'lib/rubocop/cop/performance/collection_literal_in_loop.rb', line 58%i[< <= == > >= [] any? assoc compact dig each each_key each_pair each_value empty? eql? fetch fetch_values filter flatten has_key? has_value? hash include? inspect invert key key? keys? length member? merge rassoc rehash reject select size slice to_a to_h to_hash to_proc to_s transform_keys transform_values value? values values_at].freeze
-
POST_CONDITION_LOOP_TYPES =
# File 'lib/rubocop/cop/performance/collection_literal_in_loop.rb', line 38%i[while_post until_post].freeze
Instance Method Summary
- #on_send(node)
- #check_literal?(node, method) ⇒ Boolean private
- #enumerable_method?(method_name) ⇒ Boolean private
- #keyword_loop?(type) ⇒ Boolean private
- #literal_class(node) private
- #loop?(ancestor, node) ⇒ Boolean private
- #min_size private
- #node_within_enumerable_loop?(node, ancestor) ⇒ Boolean private
- #nonmutable_method_of_array_or_hash?(node, method) ⇒ Boolean private
- #parent_is_loop?(node) ⇒ Boolean private
Instance Method Details
#check_literal?(node, method) ⇒ Boolean
(private)
# 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) ⇒ Boolean
(private)
# File 'lib/rubocop/cop/performance/collection_literal_in_loop.rb', line 128
def enumerable_method?(method_name) ENUMERABLE_METHOD_NAMES.include?(method_name) end
#keyword_loop?(type) ⇒ Boolean
(private)
# File 'lib/rubocop/cop/performance/collection_literal_in_loop.rb', line 110
def keyword_loop?(type) LOOP_TYPES.include?(type) end
#literal_class(node) (private)
[ GitHub ]# File 'lib/rubocop/cop/performance/collection_literal_in_loop.rb', line 120
def literal_class(node) if node.array_type? 'Array' elsif node.hash_type? 'Hash' end end
#loop?(ancestor, node) ⇒ Boolean
(private)
# 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 (private)
[ GitHub ]# File 'lib/rubocop/cop/performance/collection_literal_in_loop.rb', line 132
def min_size Integer(cop_config['MinSize'] || 1) end
#node_within_enumerable_loop?(node, ancestor) ⇒ Boolean
(private)
# File 'lib/rubocop/cop/performance/collection_literal_in_loop.rb', line 114
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) ⇒ Boolean
(private)
# 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
#on_send(node)
[ GitHub ]# 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) = format(MSG, literal_class: literal_class(receiver)) add_offense(receiver, message: ) end
#parent_is_loop?(node) ⇒ Boolean
(private)
# 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