gherkin 2.1.5 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/History.txt +16 -0
  2. data/README.rdoc +1 -0
  3. data/Rakefile +1 -1
  4. data/VERSION.yml +2 -2
  5. data/features/json_formatter.feature +3 -11
  6. data/features/json_parser.feature +2 -5
  7. data/features/step_definitions/json_lexer_steps.rb +1 -1
  8. data/features/step_definitions/pretty_formatter_steps.rb +1 -1
  9. data/features/support/env.rb +2 -1
  10. data/java/src/main/java/gherkin/lexer/{.gitignore → i18n/.gitignore} +0 -0
  11. data/json-simple-1.1.dll +0 -0
  12. data/lib/gherkin.rb +1 -1
  13. data/lib/gherkin/formatter/filter_formatter.rb +52 -61
  14. data/lib/gherkin/formatter/json_formatter.rb +26 -94
  15. data/lib/gherkin/formatter/line_filter.rb +3 -3
  16. data/lib/gherkin/formatter/model.rb +156 -19
  17. data/lib/gherkin/formatter/pretty_formatter.rb +25 -25
  18. data/lib/gherkin/formatter/regexp_filter.rb +5 -1
  19. data/lib/gherkin/formatter/tag_count_formatter.rb +15 -12
  20. data/lib/gherkin/formatter/tag_filter.rb +19 -0
  21. data/lib/gherkin/json_parser.rb +49 -65
  22. data/lib/gherkin/lexer/i18n_lexer.rb +40 -0
  23. data/lib/gherkin/listener/formatter_listener.rb +11 -18
  24. data/lib/gherkin/parser/parser.rb +4 -5
  25. data/lib/gherkin/tools/stats_listener.rb +1 -1
  26. data/ragel/lexer.c.rl.erb +3 -1
  27. data/ragel/lexer.java.rl.erb +4 -4
  28. data/ragel/lexer.rb.rl.erb +3 -1
  29. data/spec/gherkin/fixtures/complex.json +2 -3
  30. data/spec/gherkin/formatter/model_spec.rb +1 -1
  31. data/spec/gherkin/formatter/pretty_formatter_spec.rb +11 -8
  32. data/spec/gherkin/i18n_spec.rb +3 -3
  33. data/spec/gherkin/java_lexer_spec.rb +1 -1
  34. data/spec/gherkin/json.rb +5 -0
  35. data/spec/gherkin/json_parser_spec.rb +49 -73
  36. data/spec/gherkin/lexer/i18n_lexer_spec.rb +33 -0
  37. data/spec/gherkin/sexp_recorder.rb +0 -2
  38. data/spec/spec_helper.rb +1 -0
  39. data/tasks/bench.rake +2 -2
  40. data/tasks/compile.rake +1 -1
  41. data/tasks/ikvm.rake +3 -1
  42. data/tasks/ragel_task.rb +1 -1
  43. data/tasks/release.rake +13 -1
  44. data/tasks/rspec.rake +0 -1
  45. metadata +17 -13
  46. data/lib/gherkin/i18n_lexer.rb +0 -38
  47. data/spec/gherkin/i18n_lexer_spec.rb +0 -26
@@ -1,3 +1,19 @@
1
+ == 2.2.0 (2010-07-26)
2
+
3
+ This release breaks some APIs since the previous 2.1.5 release. If you install gherkin 2.2.0 you must also upgrade to
4
+ Cucumber 0.9.0.
5
+
6
+ === Bugfixes
7
+ * I18nLexer doesn't recognise language header with \r\n on OS X. (#70 Aslak Hellesøy)
8
+
9
+ === New Features
10
+ * Pure Java FilterFormatter. (Aslak Hellesøy)
11
+ * Pure Java JSONFormatter. (Aslak Hellesøy)
12
+
13
+ === Changed Features
14
+ * All formatter events take exactly one argument. Each argument is a single object with all data. (Aslak Hellesøy)
15
+ * Several java classes have moved to a different package in order to improve separation of concerns. (Aslak Hellesøy)
16
+
1
17
  == 2.1.5 (2010-07-17)
2
18
 
3
19
  === Bugfixes
@@ -32,6 +32,7 @@ E.g. in Bash, export RL_LANG="en,fr,no". This can be quite helpful when modifyin
32
32
  ** java/pom.xml
33
33
  ** ikvm/Gherkin/Gherkin.csproj
34
34
  * Make sure both JRuby and MRI has the latest Cucumber installed (from source) otherwise the jruby gem might not get the jar inside it.
35
+ ** Install cucumber without gherkin dep: gem install --ignore-dependencies pkg/cucumber
35
36
  * rake release:ALL
