lib/cucumber/parser/gherkin_builder.rb in cucumber-1.2.5 vs lib/cucumber/parser/gherkin_builder.rb in cucumber-1.3.0
- old
+ new
@@ -1,128 +1,284 @@
require 'cucumber/ast'
require 'gherkin/rubify'
require 'cucumber/ast/multiline_argument'
+require 'cucumber/ast/empty_background'
module Cucumber
module Parser
# This class conforms to the Gherkin event API and builds the
# "legacy" AST. It will be replaced later when we have a new "clean"
# AST.
class GherkinBuilder
include Gherkin::Rubify
- def ast
- @feature || @multiline_arg
+ def initialize(path = 'UNKNOWN-FILE')
+ @path = path
end
- def feature(feature)
- @feature = Ast::Feature.new(
- nil,
- Ast::Comment.new(feature.comments.map{|comment| comment.value}.join("\n")),
- Ast::Tags.new(nil, feature.tags),
- feature.keyword,
- feature.name.lstrip,
- feature.description.rstrip,
- []
- )
- @feature.gherkin_statement(feature)
- @feature
+ def result
+ return nil unless @feature_builder
+ @feature_builder.result(language)
end
- def background(background)
- @background = Ast::Background.new(
- Ast::Comment.new(background.comments.map{|comment| comment.value}.join("\n")),
- background.line,
- background.keyword,
- background.name,
- background.description,
- []
- )
- @feature.background = @background
- @background.feature = @feature
- @step_container = @background
- @background.gherkin_statement(background)
+ def language=(language)
+ @language = language
end
- def scenario(statement)
- scenario = Ast::Scenario.new(
- @background,
- Ast::Comment.new(statement.comments.map{|comment| comment.value}.join("\n")),
- Ast::Tags.new(nil, statement.tags),
- statement.line,
- statement.keyword,
- statement.name,
- statement.description,
- []
- )
- @feature.add_feature_element(scenario)
- @background.feature_elements << scenario if @background
- @step_container = scenario
- scenario.gherkin_statement(statement)
+ def uri(uri)
+ @path = uri
end
- def scenario_outline(statement)
- scenario_outline = Ast::ScenarioOutline.new(
- @background,
- Ast::Comment.new(statement.comments.map{|comment| comment.value}.join("\n")),
- Ast::Tags.new(nil, statement.tags),
- statement.line,
- statement.keyword,
- statement.name,
- statement.description,
- [],
- []
- )
- @feature.add_feature_element(scenario_outline)
- if @background
- @background = @background.dup
- @background.feature_elements << scenario_outline
- end
- @step_container = scenario_outline
- scenario_outline.gherkin_statement(statement)
+ def feature(node)
+ @feature_builder = FeatureBuilder.new(file, node)
end
+ def background(node)
+ builder = BackgroundBuilder.new(file, node)
+ @feature_builder.background_builder = builder
+ @current = builder
+ end
+
+ def scenario(node)
+ builder = ScenarioBuilder.new(file, node)
+ @feature_builder.add_child builder
+ @current = builder
+ end
+
+ def scenario_outline(node)
+ builder = ScenarioOutlineBuilder.new(file, node)
+ @feature_builder.add_child builder
+ @current = builder
+ end
+
def examples(examples)
examples_fields = [
+ Ast::Location.new(file, examples.line),
Ast::Comment.new(examples.comments.map{|comment| comment.value}.join("\n")),
- examples.line,
examples.keyword,
examples.name,
examples.description,
matrix(examples.rows)
]
- @step_container.add_examples(examples_fields, examples)
+ @current.add_examples examples_fields, examples
end
- def step(gherkin_step)
- step = Ast::Step.new(
- gherkin_step.line,
- gherkin_step.keyword,
- gherkin_step.name,
- Ast::MultilineArgument.from(gherkin_step.doc_string || gherkin_step.rows)
- )
- step.gherkin_statement(gherkin_step)
- @step_container.add_step(step)
+ def step(node)
+ builder = StepBuilder.new(file, node)
+ @current.add_child builder
end
def eof
end
def syntax_error(state, event, legal_events, line)
# raise "SYNTAX ERROR"
end
- private
+ private
+ if defined?(JRUBY_VERSION)
+ java_import java.util.ArrayList
+ ArrayList.__persistent__ = true
+ end
+
def matrix(gherkin_table)
gherkin_table.map do |gherkin_row|
row = gherkin_row.cells
class << row
attr_accessor :line
end
row.line = gherkin_row.line
row
end
end
+
+ def language
+ @language || raise("Language has not been set")
+ end
+
+ def file
+ if Cucumber::WINDOWS && !ENV['CUCUMBER_FORWARD_SLASH_PATHS']
+ @path.gsub(/\//, '\\')
+ else
+ @path
+ end
+ end
+
+ class Builder
+ def initialize(file, node)
+ @file, @node = file, node
+ end
+
+ private
+
+ def tags
+ Ast::Tags.new(nil, node.tags)
+ end
+
+ def location
+ Ast::Location.new(file, node.line)
+ end
+
+ def comment
+ Ast::Comment.new(node.comments.map{ |comment| comment.value }.join("\n"))
+ end
+
+ attr_reader :file, :node
+ end
+
+ class FeatureBuilder < Builder
+ def result(language)
+ background = background(language)
+ feature = Ast::Feature.new(
+ location,
+ background,
+ comment,
+ tags,
+ node.keyword,
+ node.name.lstrip,
+ node.description.rstrip,
+ children.map { |builder| builder.result(background, language, tags) }
+ )
+ feature.gherkin_statement(node)
+ feature.language = language
+ feature
+ end
+
+ def background_builder=(builder)
+ @background_builder = builder
+ end
+
+ def add_child(child)
+ children << child
+ end
+
+ def children
+ @children ||= []
+ end
+
+ private
+
+ def background(language)
+ return Ast::EmptyBackground.new unless @background_builder
+ @background ||= @background_builder.result(language)
+ end
+ end
+
+ class BackgroundBuilder < Builder
+ def result(language)
+ background = Ast::Background.new(
+ language,
+ location,
+ comment,
+ node.keyword,
+ node.name,
+ node.description,
+ steps(language)
+ )
+ background.gherkin_statement(node)
+ background
+ end
+
+ def steps(language)
+ children.map { |child| child.result(language) }
+ end
+
+ def add_child(child)
+ children << child
+ end
+
+ def children
+ @children ||= []
+ end
+
+ end
+
+ class ScenarioBuilder < Builder
+ def result(background, language, feature_tags)
+ scenario = Ast::Scenario.new(
+ language,
+ location,
+ background,
+ comment,
+ tags,
+ feature_tags,
+ node.keyword,
+ node.name,
+ node.description,
+ steps(language)
+ )
+ scenario.gherkin_statement(node)
+ scenario
+ end
+
+ def steps(language)
+ children.map { |child| child.result(language) }
+ end
+
+ def add_child(child)
+ children << child
+ end
+
+ def children
+ @children ||= []
+ end
+ end
+
+ class ScenarioOutlineBuilder < Builder
+ def result(background, language, feature_tags)
+ scenario_outline = Ast::ScenarioOutline.new(
+ language,
+ location,
+ background,
+ comment,
+ tags,
+ feature_tags,
+ node.keyword,
+ node.name,
+ node.description,
+ steps(language),
+ examples_sections
+ )
+ scenario_outline.gherkin_statement(node)
+ scenario_outline
+ end
+
+ def add_examples(examples_section, node)
+ @examples_sections ||= []
+ @examples_sections << [examples_section, node]
+ end
+
+ def steps(language)
+ children.map { |child| child.result(language) }
+ end
+
+ def add_child(child)
+ children << child
+ end
+
+ def children
+ @children ||= []
+ end
+
+ private
+
+ attr_reader :examples_sections
+ end
+
+ class StepBuilder < Builder
+ def result(language)
+ step = Ast::Step.new(
+ language,
+ location,
+ node.keyword,
+ node.name,
+ Ast::MultilineArgument.from(node.doc_string || node.rows)
+ )
+ step.gherkin_statement(node)
+ step
+ end
+ end
+
end
end
end