class Gherkin::AstBuilder

Public Class Methods

new(id_generator) click to toggle source
# File lib/gherkin/ast_builder.rb, line 6
def initialize(id_generator)
  @id_generator = id_generator
  reset
end

Public Instance Methods

build(token) click to toggle source
# File lib/gherkin/ast_builder.rb, line 25
def build(token)
  if token.matched_type == :Comment
    @comments.push(Cucumber::Messages::Comment.new(
      location: get_location(token, 0),
      text: token.matched_text
    ))
  else
    current_node.add(token.matched_type, token)
  end
end
current_node() click to toggle source
# File lib/gherkin/ast_builder.rb, line 40
def current_node
  @stack.last
end
end_rule(rule_type) click to toggle source
# File lib/gherkin/ast_builder.rb, line 20
def end_rule(rule_type)
  node = @stack.pop
  current_node.add(node.rule_type, transform_node(node))
end
ensure_cell_count(rows) click to toggle source
# File lib/gherkin/ast_builder.rb, line 82
def ensure_cell_count(rows)
  return if rows.empty?
  cell_count = rows[0].cells.length
  rows.each do |row|
    if row.cells.length != cell_count
      raise AstBuilderException.new("inconsistent cell count within the table", row.location.to_h)
    end
  end
end
get_cells(table_row_token) click to toggle source
# File lib/gherkin/ast_builder.rb, line 92
def get_cells(table_row_token)
  table_row_token.matched_items.map do |cell_item|
    Cucumber::Messages::TableCell.new(
      location: get_location(table_row_token, cell_item.column),
      value: cell_item.text
    )
  end
end
get_description(node) click to toggle source
# File lib/gherkin/ast_builder.rb, line 101
def get_description(node)
  node.get_single(:Description) || ''
end
get_location(token, column) click to toggle source
# File lib/gherkin/ast_builder.rb, line 44
def get_location(token, column)
  column = column == 0 ? token.location[:column] : column
  Cucumber::Messages::Location.new(
    line: token.location[:line],
    column: column
  )
end
get_result() click to toggle source
# File lib/gherkin/ast_builder.rb, line 36
def get_result
  current_node.get_single(:GherkinDocument)
end
get_steps(node) click to toggle source
# File lib/gherkin/ast_builder.rb, line 105
def get_steps(node)
  node.get_items(:Step)
end
get_table_rows(node) click to toggle source
# File lib/gherkin/ast_builder.rb, line 70
def get_table_rows(node)
  rows = node.get_tokens(:TableRow).map do |token|
    Cucumber::Messages::TableRow.new(
      id: @id_generator.new_id,
      location: get_location(token, 0),
      cells: get_cells(token)
    )
  end
  ensure_cell_count(rows)
  rows
end
get_tags(node) click to toggle source
# File lib/gherkin/ast_builder.rb, line 52
def get_tags(node)
  tags = []
  tags_node = node.get_single(:Tags)
  return tags unless tags_node

  tags_node.get_tokens(:TagLine).each do |token|
    token.matched_items.each do |tag_item|
      tags.push(Cucumber::Messages::Tag.new(
        location: get_location(token, tag_item.column),
        name: tag_item.text,
        id: @id_generator.new_id
      ))
    end
  end

  tags
end
reset() click to toggle source
# File lib/gherkin/ast_builder.rb, line 11
def reset
  @stack = [AstNode.new(:None)]
  @comments = []
end
start_rule(rule_type) click to toggle source
# File lib/gherkin/ast_builder.rb, line 16
def start_rule(rule_type)
  @stack.push AstNode.new(rule_type)
