class RuboCop::Cop::Style::OperatorMethodCall

Checks for redundant dot before operator method call. The target operator methods are ‘|`, `^`, `&`, “<=>“, `==`, `===`, `=~`, `>`, `>=`, `<`, “<=“, `<<`, `>>`, `+`, `-`, `*`, `/`, `%`, `**`, `~`, `!`, `!=`, and `!~`.

@example

# bad
foo.+ bar
foo.& bar

# good
foo + bar
foo & bar

Constants

INVALID_SYNTAX_ARG_TYPES
MSG
RESTRICT_ON_SEND

Public Instance Methods

on_send(node) click to toggle source

rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity

# File lib/rubocop/cop/style/operator_method_call.rb, line 30
def on_send(node)
  return unless (dot = node.loc.dot)
  return if node.receiver.const_type? || !node.arguments.one?

  _lhs, _op, rhs = *node
  if !rhs || method_call_with_parenthesized_arg?(rhs) || invalid_syntax_argument?(rhs)
    return
  end

  add_offense(dot) do |corrector|
    wrap_in_parentheses_if_chained(corrector, node)
    corrector.replace(dot, ' ')

    selector = node.loc.selector
    corrector.insert_after(selector, ' ') if insert_space_after?(node)
  end
end

Private Instance Methods

insert_space_after?(node) click to toggle source
# File lib/rubocop/cop/style/operator_method_call.rb, line 75
def insert_space_after?(node)
  _lhs, op, rhs = *node
  selector = node.loc.selector

  return true if selector.end_pos == rhs.source_range.begin_pos
  return false if node.parent&.call_type? # if chained, a space is already added

  # For `/` operations, if the RHS starts with a `(` without space,
  # add one to avoid a syntax error.
  range = selector.end.join(rhs.source_range.begin)
  return true if op == :/ && range.source == '('

  false
end
invalid_syntax_argument?(argument) click to toggle source
# File lib/rubocop/cop/style/operator_method_call.rb, line 58
def invalid_syntax_argument?(argument)
  type = argument.hash_type? ? argument.children.first&.type : argument.type

  INVALID_SYNTAX_ARG_TYPES.include?(type)
end
method_call_with_parenthesized_arg?(argument) click to toggle source

Checks for an acceptable case of ‘foo.+(bar).baz`.

# File lib/rubocop/cop/style/operator_method_call.rb, line 52
def method_call_with_parenthesized_arg?(argument)
  return false unless argument.parent.parent&.send_type?

  argument.children.first && argument.parent.parenthesized?
end
wrap_in_parentheses_if_chained(corrector, node) click to toggle source
# File lib/rubocop/cop/style/operator_method_call.rb, line 64
def wrap_in_parentheses_if_chained(corrector, node)
  return unless node.parent&.call_type?
  return if node.parent.first_argument == node

  operator = node.loc.selector

  ParenthesesCorrector.correct(corrector, node)
  corrector.insert_after(operator, ' ')
  corrector.wrap(node, '(', ')')
end