1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
|
# frozen_string_literal: true
module RuboCop
module Cop
module RSpec
# Sort RSpec metadata alphabetically.
#
# @example
# # bad
# describe 'Something', :b, :a
# context 'Something', foo: 'bar', baz: true
# it 'works', :b, :a, foo: 'bar', baz: true
#
# # good
# describe 'Something', :a, :b
# context 'Something', baz: true, foo: 'bar'
# it 'works', :a, :b, baz: true, foo: 'bar'
#
class SortMetadata < Base
extend AutoCorrector
include Metadata
include RangeHelp
MSG = 'Sort metadata alphabetically.'
def on_metadata(symbols, pairs)
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
private
def crime_scene(symbols, pairs)
metadata = symbols + pairs
range_between(
metadata.first.loc.expression.begin_pos,
metadata.last.loc.expression.end_pos
)
end
def replacement(symbols, pairs)
(sort_symbols(symbols) + sort_pairs(pairs)).map(&:source).join(', ')
end
def sorted?(symbols, pairs)
symbols == sort_symbols(symbols) && pairs == sort_pairs(pairs)
end
def sort_pairs(pairs)
pairs.sort_by { |pair| pair.key.source.downcase }
end
def sort_symbols(symbols)
symbols.sort_by do |symbol|
if %i[str sym].include?(symbol.type)
symbol.value.to_s.downcase
else
symbol.source.downcase
end
end
end
end
end
end
end
|