class RuboCop::Cop::Style::MultilineBlockLayout
}
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
arguments, if any, are on the same line as the start of the block.
after the start of the block. Additionally, it checks whether the block
This cop 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 = Parser::Source::Range.new(expression.source_buffer, expression.begin_pos, expression.end_pos) add_offense(node, range, msg) end
def autocorrect(node)
def autocorrect(node) lambda do |corrector| _method, args, block_body = *node unless args.children.empty? || args.loc.last_line == node.loc.line autocorrect_arguments(corrector, node, args) expr_before_body = args.source_range.end end return unless block_body expr_before_body ||= node.loc.begin if expr_before_body.line == block_body.loc.line autocorrect_body(corrector, node, block_body) end end end
def autocorrect_arguments(corrector, node, args)
def autocorrect_arguments(corrector, node, args) end_pos = range_with_surrounding_space(args.source_range, :right, false) .end_pos range = Parser::Source::Range.new(args.source_range.source_buffer, node.loc.begin.end.begin_pos, end_pos) corrector.replace(range, " |#{block_arg_string(args)}|") end
def autocorrect_body(corrector, node, block_body)
def autocorrect_body(corrector, node, block_body) first_node = if block_body.type == :begin block_body.children.first else block_body end block_start_col = node.source_range.column corrector.insert_before(first_node.source_range, "\n #{' ' * block_start_col}") end
def block_arg_string(args)
def block_arg_string(args) args.children.map do |arg| if arg.mlhs_type? "(#{block_arg_string(arg)})" else arg.source end end.join(', ') end
def on_block(node)
def on_block(node) end_loc = node.loc.end do_loc = node.loc.begin # Actually it's either do or {. return if do_loc.line == end_loc.line # One-liner, no newline needed. # A block node has three children: the block start, # the arguments, and the expression. We care if the block start # with arguments and the expression start on the same line. _block_start, args, last_expression = node.children unless args.children.empty? if do_loc.line != args.loc.last_line add_offense_for_expression(node, args, ARG_MSG) end end return unless last_expression expression_loc = last_expression.loc return unless do_loc.line == expression_loc.line add_offense_for_expression(node, last_expression, MSG) end