File: cucumber_expression_generator.rb

package info (click to toggle)
ruby-cucumber-expressions 8.0.0-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, forky, sid, trixie
  • size: 248 kB
  • sloc: ruby: 1,594; sh: 15; makefile: 4
file content (105 lines) | stat: -rw-r--r-- 3,761 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
require 'cucumber/cucumber_expressions/parameter_type_matcher'
require 'cucumber/cucumber_expressions/generated_expression'
require 'cucumber/cucumber_expressions/combinatorial_generated_expression_factory'

module Cucumber
  module CucumberExpressions
    class CucumberExpressionGenerator
      def initialize(parameter_type_registry)
        @parameter_type_registry = parameter_type_registry
      end

      def generate_expression(text)
        generate_expressions(text)[0]
      end

      def generate_expressions(text)
        parameter_type_combinations = []
        parameter_type_matchers = create_parameter_type_matchers(text)
        expression_template = ""
        pos = 0

        loop do
          matching_parameter_type_matchers = []
          parameter_type_matchers.each do |parameter_type_matcher|
            advanced_parameter_type_matcher = parameter_type_matcher.advance_to(pos)
            if advanced_parameter_type_matcher.find
              matching_parameter_type_matchers.push(advanced_parameter_type_matcher)
            end
          end

          if matching_parameter_type_matchers.any?
            matching_parameter_type_matchers = matching_parameter_type_matchers.sort
            best_parameter_type_matcher = matching_parameter_type_matchers[0]
            best_parameter_type_matchers = matching_parameter_type_matchers.select do |m|
              (m <=> best_parameter_type_matcher).zero?
            end

            # Build a list of parameter types without duplicates. The reason there
            # might be duplicates is that some parameter types have more than one regexp,
            # which means multiple ParameterTypeMatcher objects will have a reference to the
            # same ParameterType.
            # We're sorting the list so prefer_for_regexp_match parameter types are listed first.
            # Users are most likely to want these, so they should be listed at the top.
            parameter_types = []
            best_parameter_type_matchers.each do |parameter_type_matcher|
              unless parameter_types.include?(parameter_type_matcher.parameter_type)
                parameter_types.push(parameter_type_matcher.parameter_type)
              end
            end
            parameter_types.sort!

            parameter_type_combinations.push(parameter_types)

            expression_template += escape(text.slice(pos...best_parameter_type_matcher.start))
            expression_template += "{%s}"

            pos = best_parameter_type_matcher.start + best_parameter_type_matcher.group.length
          else
            break
          end

          if pos >= text.length
            break
          end
        end

        expression_template += escape(text.slice(pos..-1))

        CombinatorialGeneratedExpressionFactory.new(
          expression_template,
          parameter_type_combinations
        ).generate_expressions
      end

    private

      def create_parameter_type_matchers(text)
        parameter_matchers = []
        @parameter_type_registry.parameter_types.each do |parameter_type|
          if parameter_type.use_for_snippets?
            parameter_matchers += create_parameter_type_matchers2(parameter_type, text)
          end
        end
        parameter_matchers
      end

      def create_parameter_type_matchers2(parameter_type, text)
        result = []
        regexps = parameter_type.regexps
        regexps.each do |regexp|
          regexp = Regexp.new("(#{regexp})")
          result.push(ParameterTypeMatcher.new(parameter_type, regexp, text, 0))
        end
        result
      end

      def escape(s)
        s.gsub(/%/, '%%')
        .gsub(/\(/, '\\(')
        .gsub(/\{/, '\\{')
        .gsub(/\//, '\\/')
      end
    end
  end
end