gherkin 2.0.2-universal-dotnet → 2.1.0-universal-dotnet

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.
Files changed (61) hide show
  1. data/History.txt +12 -0
  2. data/LICENSE +1 -1
  3. data/README.rdoc +2 -2
  4. data/Rakefile +2 -2
  5. data/VERSION.yml +2 -2
  6. data/features/json_formatter.feature +3 -41
  7. data/features/step_definitions/gherkin_steps.rb +5 -6
  8. data/features/step_definitions/json_formatter_steps.rb +3 -2
  9. data/features/step_definitions/json_lexer_steps.rb +5 -5
  10. data/features/step_definitions/pretty_formatter_steps.rb +9 -13
  11. data/features/support/env.rb +1 -1
  12. data/lib/gherkin/formatter/argument.rb +1 -0
  13. data/lib/gherkin/formatter/filter_formatter.rb +149 -0
  14. data/lib/gherkin/formatter/json_formatter.rb +35 -45
  15. data/lib/gherkin/formatter/line_filter.rb +26 -0
  16. data/lib/gherkin/formatter/model.rb +85 -0
  17. data/lib/gherkin/formatter/pretty_formatter.rb +36 -39
  18. data/lib/gherkin/formatter/regexp_filter.rb +17 -0
  19. data/lib/gherkin/formatter/tag_count_formatter.rb +44 -0
  20. data/lib/gherkin/i18n.rb +5 -5
  21. data/lib/gherkin/i18n.yml +13 -0
  22. data/lib/gherkin/i18n_lexer.rb +2 -2
  23. data/lib/gherkin/{json_lexer.rb → json_parser.rb} +17 -5
  24. data/lib/gherkin/{parser → listener}/event.rb +1 -1
  25. data/lib/gherkin/{parser → listener}/formatter_listener.rb +30 -23
  26. data/lib/gherkin/native/java.rb +9 -1
  27. data/lib/gherkin/parser/parser.rb +27 -14
  28. data/lib/gherkin/rubify.rb +5 -1
  29. data/lib/gherkin/tag_expression.rb +62 -0
  30. data/lib/gherkin/tools/files.rb +3 -4
  31. data/lib/gherkin/tools/reformat.rb +2 -2
  32. data/lib/gherkin/tools/stats.rb +3 -4
  33. data/lib/gherkin/tools/stats_listener.rb +1 -1
  34. data/ragel/lexer.c.rl.erb +2 -3
  35. data/ragel/lexer.java.rl.erb +1 -2
  36. data/ragel/lexer.rb.rl.erb +1 -2
  37. data/spec/gherkin/fixtures/complex_for_filtering.feature +60 -0
  38. data/spec/gherkin/fixtures/complex_with_tags.feature +61 -0
  39. data/spec/gherkin/fixtures/hantu_pisang.feature +35 -0
  40. data/spec/gherkin/formatter/filter_formatter_spec.rb +156 -0
  41. data/spec/gherkin/formatter/model_spec.rb +15 -0
  42. data/spec/gherkin/formatter/pretty_formatter_spec.rb +17 -16
  43. data/spec/gherkin/formatter/tag_count_formatter_spec.rb +31 -0
  44. data/spec/gherkin/i18n_lexer_spec.rb +3 -3
  45. data/spec/gherkin/i18n_spec.rb +2 -4
  46. data/spec/gherkin/{json_lexer_spec.rb → json_parser_spec.rb} +13 -8
  47. data/spec/gherkin/sexp_recorder.rb +10 -4
  48. data/spec/gherkin/shared/lexer_group.rb +0 -40
  49. data/spec/gherkin/shared/py_string_group.rb +0 -1
  50. data/spec/gherkin/shared/row_group.rb +1 -2
  51. data/spec/gherkin/tag_expression_spec.rb +137 -0
  52. data/spec/spec_helper.rb +5 -1
  53. data/tasks/bench.rake +5 -9
  54. metadata +31 -25
  55. data/lib/gherkin/parser/filter_listener.rb +0 -203
  56. data/lib/gherkin/parser/row.rb +0 -15
  57. data/lib/gherkin/parser/tag_expression.rb +0 -50
  58. data/spec/gherkin/parser/filter_listener_spec.rb +0 -397
  59. data/spec/gherkin/parser/formatter_listener_spec.rb +0 -134
  60. data/spec/gherkin/parser/parser_spec.rb +0 -50
  61. data/spec/gherkin/parser/tag_expression_spec.rb +0 -116