36
37
  * Announce on Cucumber list, IRC and Twitter.
37
38
 
data/Rakefile CHANGED
@@ -21,7 +21,7 @@ begin
21
21
  gem.add_dependency "trollop", "~> 1.16.2"
22
22
  gem.add_development_dependency 'awesome_print', '~> 0.2.1'
23
23
  gem.add_development_dependency 'rspec', '~> 2.0.0.beta.17'
24
- gem.add_development_dependency "cucumber", "~> 0.8.5"
24
+ gem.add_development_dependency "cucumber", "~> 0.9.0"
25
25
  gem.add_development_dependency "rake-compiler", "~> 0.7.0" unless defined?(JRUBY_VERSION)
26
26
 
27
27
  gem.files -= FileList['ikvm/**/*']
@@ -1,5 +1,5 @@
1
1
  ---
2
2
  :major: 2
3
- :minor: 1
4
- :patch: 5
3
+ :minor: 2
4
+ :patch: 0
5
5
  :build:
@@ -16,13 +16,11 @@ Feature: JSON formatter
16
16
  Then the outputted JSON should be:
17
17
  """
18
18
  {
19
- "type": "feature",
20
19
  "comments": [{"value": "# language: no", "line": 1}, {"value": "# Another comment", "line": 2}],
21
20
  "keyword": "Egenskap",
22
21
  "name": "Kjapp",
23
22
  "description": "",
24
- "line": 3,
25
- "uri": "test.feature"
23
+ "line": 3
26
24
  }
27
25
  """
28
26
 
@@ -73,13 +71,11 @@ Feature: JSON formatter
73
71
  Then the outputted JSON should be:
74
72
  """
75
73
  {
76
- "type": "feature",
77
74
  "tags": [{"name": "@one", "line":1}],
78
75
  "keyword": "Feature",
79
76
  "name": "OH HAI",
80
77
  "description": "",
81
78
  "line": 2,
82
- "uri": "test.feature",
83
79
  "elements":[
84
80
  {
85
81
  "type": "scenario",
@@ -136,13 +132,12 @@ Feature: JSON formatter
136
132
  ],
137
133
  "examples": [
138
134
  {
139
- "type": "examples",
140
135
  "tags": [{"name": "@five", "line":17}],
141
136
  "keyword": "Examples",
142
137
  "name": "Real life",
143
138
  "description": "",
144
139
  "line": 18,
145
- "table": [
140
+ "rows": [
146
141
  {
147
142
  "cells": ["boredom"],
148
143
  "line": 19
@@ -209,13 +204,12 @@ Feature: JSON formatter
209
204
  ],
210
205
  "examples": [
211
206
  {
212
- "type": "examples",
213
207
  "comments": [{"value": "# comments", "line": 36}, {"value": "# everywhere", "line": 37}],
214
208
  "keyword": "Examples",
215
209
  "name": "An example",
216
210
  "description": "",
217
211
  "line": 38,
218
- "table": [
212
+ "rows": [
219
213
  {
220
214
  "comments": [{"value": "# I mean", "line": 39}],
221
215
  "line": 40,
@@ -244,12 +238,10 @@ Feature: JSON formatter
244
238
  Then the outputted JSON should be:
245
239
  """
