attribute(kind, attr)
click to toggle source
def attribute(kind, attr)
var = case attr.ivar_name
when nil
""
when false
"()"
else
"(#{attr.ivar_name})"
end
receiver = case attr.kind
when :singleton
"self."
when :instance
""
end
"attr_#{kind} #{receiver}#{attr.name}#{var}: #{attr.type}"
end
indent(size = 2)
click to toggle source
def indent(size = 2)
indentation.push(" " * size)
yield
ensure
indentation.pop
end
method_name(name)
click to toggle source
def method_name(name)
s = name.to_s
if [:tOPERATOR, :kAMP, :kHAT, :kSTAR, :kLT, :kEXCLAMATION, :kSTAR2, :kBAR].include?(Parser::PUNCTS[s]) ||
(/\A[a-zA-Z_]\w*[?!=]?\z/.match?(s) && !/\Aself\??\z/.match?(s))
s
else
"`#{s}`"
end
end
name_and_args(name, args)
click to toggle source
def name_and_args(name, args)
if name && args
if args.empty?
"#{name}"
else
"#{name}[#{args.join(", ")}]"
end
end
end
name_and_params(name, params)
click to toggle source
def name_and_params(name, params)
if params.empty?
"#{name}"
else
ps = params.each.map do |param|
s = ""
if param.skip_validation
s << "unchecked "
end
case param.variance
when :invariant
when :covariant
s << "out "
when :contravariant
s << "in "
end
s + param.name.to_s
end
"#{name}[#{ps.join(", ")}]"
end
end
prefix()
click to toggle source
def prefix
indentation.join()
end
preserve_empty_line(prev, decl)
click to toggle source
def preserve_empty_line(prev, decl)
return unless prev
if (_ = decl).respond_to?(:comment)
if comment = (_ = decl).comment
decl = comment
end
end
prev_loc = prev.location
decl_loc = decl.location
if prev_loc && decl_loc
prev_end_line = prev_loc.end_line
start_line = decl_loc.start_line
if start_line - prev_end_line > 1
puts
end
else
puts
end
end
puts(string = "")
click to toggle source
def puts(string = "")
if string.size > 0
@out.puts("#{prefix}#{string}")
else
@out.puts
end
end
write(decls)
click to toggle source
def write(decls)
[nil, *decls].each_cons(2) do |prev, decl|
raise unless decl
preserve_empty_line(prev, decl)
write_decl decl
end
end
write_annotation(annotations)
click to toggle source
def write_annotation(annotations)
annotations.each do |annotation|
string = annotation.string
case
when string !~ /\}/
puts "%a{#{string}}"
when string !~ /\)/
puts "%a(#{string})"
when string !~ /\]/
puts "%a[#{string}]"
when string !~ /\>/
puts "%a<#{string}>"
when string !~ /\|/
puts "%a|#{string}|"
end
end
end
write_decl(decl)
click to toggle source
def write_decl(decl)
case decl
when AST::Declarations::Class
super_class = if super_class = decl.super_class
" < #{name_and_args(super_class.name, super_class.args)}"
end
write_comment decl.comment
write_annotation decl.annotations
puts "class #{name_and_params(decl.name, decl.type_params)}#{super_class}"
indent do
[nil, *decl.members].each_cons(2) do |prev, member|
raise unless member
preserve_empty_line prev, member
write_member member
end
end
puts "end"
when AST::Declarations::Module
self_type = unless decl.self_types.empty?
" : #{decl.self_types.join(", ")}"
end
write_comment decl.comment
write_annotation decl.annotations
puts "module #{name_and_params(decl.name, decl.type_params)}#{self_type}"
indent do
decl.members.each.with_index do |member, index|
if index > 0
puts
end
write_member member
end
end
puts "end"
when AST::Declarations::Constant
write_comment decl.comment
puts "#{decl.name}: #{decl.type}"
when AST::Declarations::Global
write_comment decl.comment
puts "#{decl.name}: #{decl.type}"
when AST::Declarations::Alias
write_comment decl.comment
write_annotation decl.annotations
puts "type #{decl.name} = #{decl.type}"
when AST::Declarations::Interface
write_comment decl.comment
write_annotation decl.annotations
puts "interface #{name_and_params(decl.name, decl.type_params)}"
indent do
decl.members.each.with_index do |member, index|
if index > 0
puts
end
write_member member
end
end
puts "end"
end
end
write_def(member)
click to toggle source
def write_def(member)
name = case member.kind
when :instance
"#{method_name(member.name)}"
when :singleton_instance
"self?.#{method_name(member.name)}"
when :singleton
"self.#{method_name(member.name)}"
end
string = ""
prefix = "def #{name}:"
padding = " " * (prefix.size-1)
string << prefix
member.types.each.with_index do |type, index|
if index > 0
string << padding
string << "|"
end
string << " #{type}\n"
end
if member.overload
string << padding
string << "|"
string << " ...\n"
end
string.each_line do |line|
puts line.chomp
end
end
write_member(member)
click to toggle source
def write_member(member)
case member
when AST::Members::Include
write_comment member.comment
write_annotation member.annotations
puts "include #{name_and_args(member.name, member.args)}"
when AST::Members::Extend
write_comment member.comment
write_annotation member.annotations
puts "extend #{name_and_args(member.name, member.args)}"
when AST::Members::Prepend
write_comment member.comment
write_annotation member.annotations
puts "prepend #{name_and_args(member.name, member.args)}"
when AST::Members::AttrAccessor
write_comment member.comment
write_annotation member.annotations
puts "#{attribute(:accessor, member)}"
when AST::Members::AttrReader
write_comment member.comment
write_annotation member.annotations
puts "#{attribute(:reader, member)}"
when AST::Members::AttrWriter
write_comment member.comment
write_annotation member.annotations
puts "#{attribute(:writer, member)}"
when AST::Members::Public
puts "public"
when AST::Members::Private
puts "private"
when AST::Members::Alias
write_comment member.comment
write_annotation member.annotations
new_name = member.singleton? ? "self.#{member.new_name}" : member.new_name
old_name = member.singleton? ? "self.#{member.old_name}" : member.old_name
puts "alias #{new_name} #{old_name}"
when AST::Members::InstanceVariable
write_comment member.comment
puts "#{member.name}: #{member.type}"
when AST::Members::ClassInstanceVariable
write_comment member.comment
puts "self.#{member.name}: #{member.type}"
when AST::Members::ClassVariable
write_comment member.comment
puts "#{member.name}: #{member.type}"
when AST::Members::MethodDefinition
write_comment member.comment
write_annotation member.annotations
write_def member
else
write_decl member
end
end