Code refactor

This commit is contained in:
Thomas Walpole 2018-11-08 11:04:31 -08:00
parent 9a69cedb49
commit 66689fd352
2 changed files with 39 additions and 26 deletions

View File

@ -28,6 +28,10 @@ module Capybara
private private
def remove_and_covered(strings) def remove_and_covered(strings)
# delete_if is documented to modify the array after every block iteration - this doesn't appear to be true
# uniq the strings to prevent identical strings from removing each other
strings.uniq!
# If we have "ab" and "abcd" required - only need to check for "abcd" # If we have "ab" and "abcd" required - only need to check for "abcd"
strings.delete_if do |sub_string| strings.delete_if do |sub_string|
strings.any? do |cover_string| strings.any? do |cover_string|
@ -65,8 +69,12 @@ module Capybara
exp.quantifier&.min || 1 exp.quantifier&.min || 1
end end
def max_repeat(exp)
exp.quantifier&.max || 1
end
def fixed_repeat?(exp) def fixed_repeat?(exp)
min_repeat(exp) == (exp.quantifier&.max || 1) min_repeat(exp) == max_repeat(exp)
end end
def optional?(exp) def optional?(exp)
@ -97,9 +105,10 @@ module Capybara
end end
end end
def extract_strings(expression, strings = [], alternation: false) def extract_strings(expression, alternation: false)
strings = []
expression.each do |exp| # rubocop:disable Metrics/BlockLength expression.each do |exp| # rubocop:disable Metrics/BlockLength
if optional?(exp) && !(alternation && zero_or_one?(exp)) if optional?(exp) && !alternation
strings.push(nil) strings.push(nil)
next next
end end
@ -115,39 +124,33 @@ module Capybara
end end
if exp.terminal? if exp.terminal?
case exp.type text = case exp.type
when :literal when :literal then exp.text
if zero_or_one?(exp) when :escape then exp.char
strings.push(Set.new([[''], [exp.text]]))
next
else
strings.push(exp.text * min_repeat(exp))
end
when :escape
if zero_or_one?(exp)
strings.push(Set.new([[''], [exp.text]]))
next
else
strings.push(exp.char * min_repeat(exp))
end
else else
strings.push(nil) strings.push(nil)
next
end end
elsif alternation && zero_or_one?(exp)
if optional?(exp)
strings.push(Set.new([[''], [text]]))
strings.push(nil) unless max_repeat(exp) == 1
next
else
strings.push(text * min_repeat(exp))
end
elsif optional?(exp)
strings.push(Set.new([[''], extract_strings(exp, alternation: true)])) strings.push(Set.new([[''], extract_strings(exp, alternation: true)]))
strings.push(nil) unless max_repeat(exp) == 1
next next
else else
min_repeat(exp).times { extract_strings(exp, strings, alternation: alternation) } min_repeat(exp).times { strings.concat extract_strings(exp, alternation: alternation) }
end end
strings.push(nil) unless fixed_repeat?(exp) strings.push(nil) unless fixed_repeat?(exp)
end end
strings strings
end end
def zero_or_one?(exp)
exp.quantity == [0, 1]
end
def alternative_strings(expression) def alternative_strings(expression)
alternatives = expression.alternatives.map { |sub_exp| extract_strings(sub_exp, alternation: true) } alternatives = expression.alternatives.map { |sub_exp| extract_strings(sub_exp, alternation: true) }
if alternatives.all?(&:any?) if alternatives.all?(&:any?)

View File

@ -124,7 +124,12 @@ RSpec.describe Capybara::Selector::RegexpDisassembler do
/cd(ef|gh)?ij/ => %w[cd ij], /cd(ef|gh)?ij/ => %w[cd ij],
/cd(ef|gh)+ij/ => %w[cd ij], /cd(ef|gh)+ij/ => %w[cd ij],
/cd(ef|gh){2}ij/ => %w[cd ij], /cd(ef|gh){2}ij/ => %w[cd ij],
/(cd(ef|g*))/ => %w[cd] /(cd(ef|g*))/ => %w[cd],
/ab(cd){0,2}ef/ => %w[ab ef],
/ab(cd){0,1}ef/ => %w[ab ef],
/ab(cd|cd)ef/ => %w[ab ef],
/ab(cd|cd)?ef/ => %w[ab ef],
/ab\\?cd/ => %w[ab cd]
}.each do |regexp, expected| }.each do |regexp, expected|
expect(Capybara::Selector::RegexpDisassembler.new(regexp).substrings).to eq expected expect(Capybara::Selector::RegexpDisassembler.new(regexp).substrings).to eq expected
end end
@ -154,7 +159,12 @@ RSpec.describe Capybara::Selector::RegexpDisassembler do
/(abc)?(d|e)/ => [%w[d], %w[e]], /(abc)?(d|e)/ => [%w[d], %w[e]],
/(abc*de)?(d|e)/ => [%w[d], %w[e]], /(abc*de)?(d|e)/ => [%w[d], %w[e]],
/(abc*de)?(d|e?)/ => [], /(abc*de)?(d|e?)/ => [],
/(abc)?(d|e?)/ => [] /(abc)?(d|e?)/ => [],
/ab(cd){0,2}ef/ => [%w[ab ef]],
/ab(cd){0,1}ef/ => [%w[abef], %w[abcdef]],
/ab(cd|cd)ef/ => [%w[abcdef]],
/ab(cd|cd)?ef/ => [%w[abef], %w[abcdef]],
/ab\\?cd/ => [%w[abcd], %w[ab\cd]]
) )
end end