cucumber-expressions 5.0.13 → 5.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e37bfd25d2fa6ce81bb76f2a0e4b155b23d7c243
4
- data.tar.gz: a843eb27ff496f5744bb8fc9b7ff2993640a029a
3
+ metadata.gz: f0bf6d072730fe70e07cee26eb6ad35ea6da0395
4
+ data.tar.gz: 81fe11dab1fe72475a6d59902c42c83b9c9cf3c5
5
5
  SHA512:
6
- metadata.gz: 7a9c2d12d144a509ff625e72c67cf1b1e2504a2ecab38086f85aa019150e59437ee06807efb5d65c398f7314c52f1677cb7429d75ff442316c043c0d0987d4f3
7
- data.tar.gz: 8a9e6c44e79d1c713ff2dac7b6b5a2327001615df1ae4e8a356dcc682b7ac71a06629a9f0f5ac5f8d6f053380c5223657eb60ae007a3c0668bdc2a08f30996e4
6
+ metadata.gz: 48d4cee7861530cd5643c7737c7ee0aa1ac18c5c573b47eaa6a1ecce1efce1dd3f2d4eed4303d1347e9522f65557f322295dd4c7dd17f28b1c4825ce0e1ebbe3
7
+ data.tar.gz: 32c6108014efbf5ae47e260580bd919057d08f04c00c90866408d957c6c0525968c2bfb9c9b6a8d833869c0c27775b5eb7cb28faf054e357e348803dd09d4031
data/.travis.yml CHANGED
@@ -3,10 +3,12 @@
3
3
  #
4
4
  # source scripts/functions.sh && rsync_files
5
5
  #
6
+ sudo: false
6
7
  language: ruby
7
8
 
8
9
  rvm:
9
- - 2.4.2
10
- - 2.3.5
11
- - 2.2.8
12
- - jruby-9.1.13.0
10
+ - "2.5.0"
11
+ - "2.4.3"
12
+ - "2.3.6"
13
+ - "2.2.9"
14
+ - "jruby-9.1.13.0"
@@ -1,7 +1,7 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  Gem::Specification.new do |s|
3
3
  s.name = 'cucumber-expressions'
4
- s.version = '5.0.13'
4
+ s.version = '5.0.14'
5
5
  s.authors = ["Aslak Hellesøy"]
6
6
  s.description = 'Cucumber Expressions - a simpler alternative to Regular Expressions'
7
7
  s.summary = "cucumber-expressions-#{s.version}"
@@ -7,46 +7,24 @@ module Cucumber
7
7
  class CucumberExpression
8
8
  # Does not include (){} characters because they have special meaning
9
9
  ESCAPE_REGEXP = /([\\^\[$.|?*+\]])/
10
- PARAMETER_REGEXP = /{([^}]+)}/
11
- OPTIONAL_REGEXP = /\(([^)]+)\)/
10
+ PARAMETER_REGEXP = /(\\\\)?{([^}]+)}/
11
+ OPTIONAL_REGEXP = /(\\\\)?\(([^)]+)\)/
12
12
  ALTERNATIVE_NON_WHITESPACE_TEXT_REGEXP = /([^\s^\/]+)((\/[^\s^\/]+)+)/
13
+ DOUBLE_ESCAPE = '\\\\'
13
14
 
14
15
  attr_reader :source
15
16
 
16
17
  def initialize(expression, parameter_type_registry)
17
18
  @source = expression
18
19
  @parameter_types = []
19
- regexp = '^'
20
- match_offset = 0
20
+
21
+ expression = process_escapes(expression)
22
+ expression = process_optional(expression)
23
+ expression = process_alternation(expression)
24
+ expression = process_parameters(expression, parameter_type_registry)
25
+ expression = "^#{expression}$"
21
26
 
