123456789_123456789_123456789_123456789_123456789_

Module: RuboCop::Cop::EndlessMethodBodyHelp

Relationships & Source Files
Extension / Inclusion / Inheritance Descendants
Included In:
Defined in: lib/rubocop/cop/mixin/endless_method_body_help.rb

Overview

Common functionality for checking whether a method body can become the body of an endless method definition without changing its meaning.

Instance Method Summary

Instance Method Details

#argument_receiving_call(def_node) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/mixin/endless_method_body_help.rb', line 70

def argument_receiving_call(def_node)
  call = def_node.parent
  return unless call&.call_type?

  call if call.arguments.any? { |argument| argument.equal?(def_node) }
end

#assigned_value(node) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/mixin/endless_method_body_help.rb', line 86

def assigned_value(node)
  while node.assignment? || node.rescue_type?
    node = node.rescue_type? ? node.body : node.children.last
  end
  node
end

#body_disallowed_in_argument?(body) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/mixin/endless_method_body_help.rb', line 56

def body_disallowed_in_argument?(body)
  command_body_in_argument?(body) || do_end_block_body_in_command_argument?(body)
end

#command_body_in_argument?(body) ⇒ Boolean (private)

private def foo = bar baz parses only on Ruby 4.0+, and only as the sole argument.

[ GitHub ]

  
# File 'lib/rubocop/cop/mixin/endless_method_body_help.rb', line 61

def command_body_in_argument?(body)
  return false unless command_call?(body)

  call = argument_receiving_call(body.parent)
  return false if call.nil?

  target_ruby_version < 4.0 || !call.arguments.one?
end

#command_call?(node) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/mixin/endless_method_body_help.rb', line 93

def command_call?(node)
  node = node.send_node if node.any_block_type?
  return false unless node.type?(:call, :super, :yield)

  node.arguments? && !node.parenthesized? && !node.operator_method? && !node.setter_method?
end

#command_disallowed_in_endless_body?(body) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/mixin/endless_method_body_help.rb', line 46

def command_disallowed_in_endless_body?(body)
  return true if body.assignment? && command_call?(assigned_value(body))
  return true if body_disallowed_in_argument?(body)
  return true if negated_command_call?(body)

  body.each_node(:any_block).any? do |block|
    block.keywords? && command_call?(block.send_node)
  end
end

#do_end_block_body_in_command_argument?(body) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/mixin/endless_method_body_help.rb', line 77

def do_end_block_body_in_command_argument?(body)
  call = argument_receiving_call(body.parent)
  return false if call.nil? || call.parenthesized?

  body.each_node(:any_block).any? do |block|
    block.keywords? && !block.send_node.lambda_literal?
  end
end

#endless_method_body?(body) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/mixin/endless_method_body_help.rb', line 10

def endless_method_body?(body)
  return false if body.type?(:begin, :kwbegin, :rescue, :ensure, :masgn)
  return false if low_precedence_body?(body)
  return false if ends_with_omitted_hash_value?(body) || ends_with_anonymous_argument?(body)
  return false if body.assignment? && multiple_values?(assigned_value(body))

  !command_disallowed_in_endless_body?(body)
end

#ends_with_anonymous_argument?(body) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/mixin/endless_method_body_help.rb', line 37

def ends_with_anonymous_argument?(body)
  forwarding = %i[forwarded_restarg forwarded_kwrestarg block_pass]

  body.each_descendant(*forwarding).any? do |argument|
    argument.source_range.end_pos == body.source_range.end_pos &&
      (!argument.block_pass_type? || argument.children.first.nil?)
  end
end

#ends_with_omitted_hash_value?(body) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/mixin/endless_method_body_help.rb', line 31

def ends_with_omitted_hash_value?(body)
  body.each_descendant(:pair).any? do |pair|
    pair.value_omission? && pair.source_range.end_pos == body.source_range.end_pos
  end
end

#low_precedence_body?(body) ⇒ Boolean (private)

def foo = bar and baz parses as (def foo = bar) and baz.

[ GitHub ]

  
# File 'lib/rubocop/cop/mixin/endless_method_body_help.rb', line 20

def low_precedence_body?(body)
  body.type?(:any_match_pattern, :while_post, :until_post) ||
    (body.type?(:and, :or) && body.semantic_operator?) ||
    (body.type?(:if, :while, :until) && body.modifier_form?)
end

#multiple_values?(node) ⇒ Boolean (private)

foo = 1, 2 and foo = *bar assign an array without brackets.

[ GitHub ]

  
# File 'lib/rubocop/cop/mixin/endless_method_body_help.rb', line 27

def multiple_values?(node)
  node.array_type? && !node.bracketed?
end

#negated_command_call?(node) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/mixin/endless_method_body_help.rb', line 100

def negated_command_call?(node)
  node.send_type? && node.prefix_bang? && command_call?(node.receiver)
end