class RuboCop::Cop::Style::SwapValues


x, y = y, x
# good
y = tmp
x = y
tmp = x
# bad
@example
swap variables will be removed, but may be referred to elsewhere.
Autocorrection is unsafe, because the temporary variable used to
@safety
Enforces the use of shorthand-style swapping of 2 variables.

def allowed_assignment?(node)

def allowed_assignment?(node)
  node.parent&.mlhs_type? || node.parent&.shorthand_asgn?
end

def correction_range(tmp_assign, y_assign)

def correction_range(tmp_assign, y_assign)
  range_by_whole_lines(
    range_between(tmp_assign.source_range.begin_pos, y_assign.source_range.end_pos)
  )
end

def lhs(node)

def lhs(node)
  case node.type
  when :casgn
    namespace, name, = *node
    if namespace
      "#{namespace.const_name}::#{name}"
    else
      name.to_s
    end
  else
    node.children[0].to_s
  end
end

def message(x_assign, y_assign)

def message(x_assign, y_assign)
  format(
    MSG,
    x_line: x_assign.first_line,
    y_line: y_assign.first_line,
    replacement: replacement(x_assign)
  )
end

def on_asgn(node)

def on_asgn(node)
  return if allowed_assignment?(node)
  tmp_assign = node
  x_assign, y_assign = *node.right_siblings.take(2)
  return unless x_assign && y_assign && swapping_values?(tmp_assign, x_assign, y_assign)
  add_offense(node, message: message(x_assign, y_assign)) do |corrector|
    range = correction_range(tmp_assign, y_assign)
    corrector.replace(range, replacement(x_assign))
  end
end

def replacement(x_assign)

def replacement(x_assign)
  x = lhs(x_assign)
  y = rhs(x_assign)
  "#{x}, #{y} = #{y}, #{x}"
end

def rhs(node)

def rhs(node)
  case node.type
  when :casgn
    node.children[2].source
  else
    node.children[1].source
  end
end

def simple_assignment?(node)

def simple_assignment?(node)
  return false unless node.respond_to?(:type)
  SIMPLE_ASSIGNMENT_TYPES.include?(node.type)
end

def swapping_values?(tmp_assign, x_assign, y_assign)

def swapping_values?(tmp_assign, x_assign, y_assign)
  simple_assignment?(tmp_assign) &&
    simple_assignment?(x_assign) &&
    simple_assignment?(y_assign) &&
    lhs(x_assign) == rhs(tmp_assign) &&
    lhs(y_assign) == rhs(x_assign) &&
    rhs(y_assign) == lhs(tmp_assign)
end