class RuboCop::Cop::Layout::MultilineBlockLayout
}
bar(i)
foo(i)
|
fit_on_one_line
that_would_not,
of_parameters,
long_list,
blah { |
# good
}
bar(i)
foo(i)
blah { |i|
# good
}
bar(i)
blah { |i| foo(i)
# bad
end
bar(i)
foo(i)
blah do |i|
# good
end
bar(i)
|i| foo(i)
blah do
# bad
end
bar(i)
blah do |i| foo(i)
# bad
@example
line would otherwise be too long, is accepted.
block. Putting block arguments on separate lines, because the whole
arguments, if any, are on the same line as the start of the
after the start of the block. Additionally, it checks whether the block
Checks whether the multiline do end blocks have a newline
def add_offense_for_expression(node, expr, msg)
def add_offense_for_expression(node, expr, msg) expression = expr.source_range range = range_between(expression.begin_pos, expression.end_pos) add_offense(range, message: msg) { |corrector| autocorrect(corrector, node) } end
def args_on_beginning_line?(node)
def args_on_beginning_line?(node) !node.arguments? || node.loc.begin.line == node.arguments.loc.last_line end
def autocorrect(corrector, node)
def autocorrect(corrector, node) unless args_on_beginning_line?(node) autocorrect_arguments(corrector, node) expr_before_body = node.arguments.source_range.end end return unless node.body expr_before_body ||= node.loc.begin return unless same_line?(expr_before_body, node.body) autocorrect_body(corrector, node, node.body) end
def autocorrect_arguments(corrector, node)
def autocorrect_arguments(corrector, node) end_pos = range_with_surrounding_space( node.arguments.source_range, side: :right, newlines: false ).end_pos range = range_between(node.loc.begin.end.begin_pos, end_pos) corrector.replace(range, " |#{block_arg_string(node, node.arguments)}|") end
def autocorrect_body(corrector, node, block_body)
def autocorrect_body(corrector, node, block_body) first_node = if block_body.begin_type? && !block_body.source.start_with?('(') block_body.children.first else block_body end block_start_col = node.source_range.column corrector.insert_before(first_node, "\n #{' ' * block_start_col}") end
def block_arg_string(node, args)
def block_arg_string(node, args) arg_string = args.children.map do |arg| if arg.mlhs_type? "(#{block_arg_string(node, arg)})" else arg.source end end.join(', ') arg_string += ',' if include_trailing_comma?(node.arguments) arg_string end
def characters_needed_for_space_and_pipes(node)
def characters_needed_for_space_and_pipes(node) if node.source.lines.first.end_with?("|\n") PIPE_SIZE else (PIPE_SIZE * 2) + 1 end end
def include_trailing_comma?(args)
def include_trailing_comma?(args) arg_count = args.each_descendant(:arg).to_a.size arg_count == 1 && args.source.include?(',') end
def line_break_necessary_in_args?(node)
def line_break_necessary_in_args?(node) needed_length_for_args(node) > max_line_length end
def needed_length_for_args(node)
def needed_length_for_args(node) node.source_range.column + characters_needed_for_space_and_pipes(node) + node.source.lines.first.chomp.length + block_arg_string(node, node.arguments).length end
def on_block(node)
def on_block(node) return if node.single_line? unless args_on_beginning_line?(node) || line_break_necessary_in_args?(node) add_offense_for_expression(node, node.arguments, ARG_MSG) end return unless node.body && same_line?(node.loc.begin, node.body) add_offense_for_expression(node, node.body, MSG) end