require 'gherkin/native' require 'gherkin/formatter/model' module Gherkin module Listener # Adapter from the "raw" Gherkin Listener API # to the slightly more high-level Formatter API, # which is easier to implement (less state to keep track of). class FormatterListener native_impl('gherkin') def initialize(formatter) @formatter = formatter @stash = Stash.new end def comment(value, line) @stash.comment Formatter::Model::Comment.new(value, line) end def tag(name, line) @stash.tag Formatter::Model::Tag.new(name, line) end def feature(keyword, name, description, line) @stash.feature(name) do |comments, tags, id| replay Formatter::Model::Feature.new(comments, tags, keyword, name, description, line, id) end end def background(keyword, name, description, line) @stash.feature_element(name) do |comments, tags, id| replay Formatter::Model::Background.new(comments, keyword, name, description, line) end end def scenario(keyword, name, description, line) replay_step_or_examples @stash.feature_element(name) do |comments, tags, id| replay Formatter::Model::Scenario.new(comments, tags, keyword, name, description, line, id) end end def scenario_outline(keyword, name, description, line) replay_step_or_examples @stash.feature_element(name) do |comments, tags, id| replay Formatter::Model::ScenarioOutline.new(comments, tags, keyword, name, description, line, id) end end def examples(keyword, name, description, line) replay_step_or_examples @stash.examples(name) do |comments, tags, id| @current_builder = Formatter::Model::Examples::Builder.new(comments, tags, keyword, name, description, line, id) end end def step(keyword, name, line) replay_step_or_examples @stash.basic_statement do |comments| @current_builder = Formatter::Model::Step::Builder.new(comments, keyword, name, line) end end def row(cells, line) @stash.basic_statement do |comments, id| @current_builder.row(comments, cells, line, id) end end def doc_string(content_type, value, line) @current_builder.doc_string(value, content_type, line) end def eof replay_step_or_examples @formatter.eof end def syntax_error(state, ev, legal_events, uri, line) @formatter.syntax_error(state, ev, legal_events, uri, line) end private def replay(element) element.replay(@formatter) end class Stash attr_reader :comments, :tags, :ids def initialize @comments, @tags, @ids = [], [], [] @row_index = 0 end def comment(comment) @comments << comment end def feature(name) @feature_id = id(name) yield @comments, @tags, @feature_id @comments, @tags = [], [] end def feature_element(name) @feature_element_id = "#{@feature_id};#{id(name)}" yield @comments, @tags, @feature_element_id @comments, @tags = [], [] end def examples(name) @examples_id = "#{@feature_element_id};#{id(name)}" @row_index = 0 yield @comments, @tags, @examples_id @comments, @tags = [], [] end def basic_statement @row_index += 1 yield @comments, "#{@examples_id};#{@row_index}" @comments = [] end def tag(tag) @tags << tag end def id(name) (name || '').gsub(/[\s_]/, '-').downcase end end def replay_step_or_examples return unless @current_builder replay(@current_builder) @current_builder = nil end end end end