class RuboCop::Cop::Layout::SpaceAroundOperators

a ** b
# good
a**b
# bad
@example EnforcedStyleForExponentOperator: space
a**b
# good
a ** b
# bad
@example EnforcedStyleForExponentOperator: no_space (default)
}
11 => 3
1 => 2,
{
# bad
@example AllowForAlignment: false
}
11 => 3
1 => 2,
{
# good
@example AllowForAlignment: true (default)
my_number = 38 / 4
“apple” + “juice”
total = 3 * 4
# good
my_number = 38/4
“apple”+“juice”
total = 3*4
# bad
@example
the previous or next line, not counting empty lines or comment lines.
uses of extra spacing if the intent is to align with an operator on
This cop has ‘AllowForAlignment` option. When `true`, allows most
around operators.
It allows vertical alignment consisting of one or more whitespace
should or shouldn’t have surrounding space depending on configuration.
Checks that operators have space around them, except for ** which

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/HashAlignment')
end

def autocorrect(corrector, range)

def autocorrect(corrector, range)
  if /\*\*/.match?(range.source) && !space_around_exponent_operator?
    corrector.replace(range, '**')
  elsif range.source.end_with?("\n")
    corrector.replace(range, " #{range.source.strip}\n")
  else
    enclose_operator_with_space(corrector, range)
  end
end

def check_operator(type, operator, right_operand)

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

def enclose_operator_with_space(corrector, range)

def enclose_operator_with_space(corrector, range)
  operator = range.source
  # If `ForceEqualSignAlignment` is true, `Layout/ExtraSpacing` cop
  # inserts spaces before operator. If `Layout/SpaceAroundOperators` cop
  # inserts a space, it collides and raises the infinite loop error.
  if force_equal_sign_alignment? && !operator.end_with?(' ')
    corrector.insert_after(range, ' ')
  else
    corrector.replace(range, " #{operator.strip} ")
  end
end

def excess_leading_space?(type, operator, with_space)

def excess_leading_space?(type, operator, with_space)
  return false unless allow_for_alignment?
  return false unless with_space.source.start_with?(EXCESSIVE_SPACE)
  return !aligned_with_operator?(operator) unless type == :assignment
  token            = Token.new(operator, nil, operator.source)
  align_preceding  = aligned_with_preceding_assignment(token)
  return false if align_preceding == :yes ||
                  aligned_with_subsequent_assignment(token) == :none
  aligned_with_subsequent_assignment(token) != :yes
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 force_equal_sign_alignment?

def force_equal_sign_alignment?
  config.for_cop('Layout/ExtraSpacing')['ForceEqualSignAlignment']
end

def hash_table_style?

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

def offense(type, operator, with_space, right_operand)

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

def offense_message(type, operator, with_space, right_operand)

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

def on_assignment(node)

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

def on_binary(node)

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

def on_casgn(node)

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

def on_if(node)

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

def on_match_pattern(node)

def on_match_pattern(node)
  return if target_ruby_version < 3.0
  check_operator(:match_pattern, node.loc.operator, node.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(:pair, node.loc.operator, node.source_range)
end

def on_resbody(node)

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

def on_sclass(node)

def on_sclass(node)
  check_operator(:sclass, node.loc.operator, node.source_range)
end

def on_send(node)

def on_send(node)
  return if rational_literal?(node)
  if node.setter_method?
    on_special_asgn(node)
  elsif regular_operator?(node)
    check_operator(:send, 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(:special_asgn, 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

def should_not_have_surrounding_space?(operator)

def should_not_have_surrounding_space?(operator)
  operator.is?('**') ? !space_around_exponent_operator? : false
end

def space_around_exponent_operator?

def space_around_exponent_operator?
  cop_config['EnforcedStyleForExponentOperator'] == 'space'
end