class RuboCop::Cop::Style::Alias

alias_method :bar, :foo
# good
alias bar foo
alias :bar :foo
# bad
@example EnforcedStyle: prefer_alias_method
alias bar foo
# good
alias :bar :foo
alias_method :bar, :foo
# bad
@example EnforcedStyle: prefer_alias (default)
It also flags uses of ‘alias :symbol` rather than `alias bareword`.
depending on configuration.
This cop enforces the use of either `#alias` or `#alias_method`

def add_offense_for_args(node)

def add_offense_for_args(node)
  existing_args  = node.children.map(&:source).join(' ')
  preferred_args = node.children.map { |a| a.source[1..-1] }.join(' ')
  arg_ranges     = node.children.map(&:source_range)
  msg            = format(MSG_SYMBOL_ARGS,
                          prefer: preferred_args,
                          current: existing_args)
  add_offense(node, location: arg_ranges.reduce(&:join), message: msg)
end

def alias_keyword_possible?(node)

def alias_keyword_possible?(node)
  scope_type(node) != :dynamic && node.arguments.all?(&:sym_type?)
end

def alias_method_possible?(node)

def alias_method_possible?(node)
  scope_type(node) != :instance_eval &&
    node.children.none?(&:gvar_type?)
end

def autocorrect(node)

def autocorrect(node)
  if node.send_type?
    correct_alias_method_to_alias(node)
  elsif scope_type(node) == :dynamic || style == :prefer_alias_method
    correct_alias_to_alias_method(node)
  else
    correct_alias_with_symbol_args(node)
  end
end

def bareword?(sym_node)

def bareword?(sym_node)
  !sym_node.source.start_with?(':')
end

def correct_alias_method_to_alias(send_node)

def correct_alias_method_to_alias(send_node)
  lambda do |corrector|
    new, old = *send_node.arguments
    replacement = "alias #{new.children.first} #{old.children.first}"
    corrector.replace(send_node.source_range, replacement)
  end
end

def correct_alias_to_alias_method(node)

def correct_alias_to_alias_method(node)
  lambda do |corrector|
    new, old = *node
    replacement = "alias_method :#{new.children.first}, " \
                  ":#{old.children.first}"
    corrector.replace(node.source_range, replacement)
  end
end

def correct_alias_with_symbol_args(node)

def correct_alias_with_symbol_args(node)
  lambda do |corrector|
    new, old = *node
    corrector.replace(new.source_range, new.children.first.to_s)
    corrector.replace(old.source_range, old.children.first.to_s)
  end
end

def lexical_scope_type(node)

def lexical_scope_type(node)
  node.each_ancestor(:class, :module) do |ancestor|
    return ancestor.class_type? ? 'in a class body' : 'in a module body'
  end
  'at the top level'
end

def on_alias(node)

def on_alias(node)
  return unless alias_method_possible?(node)
  if scope_type(node) == :dynamic || style == :prefer_alias_method
    add_offense(node, location: :keyword, message: MSG_ALIAS)
  elsif node.children.none? { |arg| bareword?(arg) }
    add_offense_for_args(node)
  end
end

def on_send(node)

def on_send(node)
  return unless node.command?(:alias_method)
  return unless style == :prefer_alias && alias_keyword_possible?(node)
  msg = format(MSG_ALIAS_METHOD, current: lexical_scope_type(node))
  add_offense(node, location: :selector, message: msg)
end

def scope_type(node)

(:dynamic)? If we're in an instance_eval block, return that.
class or module block (:lexical)? Or will it be something else
In this expression, will `self` be the same as the innermost enclosing
def scope_type(node)
  while (parent = node.parent)
    case parent.type
    when :class, :module
      return :lexical
    when :def, :defs
      return :dynamic
    when :block
      return :instance_eval if parent.method_name == :instance_eval
      return :dynamic
    end
    node = parent
  end
  :lexical
end