@@ -11,47 +11,33 @@ module Gherkin
11
11
  @io = io
12
12
  end
13
13
 
14
- def feature(comments, tags, keyword, name, description, uri)
15
- @json_hash = {
16
- 'comments' => comments.to_a,
17
- 'tags' => tags.to_a,
18
- 'keyword' => keyword,
19
- 'name' => name,
20
- 'description' => description,
21
- 'uri' => uri
22
- }
14
+ def feature(statement, uri)
15
+ @json_hash = statement_hash(nil, statement)
16
+ @json_hash['uri'] = uri
23
17
  end
24
18
 
25
- def background(comments, keyword, name, description, line)
26
- background = {
27
- 'comments' => comments.to_a,
28
- 'keyword' => keyword,
29
- 'name' => name,
30
- 'description' => description,
31
- 'line' => line,
32
- 'steps' => [],
33
- }
34
- @json_hash['background'] = background
19
+ def background(statement)
20
+ @json_hash['background'] = statement_hash(nil, statement)
35
21
  @in_background = true
36
22
  end
37
23
 
38
- def scenario(comments, tags, keyword, name, description, line)
24
+ def scenario(statement)
39
25
  @in_background = false
40
- add_step_container(comments, tags, keyword, name, description, line, 'scenario')
26
+ add_step_container('scenario', statement)
41
27
  end
42
28
 
43
- def scenario_outline(comments, tags, keyword, name, description, line)
29
+ def scenario_outline(statement)
44
30
  @in_background = false
45
- add_step_container(comments, tags, keyword, name, description, line, 'scenario_outline')
31
+ add_step_container('scenario_outline', statement)
46
32
  end
47
33
 
48
- def examples(comments, tags, keyword, name, description, line, table)
49
- @table_container = add_examples(comments, tags, keyword, name, description, line)
50
- @table_container['table'] = to_hash_array(table)
34
+ def examples(statement, examples_rows)
35
+ @table_container = add_examples(statement)
36
+ @table_container['table'] = to_hash_array(examples_rows)
51
37
  end
52
38
 
53
- def step(comments, keyword, name, line, multiline_arg, status, exception, arguments, stepdef_location)
54
- @table_container = {'comments' => comments.to_a, 'keyword' => keyword, 'name' => name, 'line' => line}.merge(step_arg_to_hash(multiline_arg))
39
+ def step(statement, multiline_arg, result)
40
+ @table_container = statement_hash(nil, statement).merge(step_arg_to_hash(multiline_arg))
55
41
  last_element['steps'] ||= []
56
42
  last_element['steps'] << @table_container
57
43
  end
@@ -62,35 +48,35 @@ module Gherkin
62
48
 
63
49
  private
64
50
 
65
- def element_hash(comments, tags, keyword, name, description, line, type=nil)
51
+ def statement_hash(type, statement)
66
52
  element = {
67
- 'comments' => comments.to_a,
68
- 'tags' => tags.to_a,
69
- 'keyword' => keyword,
70
- 'name' => name,
71
- 'description' => description,
72
- 'line' => line,
53
+ 'comments' => statement.comments.map{|comment| comment.value},
54
+ 'tags' => statement.tags.map{|tag| tag.name},
55
+ 'keyword' => statement.keyword,
56
+ 'name' => statement.name,
57
+ 'description' => statement.description,
58
+ 'line' => statement.line,
73
59
  }
74
- element['type'] = type if type
75
- element
60
+ element['type'] = type
61
+ compact(element)
76
62
  end
77
63
 
78
- def add_element(comments, tags, keyword, name, description, line, type)
79
- element = element_hash(comments, tags, keyword, name, description, line, type)
64
+ def add_element(type, statement)
65
+ element = statement_hash(type, statement)
80
66
  @json_hash['elements'] ||= []
81
67
  @json_hash['elements'] << element
82
68
  element
83
69
  end
84
70
 
85
- def add_examples(comments, tags, keyword, name, description, line)
86
- element = element_hash(comments, tags, keyword, name, description, line)
71
+ def add_examples(statement)
72
+ element = statement_hash(nil, statement)
87
73
  last_element['examples'] ||= []
88
74
  last_element['examples'] << element
89
75
  element
90
76
  end
91
77
 
92
- def add_step_container(type, comments, tags, keyword, name, description, line)
93
- add_element(type, comments, tags, keyword, name, description, line)
78
+ def add_step_container(type, statement)
79
+ add_element(type, statement)
94
80
  last_element['steps'] = []
95
81
  end
96
82
 
@@ -104,14 +90,18 @@ module Gherkin
104
90
 
105
91
  def to_hash_array(rows)
106
92
  rows.map do |row|
107
- {"cells" => row.cells.to_a, "comments" => row.comments.to_a, "line" => row.line}
93
+ compact({"cells" => row.cells.to_a, "comments" => row.comments.map{|comment| comment.value}, "line" => row.line})
108
94
  end
109
95
  end
110
96
 
111
97
  def step_arg_to_hash(multiline_arg)
112
98
  return {} if multiline_arg.nil?
113
99
  multiline_arg = rubify(multiline_arg)
114
- Array === multiline_arg ? {"table" => to_hash_array(multiline_arg) } : { "py_string" => multiline_arg }
100
+ Array === multiline_arg ? {"table" => to_hash_array(multiline_arg) } : { "py_string" => multiline_arg.value }
101
+ end
102
+
103
+ def compact(hash)
104
+ hash.reject{|k,v| [[], "", nil].index(v)}
115
105
  end
116
106
  end
117
107
  end
@@ -0,0 +1,26 @@
1
+ module Gherkin
2
+ module Formatter
3
+ class LineFilter
4
+ def initialize(lines)
5
+ @lines = lines
6
+ end
7
+
8
+ def eval(ranges)
9
+ @lines.detect do |line|
10
+ ranges.detect do |range|
11
+ range.include?(line)
12
+ end
13
+ end
14
+ end
15
+
16
+ def filter_table_body_rows(rows)
17
+ body = rows.to_a[1..-1].select do |row|
18
+ @lines.detect do |line|
19
+ row.line == line
20
+ end
21
+ end
22
+ [rows[0]] + body
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,85 @@
1
+ require 'gherkin/native'
2
+
3
+ module Gherkin
4
+ module Formatter
5
+ module Model
6
+ class Comment
7
+ native_impl('gherkin')
8
+
9
+ attr_reader :value, :line
10
+
11
+ def initialize(value, line)
12
+ @value, @line = value, line
13
+ end
14
+ end
15
+
16
+ class Tag
17
+ native_impl('gherkin')
18
+
19
+ attr_reader :name, :line
20
+
21
+ def initialize(name, line)
22
+ @name, @line = name, line
23
+ end
24
+
25
+ def eql?(tag)
26
+ @name.eql?(tag.name)
27
+ end
28
+
29
+ def hash
30
+ @name.hash
31
+ end
32
+ end
33
+
34
+ class PyString
35
+ native_impl('gherkin')
36
+
37
+ attr_reader :value, :line
38
+
39
+ def initialize(value, line)
40
+ @value, @line = value, line
41
+ end
42
+
43
+ def line_range
44
+ line_count = value.split(/\r?\n/).length
45
+ line..(line+line_count+1)
46
+ end
47
+ end
48
+
49
+ class Row
50
+ native_impl('gherkin')
51
+
52
+ attr_reader :comments, :cells, :line
53
+
54
+ def initialize(comments, cells, line)
55
+ @comments, @cells, @line = comments, cells, line
56
+ end
57
+ end
58
+
59
+ class Statement
60
+ native_impl('gherkin')
61
+
62
+ attr_reader :comments, :tags, :keyword, :name, :description, :line
63
+
64
+ def initialize(comments, tags, keyword, name, description, line)
65
+ @comments, @tags, @keyword, @name, @description, @line = comments, tags, keyword, name, description, line
66
+ end
67
+
68
+ def line_range
69
+ first = @comments[0] ? @comments[0].line : (@tags[0] ? @tags[0].line : line)
70
+ first..line
71
+ end
72
+ end
73
+
74
+ class Result
75
+ native_impl('gherkin')
76
+
77
+ attr_reader :status, :error_message, :arguments, :stepdef_location
78
+
79
+ def initialize(status, error_message, arguments, stepdef_location)
80
+ @status, @error_message, @arguments, @stepdef_location = status, error_message, arguments, stepdef_location
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
@@ -3,6 +3,7 @@ require 'gherkin/formatter/colors'
3
3
  require 'gherkin/formatter/monochrome_format'
4
4
  require 'gherkin/formatter/argument'
5
5
  require 'gherkin/formatter/escaping'
6
+ require 'gherkin/formatter/model'
6
7
  require 'gherkin/native'
7
8
 
8
9
  module Gherkin
@@ -19,53 +20,52 @@ module Gherkin
19
20
  @format = MonochromeFormat.new #@monochrome ? MonochromeFormat.new : AnsiColorFormat.new
20
21
  end
21
22
 
22
- def feature(comments, tags, keyword, name, description, uri)
23
+ def feature(statement, uri)
23
24
  @uri = uri
24
- print_comments(comments, '')
25
- print_tags(tags, '')
26
- @io.puts "#{keyword}: #{name}"
27
- print_description(description, ' ', false)
25
+ print_comments(statement.comments, '')
26
+ print_tags(statement.tags, '')
27
+ @io.puts "#{statement.keyword}: #{statement.name}"
28
+ print_description(statement.description, ' ', false)
28
29
  end
29
30
 
30
- def background(comments, keyword, name, description, line)
31
+ def background(statement)
31
32
  @io.puts
32
- print_comments(comments, ' ')
33
- @io.puts " #{keyword}: #{name}#{indented_element_uri!(keyword, name, line)}"
34
- print_description(description, ' ')
33
+ print_comments(statement.comments, ' ')
34
+ @io.puts " #{statement.keyword}: #{statement.name}#{indented_element_uri!(statement.keyword, statement.name, statement.line)}"
35
+ print_description(statement.description, ' ')
35
36
  end
36
37
 
37
- def scenario(comments, tags, keyword, name, description, line)
38
+ def scenario(statement)
38
39
  @io.puts
39
- print_comments(comments, ' ')
40
- print_tags(tags, ' ')
41
- @io.puts " #{keyword}: #{name}#{indented_element_uri!(keyword, name, line)}"
42
- print_description(description, ' ')
40
+ print_comments(statement.comments, ' ')
41
+ print_tags(statement.tags, ' ')
42
+ @io.puts " #{statement.keyword}: #{statement.name}#{indented_element_uri!(statement.keyword, statement.name, statement.line)}"
43
+ print_description(statement.description, ' ')
43
44
  end
44
45
 
45
- def scenario_outline(comments, tags, keyword, name, description, line)
46
- scenario(comments, tags, keyword, name, description, line)
46
+ def scenario_outline(statement)
47
+ scenario(statement)
47
48
  end
48
49
 
49
- def examples(comments, tags, keyword, name, description, line, examples_table)
50
+ def examples(statement, examples_rows)
50
51
  @io.puts
