class RuboCop::Cop::Rails::EnumSyntax


enum :status, { active: 0, archived: 1 }, prefix: true
# good
enum status: { active: 0, archived: 1 }, _prefix: true
# bad
@example
Positional arguments should be used instead:
Defining enums with keyword arguments syntax is deprecated and will be removed in Rails 8.0.
Looks for enums written with keyword arguments syntax.

def check_and_correct_keyword_args(node)

def check_and_correct_keyword_args(node)
  enum?(node) do |pairs|
    pairs.each do |pair|
      next if option_key?(pair)
      correct_keyword_args(node, pair.key, pair.value, pairs[1..])
    end
  end
end

def check_enum_options(node)

def check_enum_options(node)
  enum_with_options?(node) do |key, _, options|
    options.children.each do |option|
      next unless option_key?(option)
      add_offense(option.key, message: format(MSG_OPTIONS, enum: enum_name_value(key))) do |corrector|
        corrector.replace(option.key, option.key.source.delete_prefix('_'))
      end
    end
  end
end

def correct_keyword_args(node, key, values, options)

def correct_keyword_args(node, key, values, options)
  add_offense(values, message: format(MSG, enum: enum_name_value(key))) do |corrector|
    # TODO: Multi-line autocorrect could be implemented in the future.
    next if multiple_enum_definitions?(node)
    preferred_syntax = "enum #{enum_name(key)}, #{values.source}#{correct_options(options)}"
    corrector.replace(node, preferred_syntax)
  end
end

def correct_options(options)

def correct_options(options)
  corrected_options = options.map do |pair|
    name = if pair.key.source[0] == '_'
             pair.key.source[1..]
           else
             pair.key.source
           end
    "#{name}: #{pair.value.source}"
  end.join(', ')
  ", #{corrected_options}" unless corrected_options.empty?
end

def enum_name(elem)

def enum_name(elem)
  case elem.type
  when :str
    elem.value.dump
  when :sym
    elem.value.inspect
  else
    elem.source
  end
end

def enum_name_value(key)

def enum_name_value(key)
  case key.type
  when :sym, :str
    key.value
  else
    key.source
  end
end

def multiple_enum_definitions?(node)

def multiple_enum_definitions?(node)
  keys = node.first_argument.keys.map { |key| key.source.delete_prefix('_') }
  filterred_keys = keys.filter { |key| !OPTION_NAMES.include?(key) }
  filterred_keys.size >= 2
end

def on_send(node)

def on_send(node)
  check_and_correct_keyword_args(node)
  check_enum_options(node)
end

def option_key?(pair)

def option_key?(pair)
  return false unless pair.respond_to?(:key)
  UNDERSCORED_OPTION_NAMES.include?(pair.key.source)
end