class RuboCop::Cop::Style::For
end
end
puts n
for n in [1, 2, 3] do
def foo
# good
end
end
puts n
[1, 2, 3].each do |n|
def foo
# bad
@example EnforcedStyle: for
end
end
puts n
[1, 2, 3].each do |n|
def foo
# good
end
end
puts n
for n in [1, 2, 3] do
def foo
# bad
@example EnforcedStyle: each (default)
allowed.
parameter. An ‘each` call with a block on a single line is always
preferred alternative is set in the EnforcedStyle configuration
This cop looks for uses of the `for` keyword or `each` method. The
def autocorrect(node)
def autocorrect(node) if style == :each autocorrect_to_each(node) else autocorrect_to_for(node) end end
def autocorrect_to_each(node)
def autocorrect_to_each(node) item, enumerable = deconstruct_for(node) end_pos = end_position(node, enumerable) replacement_range = replacement_range(node, end_pos) enum_source = enumerable_source(enumerable) correction = "#{enum_source}.each do |#{item.source}|" ->(corrector) { corrector.replace(replacement_range, correction) } end
def autocorrect_to_for(node)
def autocorrect_to_for(node) enumerable, items = deconstruct_each(node) variables = extract_variables(items) if variables.nil? replacement_range = replacement_range(node, node.loc.begin.end_pos) correction = "for _ in #{enumerable.source} do" else replacement_range = replacement_range(node, items.loc.expression.end_pos) correction = "for #{variables.source} in #{enumerable.source} do" end ->(corrector) { corrector.replace(replacement_range, correction) } end
def end_position(node, enumerable)
def end_position(node, enumerable) if node.do? node.loc.begin.end_pos elsif enumerable.begin_type? enumerable.loc.end.end_pos else enumerable.loc.expression.end.end_pos end end
def enumerable_source(enumerable)
def enumerable_source(enumerable) return "(#{enumerable.source})" if wrap_into_parentheses?(enumerable) enumerable.source end
def incorrect_style_detected(node)
def incorrect_style_detected(node) add_offense(node, message: PREFER_FOR) do opposite_style_detected end end
def on_block(node)
def on_block(node) return if node.single_line? return unless node.send_node.method?(:each) && !node.send_node.arguments? if style == :for incorrect_style_detected(node) else correct_style_detected end end
def on_for(node)
def on_for(node) if style == :each add_offense(node, message: PREFER_EACH) do opposite_style_detected end else correct_style_detected end end
def replacement_range(node, end_pos)
def replacement_range(node, end_pos) Parser::Source::Range.new(node.loc.expression.source_buffer, node.loc.expression.begin_pos, end_pos) end
def wrap_into_parentheses?(enumerable)
def wrap_into_parentheses?(enumerable) enumerable.irange_type? || enumerable.erange_type? end