diff --git a/lib/capybara/selector/regexp_disassembler.rb b/lib/capybara/selector/regexp_disassembler.rb index 5de51a52..e9ef4932 100644 --- a/lib/capybara/selector/regexp_disassembler.rb +++ b/lib/capybara/selector/regexp_disassembler.rb @@ -11,7 +11,7 @@ module Capybara end def alternated_substrings - @options ||= begin + @alternated_substrings ||= begin process(alternation: true) end end @@ -26,12 +26,11 @@ module Capybara def process(alternation:) strs = extract_strings(Regexp::Parser.parse(@regexp), [''], alternation: alternation) - strs = collapse(combine(strs).map &:flatten) + strs = collapse(combine(strs).map(&:flatten)) strs.each { |str| str.map!(&:upcase) } if @regexp.casefold? strs end - def min_repeat(exp) exp.quantifier&.min || 1 end @@ -44,7 +43,6 @@ module Capybara min_repeat(exp).zero? end - def combine(strs) suffixes = [[]] strs.reverse_each do |str| @@ -65,7 +63,7 @@ module Capybara def collapse(strs) strs.map do |substrings| - substrings.slice_before { |str| str.empty? }.map(&:join).reject(&:empty?).uniq + substrings.slice_before(&:empty?).map(&:join).reject(&:empty?).uniq end end @@ -77,12 +75,7 @@ module Capybara end if %i[meta].include?(exp.type) && !exp.terminal? && alternation - alternatives = exp.alternatives.map { |sub_exp| extract_strings(sub_exp, [], alternation: true) } - if alternatives.all? { |alt| alt.any? { |a| !a.empty? } } - strings.push(Set.new(alternatives)) - else - strings.push('') - end + strings.push(alternative_strings(exp)) next end @@ -94,9 +87,9 @@ module Capybara if exp.terminal? case exp.type when :literal - strings.push (exp.text * min_repeat(exp)) + strings.push(exp.text * min_repeat(exp)) when :escape - strings.push (exp.char * min_repeat(exp)) + strings.push(exp.char * min_repeat(exp)) else strings.push('') end @@ -107,6 +100,15 @@ module Capybara end strings end + + def alternative_strings(expression) + alternatives = expression.alternatives.map { |sub_exp| extract_strings(sub_exp, [], alternation: true) } + if alternatives.all? { |alt| alt.any? { |a| !a.empty? } } + Set.new(alternatives) + else + strings.push('') + end + end end end end diff --git a/spec/regexp_dissassembler_spec.rb b/spec/regexp_dissassembler_spec.rb index cc8a113f..58e8590e 100644 --- a/spec/regexp_dissassembler_spec.rb +++ b/spec/regexp_dissassembler_spec.rb @@ -113,16 +113,16 @@ RSpec.describe Capybara::Selector::RegexpDisassembler do it 'handles alternation for #options' do verify_alternated_strings( - /abc|def/ => [%w[abc],%w[def]], - /ab(?:c|d)/ => [%w[abc],%w[abd]], - /ab(c|d|e)fg/ => [%w[abcfg],%w[abdfg],%w[abefg]], + /abc|def/ => [%w[abc], %w[def]], + /ab(?:c|d)/ => [%w[abc], %w[abd]], + /ab(c|d|e)fg/ => [%w[abcfg], %w[abdfg], %w[abefg]], /ab?(c|d)fg/ => [%w[a cfg], %w[a dfg]], /ab(c|d)ef/ => [%w[abcef], %w[abdef]], /ab(cd?|ef)g/ => [%w[abc g], %w[abefg]], /ab(cd|ef*)g/ => [%w[abcdg], %w[abe g]], /ab|cd*/ => [%w[ab], %w[c]], - /cd(?:ef|gh)|xyz/ => [%w[cdef],%w[cdgh],%w[xyz]], - /(cd(?:ef|gh)|xyz)/ => [%w[cdef],%w[cdgh],%w[xyz]], + /cd(?:ef|gh)|xyz/ => [%w[cdef], %w[cdgh], %w[xyz]], + /(cd(?:ef|gh)|xyz)/ => [%w[cdef], %w[cdgh], %w[xyz]], /cd(ef|gh)+/ => [%w[cdef], %w[cdgh]], /cd(ef|gh)?/ => [%w[cd]], /cd(ef|gh)?ij/ => [%w[cd ij]],