cuke_modeler 3.10.0 → 3.14.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (28) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +31 -1
  3. data/README.md +1 -2
  4. data/cuke_modeler.gemspec +3 -4
  5. data/lib/cuke_modeler/adapters/gherkin_20_adapter.rb +350 -0
  6. data/lib/cuke_modeler/adapters/gherkin_21_adapter.rb +13 -0
  7. data/lib/cuke_modeler/adapters/gherkin_22_adapter.rb +13 -0
  8. data/lib/cuke_modeler/adapters/gherkin_9_adapter.rb +16 -5
  9. data/lib/cuke_modeler/adapters/gherkin_base_adapter.rb +14 -0
  10. data/lib/cuke_modeler/containing.rb +13 -13
  11. data/lib/cuke_modeler/nested.rb +1 -0
  12. data/lib/cuke_modeler/parsing.rb +23 -2
  13. data/lib/cuke_modeler/sourceable.rb +4 -1
  14. data/lib/cuke_modeler/version.rb +1 -1
  15. data/testing/cucumber/features/modeling/background_modeling.feature +28 -5
  16. data/testing/cucumber/features/modeling/cell_modeling.feature +46 -0
  17. data/testing/cucumber/features/modeling/comment_modeling.feature +20 -0
  18. data/testing/cucumber/features/modeling/doc_string_modeling.feature +26 -0
  19. data/testing/cucumber/features/modeling/example_modeling.feature +25 -0
  20. data/testing/cucumber/features/modeling/feature_modeling.feature +7 -0
  21. data/testing/cucumber/features/modeling/outline_modeling.feature +26 -1
  22. data/testing/cucumber/features/modeling/row_modeling.feature +23 -0
  23. data/testing/cucumber/features/modeling/rule_modeling.feature +21 -0
  24. data/testing/cucumber/features/modeling/scenario_modeling.feature +22 -0
  25. data/testing/cucumber/features/modeling/step_modeling.feature +22 -0
  26. data/testing/cucumber/features/modeling/table_modeling.feature +24 -0
  27. data/testing/cucumber/features/modeling/tag_modeling.feature +20 -0
  28. metadata +26 -22
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d7821b738cb9b7436e38de701654c9ca04d087ba2e482f01af0600f86383b47d
4
- data.tar.gz: 8b71afb721c52cc198243a468807547d45254dab84dd5bafcbec49e9bb4befb0
3
+ metadata.gz: 42e13fd543b846c0dfd1120e67c157aefb71eeeae7bc68894686813368aace1a
4
+ data.tar.gz: 676f7198e3746318b0f4a2d79c3a8c410ebcbab00b3e543dbb225cfaa8f4ee58
5
5
  SHA512:
6
- metadata.gz: f114b4de2f4f2ef4ffd95078c7b8f72db2318174a75c4d4ed86a900ed21585e91e918afe97770afc1857b3cc80c904e471717f59a90c814bd7664575879e07e8
7
- data.tar.gz: e870f0c73a8f296f6c8b108956d787586e9f47b3a2bff78db9a10db58c8df2ffc39fed04a1ace3629911c03f36ac6aee6c3e74475c60c58d7d0416f141d07037
6
+ metadata.gz: 8500092bdeeb98f81134b8e3302ddf796acd867ccd1324b09d2d75103902b6a926d1220ddbaf08aea98624fe64f1246804868fee21e56a9ec24766c0695455f3
7
+ data.tar.gz: 939fc0d59e4cf3cc194ac28f51a140c928e4ce61f493cc21b03b9a9140c80981fc9e25dbadaa46a4c09f187b8610f37d76a52b708f2ca6434500b2f7324bca7c
data/CHANGELOG.md CHANGED
@@ -8,6 +8,32 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
8
8
 
9
9
  Nothing yet...
10
10
 
11
+ ## [3.14.0] - 2021-11-22
12
+
13
+ ### Added
14
+ - All models for Gherkin elements now track the column number from which they originate in a source file.
15
+
16
+ ## [3.13.0] - 2021-09-25
17
+
18
+ ### Added
19
+ - Support added for more versions of the `cucumber-gherkin` gem
20
+ - 22.x
21
+
22
+ ## [3.12.0] - 2021-09-09
23
+
24
+ ### Added
25
+ - Support added for more versions of the `cucumber-gherkin` gem
26
+ - 21.x
27
+
28
+ ## [3.11.0] - 2021-07-31
29
+
30
+ ### Added
31
+ - Support added for more versions of the `cucumber-gherkin` gem
32
+ - 20.x
33
+
34
+ ### Fixed
35
+ - `Rule` models are now returnable from `Model#get_ancestor()`. Updating that method was missed when `Rule` models
36
+ were first added.
11
37
 
12
38
  ## [3.10.0] - 2021-05-28
13
39
 
@@ -387,7 +413,11 @@ Nothing yet...
387
413
  - Initial release
388
414
 
389
415
 
390
- [Unreleased]: https://github.com/enkessler/cuke_modeler/compare/v3.10.0...HEAD
416
+ [Unreleased]: https://github.com/enkessler/cuke_modeler/compare/v3.14.0...HEAD
417
+ [3.14.0]: https://github.com/enkessler/cuke_modeler/compare/v3.13.0...v3.14.0
418
+ [3.13.0]: https://github.com/enkessler/cuke_modeler/compare/v3.12.0...v3.13.0
419
+ [3.12.0]: https://github.com/enkessler/cuke_modeler/compare/v3.11.0...v3.12.0
420
+ [3.11.0]: https://github.com/enkessler/cuke_modeler/compare/v3.10.0...v3.11.0
391
421
  [3.10.0]: https://github.com/enkessler/cuke_modeler/compare/v3.9.0...v3.10.0
392
422
  [3.9.0]: https://github.com/enkessler/cuke_modeler/compare/v3.8.0...v3.9.0
393
423
  [3.8.0]: https://github.com/enkessler/cuke_modeler/compare/v3.7.0...v3.8.0
data/README.md CHANGED
@@ -8,8 +8,7 @@ User stuff:
8
8
  [![Yard Docs](http://img.shields.io/badge/Documentation-API-blue.svg)](https://www.rubydoc.info/gems/cuke_modeler)
9
9
 
10
10
  Developer stuff:
11
- [![Build Status](https://travis-ci.org/enkessler/cuke_modeler.svg?branch=master)](https://travis-ci.org/enkessler/cuke_modeler)
12
- [![Build status](https://ci.appveyor.com/api/projects/status/is8xqvoqn3pjh9l0/branch/master?svg=true)](https://ci.appveyor.com/project/enkessler/cuke-modeler)
11
+ [![Build Status](https://github.com/enkessler/cuke_modeler/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/enkessler/cuke_modeler/actions/workflows/ci.yml?query=branch%3Amaster)
13
12
  [![Coverage Status](https://coveralls.io/repos/github/enkessler/cuke_modeler/badge.svg?branch=master)](https://coveralls.io/github/enkessler/cuke_modeler?branch=master)
14
13
  [![Maintainability](https://api.codeclimate.com/v1/badges/83986d8f7a918fed9707/maintainability)](https://codeclimate.com/github/enkessler/cuke_modeler/maintainability)
15
14
  [![Inline docs](http://inch-ci.org/github/enkessler/cuke_modeler.svg?branch=master)](https://inch-ci.org/github/enkessler/cuke_modeler)
data/cuke_modeler.gemspec CHANGED
@@ -36,11 +36,10 @@ Gem::Specification.new do |spec|
36
36
 
37
37
  spec.required_ruby_version = '>= 2.3', '< 4.0'
38
38
 
39
- spec.add_runtime_dependency 'cucumber-gherkin', '< 20.0'
39
+ spec.add_runtime_dependency 'cucumber-gherkin', '< 23.0'
40
40
 
41
41
  spec.add_development_dependency 'bundler', '< 3.0'
42
42
  spec.add_development_dependency 'childprocess', '< 5.0'
43
- spec.add_development_dependency 'coveralls', '< 1.0.0'
44
43
  spec.add_development_dependency 'ffi', '< 2.0' # This is an invisible dependency for the `childprocess` gem on Windows
45
44
  # Cucumber 4.x is the earliest version to use cucumber-gherkin
46
45
  spec.add_development_dependency 'cucumber', '>= 4.0.0', '< 7.0.0'
@@ -50,8 +49,8 @@ Gem::Specification.new do |spec|
50
49
  # RuboCop drops Ruby 2.3 support after this version and we need to maintain Ruby 2.3 compatibility when writing code
51
50
  # for this gem
52
51
  spec.add_development_dependency 'rubocop', '< 0.82.0'
53
- # Coveralls gem does not support any newer version than this
54
- spec.add_development_dependency 'simplecov', '<= 0.16.1'
52
+ spec.add_development_dependency 'simplecov', '< 1.0'
53
+ spec.add_development_dependency 'simplecov-lcov', '< 1.0'
55
54
  spec.add_development_dependency 'test-unit', '< 4.0.0'
56
55
  spec.add_development_dependency 'yard', '< 1.0'
57
56
  end
@@ -0,0 +1,350 @@
1
+ require_relative 'gherkin_base_adapter'
2
+
3
+ # Some things just aren't going to get better due to the inherent complexity of the AST
4
+ # rubocop:disable Metrics/ClassLength, Metrics/AbcSize, Metrics/MethodLength
5
+
6
+ module CukeModeler
7
+
8
+ # NOT A PART OF THE PUBLIC API
9
+ # An adapter that can convert the output of version 20.x of the *cucumber-gherkin* gem into input that is consumable
10
+ # by this gem.
11
+ class Gherkin20Adapter < GherkinBaseAdapter
12
+
13
+ # Adapts the given AST into the shape that this gem expects
14
+ def adapt(ast)
15
+ adapted_ast = {}
16
+
17
+ # Saving off the original data and removing parsed data for child elements in order to avoid duplicating data
18
+ save_original_data(adapted_ast, ast)
19
+ clear_child_elements(adapted_ast, [[:feature], [:comments]])
20
+
21
+ adapted_ast['comments'] = adapt_comments(ast)
22
+ adapted_ast['feature'] = adapt_feature(ast.feature)
23
+
24
+ adapted_ast
25
+ end
26
+
27
+ # Adapts the AST sub-tree that is rooted at the given feature node.
28
+ def adapt_feature(feature_ast)
29
+ return nil unless feature_ast
30
+
31
+ adapted_feature = {}
32
+
33
+ # Saving off the original data and removing parsed data for child elements in order to avoid duplicating data
34
+ save_original_data(adapted_feature, feature_ast)
35
+ clear_child_elements(adapted_feature, [[:tags],
36
+ [:children]])
37
+
38
+ adapted_feature['keyword'] = feature_ast.keyword
39
+ adapted_feature['name'] = feature_ast.name
40
+ adapted_feature['description'] = feature_ast.description
41
+ adapted_feature['line'] = feature_ast.location.line
42
+ adapted_feature['column'] = feature_ast.location.column
43
+
44
+ adapted_feature['elements'] = adapt_child_elements(feature_ast)
45
+ adapted_feature['tags'] = adapt_tags(feature_ast)
46
+
47
+ adapted_feature
48
+ end
49
+
50
+ # Adapts the AST sub-tree that is rooted at the given background node.
51
+ def adapt_background(background_ast)
52
+ adapted_background = {}
53
+
54
+ # Saving off the original data and removing parsed data for child elements in order to avoid duplicating data
55
+ save_original_data(adapted_background, background_ast)
56
+ clear_child_elements(adapted_background, [[:background, :steps]])
57
+
58
+ adapted_background['type'] = 'Background'
59
+ adapted_background['keyword'] = background_ast.background.keyword
60
+ adapted_background['name'] = background_ast.background.name
61
+ adapted_background['description'] = background_ast.background.description
62
+ adapted_background['line'] = background_ast.background.location.line
63
+ adapted_background['column'] = background_ast.background.location.column
64
+
65
+ adapted_background['steps'] = adapt_steps(background_ast.background)
66
+
67
+ adapted_background
68
+ end
69
+
70
+ # Adapts the AST sub-tree that is rooted at the given rule node.
71
+ def adapt_rule(rule_ast)
72
+ adapted_rule = {}
73
+
74
+ # Saving off the original data and removing parsed data for child elements in order to avoid duplicating data
75
+ save_original_data(adapted_rule, rule_ast)
76
+ clear_child_elements(adapted_rule, [[:rule, :tags],
77
+ [:rule, :children]])
78
+
79
+ adapted_rule['type'] = 'Rule'
80
+ adapted_rule['keyword'] = rule_ast.rule.keyword
81
+ adapted_rule['name'] = rule_ast.rule.name
82
+ adapted_rule['description'] = rule_ast.rule.description
83
+ adapted_rule['line'] = rule_ast.rule.location.line
84
+ adapted_rule['column'] = rule_ast.rule.location.column
85
+
86
+ adapted_rule['elements'] = adapt_child_elements(rule_ast.rule)
87
+ adapted_rule['tags'] = adapt_tags(rule_ast.rule)
88
+
89
+ adapted_rule
90
+ end
91
+
92
+ # Adapts the AST sub-tree that is rooted at the given scenario node.
93
+ def adapt_scenario(test_ast)
94
+ adapted_scenario = {}
95
+
96
+ # Saving off the original data and removing parsed data for child elements in order to avoid duplicating data
97
+ save_original_data(adapted_scenario, test_ast)
98
+ clear_child_elements(adapted_scenario, [[:scenario, :tags],
99
+ [:scenario, :steps]])
100
+
101
+ adapted_scenario['type'] = 'Scenario'
102
+ adapted_scenario['keyword'] = test_ast.scenario.keyword
103
+ adapted_scenario['name'] = test_ast.scenario.name
104
+ adapted_scenario['description'] = test_ast.scenario.description
105
+ adapted_scenario['line'] = test_ast.scenario.location.line
106
+ adapted_scenario['column'] = test_ast.scenario.location.column
107
+
108
+ adapted_scenario['tags'] = adapt_tags(test_ast.scenario)
109
+ adapted_scenario['steps'] = adapt_steps(test_ast.scenario)
110
+
111
+ adapted_scenario
112
+ end
113
+
114
+ # Adapts the AST sub-tree that is rooted at the given outline node.
115
+ def adapt_outline(test_ast)
116
+ adapted_outline = {}
117
+
118
+ # Saving off the original data and removing parsed data for child elements in order to avoid duplicating data
119
+ save_original_data(adapted_outline, test_ast)
120
+ clear_child_elements(adapted_outline, [[:scenario, :tags],
121
+ [:scenario, :steps],
122
+ [:scenario, :examples]])
123
+
124
+ adapted_outline['type'] = 'ScenarioOutline'
125
+ adapted_outline['keyword'] = test_ast.scenario.keyword
126
+ adapted_outline['name'] = test_ast.scenario.name
127
+ adapted_outline['description'] = test_ast.scenario.description
128
+ adapted_outline['line'] = test_ast.scenario.location.line
129
+ adapted_outline['column'] = test_ast.scenario.location.column
130
+
131
+ adapted_outline['tags'] = adapt_tags(test_ast.scenario)
132
+ adapted_outline['steps'] = adapt_steps(test_ast.scenario)
133
+ adapted_outline['examples'] = adapt_examples(test_ast.scenario)
134
+
135
+ adapted_outline
136
+ end
137
+
138
+ # Adapts the AST sub-tree that is rooted at the given example node.
139
+ def adapt_example(example_ast)
140
+ adapted_example = {}
141
+
142
+ # Saving off the original data and removing parsed data for child elements in order to avoid duplicating data
143
+ save_original_data(adapted_example, example_ast)
144
+ clear_child_elements(adapted_example, [[:tags],
145
+ [:table_header],
146
+ [:table_body]])
147
+
148
+ adapted_example['keyword'] = example_ast.keyword
149
+ adapted_example['name'] = example_ast.name
150
+ adapted_example['line'] = example_ast.location.line
151
+ adapted_example['column'] = example_ast.location.column
152
+ adapted_example['description'] = example_ast.description
153
+
154
+ adapted_example['rows'] = []
155
+ adapted_example['rows'] << adapt_table_row(example_ast.table_header) if example_ast.table_header
156
+
157
+ example_ast.table_body&.each do |row|
158
+ adapted_example['rows'] << adapt_table_row(row)
159
+ end
160
+
161
+ adapted_example['tags'] = adapt_tags(example_ast)
162
+
163
+ adapted_example
164
+ end
165
+
166
+ # Adapts the AST sub-tree that is rooted at the given tag node.
167
+ def adapt_tag(tag_ast)
168
+ adapted_tag = {}
169
+
170
+ # Saving off the original data
171
+ save_original_data(adapted_tag, tag_ast)
172
+
173
+ adapted_tag['name'] = tag_ast.name
174
+ adapted_tag['line'] = tag_ast.location.line
175
+ adapted_tag['column'] = tag_ast.location.column
176
+
177
+ adapted_tag
178
+ end
179
+
180
+ # Adapts the AST sub-tree that is rooted at the given comment node.
181
+ def adapt_comment(comment_ast)
182
+ adapted_comment = {}
183
+
184
+ # Saving off the original data
185
+ save_original_data(adapted_comment, comment_ast)
186
+
187
+ adapted_comment['text'] = comment_ast.text
188
+ adapted_comment['line'] = comment_ast.location.line
189
+ adapted_comment['column'] = comment_ast.location.column
190
+
191
+ adapted_comment
192
+ end
193
+
194
+ # Adapts the AST sub-tree that is rooted at the given step node.
195
+ def adapt_step(step_ast)
196
+ adapted_step = {}
197
+
198
+ # Saving off the original data and removing parsed data for child elements in order to avoid duplicating data
199
+ save_original_data(adapted_step, step_ast)
200
+ clear_child_elements(adapted_step, [[:data_table],
201
+ [:doc_string]])
202
+
203
+ adapted_step['keyword'] = step_ast.keyword
204
+ adapted_step['name'] = step_ast.text
205
+ adapted_step['line'] = step_ast.location.line
206
+ adapted_step['column'] = step_ast.location.column
207
+
208
+ if step_ast.doc_string
209
+ adapted_step['doc_string'] = adapt_doc_string(step_ast.doc_string)
210
+ elsif step_ast.data_table
211
+ adapted_step['table'] = adapt_step_table(step_ast.data_table)
212
+ end
213
+
214
+ adapted_step
215
+ end
216
+
217
+ # Adapts the AST sub-tree that is rooted at the given doc string node.
218
+ def adapt_doc_string(doc_string_ast)
219
+ adapted_doc_string = {}
220
+
221
+ # Saving off the original data
222
+ save_original_data(adapted_doc_string, doc_string_ast)
223
+
224
+ adapted_doc_string['value'] = doc_string_ast.content
225
+ adapted_doc_string['content_type'] = doc_string_ast.media_type
226
+ adapted_doc_string['line'] = doc_string_ast.location.line
227
+ adapted_doc_string['column'] = doc_string_ast.location.column
228
+
229
+ adapted_doc_string
230
+ end
231
+
232
+ # Adapts the AST sub-tree that is rooted at the given table node.
233
+ def adapt_step_table(step_table_ast)
234
+ adapted_step_table = {}
235
+
236
+ # Saving off the original data and removing parsed data for child elements in order to avoid duplicating data
237
+ save_original_data(adapted_step_table, step_table_ast)
238
+ clear_child_elements(adapted_step_table, [[:rows]])
239
+
240
+ adapted_step_table['rows'] = []
241
+ step_table_ast.rows.each do |row|
242
+ adapted_step_table['rows'] << adapt_table_row(row)
243
+ end
244
+ adapted_step_table['line'] = step_table_ast.location.line
245
+ adapted_step_table['column'] = step_table_ast.location.column
246
+
247
+ adapted_step_table
248
+ end
249
+
250
+ # Adapts the AST sub-tree that is rooted at the given row node.
251
+ def adapt_table_row(table_row_ast)
252
+ adapted_table_row = {}
253
+
254
+ # Saving off the original data and removing parsed data for child elements in order to avoid duplicating data
255
+ save_original_data(adapted_table_row, table_row_ast)
256
+ clear_child_elements(adapted_table_row, [[:cells]])
257
+
258
+ adapted_table_row['line'] = table_row_ast.location.line
259
+ adapted_table_row['column'] = table_row_ast.location.column
260
+
261
+ adapted_table_row['cells'] = []
262
+ table_row_ast.cells.each do |row|
263
+ adapted_table_row['cells'] << adapt_table_cell(row)
264
+ end
265
+
266
+ adapted_table_row
267
+ end
268
+
269
+ # Adapts the AST sub-tree that is rooted at the given cell node.
270
+ def adapt_table_cell(cell_ast)
271
+ adapted_cell = {}
272
+
273
+ # Saving off the original data
274
+ save_original_data(adapted_cell, cell_ast)
275
+
276
+ adapted_cell['value'] = cell_ast.value
277
+ adapted_cell['line'] = cell_ast.location.line
278
+ adapted_cell['column'] = cell_ast.location.column
279
+
280
+ adapted_cell
281
+ end
282
+
283
+
284
+ private
285
+
286
+
287
+ def adapt_comments(file_ast)
288
+ file_ast.comments.map { |comment| adapt_comment(comment) }
289
+ end
290
+
291
+ def adapt_tags(element_ast)
292
+ element_ast.tags.map { |tag| adapt_tag(tag) }
293
+ end
294
+
295
+ def adapt_steps(element_ast)
296
+ element_ast.steps.map { |step| adapt_step(step) }
297
+ end
298
+
299
+ def adapt_examples(element_ast)
300
+ element_ast.examples.map { |example| adapt_example(example) }
301
+ end
302
+
303
+ def adapt_child_elements(element_ast)
304
+ adapted_children = []
305
+
306
+ element_ast.children.each do |child_element|
307
+ adapted_children << if child_element.background
308
+ adapt_background(child_element)
309
+ elsif child_element.respond_to?(:rule) && child_element.rule
310
+ adapt_rule(child_element)
311
+ else
312
+ adapt_test(child_element)
313
+ end
314
+ end
315
+
316
+ adapted_children
317
+ end
318
+
319
+ def adapt_test(test_ast)
320
+ if test_has_examples?(test_ast) || test_uses_outline_keyword?(test_ast)
321
+ adapt_outline(test_ast)
322
+ else
323
+ adapt_scenario(test_ast)
324
+ end
325
+ end
326
+
327
+ def clear_child_elements(ast, child_paths)
328
+ # rubocop:disable Security/Eval - This is not blind data
329
+ child_paths.each do |traversal_path|
330
+ # Wipe the value if it's there but don't add any attributes to the object if it didn't already have them
331
+ if eval("ast['cuke_modeler_parsing_data'].#{traversal_path.join('.')}", binding, __FILE__, __LINE__)
332
+ property_path = traversal_path[0..-2].join('.')
333
+ eval("ast['cuke_modeler_parsing_data']#{property_path.empty? ? '' : '.' + property_path}.instance_variable_set(\"@#{traversal_path.last}\", nil)", binding, __FILE__, __LINE__) # rubocop:disable Layout/LineLength
334
+ end
335
+ end
336
+ # rubocop:enable Security/Eval
337
+ end
338
+
339
+ def test_has_examples?(ast_node)
340
+ ast_node.scenario.examples.any?
341
+ end
342
+
343
+ def test_uses_outline_keyword?(test_ast)
344
+ Parsing.dialects[Parsing.dialect]['scenarioOutline'].include?(test_ast.scenario.keyword)
345
+ end
346
+
347
+ end
348
+ end
349
+
350
+ # rubocop:enable Metrics/ClassLength, Metrics/AbcSize, Metrics/MethodLength
@@ -0,0 +1,13 @@
1
+ require_relative 'gherkin_20_adapter'
2
+
3
+
4
+ module CukeModeler
5
+
6
+ # NOT A PART OF THE PUBLIC API
7
+ # An adapter that can convert the output of version 21.x of the *cucumber-gherkin* gem into input that is consumable
8
+ # by this gem.
9
+
10
+ class Gherkin21Adapter < Gherkin20Adapter
11
+
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ require_relative 'gherkin_20_adapter'
2
+
3
+
4
+ module CukeModeler
5
+
6
+ # NOT A PART OF THE PUBLIC API
7
+ # An adapter that can convert the output of version 22.x of the *cucumber-gherkin* gem into input that is consumable
8
+ # by this gem.
9
+
10
+ class Gherkin22Adapter < Gherkin20Adapter
11
+
12
+ end
13
+ end
@@ -1,3 +1,5 @@
1
+ require_relative 'gherkin_base_adapter'
2
+
1
3
  # Some things just aren't going to get better due to the inherent complexity of the AST
2
4
  # rubocop:disable Metrics/ClassLength, Metrics/AbcSize, Metrics/MethodLength
3
5
 
@@ -6,7 +8,7 @@ module CukeModeler
6
8
  # NOT A PART OF THE PUBLIC API
7
9
  # An adapter that can convert the output of version 9.x of the *cucumber-gherkin* gem into input that is consumable
8
10
  # by this gem.
9
- class Gherkin9Adapter
11
+ class Gherkin9Adapter < GherkinBaseAdapter
10
12
 
11
13
  # Adapts the given AST into the shape that this gem expects
12
14
  def adapt(ast)
@@ -38,6 +40,7 @@ module CukeModeler
38
40
  adapted_feature['name'] = feature_ast[:name]
39
41
  adapted_feature['description'] = feature_ast[:description] || ''
40
42
  adapted_feature['line'] = feature_ast[:location][:line]
43
+ adapted_feature['column'] = feature_ast[:location][:column]
41
44
 
42
45
  adapted_feature['elements'] = adapt_child_elements(feature_ast)
43
46
  adapted_feature['tags'] = adapt_tags(feature_ast)
@@ -58,6 +61,7 @@ module CukeModeler
58
61
  adapted_background['name'] = background_ast[:background][:name]
59
62
  adapted_background['description'] = background_ast[:background][:description] || ''
60
63
  adapted_background['line'] = background_ast[:background][:location][:line]
64
+ adapted_background['column'] = background_ast[:background][:location][:column]
61
65
 
62
66
  adapted_background['steps'] = adapt_steps(background_ast[:background])
63
67
 
@@ -77,6 +81,7 @@ module CukeModeler
77
81
  adapted_rule['name'] = rule_ast[:rule][:name]
78
82
  adapted_rule['description'] = rule_ast[:rule][:description] || ''
79
83
  adapted_rule['line'] = rule_ast[:rule][:location][:line]
84
+ adapted_rule['column'] = rule_ast[:rule][:location][:column]
80
85
 
81
86
  adapted_rule['elements'] = adapt_child_elements(rule_ast[:rule])
82
87
 
@@ -97,6 +102,7 @@ module CukeModeler
97
102
  adapted_scenario['name'] = test_ast[:scenario][:name]
98
103
  adapted_scenario['description'] = test_ast[:scenario][:description] || ''
99
104
  adapted_scenario['line'] = test_ast[:scenario][:location][:line]
105
+ adapted_scenario['column'] = test_ast[:scenario][:location][:column]
100
106
 
101
107
  adapted_scenario['tags'] = adapt_tags(test_ast[:scenario])
102
108
  adapted_scenario['steps'] = adapt_steps(test_ast[:scenario])
@@ -119,6 +125,7 @@ module CukeModeler
119
125
  adapted_outline['name'] = test_ast[:scenario][:name]
120
126
  adapted_outline['description'] = test_ast[:scenario][:description] || ''
121
127
  adapted_outline['line'] = test_ast[:scenario][:location][:line]
128
+ adapted_outline['column'] = test_ast[:scenario][:location][:column]
122
129
 
123
130
  adapted_outline['tags'] = adapt_tags(test_ast[:scenario])
124
131
  adapted_outline['steps'] = adapt_steps(test_ast[:scenario])
@@ -140,6 +147,7 @@ module CukeModeler
140
147
  adapted_example['keyword'] = example_ast[:keyword]
141
148
  adapted_example['name'] = example_ast[:name]
142
149
  adapted_example['line'] = example_ast[:location][:line]
150
+ adapted_example['column'] = example_ast[:location][:column]
143
151
  adapted_example['description'] = example_ast[:description] || ''
144
152
 
145
153
  adapted_example['rows'] = []
@@ -163,6 +171,7 @@ module CukeModeler
163
171
 
164
172
  adapted_tag['name'] = tag_ast[:name]
165
173
  adapted_tag['line'] = tag_ast[:location][:line]
174
+ adapted_tag['column'] = tag_ast[:location][:column]
166
175
 
167
176
  adapted_tag
168
177
  end
@@ -176,6 +185,7 @@ module CukeModeler
176
185
 
177
186
  adapted_comment['text'] = comment_ast[:text]
178
187
  adapted_comment['line'] = comment_ast[:location][:line]
188
+ adapted_comment['column'] = comment_ast[:location][:column]
179
189
 
180
190
  adapted_comment
181
191
  end
@@ -192,6 +202,7 @@ module CukeModeler
192
202
  adapted_step['keyword'] = step_ast[:keyword]
193
203
  adapted_step['name'] = step_ast[:text]
194
204
  adapted_step['line'] = step_ast[:location][:line]
205
+ adapted_step['column'] = step_ast[:location][:column]
195
206
 
196
207
  if step_ast[:doc_string]
197
208
  adapted_step['doc_string'] = adapt_doc_string(step_ast[:doc_string])
@@ -212,6 +223,7 @@ module CukeModeler
212
223
  adapted_doc_string['value'] = doc_string_ast[:content]
213
224
  adapted_doc_string['content_type'] = doc_string_ast[:media_type]
214
225
  adapted_doc_string['line'] = doc_string_ast[:location][:line]
226
+ adapted_doc_string['column'] = doc_string_ast[:location][:column]
215
227
 
216
228
  adapted_doc_string
217
229
  end
@@ -229,6 +241,7 @@ module CukeModeler
229
241
  adapted_step_table['rows'] << adapt_table_row(row)
230
242
  end
231
243
  adapted_step_table['line'] = step_table_ast[:location][:line]
244
+ adapted_step_table['column'] = step_table_ast[:location][:column]
232
245
 
233
246
  adapted_step_table
234
247
  end
@@ -242,6 +255,7 @@ module CukeModeler
242
255
  clear_child_elements(adapted_table_row, [[:cells]])
243
256
 
244
257
  adapted_table_row['line'] = table_row_ast[:location][:line]
258
+ adapted_table_row['column'] = table_row_ast[:location][:column]
245
259
 
246
260
  adapted_table_row['cells'] = []
247
261
  table_row_ast[:cells].each do |row|
@@ -260,6 +274,7 @@ module CukeModeler
260
274
 
261
275
  adapted_cell['value'] = cell_ast[:value]
262
276
  adapted_cell['line'] = cell_ast[:location][:line]
277
+ adapted_cell['column'] = cell_ast[:location][:column]
263
278
 
264
279
  adapted_cell
265
280
  end
@@ -322,10 +337,6 @@ module CukeModeler
322
337
  end
323
338
  end
324
339
 
325
- def save_original_data(adapted_ast, raw_ast)
326
- adapted_ast['cuke_modeler_parsing_data'] = Marshal.load(Marshal.dump(raw_ast))
327
- end
328
-
329
340
  def clear_child_elements(ast, child_paths)
330
341
  child_paths.each do |traversal_path|
331
342
  # Wipe the value if it's there but don't add any keys to the hash if it didn't already have them
@@ -0,0 +1,14 @@
1
+ module CukeModeler
2
+
3
+ # NOT A PART OF THE PUBLIC API
4
+ # A class providing some basic and common adapter functionality.
5
+ class GherkinBaseAdapter
6
+
7
+ private
8
+
9
+ def save_original_data(adapted_ast, raw_ast)
10
+ adapted_ast['cuke_modeler_parsing_data'] = Marshal.load(Marshal.dump(raw_ast))
11
+ end
12
+
13
+ end
14
+ end