bryanl-gherkin 2.11.1.1

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 (187) hide show
  1. data/.gitattributes +2 -0
  2. data/.mailmap +2 -0
  3. data/.rbenv-gemsets +1 -0
  4. data/.rspec +1 -0
  5. data/.rvmrc +1 -0
  6. data/.travis.yml +16 -0
  7. data/.yardopts +5 -0
  8. data/Gemfile +5 -0
  9. data/History.md +788 -0
  10. data/LICENSE +20 -0
  11. data/README.md +272 -0
  12. data/Rakefile +26 -0
  13. data/build_native_gems.sh +7 -0
  14. data/cucumber.yml +4 -0
  15. data/examples/parse_and_output_json.rb +19 -0
  16. data/features/.cucumber/stepdefs.json +244 -0
  17. data/features/escaped_pipes.feature +8 -0
  18. data/features/feature_parser.feature +237 -0
  19. data/features/json_formatter.feature +498 -0
  20. data/features/json_parser.feature +331 -0
  21. data/features/native_lexer.feature +19 -0
  22. data/features/parser_with_native_lexer.feature +205 -0
  23. data/features/pretty_formatter.feature +16 -0
  24. data/features/step_definitions/eyeball_steps.rb +3 -0
  25. data/features/step_definitions/gherkin_steps.rb +29 -0
  26. data/features/step_definitions/json_formatter_steps.rb +30 -0
  27. data/features/step_definitions/json_parser_steps.rb +20 -0
  28. data/features/step_definitions/pretty_formatter_steps.rb +85 -0
  29. data/features/steps_parser.feature +46 -0
  30. data/features/support/env.rb +42 -0
  31. data/gherkin.gemspec +77 -0
  32. data/install_mingw_os_x.sh +7 -0
  33. data/js/.npmignore +1 -0
  34. data/js/lib/gherkin/lexer/.npmignore +0 -0
  35. data/lib/gherkin.rb +2 -0
  36. data/lib/gherkin/c_lexer.rb +17 -0
  37. data/lib/gherkin/formatter/ansi_escapes.rb +97 -0
  38. data/lib/gherkin/formatter/argument.rb +16 -0
  39. data/lib/gherkin/formatter/escaping.rb +15 -0
  40. data/lib/gherkin/formatter/filter_formatter.rb +146 -0
  41. data/lib/gherkin/formatter/hashable.rb +19 -0
  42. data/lib/gherkin/formatter/json_formatter.rb +122 -0
  43. data/lib/gherkin/formatter/line_filter.rb +26 -0
  44. data/lib/gherkin/formatter/model.rb +281 -0
  45. data/lib/gherkin/formatter/pretty_formatter.rb +244 -0
  46. data/lib/gherkin/formatter/regexp_filter.rb +21 -0
  47. data/lib/gherkin/formatter/step_printer.rb +21 -0
  48. data/lib/gherkin/formatter/tag_count_formatter.rb +47 -0
  49. data/lib/gherkin/formatter/tag_filter.rb +19 -0
  50. data/lib/gherkin/i18n.rb +180 -0
  51. data/lib/gherkin/i18n.yml +613 -0
  52. data/lib/gherkin/js_lexer.rb +20 -0
  53. data/lib/gherkin/json_parser.rb +177 -0
  54. data/lib/gherkin/lexer/i18n_lexer.rb +46 -0
  55. data/lib/gherkin/listener/event.rb +45 -0
  56. data/lib/gherkin/listener/formatter_listener.rb +143 -0
  57. data/lib/gherkin/native.rb +7 -0
  58. data/lib/gherkin/native/java.rb +72 -0
  59. data/lib/gherkin/native/null.rb +5 -0
  60. data/lib/gherkin/native/therubyracer.rb +39 -0
  61. data/lib/gherkin/parser/meta.txt +5 -0
  62. data/lib/gherkin/parser/parser.rb +164 -0
  63. data/lib/gherkin/parser/root.txt +11 -0
  64. data/lib/gherkin/parser/steps.txt +4 -0
  65. data/lib/gherkin/rb_lexer.rb +8 -0
  66. data/lib/gherkin/rb_lexer/README.rdoc +8 -0
  67. data/lib/gherkin/rb_lexer/ar.rb +1165 -0
  68. data/lib/gherkin/rb_lexer/bg.rb +1377 -0
  69. data/lib/gherkin/rb_lexer/bm.rb +1081 -0
  70. data/lib/gherkin/rb_lexer/ca.rb +1305 -0
  71. data/lib/gherkin/rb_lexer/cs.rb +1157 -0
  72. data/lib/gherkin/rb_lexer/cy_gb.rb +1027 -0
  73. data/lib/gherkin/rb_lexer/da.rb +1043 -0
  74. data/lib/gherkin/rb_lexer/de.rb +1151 -0
  75. data/lib/gherkin/rb_lexer/en.rb +1151 -0
  76. data/lib/gherkin/rb_lexer/en_au.rb +971 -0
  77. data/lib/gherkin/rb_lexer/en_lol.rb +929 -0
  78. data/lib/gherkin/rb_lexer/en_pirate.rb +1205 -0
  79. data/lib/gherkin/rb_lexer/en_scouse.rb +1357 -0
  80. data/lib/gherkin/rb_lexer/en_tx.rb +1011 -0
  81. data/lib/gherkin/rb_lexer/eo.rb +990 -0
  82. data/lib/gherkin/rb_lexer/es.rb +1135 -0
  83. data/lib/gherkin/rb_lexer/et.rb +985 -0
  84. data/lib/gherkin/rb_lexer/fi.rb +964 -0
  85. data/lib/gherkin/rb_lexer/fr.rb +1223 -0
  86. data/lib/gherkin/rb_lexer/he.rb +1113 -0
  87. data/lib/gherkin/rb_lexer/hr.rb +1061 -0
  88. data/lib/gherkin/rb_lexer/hu.rb +1113 -0
  89. data/lib/gherkin/rb_lexer/id.rb +958 -0
  90. data/lib/gherkin/rb_lexer/is.rb +1115 -0
  91. data/lib/gherkin/rb_lexer/it.rb +1081 -0
  92. data/lib/gherkin/rb_lexer/ja.rb +1413 -0
  93. data/lib/gherkin/rb_lexer/ko.rb +1097 -0
  94. data/lib/gherkin/rb_lexer/lt.rb +1040 -0
  95. data/lib/gherkin/rb_lexer/lu.rb +1127 -0
  96. data/lib/gherkin/rb_lexer/lv.rb +1161 -0
  97. data/lib/gherkin/rb_lexer/nl.rb +1110 -0
  98. data/lib/gherkin/rb_lexer/no.rb +1055 -0
  99. data/lib/gherkin/rb_lexer/pl.rb +1452 -0
  100. data/lib/gherkin/rb_lexer/pt.rb +1425 -0
  101. data/lib/gherkin/rb_lexer/ro.rb +1159 -0
  102. data/lib/gherkin/rb_lexer/ru.rb +1749 -0
  103. data/lib/gherkin/rb_lexer/sk.rb +1041 -0
  104. data/lib/gherkin/rb_lexer/sr_cyrl.rb +1798 -0
  105. data/lib/gherkin/rb_lexer/sr_latn.rb +1289 -0
  106. data/lib/gherkin/rb_lexer/sv.rb +1065 -0
  107. data/lib/gherkin/rb_lexer/tr.rb +1087 -0
  108. data/lib/gherkin/rb_lexer/uk.rb +1641 -0
  109. data/lib/gherkin/rb_lexer/uz.rb +1371 -0
  110. data/lib/gherkin/rb_lexer/vi.rb +1193 -0
  111. data/lib/gherkin/rb_lexer/zh_cn.rb +1053 -0
  112. data/lib/gherkin/rb_lexer/zh_tw.rb +1047 -0
  113. data/lib/gherkin/rubify.rb +24 -0
  114. data/lib/gherkin/tag_expression.rb +62 -0
  115. data/ragel/lexer.c.rl.erb +454 -0
  116. data/ragel/lexer.java.rl.erb +219 -0
  117. data/ragel/lexer.js.rl.erb +227 -0
  118. data/ragel/lexer.rb.rl.erb +174 -0
  119. data/ragel/lexer_common.rl.erb +50 -0
  120. data/spec/gherkin/c_lexer_spec.rb +22 -0
  121. data/spec/gherkin/fixtures/1.feature +8 -0
  122. data/spec/gherkin/fixtures/comments_in_table.feature +9 -0
  123. data/spec/gherkin/fixtures/complex.feature +45 -0
  124. data/spec/gherkin/fixtures/complex.json +139 -0
  125. data/spec/gherkin/fixtures/complex_for_filtering.feature +60 -0
  126. data/spec/gherkin/fixtures/complex_with_tags.feature +61 -0
  127. data/spec/gherkin/fixtures/dos_line_endings.feature +45 -0
  128. data/spec/gherkin/fixtures/examples_with_only_header.feature +14 -0
  129. data/spec/gherkin/fixtures/hantu_pisang.feature +35 -0
  130. data/spec/gherkin/fixtures/i18n_fr.feature +14 -0
  131. data/spec/gherkin/fixtures/i18n_fr2.feature +8 -0
  132. data/spec/gherkin/fixtures/i18n_no.feature +7 -0
  133. data/spec/gherkin/fixtures/i18n_pt1.feature +44 -0
  134. data/spec/gherkin/fixtures/i18n_pt2.feature +4 -0
  135. data/spec/gherkin/fixtures/i18n_pt3.feature +4 -0
  136. data/spec/gherkin/fixtures/i18n_pt4.feature +4 -0
  137. data/spec/gherkin/fixtures/i18n_zh-CN.feature +9 -0
  138. data/spec/gherkin/fixtures/issue_145.feature +22 -0
  139. data/spec/gherkin/fixtures/scenario_outline_with_tags.feature +13 -0
  140. data/spec/gherkin/fixtures/scenario_without_steps.feature +5 -0
  141. data/spec/gherkin/fixtures/simple_with_comments.feature +7 -0
  142. data/spec/gherkin/fixtures/simple_with_tags.feature +11 -0
  143. data/spec/gherkin/fixtures/with_bom.feature +3 -0
  144. data/spec/gherkin/formatter/ansi_escapes_spec.rb +32 -0
  145. data/spec/gherkin/formatter/filter_formatter_spec.rb +204 -0
  146. data/spec/gherkin/formatter/json_formatter_spec.rb +92 -0
  147. data/spec/gherkin/formatter/model_spec.rb +28 -0
  148. data/spec/gherkin/formatter/pretty_formatter_spec.rb +177 -0
  149. data/spec/gherkin/formatter/spaces.feature +9 -0
  150. data/spec/gherkin/formatter/step_printer_spec.rb +55 -0
  151. data/spec/gherkin/formatter/tabs.feature +9 -0
  152. data/spec/gherkin/formatter/tag_count_formatter_spec.rb +30 -0
  153. data/spec/gherkin/i18n_spec.rb +241 -0
  154. data/spec/gherkin/java_lexer_spec.rb +20 -0
  155. data/spec/gherkin/js_lexer_spec.rb +23 -0
  156. data/spec/gherkin/json_parser_spec.rb +176 -0
  157. data/spec/gherkin/lexer/i18n_lexer_spec.rb +43 -0
  158. data/spec/gherkin/output_stream_string_io.rb +20 -0
  159. data/spec/gherkin/parser/parser_spec.rb +16 -0
  160. data/spec/gherkin/rb_lexer_spec.rb +20 -0
  161. data/spec/gherkin/sexp_recorder.rb +59 -0
  162. data/spec/gherkin/shared/bom_group.rb +20 -0
  163. data/spec/gherkin/shared/doc_string_group.rb +163 -0
  164. data/spec/gherkin/shared/lexer_group.rb +591 -0
  165. data/spec/gherkin/shared/row_group.rb +125 -0
  166. data/spec/gherkin/shared/tags_group.rb +54 -0
  167. data/spec/gherkin/tag_expression_spec.rb +142 -0
  168. data/spec/spec_helper.rb +75 -0
  169. data/tasks/bench.rake +184 -0
  170. data/tasks/bench/feature_builder.rb +49 -0
  171. data/tasks/bench/null_listener.rb +4 -0
  172. data/tasks/compile.rake +120 -0
  173. data/tasks/cucumber.rake +22 -0
  174. data/tasks/gems.rake +31 -0
  175. data/tasks/ikvm.rake +124 -0
  176. data/tasks/ragel_task.rb +100 -0
  177. data/tasks/release.rake +49 -0
  178. data/tasks/rspec.rake +8 -0
  179. data/tasks/yard.rake +7 -0
  180. data/tasks/yard/default/layout/html/bubble_32x32.png +0 -0
  181. data/tasks/yard/default/layout/html/bubble_48x48.png +0 -0
  182. data/tasks/yard/default/layout/html/footer.erb +5 -0
  183. data/tasks/yard/default/layout/html/index.erb +1 -0
  184. data/tasks/yard/default/layout/html/layout.erb +25 -0
  185. data/tasks/yard/default/layout/html/logo.erb +1 -0
  186. data/tasks/yard/default/layout/html/setup.rb +4 -0
  187. metadata +473 -0