246
240
  {
247
- "type": "feature",
248
241
  "keyword": "Feature",
249
242
  "name": "Kjapp",
250
243
  "description": "",
251
244
  "line": 1,
252
- "uri": "test.feature",
253
245
  "elements": [
254
246
  {
255
247
  "type": "background",
@@ -10,7 +10,6 @@ Feature: JSON lexer
10
10
  Given the following JSON is parsed:
11
11
  """
12
12
  {
13
- "type": "feature",
14
13
  "comments": [
15
14
  {"value": "# language: no"},
16
15
  {"value": "# Another comment"}
@@ -33,7 +32,6 @@ Feature: JSON lexer
33
32
  Given the following JSON is parsed:
34
33
  """
35
34
  {
36
- "type": "feature",
37
35
  "comments": [],
38
36
  "keyword": "Feature",
39
37
  "name": "OH HAI",
@@ -112,7 +110,7 @@ Feature: JSON lexer
112
110
  "name": "Real life",
113
111
  "description": "",
114
112
  "line": 18,
115
- "table": [
113
+ "rows": [
116
114
  {
117
115
  "comments": [],
118
116
  "cells": ["boredom"],
@@ -195,7 +193,7 @@ Feature: JSON lexer
195
193
  "name": "An example",
196
194
  "description": "",
197
195
  "line": 38,
198
- "table": [
196
+ "rows": [
199
197
  {
200
198
  "comments": [{"value": "# I mean"}],
201
199
  "line": 40,
@@ -263,7 +261,6 @@ Feature: JSON lexer
263
261
  Given the following JSON is parsed:
264
262
  """
265
263
  {
266
- "type": "feature",
267
264
  "comments": [],
268
265
  "description": "",
269
266
  "keyword": "Feature",
@@ -12,7 +12,7 @@ Given /^a JSON lexer$/ do
12
12
  end
13
13
 
14
14
  Given /^the following JSON is parsed:$/ do |text|
15
- @json_parser.parse(JSON.pretty_generate(JSON.parse(text)))
15
+ @json_parser.parse(JSON.pretty_generate(JSON.parse(text)), "unknown.json")
16
16
  end
17
17
 
18
18
  Then /^the outputted text should be:$/ do |expected_text|
@@ -23,7 +23,7 @@ module PrettyPlease
23
23
  result = StringIO.new
24
24
  pretty_formatter = Gherkin::Formatter::PrettyFormatter.new(result, false)
25
25
  json_parser = Gherkin::JSONParser.new(pretty_formatter)
26
- json_parser.parse(json.string)
26
+ json_parser.parse(json.string, "#{feature_path}.json")
27
27
 
28
28
  result.string
29
29
  end
@@ -3,8 +3,9 @@
3
3
  $LOAD_PATH << File.expand_path(File.dirname(__FILE__) + path)
4
4
  end
5
5
  require 'gherkin'
6
- require "gherkin/sexp_recorder"
6
+ require 'gherkin/sexp_recorder'
7
7
  require 'gherkin/output_stream_string_io'
8
+ require 'gherkin/json'
8
9
 
9
10
  module TransformHelpers
10
11
  def tr_line_number(step_arg)
Binary file
@@ -1,2 +1,2 @@
1
- require 'gherkin/i18n_lexer'
1
+ require 'gherkin/lexer/i18n_lexer'
2
2
  require 'gherkin/parser/parser'
@@ -1,19 +1,19 @@
1
- require 'gherkin/rubify'
2
1
  require 'gherkin/tag_expression'
3
2
  require 'gherkin/formatter/regexp_filter'
4
3
  require 'gherkin/formatter/line_filter'
4
+ require 'gherkin/formatter/tag_filter'
5
5
  require 'gherkin/formatter/model'
6
+ require 'gherkin/native'
6
7
 
7
8
  module Gherkin
8
9
  module Formatter
9
10
  class FilterFormatter
10
- include Rubify
11
+ native_impl('gherkin')
11
12
 
12
13
  def initialize(formatter, filters)
13
14
  @formatter = formatter
14
15
  @filter = detect_filter(filters)
15
16
 
16
-
17
17
  @feature_tags = []
18
18
  @feature_element_tags = []
19
19
  @examples_tags = []
@@ -24,67 +24,59 @@ module Gherkin
24
24
  @examples_events = []
25
25
  end
26
26
 
27
- def feature(statement, uri)
28
- @feature_tags = statement.tags
29
- @feature_name = statement.name
30
- @feature_events = [[:feature, statement, uri]]
27
+ def uri(uri)
28
+ @formatter.uri(uri)
29
+ end
30
+
31
+ def feature(feature)
32
+ @feature_tags = feature.tags
33
+ @feature_name = feature.name
34
+ @feature_events = [feature]
31
35
  end
32
36
 
33
- def background(statement)
34
- @feature_element_name = statement.name
35
- @feature_element_range = statement.line_range
36
- @background_events = [[:background, statement]]
37
+ def background(background)
38
+ @feature_element_name = background.name
39
+ @feature_element_range = background.line_range
40
+ @background_events = [background]
37
41
  end
38
42
 
39
- def scenario(statement)
43
+ def scenario(scenario)
40
44
  replay!
41
- @feature_element_tags = statement.tags
42
- @feature_element_name = statement.name
43
- @feature_element_range = statement.line_range
44
- @feature_element_events = [[:scenario, statement]]
45
- @examples_events.clear
45
+ @feature_element_tags = scenario.tags
46
+ @feature_element_name = scenario.name
47
+ @feature_element_range = scenario.line_range
48
+ @feature_element_events = [scenario]
46
49
  end
47
50
 
48
- def scenario_outline(statement)
51
+ def scenario_outline(scenario_outline)
49
52
  replay!
50
- @feature_element_tags = statement.tags
51
- @feature_element_name = statement.name
52
- @feature_element_range = statement.line_range
53
- @feature_element_events = [[:scenario_outline, statement]]
54
- @examples_events.clear
53
+ @feature_element_tags = scenario_outline.tags
54
+ @feature_element_name = scenario_outline.name
55
+ @feature_element_range = scenario_outline.line_range
56
+ @feature_element_events = [scenario_outline]
55
57
  end
56
58
 
57
- def examples(statement, examples_rows)
59
+ def examples(examples)
58
60
  replay!
59
- @examples_tags = statement.tags
60
- @examples_name = statement.name
61
+ @examples_tags = examples.tags
62
+ @examples_name = examples.name
61
63
 
62
- table_body_range = examples_rows.to_a[1].line..examples_rows.to_a[-1].line
63
- @examples_range = statement.line_range.first..table_body_range.last
64
- if(LineFilter === @filter && @filter.eval([table_body_range]))
65
- examples_rows = @filter.filter_table_body_rows(examples_rows)
64
+ table_body_range = examples.rows[1].line..examples.rows[-1].line
65
+ @examples_range = examples.line_range.first..table_body_range.last
66
+ if(@filter.eval([], [], [table_body_range]))
67
+ examples.rows = @filter.filter_table_body_rows(examples.rows)
66
68
  end
67
- @examples_events = [[:examples, statement, examples_rows]]
69
+ @examples_events = [examples]
68
70
  end
69
71
 
70
- def step(statement, multiline_arg, result)
71
- args = [:step, statement, multiline_arg, result]
72
+ def step(step)
72
73
  if @feature_element_events.any?
73
- @feature_element_events << args
74
+ @feature_element_events << step
74
75
  else
75
- @background_events << args
76
+ @background_events << step
76
77
  end
77
78
 
78
- if LineFilter === @filter
79
- step_range = statement.line_range
80
- case rubify(multiline_arg)
81
- when Model::PyString
82
- step_range = step_range.first..multiline_arg.line_range.last
83
- when Array
84
- step_range = step_range.first..multiline_arg.to_a[-1].line
85
- end
86
- @feature_element_range = @feature_element_range.first..step_range.last
87
- end
79
+ @feature_element_range = @feature_element_range.first..step.line_range.last
88
80
  end
89
81
 
90
82
  def eof
@@ -102,22 +94,21 @@ module Gherkin
102
94
  when Regexp
103
95
  RegexpFilter.new(filters)
104
96
  when String
105
- TagExpression.new(filters)
97
+ TagFilter.new(filters)
106
98
  end
107
99
  end
108
100
 
109
101
  def replay!
110
- case @filter
111
- when TagExpression
112
- feature_element_ok = @filter.eval(tag_names(@feature_tags.to_a + @feature_element_tags.to_a))
113
- examples_ok = @filter.eval(tag_names(@feature_tags.to_a + @feature_element_tags.to_a + @examples_tags.to_a)) if @examples_tags
114
- when RegexpFilter
115
- feature_element_ok = @filter.eval([@feature_element_name])
116
- examples_ok = @filter.eval([@feature_element_name, @examples_name]) if @examples_name
117
- when LineFilter
118
- feature_element_ok = @filter.eval([@feature_element_range]) if @feature_element_range
119
- examples_ok = @filter.eval([@feature_element_range, @examples_range]) if @examples_range
120
- end
102
+ feature_element_ok = @filter.eval(
103
+ (@feature_tags + @feature_element_tags),
104
+ [@feature_name, @feature_element_name].compact,
105
+ [@feature_element_range].compact
106
+ )
107
+ examples_ok = @filter.eval(
108
+ (@feature_tags + @feature_element_tags + @examples_tags),
109
+ [@feature_name, @feature_element_name, @examples_name].compact,
110
+ [@feature_element_range, @examples_range].compact
111
+ )
121
112
 
122
113
  if feature_element_ok || examples_ok
123
114
  replay_events!(@feature_events)
@@ -128,15 +119,15 @@ module Gherkin
128
119
  replay_events!(@examples_events)
129
120
  end
130
121
  end
131
- end
132
122
 
133
- def tag_names(tags)
134
- tags.to_a.uniq.map{|tag| tag.name}
123
+ @examples_events.clear
124
+ @examples_tags.clear
125
+ @examples_name = nil
135
126
  end
136
127
 
137
128
  def replay_events!(events)
138
129
  events.each do |event|
139
- @formatter.__send__(*event)
130
+ event.replay(@formatter)
140
131
  end
141
132
  events.clear
142
133
  end
@@ -1,132 +1,64 @@
1
1
  require 'json'
2
2
  require 'json/pure' # Needed to make JSON.generate work.
3
- require 'gherkin/rubify'
4
3
  require 'gherkin/formatter/model'
4
+ require 'gherkin/native'
5
5
 
6
6
  module Gherkin
7
7
  module Formatter
8
8
  class JSONFormatter
9
- include Rubify
9
+ native_impl('gherkin')
10
10
 
11
11
  def initialize(io)
12
12
  @io = io
13
13
  end
14
14
 
15
- def feature(statement, uri)
16
- @json_hash = statement_hash('feature', statement)
17
- @json_hash['uri'] = uri
15
+ def uri(uri)
18
16
  end
19
17
 
20
- def background(statement)
21
- add_step_container('background', statement)
18
+ def feature(feature)
19
+ @feature_hash = feature.to_hash
22
20
  end
23
21
 
24
- def scenario(statement)
25
- add_step_container('scenario', statement)
22
+ def background(background)
23
+ feature_elements << background.to_hash
26
24
  end
27
25
 
28
- def scenario_outline(statement)
29
- add_step_container('scenario_outline', statement)
26
+ def scenario(scenario)
27
+ feature_elements << scenario.to_hash
30
28
  end
31
29
 
32
- def examples(statement, examples_rows)
33
- @table_container = add_examples(statement)
34
- @table_container['table'] = to_hash_array(examples_rows)
30
+ def scenario_outline(scenario_outline)
31
+ feature_elements << scenario_outline.to_hash
35
32
  end
36
33
 
37
- def step(statement, multiline_arg, result)
38
- @table_container = statement_hash(nil, statement).merge(step_arg_to_hash(multiline_arg))
39
- last_element['steps'] ||= []
40
- last_element['steps'] << @table_container
34
+ def examples(examples)
35
+ all_examples << examples.to_hash
41
36
  end
42
37
 
43
- def eof
44
- @io.write(@json_hash.to_json)
45
- end
46
-
47
- private
48
-
49
- def statement_hash(type, statement)
50
- element = {
51
- 'keyword' => statement.keyword,
52
- 'name' => statement.name,
53
- 'line' => statement.line,
54
- }
55
- element['type'] = type if type
56
- add_comments(element, statement)
57
- add_tags(element, statement)
58
- element['description'] = statement.description if statement.description
59
- element
60
- end
61
-
62
- def add_comments(element, comment_holder)
63
- if comment_holder.comments && comment_holder.comments.any?
64
- element['comments'] = comment_holder.comments.map do |comment|
65
- {'value' => comment.value, 'line' => comment.line}
66
- end
67
- end
68
- end
69
-
70
- def add_tags(element, statement)
71
- if statement.tags && statement.tags.any?
72
- element['tags'] = statement.tags.map do |tag|
73
- {'name' => tag.name, 'line' => tag.line}
74
- end
75
- end
38
+ def step(step)
39
+ steps << step.to_hash
76
40
  end
77
41
 
78
- def add_element(type, statement)
79
- element = statement_hash(type, statement)
80
- @json_hash['elements'] ||= []
81
- @json_hash['elements'] << element
82
- element
42
+ def eof
43
+ @io.write(@feature_hash.to_json)
83
44
  end
84
45
 
85
- def add_examples(statement)
86
- element = statement_hash('examples', statement)
87
- last_element['examples'] ||= []
88
- last_element['examples'] << element
89
- element
90
- end
46
+ private
91
47
 
92
- def add_step_container(type, statement)
93
- add_element(type, statement)
94
- last_element['steps'] = []
48
+ def feature_elements
49
+ @feature_hash['elements'] ||= []
95
50
  end
96
51
 
97
- def last_element
98
- @json_hash['elements'][-1]
52
+ def feature_element
53
+ feature_elements[-1]
99
54
  end
100
55
 
101
- def to_hash_array(rows)
102
- rows.map do |row|
103
- e = {"cells" => row.cells.to_a, "line" => row.line}
104
- add_comments(e, row)
105
- e
106
- end
56
+ def all_examples
57
+ feature_element['examples'] ||= []
107
58
  end
108
59
 
109
- def step_arg_to_hash(multiline_arg)
110
- multiline_arg = rubify(multiline_arg)
111
- case multiline_arg
112
- when Array
113
- {
114
- "multiline_arg" => {
115
- "type" => "table",
116
- "value" => to_hash_array(multiline_arg)
117
- }
118
- }
119
- when Model::PyString
120
- {
121
- "multiline_arg" => {
122
- "type" => "py_string",
123
- "value" => multiline_arg.value,
124
- "line" => multiline_arg.line
125
- }
126
- }
127
- else
128
- {}
129
- end
60
+ def steps
61
+ feature_element['steps'] ||= []
130
62
  end
131
63
  end
132
64
  end