1
0
Fork 0
mirror of https://github.com/teamcapybara/capybara.git synced 2022-11-09 12:08:07 -05:00

Encapsulate regexp string extraction

This commit is contained in:
Thomas Walpole 2018-11-15 15:05:30 -08:00
parent 7a89305c7c
commit 72155bd82f

View file

@ -65,22 +65,6 @@ module Capybara
strs
end
def min_repeat(exp)
exp.quantifier&.min || 1
end
def max_repeat(exp)
exp.quantifier&.max || 1
end
def fixed_repeat?(exp)
min_repeat(exp) == max_repeat(exp)
end
def optional?(exp)
min_repeat(exp).zero?
end
def combine(strs)
suffixes = [[]]
strs.reverse_each do |str|
@ -91,9 +75,7 @@ module Capybara
prefixes.product(suffixes) { |pair| result << pair.flatten(1) }
suffixes = result
else
suffixes.each do |arr|
arr.unshift str
end
suffixes.each { |arr| arr.unshift str }
end
end
suffixes
@ -106,53 +88,120 @@ module Capybara
end
def extract_strings(expression, alternation: false)
strings = []
expression.each do |exp| # rubocop:disable Metrics/BlockLength
next strings.push(nil) if optional?(exp) && !alternation
Expression.new(expression).extract_strings(alternation)
end
next strings.push(alternative_strings(exp)) if %i[meta].include?(exp.type) && !exp.terminal? && alternation
# @api private
class Expression
def initialize(exp)
@exp = exp
end
next strings.push(nil) if %i[meta set].include?(exp.type)
def extract_strings(process_alternatives)
strings = []
each do |exp|
next strings.push(nil) if exp.optional? && !process_alternatives
strs = if exp.terminal?
terminal_strings(exp)
elsif optional?(exp)
optional_strings(exp, extract_strings(exp, alternation: true))
else
repeated_strings(exp, extract_strings(exp, alternation: alternation))
next strings.push(exp.alternative_strings) if exp.alternation? && process_alternatives
strings.concat(exp.strings(process_alternatives))
end
strings.concat(strs)
end
strings
end
def alternative_strings(expression)
alternatives = expression.alternatives.map { |sub_exp| extract_strings(sub_exp, alternation: true) }
alternatives.all?(&:any?) ? Set.new(alternatives) : nil
end
def terminal_strings(exp)
text = case exp.type
when :literal then exp.text
when :escape then exp.char
else
return [nil]
strings
end
optional?(exp) ? optional_strings(exp, text) : repeated_strings(exp, text)
end
protected
def optional_strings(exp, text)
strs = [Set.new([[''], Array(text)])]
strs.push(nil) unless max_repeat(exp) == 1
strs
end
def alternation?
(type == :meta) && !terminal?
end
def repeated_strings(exp, text)
strs = Array(text * min_repeat(exp))
strs.push(nil) unless fixed_repeat?(exp)
strs
def optional?
min_repeat.zero?
end
def terminal?
@exp.terminal?
end
def strings(process_alternatives)
if indeterminate?
[nil]
elsif terminal?
terminal_strings
elsif optional?
optional_strings
else
repeated_strings(process_alternatives)
end
end
def terminal_strings
text = case @exp.type
when :literal then @exp.text
when :escape then @exp.char
else
return [nil]
end
optional? ? options_set(text) : repeat_set(text)
end
def optional_strings
options_set(extract_strings(true))
end
def repeated_strings(process_alternatives)
repeat_set extract_strings(process_alternatives)
end
def alternative_strings
alts = alternatives.map { |sub_exp| sub_exp.extract_strings(alternation: true) }
alts.all?(&:any?) ? Set.new(alts) : nil
end
private
def indeterminate?
%i[meta set].include?(type)
end
def min_repeat
@exp.quantifier&.min || 1
end
def max_repeat
@exp.quantifier&.max || 1
end
def fixed_repeat?
min_repeat == max_repeat
end
def type
@exp.type
end
def repeat_set(str)
strs = Array(str * min_repeat)
strs.push(nil) unless fixed_repeat?
strs
end
def options_set(strs)
strs = [Set.new([[''], Array(strs)])]
strs.push(nil) unless max_repeat == 1
strs
end
def alternatives
@exp.alternatives.map { |exp| Expression.new(exp) }
end
def each
@exp.each { |exp| yield Expression.new(exp) }
end
end
private_constant :Expression
end
end
end