end
transform_node(node) click to toggle source
# File lib/gherkin/ast_builder.rb, line 109
def transform_node(node)
  case node.rule_type
  when :Step
    step_line = node.get_token(:StepLine)
    data_table = node.get_single(:DataTable)
    doc_string = node.get_single(:DocString)

    step = Cucumber::Messages::Step.new(
      location: get_location(step_line, 0),
      keyword: step_line.matched_keyword,
      text: step_line.matched_text,
      data_table: data_table,
      doc_string: doc_string,
      id: @id_generator.new_id
    )
  when :DocString
    separator_token = node.get_tokens(:DocStringSeparator)[0]
    media_type = separator_token.matched_text == '' ? nil : separator_token.matched_text
    line_tokens = node.get_tokens(:Other)
    content = line_tokens.map { |t| t.matched_text }.join("\n")

    Cucumber::Messages::DocString.new(
      location: get_location(separator_token, 0),
      content: content,
      delimiter: separator_token.matched_keyword,
      media_type: media_type
    )
  when :DataTable
    rows = get_table_rows(node)
    Cucumber::Messages::DataTable.new(
      location: rows[0].location,
      rows: rows
    )
  when :Background
    background_line = node.get_token(:BackgroundLine)
    description = get_description(node)
    steps = get_steps(node)

    Cucumber::Messages::Background.new(
      id: @id_generator.new_id,
      location: get_location(background_line, 0),
      keyword: background_line.matched_keyword,
      name: background_line.matched_text,
      description: description,
      steps: steps
    )
  when :ScenarioDefinition
    tags = get_tags(node)
    scenario_node = node.get_single(:Scenario)
    scenario_line = scenario_node.get_token(:ScenarioLine)
    description = get_description(scenario_node)
    steps = get_steps(scenario_node)
    examples = scenario_node.get_items(:ExamplesDefinition)
    Cucumber::Messages::Scenario.new(
      id: @id_generator.new_id,
      tags: tags,
      location: get_location(scenario_line, 0),
      keyword: scenario_line.matched_keyword,
      name: scenario_line.matched_text,
      description: description,
      steps: steps,
      examples: examples
    )
  when :ExamplesDefinition
    tags = get_tags(node)
    examples_node = node.get_single(:Examples)
    examples_line = examples_node.get_token(:ExamplesLine)
    description = get_description(examples_node)
    rows = examples_node.get_single(:ExamplesTable)

    table_header = rows.nil? ? nil : rows.first
    table_body = rows.nil? ? [] : rows[1..-1]

    Cucumber::Messages::Examples.new(
      id: @id_generator.new_id,
      tags: tags,
      location: get_location(examples_line, 0),
      keyword: examples_line.matched_keyword,
      name: examples_line.matched_text,
      description: description,
      table_header: table_header,
      table_body: table_body
    )
  when :ExamplesTable
    get_table_rows(node)
  when :Description
    line_tokens = node.get_tokens(:Other)
    # Trim trailing empty lines
    last_non_empty = line_tokens.rindex { |token| !token.line.trimmed_line_text.empty? }
    description = line_tokens[0..last_non_empty].map { |token| token.matched_text }.join("\n")
    return description
  when :Feature
    header = node.get_single(:FeatureHeader)
    return unless header
    tags = get_tags(header)
    feature_line = header.get_token(:FeatureLine)
    return unless feature_line
    children = []
    background = node.get_single(:Background)
    children.push(Cucumber::Messages::FeatureChild.new(background: background)) if background
    node.get_items(:ScenarioDefinition).each do |scenario|
      children.push(Cucumber::Messages::FeatureChild.new(scenario: scenario))
    end
    node.get_items(:Rule).each do |rule|
      children.push(Cucumber::Messages::FeatureChild.new(rule: rule))
    end
    description = get_description(header)
    language = feature_line.matched_gherkin_dialect

    Cucumber::Messages::Feature.new(
      tags: tags,
      location: get_location(feature_line, 0),
      language: language,
      keyword: feature_line.matched_keyword,
      name: feature_line.matched_text,
      description: description,
      children: children,
    )
  when :Rule
    header = node.get_single(:RuleHeader)
    return unless header
    rule_line = header.get_token(:RuleLine)
    return unless rule_line
    tags = get_tags(header)
    children = []
    background = node.get_single(:Background)
    children.push(Cucumber::Messages::RuleChild.new(background: background)) if background
    node.get_items(:ScenarioDefinition).each do |scenario|
      children.push(Cucumber::Messages::RuleChild.new(scenario: scenario))
    end
    description = get_description(header)

    Cucumber::Messages::Rule.new(
      id: @id_generator.new_id,
      tags: tags,
      location: get_location(rule_line, 0),
      keyword: rule_line.matched_keyword,
      name: rule_line.matched_text,
      description: description,
      children: children,
    )
  when :GherkinDocument
    feature = node.get_single(:Feature)
    Cucumber::Messages::GherkinDocument.new(
      comments: @comments,
      feature: feature
    )
  else
    return node
  end
end