class Yard2steep::Gen

Public Class Methods

new() click to toggle source
# File lib/yard2steep/gen.rb, line 5
def initialize
  @out = StringIO.new # Output buffer
end

Public Instance Methods

emit!(s, off: 0) click to toggle source

@param [String] s @param [Integer] off @return [void]

# File lib/yard2steep/gen.rb, line 21
def emit!(s, off: 0)
  Util.assert! { off >= 0 }
  if off == 0
    @out.print(s)
  else
    @out.print("#{' ' * off}#{s}")
  end
end
gen(ast) click to toggle source

@param [AST::ClassNode] ast @return [String]

# File lib/yard2steep/gen.rb, line 11
def gen(ast)
  gen_child!(ast, off: 0)

  @out.rewind
  @out.read
end
gen_block_p!(p) click to toggle source

TODO(south37) Represents block param and return type separately

@param [AST::PNode] p @return [void]

# File lib/yard2steep/gen.rb, line 141
def gen_block_p!(p)
  emit! "#{p.type_node.p_type} "
end
gen_c!(c_node, off:) click to toggle source

@param [AST::ConstantNode] c_node @param [Integer] off @return [void]

# File lib/yard2steep/gen.rb, line 94
def gen_c!(c_node, off:)
  Util.assert! { c_node.is_a?(AST::ConstantNode) }
  # NOTE: Use any as constant type.
  emit! "#{c_node.long_name}: #{c_node.v_type}\n", off: off
end
gen_c_list!(c_node, off:) click to toggle source

@param [AST::ClassNode] c_node @param [Integer] off @return [void]

# File lib/yard2steep/gen.rb, line 76
def gen_c_list!(c_node, off:)
  c_node.c_list.each do |c_node|
    gen_c!(c_node, off: off)
  end
end
gen_child!(c_node, off:) click to toggle source

@param [AST::ClassNode] c_node @param [Integer] off @return [void]

# File lib/yard2steep/gen.rb, line 33
def gen_child!(c_node, off:)
  Util.assert! { c_node.is_a?(AST::ClassNode) }

  # TODO(south37) We should check `main` by class_node's type (not name).
  if c_node.c_name == 'main'
    # NOTE: In main, steep does not check method type, so we does not
    # generate type definition of methods.
    gen_children!(c_node, off: 0)
  else
    if (c_node.m_list.size > 0) || (c_node.ivar_list.size > 0)
      emit! "#{c_node.kind} #{c_node.long_name}#{c_node.super_c ? " <: #{c_node.long_super}" : nil}\n", off: off
      gen_ivar_list!(c_node, off: off + 2)
      gen_m_list!(c_node, off: off + 2)
      emit! "end\n", off: off
    end
    gen_c_list!(c_node, off: off)
    gen_children!(c_node, off: off)
  end
end
gen_children!(c_node, off:) click to toggle source

@param [AST::ClassNode] c_node @param [Integer] off @return [void]

# File lib/yard2steep/gen.rb, line 85
def gen_children!(c_node, off:)
  c_node.children.each do |child|
    gen_child!(child, off: off)
  end
end
gen_ivar_list!(c_node, off:) click to toggle source

NOTE: In current impl, ivar's type is declared as any

@param [AST::ClassNode] c_node @param [Integer] off @return [void]

# File lib/yard2steep/gen.rb, line 67
def gen_ivar_list!(c_node, off:)
  c_node.ivar_list.each do |ivar_node|
    emit! "@#{ivar_node.name}: any\n", off: off
  end
end
gen_m!(m_node, off:) click to toggle source

@param [AST::MethodNode] m_node @param [Integer] off @return [void]

# File lib/yard2steep/gen.rb, line 103
def gen_m!(m_node, off:)
  Util.assert! { m_node.is_a?(AST::MethodNode) }
  emit! "def #{m_node.m_name}: ", off: off
  p_list = m_node.p_list

  # NOTE: Check presence of block variable at last.
  if p_list[-1] && (p_list[-1].type_node.kind == AST::PTypeNode::KIND[:block])
    gen_p_list!(p_list[0..-2])
    gen_block_p!(p_list[-1])
  else
    gen_p_list!(p_list)
  end

  emit! "-> #{m_node.r_type}\n"
end
gen_m_list!(c_node, off:) click to toggle source

@param [AST::ClassNode] c_node @param [Integer] off @return [void]

# File lib/yard2steep/gen.rb, line 56
def gen_m_list!(c_node, off:)
  c_node.m_list.each do |m_node|
    gen_m!(m_node, off: off)
  end
end
gen_m_p!(p_node) click to toggle source

@param [AST::PNode] p_node @return [void]

# File lib/yard2steep/gen.rb, line 147
def gen_m_p!(p_node)
  t = p_node.type_node

  case p_node.style
  when AST::PNode::STYLE[:normal]
    emit! t.p_type
  when AST::PNode::STYLE[:normal_with_default]
    emit! "?#{t.p_type}"
  when AST::PNode::STYLE[:keyword]
    emit! "#{t.p_name}: #{t.p_type}"
  when AST::PNode::STYLE[:keyword_with_default]
    emit! "?#{t.p_name}: #{t.p_type}"
  else
    raise "invalid style: #{p_node.style}"
  end
end
gen_p_list!(p_list) click to toggle source

@param [Array<AST::PNode>] p_list @return [void]

# File lib/yard2steep/gen.rb, line 121
def gen_p_list!(p_list)
  len = p_list.size
  if len > 0
    emit! "("

    p_list.each.with_index do |p, i|
      gen_m_p!(p)
      if i < (len - 1)
        emit!(", ")
      end
    end

    emit! ") "
  end
end