22
- expression = expression.gsub(ESCAPE_REGEXP, '\\\\\1')
23
-
24
- # Create non-capturing, optional capture groups from parenthesis
25
- expression = expression.gsub(OPTIONAL_REGEXP, '(?:\1)?')
26
-
27
- expression = expression.gsub(ALTERNATIVE_NON_WHITESPACE_TEXT_REGEXP) do |_|
28
- "(?:#{$1}#{$2.tr('/', '|')})"
29
- end
30
-
31
- loop do
32
- match = PARAMETER_REGEXP.match(expression, match_offset)
33
- break if match.nil?
34
-
35
- type_name = match[1]
36
-
37
- parameter_type = parameter_type_registry.lookup_by_type_name(type_name)
38
- raise UndefinedParameterTypeError.new(type_name) if parameter_type.nil?
39
- @parameter_types.push(parameter_type)
40
-
41
- text = expression.slice(match_offset...match.offset(0)[0])
42
- capture_regexp = build_capture_regexp(parameter_type.regexps)
43
- match_offset = match.offset(0)[1]
44
- regexp += text
45
- regexp += capture_regexp
46
- end
47
- regexp += expression.slice(match_offset..-1)
48
- regexp += '$'
49
- @tree_regexp = TreeRegexp.new(regexp)
27
+ @tree_regexp = TreeRegexp.new(expression)
50
28
  end
51
29
 
52
30
  def match(text)
@@ -63,6 +41,40 @@ module Cucumber
63
41
 
64
42
  private
65
43
 
44
+ def process_escapes(expression)
45
+ expression.gsub(ESCAPE_REGEXP, '\\\\\1')
46
+ end
47
+
48
+ def process_optional(expression)
49
+ # Create non-capturing, optional capture groups from parenthesis
50
+ expression.gsub(OPTIONAL_REGEXP) do
51
+ # look for double-escaped parentheses
52
+ $1 == DOUBLE_ESCAPE ? "\\(#{$2}\\)" : "(?:#{$2})?"
53
+ end
54
+ end
55
+
56
+ def process_alternation(expression)
57
+ expression.gsub(ALTERNATIVE_NON_WHITESPACE_TEXT_REGEXP) do
58
+ "(?:#{$1}#{$2.tr('/', '|')})"
59
+ end
60
+ end
61
+
62
+ def process_parameters(expression, parameter_type_registry)
63
+ # Create non-capturing, optional capture groups from parenthesis
64
+ expression.gsub(PARAMETER_REGEXP) do
65
+ if ($1 == DOUBLE_ESCAPE)
66
+ "\\{#{$2}\\}"
67
+ else
68
+ type_name = $2
69
+ parameter_type = parameter_type_registry.lookup_by_type_name(type_name)
70
+ raise UndefinedParameterTypeError.new(type_name) if parameter_type.nil?
71
+ @parameter_types.push(parameter_type)
72
+
73
+ build_capture_regexp(parameter_type.regexps)
74
+ end
75
+ end
76
+ end
77
+
66
78
  def build_capture_regexp(regexps)
67
79
  return "(#{regexps[0]})" if regexps.size == 1
68
80
  capture_groups = regexps.map { |group| "(?:#{group})" }
@@ -51,7 +51,7 @@ module Cucumber
51
51
 
52
52
  parameter_type_combinations.push(parameter_types)
53
53
 
54
- expression_template += escape_for_sprintf(text.slice(pos...best_parameter_type_matcher.start))
54
+ expression_template += escape(text.slice(pos...best_parameter_type_matcher.start))
55
55
  expression_template += "{%s}"
56
56
 
57
57
  pos = best_parameter_type_matcher.start + best_parameter_type_matcher.group.length
@@ -64,7 +64,7 @@ module Cucumber
64
64
  end
65
65
  end
66
66
 
67
- expression_template += escape_for_sprintf(text.slice(pos..-1))
67
+ expression_template += escape(text.slice(pos..-1))
68
68
 
