class RuboCop::Cop::Style::SingleLineMethods
def no_op; end
# bad
@example AllowIfMethodIsEmpty: false
def no_op; end
# good
@example AllowIfMethodIsEmpty: true (default)
def some_method() = body
def @table.columns; end
def self.resource_class=(klass); end
# good
def @table.columns; super; end
def link_to(url); {:name => url}; end
def some_method; body end
# bad
@example
methods if there is only one statement in the body.
‘allow_always`, single-line methods will be auto-corrected to endless
If `Style/EndlessMethod` is enabled with `EnforcedStyle: allow_single_line` or
Endless methods added in Ruby 3.0 are also accepted by this cop.
It will accept single-line methods with no body.
This cop checks for single-line method definitions that contain a body.
def allow_empty?
def allow_empty? cop_config['AllowIfMethodIsEmpty'] end
def autocorrect(corrector, node)
def autocorrect(corrector, node) if correct_to_endless?(node.body) correct_to_endless(corrector, node) else correct_to_multiline(corrector, node) end end
def break_line_before(corrector, node, range, indent_steps: 1)
def break_line_before(corrector, node, range, indent_steps: 1) LineBreakCorrector.break_line_before( range: range, node: node, corrector: corrector, configured_width: configured_indentation_width, indent_steps: indent_steps ) end
def correct_to_endless(corrector, node)
def correct_to_endless(corrector, node) self_receiver = node.self_receiver? ? 'self.' : '' arguments = node.arguments.any? ? node.arguments.source : '()' body_source = method_body_source(node.body) replacement = "def #{self_receiver}#{node.method_name}#{arguments} = #{body_source}" corrector.replace(node, replacement) end
def correct_to_endless?(body_node)
def correct_to_endless?(body_node) return false if target_ruby_version < 3.0 return false if disallow_endless_method_style? return false unless body_node return false if body_node.parent.assignment_method? || NOT_SUPPORTED_ENDLESS_METHOD_BODY_TYPES.include?(body_node.type) !(body_node.begin_type? || body_node.kwbegin_type?) end
def correct_to_multiline(corrector, node)
def correct_to_multiline(corrector, node) if (body = node.body) && body.begin_type? && body.parenthesized_call? break_line_before(corrector, node, body) else each_part(body) do |part| break_line_before(corrector, node, part) end end break_line_before(corrector, node, node.loc.end, indent_steps: 0) move_comment(node, corrector) end
def disallow_endless_method_style?
def disallow_endless_method_style? endless_method_config = config.for_cop('Style/EndlessMethod') return false unless endless_method_config['Enabled'] endless_method_config['EnforcedStyle'] == 'disallow' end
def each_part(body)
def each_part(body) return unless body if body.begin_type? body.each_child_node { |part| yield part.source_range } else yield body.source_range end end
def method_body_source(method_body)
def method_body_source(method_body) if require_parentheses?(method_body) arguments_source = method_body.arguments.map(&:source).join(', ') body_source = "#{method_body.method_name}(#{arguments_source})" method_body.receiver ? "#{method_body.receiver.source}.#{body_source}" : body_source else method_body.source end end
def move_comment(node, corrector)
def move_comment(node, corrector) LineBreakCorrector.move_comment( eol_comment: processed_source.comment_at_line(node.source_range.line), node: node, corrector: corrector ) end
def on_def(node)
def on_def(node) return unless node.single_line? return if node.endless? return if allow_empty? && !node.body add_offense(node) { |corrector| autocorrect(corrector, node) } end
def require_parentheses?(method_body)
def require_parentheses?(method_body) method_body.send_type? && !method_body.arguments.empty? && !method_body.comparison_method? end