class RuboCop::Cop::RSpec::SortMetadata

context ‘Something’, :z, variable, :a, :b
describe ‘Something’, ‘description’, :a, :b, :z
# good, trailing metadata is sorted
it ‘works’, :a, :b, baz: true, foo: ‘bar’
context ‘Something’, baz: true, foo: ‘bar’
describe ‘Something’, :a, :b
# good
it ‘works’, :b, :a, foo: ‘bar’, baz: true
context ‘Something’, foo: ‘bar’, baz: true
describe ‘Something’, :b, :a
# bad
@example
Only the trailing metadata is sorted.
Sort RSpec metadata alphabetically.

def crime_scene(symbols, pairs)

def crime_scene(symbols, pairs)
  metadata = symbols + pairs
  range_between(
    metadata.first.source_range.begin_pos,
    metadata.last.source_range.end_pos
  )
end

def last_arg_could_be_a_hash?(args)

def last_arg_could_be_a_hash?(args)
  args.last && match_ambiguous_trailing_metadata?(args.last.parent)
end

def on_metadata(args, hash)

def on_metadata(args, hash)
  pairs = hash&.pairs || []
  symbols = trailing_symbols(args)
  return if sorted?(symbols, pairs)
  crime_scene = crime_scene(symbols, pairs)
  add_offense(crime_scene) do |corrector|
    corrector.replace(crime_scene, replacement(symbols, pairs))
  end
end

def replacement(symbols, pairs)

def replacement(symbols, pairs)
  (sort_symbols(symbols) + sort_pairs(pairs)).map(&:source).join(', ')
end

def sort_pairs(pairs)

def sort_pairs(pairs)
  pairs.sort_by { |pair| pair.key.source.downcase }
end

def sort_symbols(symbols)

def sort_symbols(symbols)
  symbols.sort_by { |symbol| symbol.value.to_s.downcase }
end

def sorted?(symbols, pairs)

def sorted?(symbols, pairs)
  symbols == sort_symbols(symbols) && pairs == sort_pairs(pairs)
end

def trailing_symbols(args)

def trailing_symbols(args)
  args = args[...-1] if last_arg_could_be_a_hash?(args)
  args.reverse.take_while(&:sym_type?).reverse
end