class RuboCop::Cop::Layout::SpaceAroundOperators

a**b
my_number = 38 / 4
“apple” + “juice”
total = 3 * 4
# good
a ** b
my_number = 38/4
“apple”+“juice”
total = 3*4
# bad
@example
which should not have surrounding space.
Checks that operators have space around them, except for **

def self.autocorrect_incompatible_with

def self.autocorrect_incompatible_with
  [Style::SelfAssignment]
end

def align_hash_cop_config

def align_hash_cop_config
  config.for_cop('Layout/AlignHash')
end

def autocorrect(range)

def autocorrect(range)
  lambda do |corrector|
    if range.source =~ /\*\*/
      corrector.replace(range, '**')
    elsif range.source.end_with?("\n")
      corrector.replace(range, " #{range.source.strip}\n")
    else
      corrector.replace(range, " #{range.source.strip} ")
    end
  end
end

def check_operator(operator, right_operand)

def check_operator(operator, right_operand)
  with_space = range_with_surrounding_space(range: operator)
  return if with_space.source.start_with?("\n")
  offense(operator, with_space, right_operand) do |msg|
    add_offense(with_space, location: operator, message: msg)
  end
end

def excess_leading_space?(operator, with_space)

def excess_leading_space?(operator, with_space)
  with_space.source.start_with?(EXCESSIVE_SPACE) &&
    (!allow_for_alignment? || !aligned_with_operator?(operator))
end

def excess_trailing_space?(right_operand, with_space)

def excess_trailing_space?(right_operand, with_space)
  with_space.source.end_with?(EXCESSIVE_SPACE) &&
    (!allow_for_alignment? || !aligned_with_something?(right_operand))
end

def hash_table_style?

def hash_table_style?
  align_hash_cop_config &&
    align_hash_cop_config['EnforcedHashRocketStyle'] == 'table'
end

def offense(operator, with_space, right_operand)

def offense(operator, with_space, right_operand)
  msg = offense_message(operator, with_space, right_operand)
  yield msg if msg
end

def offense_message(operator, with_space, right_operand)

def offense_message(operator, with_space, right_operand)
  if operator.is?('**')
    'Space around operator `**` detected.' unless with_space.is?('**')
  elsif with_space.source !~ /^\s.*\s$/
    "Surrounding space missing for operator `#{operator.source}`."
  elsif excess_leading_space?(operator, with_space) ||
        excess_trailing_space?(right_operand, with_space)
    "Operator `#{operator.source}` should be surrounded " \
    'by a single space.'
  end
end

def on_binary(node)

def on_binary(node)
  _, rhs, = *node
  return unless rhs
  check_operator(node.loc.operator, rhs.source_range)
end

def on_if(node)

def on_if(node)
  return unless node.ternary?
  check_operator(node.loc.question, node.if_branch.source_range)
  check_operator(node.loc.colon, node.else_branch.source_range)
end

def on_pair(node)

def on_pair(node)
  return unless node.hash_rocket?
  return if hash_table_style? && !node.parent.pairs_on_same_line?
  check_operator(node.loc.operator, node.source_range)
end

def on_resbody(node)

def on_resbody(node)
  return unless node.loc.assoc
  _, variable, = *node
  check_operator(node.loc.assoc, variable.source_range)
end

def on_send(node)

def on_send(node)
  if node.setter_method?
    on_special_asgn(node)
  elsif regular_operator?(node)
    check_operator(node.loc.selector, node.first_argument.source_range)
  end
end

def on_special_asgn(node)

def on_special_asgn(node)
  _, _, right, = *node
  return unless right
  check_operator(node.loc.operator, right.source_range)
end

def operator_with_regular_syntax?(send_node)

def operator_with_regular_syntax?(send_node)
  send_node.operator_method? &&
    !IRREGULAR_METHODS.include?(send_node.method_name)
end

def regular_operator?(send_node)

def regular_operator?(send_node)
  !send_node.unary_operation? && !send_node.dot? &&
    operator_with_regular_syntax?(send_node)
end