yard-nrser-cucumber 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +61 -0
  3. data/.rspec +3 -0
  4. data/.yardopts +2 -0
  5. data/Gemfile +6 -0
  6. data/History.txt +288 -0
  7. data/LICENSE.txt +22 -0
  8. data/NAME +1 -0
  9. data/README.md +198 -0
  10. data/Rakefile +27 -0
  11. data/VERSION +1 -0
  12. data/example/README.md +8 -0
  13. data/example/child_feature/README.md +21 -0
  14. data/example/child_feature/child.feature +11 -0
  15. data/example/child_feature/grandchild_feature/grandchild.feature +12 -0
  16. data/example/empty.feature +2 -0
  17. data/example/french.feature +18 -0
  18. data/example/scenario.feature +63 -0
  19. data/example/scenario_outline.feature +100 -0
  20. data/example/scenario_outline_multi.feature +15 -0
  21. data/example/step_definitions/example.step.rb +122 -0
  22. data/example/step_definitions/first.step.rb +21 -0
  23. data/example/step_definitions/french_steps.rb +32 -0
  24. data/example/step_definitions/struct.rb +11 -0
  25. data/example/step_definitions/support/env.rb +7 -0
  26. data/example/step_definitions/support/env_support.rb +12 -0
  27. data/example/step_definitions/support/support.rb +6 -0
  28. data/example/tags.feature +18 -0
  29. data/example/transform.feature +18 -0
  30. data/lib/cucumber/city_builder.rb +412 -0
  31. data/lib/docserver/default/fulldoc/html/js/cucumber.js +85 -0
  32. data/lib/docserver/default/layout/html/headers.erb +13 -0
  33. data/lib/docserver/doc_server/full_list/html/full_list.erb +39 -0
  34. data/lib/docserver/doc_server/full_list/html/setup.rb +18 -0
  35. data/lib/templates/default/feature/html/feature.erb +39 -0
  36. data/lib/templates/default/feature/html/no_steps_defined.erb +1 -0
  37. data/lib/templates/default/feature/html/outline.erb +56 -0
  38. data/lib/templates/default/feature/html/pystring.erb +3 -0
  39. data/lib/templates/default/feature/html/scenario.erb +57 -0
  40. data/lib/templates/default/feature/html/setup.rb +51 -0
  41. data/lib/templates/default/feature/html/steps.erb +39 -0
  42. data/lib/templates/default/feature/html/table.erb +20 -0
  43. data/lib/templates/default/featuredirectory/html/alpha_table.erb +30 -0
  44. data/lib/templates/default/featuredirectory/html/directory.erb +32 -0
  45. data/lib/templates/default/featuredirectory/html/setup.rb +37 -0
  46. data/lib/templates/default/featuretags/html/namespace.erb +159 -0
  47. data/lib/templates/default/featuretags/html/setup.rb +34 -0
  48. data/lib/templates/default/fulldoc/html/css/cucumber.css +226 -0
  49. data/lib/templates/default/fulldoc/html/directories.erb +27 -0
  50. data/lib/templates/default/fulldoc/html/full_list_featuredirectories.erb +11 -0
  51. data/lib/templates/default/fulldoc/html/full_list_features.erb +37 -0
  52. data/lib/templates/default/fulldoc/html/full_list_stepdefinitions.erb +20 -0
  53. data/lib/templates/default/fulldoc/html/full_list_steps.erb +20 -0
  54. data/lib/templates/default/fulldoc/html/full_list_tags.erb +16 -0
  55. data/lib/templates/default/fulldoc/html/js/cucumber.js +333 -0
  56. data/lib/templates/default/fulldoc/html/setup.rb +208 -0
  57. data/lib/templates/default/layout/html/setup.rb +131 -0
  58. data/lib/templates/default/requirements/html/alpha_table.erb +26 -0
  59. data/lib/templates/default/requirements/html/requirements.erb +50 -0
  60. data/lib/templates/default/requirements/html/setup.rb +51 -0
  61. data/lib/templates/default/steptransformers/html/header.erb +12 -0
  62. data/lib/templates/default/steptransformers/html/index.erb +10 -0
  63. data/lib/templates/default/steptransformers/html/setup.rb +94 -0
  64. data/lib/templates/default/steptransformers/html/transformers.erb +80 -0
  65. data/lib/templates/default/steptransformers/html/undefinedsteps.erb +26 -0
  66. data/lib/templates/default/tag/html/alpha_table.erb +33 -0
  67. data/lib/templates/default/tag/html/setup.rb +27 -0
  68. data/lib/templates/default/tag/html/tag.erb +35 -0
  69. data/lib/yard-nrser-cucumber.rb +49 -0
  70. data/lib/yard/code_objects/cucumber/base.rb +24 -0
  71. data/lib/yard/code_objects/cucumber/feature.rb +16 -0
  72. data/lib/yard/code_objects/cucumber/namespace_object.rb +55 -0
  73. data/lib/yard/code_objects/cucumber/scenario.rb +25 -0
  74. data/lib/yard/code_objects/cucumber/scenario_outline.rb +68 -0
  75. data/lib/yard/code_objects/cucumber/step.rb +41 -0
  76. data/lib/yard/code_objects/cucumber/tag.rb +31 -0
  77. data/lib/yard/code_objects/step_definition.rb +4 -0
  78. data/lib/yard/code_objects/step_transform.rb +4 -0
  79. data/lib/yard/code_objects/step_transformer.rb +94 -0
  80. data/lib/yard/handlers/constant_transform_handler.rb +98 -0
  81. data/lib/yard/handlers/cucumber/base.rb +21 -0
  82. data/lib/yard/handlers/cucumber/feature_handler.rb +131 -0
  83. data/lib/yard/handlers/legacy/step_definition_handler.rb +45 -0
  84. data/lib/yard/handlers/legacy/step_transform_handler.rb +24 -0
  85. data/lib/yard/handlers/step_definition_handler.rb +86 -0
  86. data/lib/yard/handlers/step_transform_handler.rb +50 -0
  87. data/lib/yard/nrser/cucumber/version.rb +103 -0
  88. data/lib/yard/parser/cucumber/feature.rb +72 -0
  89. data/lib/yard/server/adapter.rb +43 -0
  90. data/lib/yard/server/commands/list_command.rb +31 -0
  91. data/lib/yard/server/router.rb +32 -0
  92. data/lib/yard/templates/helpers/base_helper.rb +26 -0
  93. data/lib/yard/templates/helpers/html_helper.rb +153 -0
  94. data/yard-nrser-cucumber.gemspec +75 -0
  95. metadata +220 -0
@@ -0,0 +1,11 @@
1
+ #
2
+ # @see https://github.com/burtlo/yard-cucumber/issues/18
3
+ #
4
+ CustomerUsageBehavior = Struct.new(:weight, :days, :time, :location, :other_party, :usage_type, :direction, :quantity)
5
+
6
+
7
+ class CustomerProfile
8
+ def generate_winner(max=@total_weight)
9
+ # blah
10
+ end
11
+ end
@@ -0,0 +1,7 @@
1
+
2
+ module Environment
3
+ module Database
4
+ class Connection
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,12 @@
1
+
2
+ class SupportClass
3
+
4
+ end
5
+
6
+ module Web
7
+ module Interface
8
+ class CachedReference
9
+
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,6 @@
1
+
2
+ ORDER = /(?:first|second|third)/
3
+
4
+ TEDDY_BEAR = /teddy bear/
5
+
6
+ CUSTOMER = /(?:(?:an?|the|#{ORDER}) customer|#{TEDDY_BEAR})/
@@ -0,0 +1,18 @@
1
+ @tags
2
+ Feature: Tags
3
+ As a developer of the test suite I expect that various tags will be supported
4
+
5
+ @tag
6
+ Scenario: Basic Tag
7
+
8
+ @tag123456
9
+ Scenario: Tag With Numbers
10
+
11
+ @tag_with_underscore
12
+ Scenario: Tag With Underscore
13
+
14
+ @tag-with-dash
15
+ Scenario: Tag With Dash
16
+
17
+ @tag+with+plus
18
+ Scenario: Tag With Plus
@@ -0,0 +1,18 @@
1
+ @scenarios @bvt
2
+ Feature: Step Transforms
3
+ As a developer of the test suite I expect that step transforms are documented correctly
4
+
5
+ @first
6
+ Scenario: Step with step transformation
7
+ Given this scenario step
8
+ Then I expect that the step, on the step transformer page, will link to the step transform
9
+
10
+ @second
11
+ Scenario: Step Transform uses a constant
12
+ Given this first step
13
+ Then I expect that the step, on the step transformer page, will link to the step transform
14
+
15
+ @third
16
+ Scenario: Step Transform uses an interpolated transform
17
+ Given this first step
18
+ Then the file './somelocation/somefile.input' will be replaced with the file contents
@@ -0,0 +1,412 @@
1
+ module Cucumber
2
+ module Parser
3
+ class CityBuilder < ::Gherkin::AstBuilder
4
+
5
+ #
6
+ # The Gherkin Parser is going to call the various methods within this
7
+ # class as it finds items. This is similar to how Cucumber generates
8
+ # it's Abstract Syntax Tree (AST). Here instead this generates the
9
+ # various YARD::CodeObjects defined within this template.
10
+ #
11
+ # A namespace is specified and that is the place in the YARD namespacing
12
+ # where all cucumber features generated will reside. The namespace specified
13
+ # is the root namespaces.
14
+ #
15
+ # @param [String] file the name of the file which the content belongs
16
+ #
17
+ def initialize(file)
18
+ super()
19
+ @namespace = YARD::CodeObjects::Cucumber::CUCUMBER_NAMESPACE
20
+ find_or_create_namespace(file)
21
+ @file = file
22
+ end
23
+
24
+ # Return the feature that has been defined. This method is the final
25
+ # method that is called when all the work is done. It is called by
26
+ # the feature parser to return the complete Feature object that was created
27
+ #
28
+ # @return [YARD::CodeObject::Cucumber::Feature] the completed feature
29
+ #
30
+ # @see YARD::Parser::Cucumber::FeatureParser
31
+ def ast
32
+ feature(get_result) unless @feature
33
+ @feature
34
+ end
35
+
36
+ #
37
+ # Feature that are found in sub-directories are considered, in the way
38
+ # that I chose to implement it, in another namespace. This is because
39
+ # when you execute a cucumber test run on a directory any sub-directories
40
+ # of features will be executed with that directory so the file is split
41
+ # and then namespaces are generated if they have not already have been.
42
+ #
43
+ # The other duty that this does is look for a README.md file within the
44
+ # specified directory of the file and loads it as the description for the
45
+ # namespace. This is useful if you want to give a particular directory
46
+ # some flavor or text to describe what is going on.
47
+ #
48
+ def find_or_create_namespace(file)
49
+ @namespace = YARD::CodeObjects::Cucumber::CUCUMBER_NAMESPACE
50
+
51
+ File.dirname(file).split('/').each do |directory|
52
+ @namespace = @namespace.children.find {|child| child.is_a?(YARD::CodeObjects::Cucumber::FeatureDirectory) && child.name.to_s == directory } ||
53
+ @namespace = YARD::CodeObjects::Cucumber::FeatureDirectory.new(@namespace,directory) {|dir| dir.add_file(directory)}
54
+ end
55
+
56
+ if @namespace.description == "" && File.exists?("#{File.dirname(file)}/README.md")
57
+ @namespace.description = File.read("#{File.dirname(file)}/README.md")
58
+ end
59
+ end
60
+
61
+ #
62
+ # Find the tag if it exists within the YARD Registry, if it doesn't then
63
+ # create it.
64
+ #
65
+ # We note that the tag was used in this file at the current line.
66
+ #
67
+ # Then we add the tag to the current scenario or feature. We also add the
68
+ # feature or scenario to the tag.
69
+ #
70
+ # @param [String] tag_name the name of the tag
71
+ # @param [parent] parent the scenario or feature that is going to adopt
72
+ # this tag.
73
+ #
74
+ def find_or_create_tag(tag_name,parent)
75
+ #log.debug "Processing tag #{tag_name}"
76
+ tag_code_object = YARD::Registry.all(:tag).find {|tag| tag.value == tag_name } ||
77
+ YARD::CodeObjects::Cucumber::Tag.new(YARD::CodeObjects::Cucumber::CUCUMBER_TAG_NAMESPACE,tag_name.gsub('@','')) {|t| t.owners = [] ; t.value = tag_name ; t.total_scenarios = 0}
78
+
79
+ tag_code_object.add_file(@file,parent.line)
80
+
81
+ parent.tags << tag_code_object unless parent.tags.find {|tag| tag == tag_code_object }
82
+ tag_code_object.owners << parent unless tag_code_object.owners.find {|owner| owner == parent}
83
+ end
84
+
85
+ #
86
+ # Each feature found will call this method, generating the feature object.
87
+ # This is once, as the gherkin parser does not like multiple feature per
88
+ # file.
89
+ #
90
+ def feature(document)
91
+ #log.debug "FEATURE"
92
+ feature = document[:feature]
93
+ return unless document[:feature]
94
+ return if has_exclude_tags?(feature[:tags].map { |t| t[:name].gsub(/^@/, '') })
95
+
96
+ @feature = YARD::CodeObjects::Cucumber::Feature.new(@namespace,File.basename(@file.gsub('.feature','').gsub('.','_'))) do |f|
97
+ f.comments = feature[:comments] ? feature[:comments].map{|comment| comment[:text]}.join("\n") : ''
98
+ f.description = feature[:description] || ''
99
+ f.add_file(@file,feature[:location][:line])
100
+ f.keyword = feature[:keyword]
101
+ f.value = feature[:name]
102
+ f.tags = []
103
+
104
+ feature[:tags].each {|feature_tag| find_or_create_tag(feature_tag[:name],f) }
105
+ end
106
+
107
+ background(feature[:background]) if feature[:background]
108
+
109
+ feature[:children].each do |child|
110
+ case child[:type]
111
+ when :Background
112
+ background(child)
113
+ when :ScenarioOutline
114
+ outline = scenario_outline(child)
115
+ @feature.total_scenarios += outline.scenarios.size
116
+ when :Scenario
117
+ scenario(child)
118
+ end
119
+ end
120
+
121
+ @feature.tags.each do |feature_tag|
122
+ tag_code_object = YARD::Registry.all(:tag).find {|tag| tag.name.to_s == feature_tag[:name].to_s }
123
+ tag_code_object.total_scenarios += @feature.total_scenarios
124
+ end
125
+ end
126
+
127
+ #
128
+ # Called when a background has been found
129
+ #
130
+ # @see #feature
131
+ def background(background)
132
+ #log.debug "BACKGROUND"
133
+
134
+ @background = YARD::CodeObjects::Cucumber::Scenario.new(@feature,"background") do |b|
135
+ b.comments = background[:comments] ? background[:comments].map{|comment| comment.value}.join("\n") : ''
136
+ b.description = background[:description] || ''
137
+ b.keyword = background[:keyword]
138
+ b.value = background[:name]
139
+ b.add_file(@file,background[:location][:line])
140
+ end
141
+
142
+ @feature.background = @background
143
+ @background.feature = @feature
144
+ @step_container = @background
145
+ background[:steps].each { |s|
146
+ step(s)
147
+ }
148
+ end
149
+
150
+ #
151
+ # Called when a scenario has been found
152
+ # - create a scenario
153
+ # - assign the scenario to the feature
154
+ # - assign the feature to the scenario
155
+ # - find or create tags associated with the scenario
156
+ #
157
+ # The scenario is set as the @step_container, which means that any steps
158
+ # found before another scenario is defined belong to this scenario
159
+ #
160
+ # @param [Scenario] statement is a scenario object returned from Gherkin
161
+ # @see #find_or_create_tag
162
+ #
163
+ def scenario(statement)
164
+ #log.debug "SCENARIO"
165
+
166
+ return if has_exclude_tags?(statement[:tags].map { |t| t[:name].gsub(/^@/, '') })
167
+
168
+ scenario = YARD::CodeObjects::Cucumber::Scenario.new(@feature,"scenario_#{@feature.scenarios.length + 1}") do |s|
169
+ s.comments = statement[:comments] ? statement[:comments].map{|comment| comment.value}.join("\n") : ''
170
+ s.description = statement[:description] || ''
171
+ s.add_file(@file,statement[:location][:line])
172
+ s.keyword = statement[:keyword]
173
+ s.value = statement[:name]
174
+
175
+ statement[:tags].each {|scenario_tag| find_or_create_tag(scenario_tag[:name],s) }
176
+ end
177
+
178
+ scenario.feature = @feature
179
+ @feature.scenarios << scenario
180
+ @step_container = scenario
181
+ statement[:steps].each { |s|
182
+ step(s)
183
+ }
184
+
185
+ # count scenarios for scenario level tags
186
+ scenario.tags.uniq.each { |scenario_tag|
187
+ if !scenario.feature.tags.include?(scenario_tag)
188
+ tag_code_object = YARD::Registry.all(:tag).find {|tag| tag.name.to_s == scenario_tag[:name].to_s }
189
+ tag_code_object.total_scenarios += 1
190
+ end
191
+ }
192
+ end
193
+
194
+ #
195
+ # Called when a scenario outline is found. Very similar to a scenario,
196
+ # the ScenarioOutline is still a distinct object as it can contain
197
+ # multiple different example groups that can contain different values.
198
+ #
199
+ # @see #scenario
200
+ #
201
+ def scenario_outline(statement)
202
+ #log.debug "SCENARIO OUTLINE"
203
+
204
+ return if has_exclude_tags?(statement[:tags].map { |t| t[:name].gsub(/^@/, '') })
205
+
206
+ outline = YARD::CodeObjects::Cucumber::ScenarioOutline.new(@feature,"scenario_#{@feature.scenarios.length + 1}") do |s|
207
+ s.comments = statement[:comments] ? statement[:comments].map{|comment| comment.value}.join("\n") : ''
208
+ s.description = statement[:description] || ''
209
+ s.add_file(@file,statement[:location][:line])
210
+ s.keyword = statement[:keyword]
211
+ s.value = statement[:name]
212
+
213
+ statement[:tags].each {|scenario_tag| find_or_create_tag(scenario_tag[:name],s) }
214
+ end
215
+
216
+ outline.feature = @feature
217
+ @step_container = outline
218
+ statement[:steps].each { |s|
219
+ step(s)
220
+ }
221
+
222
+ statement[:examples].each { |e|
223
+ example = examples(e, outline)
224
+ }
225
+
226
+ @feature.scenarios << outline
227
+
228
+ # count scenarios for scenario outline level tags
229
+ outline.tags.uniq.each { |outline_tag|
230
+ if !outline.feature.tags.include?(outline_tag)
231
+ tag_code_object = YARD::Registry.all(:tag).find {|tag| tag.name.to_s == outline_tag[:name].to_s }
232
+ tag_code_object.total_scenarios += outline.scenarios.size
233
+ end
234
+ }
235
+
236
+ # count scenarios for example table level tags
237
+ outline.examples.each { |example|
238
+ unless !example.tags.any?
239
+ example.tags.uniq.each { |example_tag|
240
+ if !outline.feature.tags.include?(example_tag) && !outline.tags.include?(example_tag)
241
+ tag_code_object = YARD::Registry.all(:tag).find {|tag| tag.name.to_s == example_tag[:name].to_s }
242
+ tag_code_object.total_scenarios += example.data.size
243
+ end
244
+ }
245
+ end
246
+ }
247
+
248
+ return outline
249
+ end
250
+
251
+
252
+ #
253
+ # Examples for a scenario outline are called here. This section differs
254
+ # from the Cucumber parser because here each of the examples are exploded
255
+ # out here as individual scenarios and step definitions. This is so that
256
+ # later we can ensure that we have all the variations of the scenario
257
+ # outline defined to be displayed.
258
+ #
259
+ def examples(examples, outline)
260
+ #log.debug "EXAMPLES"
261
+ return if has_exclude_tags?(examples[:tags].map { |t| t[:name].gsub(/^@/, '') })
262
+ example = YARD::CodeObjects::Cucumber::ScenarioOutline::Examples.new(:keyword => examples[:keyword],
263
+ :name => examples[:name],
264
+ :line => examples[:location][:line],
265
+ :comments => examples[:comments] ? examples.comments.map{|comment| comment.value}.join("\n") : '',
266
+ :rows => [],
267
+ :tags => [],
268
+ :scenario => outline )
269
+
270
+ unless !examples[:tags].any?
271
+ examples[:tags].each {|example_tag| find_or_create_tag(example_tag[:name], example)}
272
+ end
273
+
274
+ example.rows = [examples[:tableHeader][:cells].map{ |c| c[:value] }] if examples[:tableHeader]
275
+ example.rows += matrix(examples[:tableBody]) if examples[:tableBody]
276
+
277
+ # add the example to the step containers list of examples
278
+
279
+ @step_container.examples << example
280
+
281
+ # For each example data row we want to generate a new scenario using our
282
+ # current scenario as the template.
283
+
284
+ example.data.length.times do |row_index|
285
+
286
+ # Generate a copy of the scenario.
287
+
288
+ scenario = YARD::CodeObjects::Cucumber::Scenario.new(@step_container,"example_#{@step_container.scenarios.length + 1}") do |s|
289
+ s.comments = @step_container.comments
290
+ s.description = @step_container.description
291
+ s.add_file(@file,@step_container.line_number)
292
+ s.keyword = @step_container.keyword
293
+ s.value = "#{@step_container.value} (#{@step_container.scenarios.length + 1})"
294
+ end
295
+
296
+ # Generate a copy of the scenario steps.
297
+
298
+ @step_container.steps.each do |step|
299
+ step_instance = YARD::CodeObjects::Cucumber::Step.new(scenario,step.line_number) do |s|
300
+ s.keyword = step.keyword.dup
301
+ s.value = step.value.dup
302
+ s.add_file(@file,step.line_number)
303
+
304
+ s.text = step.text.dup if step.has_text?
305
+ s.table = clone_table(step.table) if step.has_table?
306
+ end
307
+
308
+ # Look at the particular data for the example row and do a simple
309
+ # find and replace of the <key> with the associated values.
310
+
311
+ example.values_for_row(row_index).each do |key,text|
312
+ text ||= "" #handle empty cells in the example table
313
+ step_instance.value.gsub!("<#{key}>",text)
314
+ step_instance.text.gsub!("<#{key}>",text) if step_instance.has_text?
315
+ step_instance.table.each{|row| row.each{|col| col.gsub!("<#{key}>",text)}} if step_instance.has_table?
316
+ end
317
+
318
+ # Connect these steps that we created to the scenario we created
319
+ # and then add the steps to the scenario created.
320
+
321
+ step_instance.scenario = scenario
322
+ scenario.steps << step_instance
323
+ end
324
+
325
+ # Add the scenario to the list of scenarios maintained by the feature
326
+ # and add the feature to the scenario
327
+
328
+ scenario.feature = @feature
329
+ @step_container.scenarios << scenario
330
+
331
+ end
332
+
333
+ return example
334
+ end
335
+
336
+ #
337
+ # Called when a step is found. The step is refered to a table owner, though
338
+ # not all steps have a table or multliline arguments associated with them.
339
+ #
340
+ # If a multiline string is present with the step it is included as the text
341
+ # of the step. If the step has a table it is added to the step using the
342
+ # same method used by the Cucumber Gherkin model.
343
+ #
344
+ def step(step)
345
+ #log.debug "STEP"
346
+
347
+ @table_owner = YARD::CodeObjects::Cucumber::Step.new(@step_container,"#{step[:location][:line]}") do |s|
348
+ s.keyword = step[:keyword]
349
+ s.value = step[:text]
350
+ s.add_file(@file,step[:location][:line])
351
+ end
352
+
353
+ @table_owner.comments = step[:comments] ? step[:comments].map{|comment| comment.value}.join("\n") : ''
354
+
355
+ multiline_arg = step[:argument]
356
+
357
+ case(multiline_arg[:type])
358
+ when :DocString
359
+ @table_owner.text = multiline_arg[:content]
360
+ when :DataTable
361
+ #log.info "Matrix: #{matrix(multiline_arg).collect{|row| row.collect{|cell| cell.class } }.flatten.join("\n")}"
362
+ @table_owner.table = matrix(multiline_arg[:rows])
363
+ end if multiline_arg
364
+
365
+ @table_owner.scenario = @step_container
366
+ @step_container.steps << @table_owner
367
+ end
368
+
369
+ # Defined in the cucumber version so left here. No events for the end-of-file
370
+ def eof
371
+ end
372
+
373
+ # When a syntax error were to occurr. This parser is not interested in errors
374
+ def syntax_error(state, event, legal_events, line)
375
+ # raise "SYNTAX ERROR"
376
+ end
377
+
378
+ private
379
+ def matrix(gherkin_table)
380
+ gherkin_table.map {|gherkin_row| gherkin_row[:cells].map{ |cell| cell[:value] } }
381
+ end
382
+
383
+ #
384
+ # This helper method is used to deteremine what class is the current
385
+ # Gherkin class.
386
+ #
387
+ # @return [Class] the class that is the current supported Gherkin Model
388
+ # for multiline strings. Prior to Gherkin 2.4.0 this was the PyString
389
+ # class. As of Gherkin 2.4.0 it is the DocString class.
390
+ def gherkin_multiline_string_class
391
+ if defined?(Gherkin::Formatter::Model::PyString)
392
+ Gherkin::Formatter::Model::PyString
393
+ elsif defined?(Gherkin::Formatter::Model::DocString)
394
+ Gherkin::Formatter::Model::DocString
395
+ else
396
+ raise "Unable to find a suitable class in the Gherkin Library to parse the multiline step data."
397
+ end
398
+ end
399
+
400
+ def clone_table(base)
401
+ base.map {|row| row.map {|cell| cell.dup }}
402
+ end
403
+
404
+ def has_exclude_tags?(tags)
405
+ if YARD::Config.options["yard-cucumber"] and YARD::Config.options["yard-cucumber"]["exclude_tags"]
406
+ return true unless (YARD::Config.options["yard-cucumber"]["exclude_tags"] & tags).empty?
407
+ end
408
+ end
409
+
410
+ end
411
+ end
412
+ end