69
69
  CombinatorialGeneratedExpressionFactory.new(
70
70
  expression_template,
@@ -94,8 +94,10 @@ module Cucumber
94
94
  result
95
95
  end
96
96
 
97
- def escape_for_sprintf(s)
97
+ def escape(s)
98
98
  s.gsub(/%/, '%%')
99
+ .gsub(/\(/, '\\(')
100
+ .gsub(/\{/, '\\{')
99
101
  end
100
102
  end
101
103
  end
@@ -1,4 +1,5 @@
1
1
  require 'cucumber/cucumber_expressions/group_builder'
2
+ require 'cucumber/cucumber_expressions/errors'
2
3
 
3
4
  module Cucumber
4
5
  module CucumberExpressions
@@ -33,6 +34,8 @@ module Cucumber
33
34
  elsif c == ':' && non_capturing_maybe
34
35
  stack.last.set_non_capturing!
35
36
  non_capturing_maybe = false
37
+ elsif c == '<' && non_capturing_maybe
38
+ raise CucumberExpressionError.new("Named capture groups are not supported. See https://github.com/cucumber/cucumber/issues/329")
36
39
  end
37
40
 
38
41
  escaping = c == '\\' && !escaping
@@ -1,4 +1,5 @@
1
1
  require 'cucumber/cucumber_expressions/cucumber_expression_generator'
2
+ require 'cucumber/cucumber_expressions/cucumber_expression'
2
3
  require 'cucumber/cucumber_expressions/parameter_type'
3
4
  require 'cucumber/cucumber_expressions/parameter_type_registry'
4
5
 
@@ -28,6 +29,18 @@ module Cucumber
28
29
  assert_expression("hello", [], "hello")
29
30
  end
30
31
 
32
+ it "generates expression with escaped left parenthesis" do
33
+ assert_expression(
34
+ "\\(iii)", [],
35
+ "(iii)")
36
+ end
37
+
38
+ it "generates expression with escaped left curly brace" do
39
+ assert_expression(
40
+ "\\{iii}", [],
41
+ "{iii}")
42
+ end
43
+
31
44
  it "generates expression for int float arg" do
32
45
  assert_expression(
33
46
  "I have {int} cukes and {float} euro", ["int", "float"],
@@ -105,6 +118,10 @@ module Cucumber
105
118
  generated_expression = @generator.generate_expression(text)
106
119
  expect(generated_expression.parameter_names).to eq(expected_argument_names)
107
120
  expect(generated_expression.source).to eq(expected_expression)
121
+
122
+ cucumber_expression = CucumberExpression.new(generated_expression.source, @parameter_type_registry)
123
+ match = cucumber_expression.match(text)
124
+ expect(match.length).to eq(expected_argument_names.length)
108
125
  end
109
126
  end
110
127
  end
@@ -26,7 +26,7 @@ module Cucumber
26
26
  it('matches multiple double quoted strings') do
27
27
  expect(match('three {string} and {string} mice', 'three "blind" and "crippled" mice')).to eq(['blind', 'crippled'])
28
28
  end
29
-
29
+
30
30
  it('matches single quoted string') do
31
31
  expect(match('three {string} mice', "three 'blind' mice")).to eq(['blind'])
32
32
  end
@@ -55,6 +55,10 @@ module Cucumber
55
55
  expect(match('three {string} mice', "three 'bl\\'nd' mice")).to eq(["bl'nd"])
56
56
  end
57
57
 
58
+ it 'matches escaped parentheses' do
59
+ expect(match('three \\(exceptionally) {string} mice', 'three (exceptionally) "blind" mice')).to eq(['blind'])
60
+ end
61
+
58
62
  it "matches int" do
59
63
  expect(match("{int}", "22")).to eq([22])
60
64
  end
@@ -84,6 +84,13 @@ module Cucumber
84
84
  group = tr.match("hello")
85
85
  expect(group.value).to eq("hello")
86
86
  end
87
+
88
+ it 'throws an error when there are named capture groups because they are buggy in Ruby' do
89
+ # https://github.com/cucumber/cucumber/issues/329
90
+ expect {
91
+ TreeRegexp.new(/^I am a person( named "(?<first_name>.+) (?<last_name>.+)")?$/)
92
+ }.to raise_error(/Named capture groups are not supported/)
93
+ end
87
94
  end
88
95
  end
89
96
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cucumber-expressions
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.0.13
4
+ version: 5.0.14
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aslak Hellesøy
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-01-21 00:00:00.000000000 Z
11
+ date: 2018-04-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -131,7 +131,7 @@ rubyforge_project:
131
131
  rubygems_version: 2.6.8
132
132
  signing_key:
133
133
  specification_version: 4
134
- summary: cucumber-expressions-5.0.13
134
+ summary: cucumber-expressions-5.0.14
135
135
  test_files:
136
136
  - spec/capture_warnings.rb
137
137
  - spec/coverage.rb