@@ -0,0 +1,20 @@
1
+ require 'v8'
2
+
3
+ module Gherkin
4
+ # Thin adapter for the JavaScript lexer, primarily used for testing.
5
+ class JsLexer
6
+ def self.[](i18n_underscored_iso_code)
7
+ cxt = V8::Context.new
8
+ cxt['exports'] = {}
9
+
10
+ # Mimic Node.js / Firebug console.log
11
+ cxt['console'] = STDOUT
12
+ def STDOUT.log(*a)
13
+ p a
14
+ end
15
+
16
+ cxt.load(File.dirname(__FILE__) + "/../../js/lib/gherkin/lexer/#{i18n_underscored_iso_code}.min.js")
17
+ cxt['exports']['Lexer']
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,177 @@
1
+ require 'json'
2
+ require 'gherkin/formatter/model'
3
+ require 'gherkin/formatter/argument'
4
+ require 'gherkin/native'
5
+ require 'base64'
6
+
7
+ module Gherkin
8
+ class JSONParser
9
+ native_impl('gherkin')
10
+
11
+ include Base64
12
+
13
+ def initialize(reporter, formatter)
14
+ @reporter, @formatter = reporter, formatter
15
+ end
16
+
17
+ # Parse a gherkin object +o+, which can either be a JSON String,
18
+ # or a Hash (from a parsed JSON String).
19
+ def parse(o)
20
+ o = JSON.parse(o) if String === o
21
+
22
+ o.each do |f|
23
+ @formatter.uri(f['uri'])
24
+ Formatter::Model::Feature.new(comments(f), tags(f), keyword(f), name(f), description(f), line(f), id(f)).replay(@formatter)
25
+ (f["elements"] || []).each do |feature_element|
26
+ feature_element(feature_element).replay(@formatter)
27
+
28
+ (feature_element["before"] || []).each do |hook|
29
+ before(hook)
30
+ end
31
+
32
+ (feature_element["steps"] || []).each do |step|
33
+ step(step).replay(@formatter)
34
+ match(step)
35
+ result(step)
36
+ embeddings(step)
37
+ output(step)
38
+ end
39
+
40
+ (feature_element["after"] || []).each do |hook|
41
+ after(hook)
42
+ end
43
+
44
+ (feature_element["examples"] || []).each do |eo|
45
+ Formatter::Model::Examples.new(comments(eo), tags(eo), keyword(eo), name(eo), description(eo), line(eo), id(eo), examples_rows(eo['rows'])).replay(@formatter)
46
+ end
47
+ end
48
+ end
49
+
50
+ @formatter.eof
51
+ end
52
+
53
+ private
54
+
55
+ def feature_element(o)
56
+ case o['type']
57
+ when 'background'
58
+ Formatter::Model::Background.new(comments(o), keyword(o), name(o), description(o), line(o))
59
+ when 'scenario'
60
+ Formatter::Model::Scenario.new(comments(o), tags(o), keyword(o), name(o), description(o), line(o), id(o))
61
+ when 'scenario_outline'
62
+ Formatter::Model::ScenarioOutline.new(comments(o), tags(o), keyword(o), name(o), description(o), line(o), id(o))
63
+ end
64
+ end
65
+
66
+ def step(o)
67
+ builder = Formatter::Model::Step::Builder.new(comments(o), keyword(o), name(o), line(o))
68
+
69
+ (o['rows'] || []).each do |row|
70
+ builder.row comments(row), row['cells'], row['line'], nil
71
+ end
72
+
73
+ if(o['doc_string'])
74
+ ds = o['doc_string']
75
+ builder.doc_string ds['value'], ds['content_type'].to_s, ds['line']
76
+ end
77
+
78
+ builder.build
79
+ end
80
+
81
+ def match(o)
82
+ if(m = o['match'])
83
+ Formatter::Model::Match.new(arguments(m), location(m)).replay(@reporter)
84
+ end
85
+ end
86
+
87
+ def result(o)
88
+ if(r = o['result'])
89
+ Formatter::Model::Result.new(status(r), duration(r), error_message(r)).replay(@reporter)
90
+ end
91
+ end
92
+
93
+ def before(o)
94
+ m = o['match']
95
+ match = Formatter::Model::Match.new([], location(m))
96
+ r = o['result']
97
+ result = Formatter::Model::Result.new(status(r), duration(r), error_message(r))
98
+ @reporter.before(match, result)
99
+ end
100
+
101
+ def after(o)
102
+ m = o['match']
103
+ match = Formatter::Model::Match.new([], location(m))
104
+ r = o['result']
105
+ result = Formatter::Model::Result.new(status(r), duration(r), error_message(r))
106
+ @reporter.after(match, result)
107
+ end
108
+
109
+ def embeddings(o)
110
+ (o['embeddings'] || []).each do |embedding|
111
+ @reporter.embedding(embedding['mime_type'], Base64::decode64(embedding['data']))
112
+ end
113
+ end
114
+
115
+ def output(o)
116
+ (o['output'] || []).each do |text|
117
+ @reporter.write(text)
118
+ end
119
+ end
120
+
121
+ def examples_rows(o)
122
+ o.map{|row| Formatter::Model::ExamplesTableRow.new(comments(row), row['cells'], row['line'], row['id'])}
123
+ end
124
+
125
+ def comments(o)
126
+ (o['comments'] || []).map do |comment|
127
+ Formatter::Model::Comment.new(comment['value'], comment['line'])
128
+ end
129
+ end
130
+
131
+ def tags(o)
132
+ (o['tags'] || []).map do |tag|
133
+ Formatter::Model::Tag.new(tag['name'], tag['line'])
134
+ end
135
+ end
136
+
137
+ def keyword(o)
138
+ o['keyword']
139
+ end
140
+
141
+ def name(o)
142
+ o['name']
143
+ end
144
+
145
+ def description(o)
146
+ o['description']
147
+ end
148
+
149
+ def line(o)
150
+ o['line']
151
+ end
152
+
153
+ def id(o)
154
+ o['id']
155
+ end
156
+
157
+ def arguments(m)
158
+ m['arguments'].map{|a| Formatter::Argument.new(a['offset'], a['val'])}
159
+ end
160
+
161
+ def location(m)
162
+ m['location']
163
+ end
164
+
165
+ def status(r)
166
+ r['status']
167
+ end
168
+
169
+ def duration(r)
170
+ r['duration']
171
+ end
172
+
173
+ def error_message(r)
174
+ r['error_message']
175
+ end
176
+ end
177
+ end
@@ -0,0 +1,46 @@
1
+ require 'gherkin/i18n'
2
+ require 'gherkin/native'
3
+
4
+ module Gherkin
5
+ module Lexer
6
+ LexingError = Class.new(StandardError)
7
+
8
+ # The main entry point to lexing Gherkin source.
9
+ class I18nLexer
10
+ native_impl('gherkin')
11
+
12
+ COMMENT_OR_EMPTY_LINE_PATTERN = /^\s*#|^\s*$/
13
+ LANGUAGE_PATTERN = /^\s*#\s*language\s*:\s*([a-zA-Z\-]+)/ #:nodoc:
14
+ attr_reader :i18n_language
15
+
16
+ def initialize(listener, force_ruby=false)
17
+ @listener = listener
18
+ @force_ruby = force_ruby
19
+ end
20
+
21
+ def scan(source)
22
+ create_delegate(source).scan(source)
23
+ end
24
+
25
+ private
26
+
27
+ def create_delegate(source)
28
+ @i18n_language = lang(source)
29
+ @i18n_language.lexer(@listener, @force_ruby)
30
+ end
31
+
32
+ def lang(source)
33
+ key = 'en'
34
+ source.each_line do |line|
35
+ break unless COMMENT_OR_EMPTY_LINE_PATTERN =~ line
36
+ if LANGUAGE_PATTERN =~ line
37
+ key = $1
38
+ break
39
+ end
40
+ end
41
+ I18n.get(key)
42
+ end
43
+
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,45 @@
1
+ module Gherkin
2
+ module Listener
3
+ class Event < Array
4
+ def event
5
+ self[0]
6
+ end
7
+
8
+ def keyword
9
+ self[1]
10
+ end
11
+
12
+ def line_match?(lines)
13
+ lines.include?(line)
14
+ end
15
+
16
+ def name_match?(name_regexen)
17
+ return false unless [:feature, :background, :scenario, :scenario_outline, :examples].include?(event)
18
+ name_regexen.detect{|name_regex| name =~ name_regex}
19
+ end
20
+
21
+ def replay(listener)
22
+ begin
23
+ listener.__send__(event, *args)
24
+ rescue ArgumentError => e
25
+ e.message << "\nListener: #{listener.class}, args: #{args.inspect}"
26
+ raise e
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ def name
33
+ self[2]
34
+ end
35
+
36
+ def line
37
+ self[-1]
38
+ end
39
+
40
+ def args
41
+ self[1..-1]
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,143 @@
1
+ require 'gherkin/native'
2
+ require 'gherkin/formatter/model'
3
+
4
+ module Gherkin
5
+ module Listener
6
+ # Adapter from the "raw" Gherkin <tt>Listener</tt> API
7
+ # to the slightly more high-level <tt>Formatter</tt> API,
8
+ # which is easier to implement (less state to keep track of).
9
+ class FormatterListener
10
+ native_impl('gherkin')
11
+
12
+ def initialize(formatter)
13
+ @formatter = formatter
14
+ @stash = Stash.new
15
+ end
16
+
17
+ def comment(value, line)
18
+ @stash.comment Formatter::Model::Comment.new(value, line)
19
+ end
20
+
21
+ def tag(name, line)
22
+ @stash.tag Formatter::Model::Tag.new(name, line)
23
+ end
24
+
25
+ def feature(keyword, name, description, line)
26
+ @stash.feature(name) do |comments, tags, id|
27
+ replay Formatter::Model::Feature.new(comments, tags, keyword, name, description, line, id)
28
+ end
29
+ end
30
+
31
+ def background(keyword, name, description, line)
32
+ @stash.feature_element(name) do |comments, tags, id|
33
+ replay Formatter::Model::Background.new(comments, keyword, name, description, line)
34
+ end
35
+ end
36
+
37
+ def scenario(keyword, name, description, line)
38
+ replay_step_or_examples
39
+ @stash.feature_element(name) do |comments, tags, id|
40
+ replay Formatter::Model::Scenario.new(comments, tags, keyword, name, description, line, id)
41
+ end
42
+ end
43
+
44
+ def scenario_outline(keyword, name, description, line)
45
+ replay_step_or_examples
46
+ @stash.feature_element(name) do |comments, tags, id|
47
+ replay Formatter::Model::ScenarioOutline.new(comments, tags, keyword, name, description, line, id)
48
+ end
49
+ end
50
+
51
+ def examples(keyword, name, description, line)
52
+ replay_step_or_examples
53
+ @stash.examples(name) do |comments, tags, id|
54
+ @current_builder = Formatter::Model::Examples::Builder.new(comments, tags, keyword, name, description, line, id)
55
+ end
56
+ end
57
+
58
+ def step(keyword, name, line)
59
+ replay_step_or_examples
60
+ @stash.basic_statement do |comments, id|
61
+ @current_builder = Formatter::Model::Step::Builder.new(comments, keyword, name, line)
62
+ end
63
+ end
64
+
65
+ def row(cells, line)
66
+ @stash.basic_statement do |comments, id|
67
+ @current_builder.row(comments, cells, line, id)
68
+ end
69
+ end
70
+
71
+ def doc_string(content_type, value, line)
72
+ @current_builder.doc_string(value, content_type, line)
73
+ end
74
+
75
+ def eof
76
+ replay_step_or_examples
77
+ @formatter.eof
78
+ end
79
+
80
+ def syntax_error(state, ev, legal_events, uri, line)
81
+ @formatter.syntax_error(state, ev, legal_events, uri, line)
82
+ end
83
+
84
+ private
85
+
86
+ def replay(element)
87
+ element.replay(@formatter)
88
+ end
89
+
90
+ class Stash
91
+ attr_reader :comments, :tags, :ids
92
+
93
+ def initialize
94
+ @comments, @tags, @ids = [], [], []
95
+ @row_index = 0
96
+ end
97
+
98
+ def comment(comment)
99
+ @comments << comment
100
+ end
101
+
102
+ def feature(name)
103
+ @feature_id = id(name)
104
+ yield @comments, @tags, @feature_id
105
+ @comments, @tags = [], []
106
+ end
107
+
108
+ def feature_element(name)
109
+ @feature_element_id = "#{@feature_id};#{id(name)}"
110
+ yield @comments, @tags, @feature_element_id
111
+ @comments, @tags = [], []
112
+ end
113
+
114
+ def examples(name)
115
+ @examples_id = "#{@feature_element_id};#{id(name)}"
116
+ @row_index = 0
117
+ yield @comments, @tags, @examples_id
118
+ @comments, @tags = [], []
119
+ end
120
+
121
+ def basic_statement
122
+ @row_index += 1
123
+ yield @comments, "#{@examples_id};#{@row_index}"
124
+ @comments = []
125
+ end
126
+
127
+ def tag(tag)
128
+ @tags << tag
129
+ end
130
+
131
+ def id(name)
132
+ (name || '').gsub(/[\s_]/, '-').downcase
133
+ end
134
+ end
135
+
136
+ def replay_step_or_examples
137
+ return unless @current_builder
138
+ replay(@current_builder)
139
+ @current_builder = nil
140
+ end
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,7 @@
1
+ if defined?(JRUBY_VERSION)
2
+ require 'gherkin/native/java'
3
+ elsif ENV['GHERKIN_JS_NATIVE']
4
+ require 'gherkin/native/therubyracer'
5
+ else
6
+ require 'gherkin/native/null'
7
+ end
@@ -0,0 +1,72 @@
1
+ class Class
2
+ class IOWriter < Java.java.io.Writer
3
+ def initialize(io)
4
+ @io = io
5
+ end
6
+
7
+ def write(cbuf, off, len)
8
+ @io.write(cbuf.unpack("U*")[off..len].pack("U*"))
9
+ end
10
+
11
+ def flush
12
+ @io.flush
13
+ end
14
+
15
+ def close
16
+ @io.close
17
+ end
18
+ end
19
+
20
+ # Causes a Java class to be instantiated instead of the Ruby class when
21
+ # running on JRuby. This is used to test both pure Java and pure Ruby classes
22
+ # from the same Ruby based test suite. The Java Class must have a package name
23
+ # that corresponds with the Ruby class.
24
+ def native_impl(lib)
25
+ require "#{lib}.jar"
26
+
27
+ class << self
28
+ def new(*args)
29
+ begin
30
+ java_class.new(*javaify(args))
31
+ rescue ArgumentError => e
32
+ e.message << "\n#{java_class.name}"
33
+ raise e
34
+ rescue NameError => e
35
+ e.message << "\n args: #{args.inspect}"
36
+ raise e
37
+ end
38
+ end
39
+
40
+ def javaify(arg)
41
+ if Array === arg
42
+ arg.map{|a| javaify(a)}
43
+ else
44
+ case(arg)
45
+ when Regexp
46
+ java.util.regex.Pattern.compile(arg.source)
47
+ when Symbol
48
+ arg.to_s
49
+ when IO
50
+ IOWriter.new(arg)
51
+ else
52
+ arg
53
+ end
54
+ end
55
+ end
56
+
57
+ def ===(object)
58
+ super || object.java_kind_of?(java_class)
59
+ end
60
+
61
+ def java_class
62
+ names = self.name.split('::')
63
+ package = Java
64
+ names[0..-2].each do |module_name|
65
+ package = package.__send__(module_name.downcase)
66
+ end
67
+
68
+ package.__send__(names[-1])
69
+ end
70
+ end
71
+ end
72
+ end