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:
parent
7a89305c7c
commit
72155bd82f
1 changed files with 106 additions and 57 deletions
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue