gherkin 1.0.30-i386-mingw32 → 2.0.0-i386-mingw32

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 (58) hide show
  1. data/.rspec +1 -0
  2. data/History.txt +19 -0
  3. data/Rakefile +4 -4
  4. data/VERSION.yml +2 -2
  5. data/features/feature_parser.feature +11 -0
  6. data/features/json_formatter.feature +238 -0
  7. data/features/pretty_formatter.feature +9 -0
  8. data/features/step_definitions/gherkin_steps.rb +1 -1
  9. data/features/step_definitions/json_formatter_steps.rb +32 -0
  10. data/features/step_definitions/pretty_formatter_steps.rb +24 -23
  11. data/features/support/env.rb +3 -3
  12. data/lib/gherkin/formatter/json_formatter.rb +82 -0
  13. data/lib/gherkin/formatter/pretty_formatter.rb +73 -78
  14. data/lib/gherkin/i18n.rb +22 -18
  15. data/lib/gherkin/i18n.yml +9 -9
  16. data/lib/gherkin/i18n_lexer.rb +2 -2
  17. data/lib/gherkin/parser/event.rb +6 -6
  18. data/lib/gherkin/parser/filter_listener.rb +5 -1
  19. data/lib/gherkin/parser/formatter_listener.rb +113 -0
  20. data/lib/gherkin/parser/json_parser.rb +102 -0
  21. data/lib/gherkin/parser/parser.rb +10 -2
  22. data/lib/gherkin/parser/row.rb +15 -0
  23. data/lib/gherkin/rubify.rb +2 -0
  24. data/lib/gherkin/tools/files.rb +1 -1
  25. data/lib/gherkin/tools/reformat.rb +1 -2
  26. data/lib/gherkin/tools/stats.rb +1 -1
  27. data/lib/gherkin/tools/stats_listener.rb +5 -5
  28. data/ragel/lexer.c.rl.erb +41 -12
  29. data/ragel/lexer.java.rl.erb +26 -17
  30. data/ragel/lexer.rb.rl.erb +10 -5
  31. data/ragel/lexer_common.rl.erb +6 -6
  32. data/spec/gherkin/c_lexer_spec.rb +2 -2
  33. data/spec/gherkin/fixtures/complex.js +105 -0
  34. data/spec/gherkin/formatter/argument_spec.rb +3 -3
  35. data/spec/gherkin/formatter/colors_spec.rb +3 -4
  36. data/spec/gherkin/formatter/pretty_formatter_spec.rb +21 -50
  37. data/spec/gherkin/i18n_lexer_spec.rb +6 -6
  38. data/spec/gherkin/i18n_spec.rb +16 -9
  39. data/spec/gherkin/java_lexer_spec.rb +1 -2
  40. data/spec/gherkin/output_stream_string_io.rb +24 -0
  41. data/spec/gherkin/parser/filter_listener_spec.rb +16 -9
  42. data/spec/gherkin/parser/formatter_listener_spec.rb +134 -0
  43. data/spec/gherkin/parser/json_parser_spec.rb +129 -0
  44. data/spec/gherkin/parser/parser_spec.rb +9 -9
  45. data/spec/gherkin/parser/tag_expression_spec.rb +8 -8
  46. data/spec/gherkin/rb_lexer_spec.rb +1 -1
  47. data/spec/gherkin/sexp_recorder.rb +21 -1
  48. data/spec/gherkin/shared/{lexer_spec.rb → lexer_group.rb} +172 -102
  49. data/spec/gherkin/shared/{py_string_spec.rb → py_string_group.rb} +21 -17
  50. data/spec/gherkin/shared/{row_spec.rb → row_group.rb} +36 -19
  51. data/spec/gherkin/shared/{tags_spec.rb → tags_group.rb} +13 -9
  52. data/spec/spec_helper.rb +18 -38
  53. data/tasks/bench.rake +3 -3
  54. data/tasks/compile.rake +13 -14
  55. data/tasks/rspec.rake +6 -11
  56. metadata +42 -28
  57. data/features/pretty_printer.feature +0 -14
  58. data/spec/gherkin/csharp_lexer_spec.rb +0 -20
@@ -0,0 +1,82 @@
1
+ require 'json'
2
+ require 'json/pure' # Needed to make JSON.generate work.
3
+ require 'gherkin/rubify'
4
+
5
+ module Gherkin
6
+ module Formatter
7
+ class JSONFormatter
8
+ include Rubify
9
+
10
+ def initialize(io)
11
+ @io = io
12
+ end
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
+ }
23
+ end
24
+
25
+ def scenario(comments, tags, keyword, name, description, line)
26
+ add_step_container(comments, tags, keyword, name, description, line)
27
+ end
28
+
29
+ def scenario_outline(comments, tags, keyword, name, description, line)
30
+ add_step_container(comments, tags, keyword, name, description, line)
31
+ end
32
+
33
+ def examples(comments, tags, keyword, name, description, line, table)
34
+ @table_container = add_element(comments, tags, keyword, name, description, line)
35
+ @table_container['examples_table'] = to_hash_array(table)
36
+ end
37
+
38
+ def step(comments, keyword, name, line, multiline_arg, status, exception, arguments, stepdef_location)
39
+ multiline_arg = rubify(multiline_arg)
40
+ multiline_arg = to_hash_array(multiline_arg) if Array === multiline_arg
41
+ @table_container = {'comments' => comments.to_a, 'keyword' => keyword, 'name' => name, 'line' => line, 'multiline_arg' => multiline_arg}
42
+ last_element['steps'] ||= []
43
+ last_element['steps'] << @table_container
44
+ end
45
+
46
+ def eof
47
+ @io.write(@json_hash.to_json)
48
+ end
49
+
50
+ private
51
+
52
+ def add_element(comments, tags, keyword, name, description, line)
53
+ element = {
54
+ 'comments' => comments.to_a,
55
+ 'tags' => tags.to_a,
56
+ 'keyword' => keyword,
57
+ 'name' => name,
58
+ 'description' => description,
59
+ 'line' => line
60
+ }
61
+ @json_hash['elements'] ||= []
62
+ @json_hash['elements'] << element
63
+ element
64
+ end
65
+
66
+ def add_step_container(comments, tags, keyword, name, description, line)
67
+ add_element(comments, tags, keyword, name, description, line)
68
+ last_element['steps'] = []
69
+ end
70
+
71
+ def last_element
72
+ @json_hash['elements'][-1]
73
+ end
74
+
75
+ def to_hash_array(rows)
76
+ rows.map do |row|
77
+ {"cells" => row.cells.to_a, "comments" => row.comments.to_a, "line" => row.line}
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -13,66 +13,66 @@ module Gherkin
13
13
  include Colors
14
14
  include Escaping
15
15
 
16
- def initialize(io, monochrome=false)
16
+ def initialize(io, monochrome)
17
17
  @io = io
18
18
  @monochrome = monochrome
19
19
  @format = MonochromeFormat.new #@monochrome ? MonochromeFormat.new : AnsiColorFormat.new
20
- @tags = nil
21
- @comments = nil
22
20
  end
23
21
 
24
- def tag(name, line)
25
- @tags ||= []
26
- @tags << name
22
+ def feature(comments, tags, keyword, name, description, uri)
23
+ @uri = uri
24
+ print_comments(comments, '')
25
+ print_tags(tags, '')
26
+ @io.puts "#{keyword}: #{name}"
27
+ @io.puts indent(description, ' ') unless description == ""
27
28
  end
28
29
 
29
- def comment(content, line)
30
- @comments ||= []
31
- @comments << content
30
+ def background(comments, keyword, name, description, line)
31
+ @io.puts
32
+ print_comments(comments, ' ')
33
+ @io.puts " #{keyword}: #{name}#{indented_element_uri!(keyword, name, line)}"
34
+ @io.puts indent(description, ' ') unless description == ""
32
35
  end
33
36
 
34
- def feature(keyword, name, line)
35
- @io.puts "#{grab_comments!('')}#{grab_tags!('')}#{keyword}: #{indent(name, ' ')}"
37
+ def scenario(comments, tags, keyword, name, description, line)
38
+ @io.puts
39
+ print_comments(comments, ' ')
40
+ print_tags(tags, ' ')
41
+ @io.puts " #{keyword}: #{name}#{indented_element_uri!(keyword, name, line)}"
42
+ @io.puts indent(description, ' ') unless description == ""
36
43
  end
37
44
 
38
- def background(keyword, name, line)
39
- @io.puts "\n#{grab_comments!(' ')} #{keyword}: #{indent(name, ' ')}"
45
+ def scenario_outline(comments, tags, keyword, name, description, line)
46
+ scenario(comments, tags, keyword, name, description, line)
40
47
  end
41
48
 
42
- def scenario(keyword, name, line, location=nil)
43
- flush_table
44
- @io.puts "\n#{grab_comments!(' ')}#{grab_tags!(' ')} #{keyword}: #{indent(name, ' ')}#{indented_scenario_location!(keyword, name, location)}"
49
+ def examples(comments, tags, keyword, name, description, line, examples_table)
50
+ @io.puts
51
+ print_comments(comments, ' ')
52
+ print_tags(tags, ' ')
53
+ @io.puts " #{keyword}: #{name}"
54
+ @io.puts indent(description, ' ') unless description == ""
55
+ table(examples_table)
45
56
  end
46
57
 
47
- def scenario_outline(keyword, name, line)
48
- flush_table
49
- @io.puts "\n#{grab_comments!(' ')}#{grab_tags!(' ')} #{keyword}: #{indent(name, ' ')}"
50
- end
51
-
52
- def examples(keyword, name, line)
53
- flush_table
54
- @io.puts "\n#{grab_comments!(' ')}#{grab_tags!(' ')} #{keyword}: #{indent(name, ' ')}"
55
- end
56
-
57
- def step(keyword, name, line, status=nil, exception=nil, arguments=nil, location=nil)
58
- flush_table
58
+ def step(comments, keyword, name, line, multiline_arg, status, exception, arguments, stepdef_location)
59
59
  status_param = "#{status}_param" if status
60
60
  name = Gherkin::Formatter::Argument.format(name, @format, (arguments || []))
61
- #{|arg| status_param ? self.__send__(status_param, arg, @monochrome) : arg} if arguments
62
61
 
63
- step = "#{keyword}#{indent(name, ' ')}"
62
+ step = "#{keyword}#{name}"
64
63
  step = self.__send__(status, step, @monochrome) if status
65
64
 
66
- @io.puts("#{grab_comments!(' ')} #{step}#{indented_step_location!(location)}")
67
- end
68
-
69
- def row(row, line)
70
- @rows ||= []
71
- @rows << row.map{|cell| escape_cell(cell)}
72
- end
73
-
74
- def py_string(string, line)
75
- @io.puts " \"\"\"\n" + string.gsub(START, ' ').gsub(/"""/,'\"\"\"') + "\n \"\"\""
65
+ print_comments(comments, ' ')
66
+ @io.puts(" #{step}#{indented_step_location!(stepdef_location)}")
67
+ case multiline_arg
68
+ when String
69
+ py_string(multiline_arg)
70
+ when Array
71
+ table(multiline_arg)
72
+ when NilClass
73
+ else
74
+ raise "Bad multiline_arg: #{multiline_arg.inspect}"
75
+ end
76
76
  end
77
77
 
78
78
  def syntax_error(state, event, legal_events, line)
@@ -80,7 +80,6 @@ module Gherkin
80
80
  end
81
81
 
82
82
  def eof
83
- flush_table
84
83
  end
85
84
 
86
85
  # This method can be invoked before a #scenario, to ensure location arguments are aligned
@@ -90,79 +89,75 @@ module Gherkin
90
89
  @step_index = -1
91
90
  end
92
91
 
93
- def exception(exception)
94
- exception_text = "#{exception.message} (#{exception.class})\n#{(exception.backtrace || []).join("\n")}".gsub(/^/, ' ')
95
- @io.puts(failed(exception_text, @monochrome))
96
- end
97
-
98
- def flush_table(exception=nil, statuses=nil)
99
- return if @rows.nil?
100
- cell_lengths = @rows.map { |col| col.map { |cell| cell.unpack("U*").length }}
92
+ def table(rows)
93
+ cell_lengths = rows.map do |row|
94
+ row.cells.map do |cell|
95
+ escape_cell(cell).unpack("U*").length
96
+ end
97
+ end
101
98
  max_lengths = cell_lengths.transpose.map { |col_lengths| col_lengths.max }.flatten
102
99
 
103
- @rows.each_with_index do |row, i|
100
+ rows.each_with_index do |row, i|
104
101
  j = -1
105
- @io.puts ' | ' + row.zip(max_lengths).map { |cell, max_length|
102
+ @io.puts ' | ' + row.cells.zip(max_lengths).map { |cell, max_length|
106
103
  j += 1
107
- color(cell, statuses, j) + ' ' * (max_length - cell_lengths[i][j])
104
+ color(cell, nil, j) + ' ' * (max_length - cell_lengths[i][j])
108
105
  }.join(' | ') + ' |'
109
- exception(exception) if exception
110
106
  end
111
- @rows = nil
112
107
  end
113
108
 
114
- private
109
+ private
110
+
111
+ def py_string(string)
112
+ @io.puts " \"\"\"\n" + string.gsub(START, ' ').gsub(/"""/,'\"\"\"') + "\n \"\"\""
113
+ end
114
+
115
+ def exception(exception)
116
+ exception_text = "#{exception.message} (#{exception.class})\n#{(exception.backtrace || []).join("\n")}".gsub(/^/, ' ')
117
+ @io.puts(failed(exception_text, @monochrome))
118
+ end
115
119
 
116
120
  def color(cell, statuses, col)
117
121
  if statuses
118
- self.__send__(statuses[col], cell, @monochrome) + (@monochrome ? '' : reset)
122
+ self.__send__(statuses[col], escape_cell(cell), @monochrome) + (@monochrome ? '' : reset)
119
123
  else
120
- cell
124
+ escape_cell(cell)
121
125
  end
122
126
  end
123
127
 
124
128
  if(RUBY_VERSION =~ /^1\.9/)
125
129
  START = /#{"^".encode('UTF-8')}/
126
- NL = Regexp.new("\n".encode('UTF-8'))
130
+ CRLF = Regexp.new("\r\n".encode('UTF-8'))
127
131
  else
128
132
  START = /^/
129
- NL = /\n/n
133
+ CRLF = /\r\n/n
130
134
  end
131
135
 
132
136
  def indent(string, indentation)
133
- indent = ""
134
- string.split(NL).map do |l|
135
- s = "#{indent}#{l}"
136
- indent = indentation
137
- s
138
- end.join("\n")
137
+ string.gsub(/^/, indentation)
139
138
  end
140
139
 
141
- def grab_tags!(indent)
142
- tags = @tags ? indent + @tags.join(' ') + "\n" : ''
143
- @tags = nil
144
- tags
140
+ def print_tags(tags, indent)
141
+ @io.write(tags.empty? ? '' : indent + tags.join(' ') + "\n")
145
142
  end
146
143
 
147
- def grab_comments!(indent)
148
- comments = @comments ? indent + @comments.join("\n#{indent}") + "\n" : ''
149
- @comments = nil
150
- comments
144
+ def print_comments(comments, indent)
145
+ @io.write(comments.empty? ? '' : indent + comments.join("\n#{indent}") + "\n")
151
146
  end
152
147
 
153
- def indented_scenario_location!(keyword, name, location)
154
- return "" if location.nil?
148
+ def indented_element_uri!(keyword, name, line)
149
+ return '' if @max_step_length.nil?
155
150
  l = (keyword+name).unpack("U*").length
156
151
  @max_step_length = [@max_step_length, l].max
157
152
  indent = @max_step_length - l
158
- ' ' * indent + ' ' + comments("# #{location}", @monochrome)
153
+ ' ' * indent + ' ' + comments("# #{@uri}:#{line}", @monochrome)
159
154
  end
160
155
 
161
156
  def indented_step_location!(location)
162
- return "" if location.nil?
157
+ return '' if location.nil?
163
158
  indent = @max_step_length - @step_lengths[@step_index+=1]
164
159
  ' ' * indent + ' ' + comments("# #{location}", @monochrome)
165
160
  end
166
161
  end
167
162
  end
168
- end
163
+ end
@@ -34,14 +34,14 @@ module Gherkin
34
34
  unique_keywords = all.map do |i18n|
35
35
  keywords.map do |keyword|
36
36
  if keyword.to_s == 'step'
37
- i18n.step_keywords
37
+ i18n.step_keywords.to_a
38
38
  else
39
- i18n.keywords(keyword)
39
+ i18n.keywords(keyword).to_a
40
40
  end
41
41
  end
42
42
  end
43
43
 
44
- unique_keywords.flatten.compact.sort.reverse.uniq.join('|').gsub(/\*/, '\*')
44
+ unique_keywords.flatten.compact.map{|kw| kw.to_s}.sort.reverse.uniq.join('|').gsub(/\*/, '\*')
45
45
  end
46
46
 
47
47
  def code_keywords
@@ -55,15 +55,17 @@ module Gherkin
55
55
  def language_table
56
56
  require 'stringio'
57
57
  require 'gherkin/formatter/pretty_formatter'
58
+ require 'gherkin/parser/row'
58
59
  io = defined?(JRUBY_VERSION) ? Java.java.io.StringWriter.new : StringIO.new
59
60
  pf = Gherkin::Formatter::PrettyFormatter.new(io, true)
60
- all.each{|i18n| pf.row([i18n.iso_code, i18n.keywords('name')[0], i18n.keywords('native')[0]], 0)}
61
- pf.flush_table
61
+ table = all.map do |i18n|
62
+ Parser::Row.new([i18n.iso_code, i18n.keywords('name')[0], i18n.keywords('native')[0]], [], nil)
63
+ end
64
+ pf.table(table)
62
65
  if defined?(JRUBY_VERSION)
63
66
  io.getBuffer.toString
64
67
  else
65
- io.rewind
66
- io.read
68
+ io.string
67
69
  end
68
70
  end
69
71
 
@@ -136,37 +138,39 @@ module Gherkin
136
138
  result
137
139
  end
138
140
 
139
- def keywords(iso_code)
140
- iso_code = iso_code.to_s
141
- raise "No #{iso_code.inspect} in #{@keywords.inspect}" if @keywords[iso_code].nil?
142
- @keywords[iso_code].split('|').map{|keyword| real_keyword(iso_code, keyword)}
141
+ def keywords(key)
142
+ key = key.to_s
143
+ raise "No #{key.inspect} in #{@keywords.inspect}" if @keywords[key].nil?
144
+ @keywords[key].split('|').map{|keyword| real_keyword(key, keyword)}
143
145
  end
144
146
 
145
147
  def keyword_table
146
148
  require 'stringio'
147
149
  require 'gherkin/formatter/pretty_formatter'
150
+ require 'gherkin/parser/row'
148
151
  io = StringIO.new
149
152
  pf = Gherkin::Formatter::PrettyFormatter.new(io, true)
150
153
 
151
- KEYWORD_KEYS.each do |key|
152
- pf.row([key, keywords(key).map{|keyword| %{"#{keyword}"}}.join(', ')], 0)
154
+ gherkin_keyword_table = KEYWORD_KEYS.map do |key|
155
+ Parser::Row.new([key, keywords(key).map{|keyword| %{"#{keyword}"}}.join(', ')], [], nil)
153
156
  end
154
- STEP_KEYWORD_KEYS.each do |key|
157
+
158
+ code_keyword_table = STEP_KEYWORD_KEYS.map do |key|
155
159
  code_keywords = keywords(key).reject{|keyword| keyword == '* '}.map do |keyword|
156
160
  %{"#{self.class.code_keyword_for(keyword)}"}
157
161
  end.join(', ')
158
- pf.row(["#{key} (code)", code_keywords], 0)
162
+ Parser::Row.new(["#{key} (code)", code_keywords], [], nil)
159
163
  end
160
164
 
161
- pf.flush_table
165
+ pf.table(gherkin_keyword_table + code_keyword_table)
162
166
  io.rewind
163
167
  io.read
164
168
  end
165
169
 
166
170
  private
167
171
 
168
- def real_keyword(iso_code, keyword)
169
- if(STEP_KEYWORD_KEYS.index(iso_code))
172
+ def real_keyword(key, keyword)
173
+ if(STEP_KEYWORD_KEYS.index(key))
170
174
  (keyword + ' ').sub(/< $/, '')
171
175
  else
172
176
  keyword
@@ -269,8 +269,8 @@
269
269
  scenario: Forgatókönyv
270
270
  scenario_outline: Forgatókönyv vázlat
271
271
  examples: Példák
272
- given: "*|Ha"
273
- when: "*|Majd"
272
+ given: "*|Amennyiben|Adott"
273
+ when: "*|Majd|Ha|Amikor"
274
274
  then: "*|Akkor"
275
275
  and: "*|És"
276
276
  but: "*|De"
@@ -451,9 +451,9 @@
451
451
  scenario: Сценарий
452
452
  scenario_outline: Структура сценария
453
453
  examples: Значения
454
- given: "*|Допустим"
455
- when: "*|Если"
456
- then: "*|То"
454
+ given: "*|Допустим|Дано|Пусть"
455
+ when: "*|Если|Когда"
456
+ then: "*|То|Тогда"
457
457
  and: "*|И|К тому же"
458
458
  but: "*|Но|А"
459
459
  "sv":
@@ -529,10 +529,10 @@
529
529
  scenario: Сценарій
530
530
  scenario_outline: Структура сценарію
531
531
  examples: Приклади
532
- given: "*|Припустимо|Припустимо, що|Нехай"
533
- when: "*|Якщо"
534
- then: "*|То"
535
- and: "*|І"
532
+ given: "*|Припустимо|Припустимо, що|Нехай|Дано"
533
+ when: "*|Якщо|Коли"
534
+ then: "*|То|Тоді"
535
+ and: "*|І|А також|Та"
536
536
  but: "*|Але"
537
537
  "uz":
538
538
  name: Uzbek
@@ -17,8 +17,8 @@ module Gherkin
17
17
  @force_ruby = force_ruby
18
18
  end
19
19
 
20
- def scan(source)
21
- create_delegate(source).scan(source)
20
+ def scan(source, uri, offset)
21
+ create_delegate(source).scan(source, uri, offset)
22
22
  end
23
23
 
24
24
  private