51
- print_comments(comments, ' ')
52
- print_tags(tags, ' ')
53
- @io.puts " #{keyword}: #{name}"
54
- print_description(description, ' ')
55
- table(examples_table)
52
+ print_comments(statement.comments, ' ')
53
+ print_tags(statement.tags, ' ')
54
+ @io.puts " #{statement.keyword}: #{statement.name}"
55
+ print_description(statement.description, ' ')
56
+ table(examples_rows)
56
57
  end
57
58
 
58
- def step(comments, keyword, name, line, multiline_arg, status, exception, arguments, stepdef_location)
59
- status_param = "#{status}_param" if status
60
- name = Gherkin::Formatter::Argument.format(name, @format, (arguments || []))
59
+ def step(statement, multiline_arg, result)
60
+ name = Gherkin::Formatter::Argument.format(statement.name, @format, (result ? result.arguments : []))
61
61
 
62
- step = "#{keyword}#{name}"
63
- step = self.__send__(status, step, @monochrome) if status
62
+ step = "#{statement.keyword}#{statement.name}"
63
+ step = self.__send__(result.status, step, @monochrome) if result
64
64
 
65
- print_comments(comments, ' ')
66
- @io.puts(" #{step}#{indented_step_location!(stepdef_location)}")
65
+ print_comments(statement.comments, ' ')
66
+ @io.puts(" #{step}#{indented_step_location!(result ? result.stepdef_location : nil)}")
67
67
  case multiline_arg
68
- when String
68
+ when Model::PyString
69
69
  py_string(multiline_arg)
70
70
  when Array
71
71
  table(multiline_arg)
@@ -75,11 +75,8 @@ module Gherkin
75
75
  end
76
76
  end
77
77
 
78
- def syntax_error(state, event, legal_events, line)
79
- raise "SYNTAX ERROR"
80
- end
81
-
82
78
  def eof
79
+ # NO-OP
83
80
  end
84
81
 
85
82
  # This method can be invoked before a #scenario, to ensure location arguments are aligned
@@ -99,7 +96,7 @@ module Gherkin
99
96
 
100
97
  rows.each_with_index do |row, i|
101
98
  row.comments.each do |comment|
102
- @io.puts " #{comment}"
99
+ @io.puts " #{comment.value}"
103
100
  end
104
101
  j = -1
