lib/rubocop/rspec/wording.rb
# frozen_string_literal: true
module RuboCop
module RSpec
# RSpec example wording rewriter
class Wording
SHOULDNT_PREFIX = /\Ashould(?:n't|n’t| not)\b/i.freeze
SHOULDNT_BE_PREFIX = /#{SHOULDNT_PREFIX} be\b/i.freeze
WILL_NOT_PREFIX = /\Awill not\b/i.freeze
WONT_PREFIX = /\Awo(?:n't|n’t)\b/i.freeze
ES_SUFFIX_PATTERN = /(?:o|s|x|ch|sh|z)\z/i.freeze
IES_SUFFIX_PATTERN = /[^aeou]y\z/i.freeze
def initialize(text, ignore:, replace:)
@text = text
@ignores = ignore
@replacements = replace
end
# rubocop:disable Metrics/MethodLength
def rewrite
case text
when SHOULDNT_BE_PREFIX
replace_prefix(SHOULDNT_BE_PREFIX, 'is not')
when SHOULDNT_PREFIX
replace_prefix(SHOULDNT_PREFIX, 'does not')
when WILL_NOT_PREFIX
replace_prefix(WILL_NOT_PREFIX, 'does not')
when WONT_PREFIX
replace_prefix(WONT_PREFIX, 'does not')
else
remove_should_and_pluralize
end
end
# rubocop:enable Metrics/MethodLength
private
attr_reader :text, :ignores, :replacements
def replace_prefix(pattern, replacement)
text.sub(pattern) do |matched|
uppercase?(matched) ? replacement.upcase : replacement
end
end
def uppercase?(word)
word.upcase.eql?(word)
end
def remove_should_and_pluralize
_should, *words = text.split
words.each_with_index do |word, index|
next if ignored_word?(word)
words[index] = substitute(word)
break
end
words.join(' ')
end
def ignored_word?(word)
ignores.any? { |ignore| ignore.casecmp(word).zero? }
end
def substitute(word)
# NOTE: Custom replacements are case sensitive.
return replacements.fetch(word) if replacements.key?(word)
case word
when ES_SUFFIX_PATTERN then append_suffix(word, 'es')
when IES_SUFFIX_PATTERN then append_suffix(word[0..-2], 'ies')
else append_suffix(word, 's')
end
end
def append_suffix(word, suffix)
suffix = suffix.upcase if uppercase?(word)
"#{word}#{suffix}"
end
private_constant(*constants(false))
end
end
end