105
102
  @io.puts ' | ' + row.cells.zip(max_lengths).map { |cell, max_length|
@@ -111,8 +108,8 @@ module Gherkin
111
108
 
112
109
  private
113
110
 
114
- def py_string(string)
115
- @io.puts " \"\"\"\n" + escape_triple_quotes(indent(string, ' ')) + "\n \"\"\""
111
+ def py_string(py_string)
112
+ @io.puts " \"\"\"\n" + escape_triple_quotes(indent(py_string.value, ' ')) + "\n \"\"\""
116
113
  end
117
114
 
118
115
  def exception(exception)
@@ -145,11 +142,11 @@ module Gherkin
145
142
  end
146
143
 
147
144
  def print_tags(tags, indent)
148
- @io.write(tags.empty? ? '' : indent + tags.join(' ') + "\n")
145
+ @io.write(tags.empty? ? '' : indent + tags.map{|tag| tag.name}.join(' ') + "\n")
149
146
  end
150
147
 
151
148
  def print_comments(comments, indent)
152
- @io.write(comments.empty? ? '' : indent + comments.join("\n#{indent}") + "\n")
149
+ @io.write(comments.empty? ? '' : indent + comments.map{|comment| comment.value}.join("\n#{indent}") + "\n")
153
150
  end
154
151
 
155
152
  def print_description(description, indent, newline=true)
@@ -0,0 +1,17 @@
1
+ module Gherkin
2
+ module Formatter
3
+ class RegexpFilter
4
+ def initialize(regexen)
5
+ @regexen = regexen
6
+ end
7
+
8
+ def eval(names)
9
+ @regexen.detect do |regexp|
10
+ names.detect do |name|
11
+ name =~ regexp
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,44 @@
1
+ module Gherkin
2
+ module Formatter
3
+ class TagCountFormatter
4
+ def initialize(formatter, tag_counts)
5
+ @formatter = formatter
6
+ @tag_counts = tag_counts
7
+ end
8
+
9
+ def feature(statement, uri)
10
+ @feature_tags = statement.tags
11
+ @uri = uri
12
+ @formatter.feature(statement, uri)
13
+ end
14
+
15
+ def scenario(statement)
16
+ record_tags((@feature_tags.to_a + statement.tags.to_a).uniq, statement.line)
17
+ @formatter.scenario(statement)
18
+ end
19
+
20
+ def scenario_outline(statement)
21
+ @scenario_outline_tags = statement.tags
22
+ @formatter.scenario_outline(statement)
23
+ end
24
+
25
+ def examples(statement, examples_rows)
26
+ record_tags((@feature_tags.to_a + @scenario_outline_tags.to_a + statement.tags.to_a).uniq, statement.line)
27
+ @formatter.examples(statement, examples_rows)
28
+ end
29
+
30
+ private
31
+
32
+ def record_tags(tags, line)
33
+ tags.each do |tag|
34
+ @tag_counts[tag.name] ||= []
35
+ @tag_counts[tag.name] << "#{@uri}:#{line}"
36
+ end
37
+ end
38
+
39
+ def method_missing(*args)
40
+ @formatter.__send__(*args)
41
+ end
42
+ end
43
+ end
44
+ end
@@ -55,11 +55,11 @@ module Gherkin
55
55
  def language_table
56
56
  require 'stringio'
57
57
  require 'gherkin/formatter/pretty_formatter'
58
- require 'gherkin/parser/row'
58
+ require 'gherkin/formatter/model'
59
59
  io = defined?(JRUBY_VERSION) ? Java.java.io.StringWriter.new : StringIO.new
60
60
  pf = Gherkin::Formatter::PrettyFormatter.new(io, true)
61
61
  table = all.map do |i18n|
62
- Parser::Row.new([i18n.iso_code, i18n.keywords('name')[0], i18n.keywords('native')[0]], [], nil)
62
+ Formatter::Model::Row.new([], [i18n.iso_code, i18n.keywords('name')[0], i18n.keywords('native')[0]], nil)
63
63
  end
64
64
  pf.table(table)
65
65
  if defined?(JRUBY_VERSION)
@@ -147,19 +147,19 @@ module Gherkin
147
147
  def keyword_table
148
148
  require 'stringio'
149
149
  require 'gherkin/formatter/pretty_formatter'
150
- require 'gherkin/parser/row'
150
+ require 'gherkin/formatter/model'
151
151
  io = StringIO.new
152
152
  pf = Gherkin::Formatter::PrettyFormatter.new(io, true)
153
153
 
154
154
  gherkin_keyword_table = KEYWORD_KEYS.map do |key|
155
- Parser::Row.new([key, keywords(key).map{|keyword| %{"#{keyword}"}}.join(', ')], [], nil)
155
+ Formatter::Model::Row.new([], [key, keywords(key).map{|keyword| %{"#{keyword}"}}.join(', ')], nil)
156
156
  end
157
157
 
158
158
  code_keyword_table = STEP_KEYWORD_KEYS.map do |key|
159
159
  code_keywords = keywords(key).reject{|keyword| keyword == '* '}.map do |keyword|
160
160
  %{"#{self.class.code_keyword_for(keyword)}"}
161
161
  end.join(', ')
162
- Parser::Row.new(["#{key} (code)", code_keywords], [], nil)
162
+ Formatter::Model::Row.new([], ["#{key} (code)", code_keywords], nil)
163
163
  end
164
164
 
165
165
  pf.table(gherkin_keyword_table + code_keyword_table)