Class: RBS::Writer
Relationships & Source Files | |
Inherits: | Object |
Defined in: | lib/rbs/writer.rb |
Class Method Summary
- .new(out:) ⇒ Writer constructor
Instance Attribute Summary
- #indentation readonly
- #out readonly
- #preserve? ⇒ Boolean readonly
Instance Method Summary
- #attribute(kind, attr)
- #format_annotation(annotation)
- #indent(size = 2)
- #method_name(name)
- #name_and_args(name, args)
- #name_and_params(name, params)
- #prefix
- #preserve!(preserve: true)
- #preserve_empty_line(prev, decl)
- #put_lines(lines, leading_spaces:)
- #puts(string = "")
- #write(contents)
- #write_annotation(annotations)
- #write_comment(comment)
- #write_decl(decl)
- #write_def(member)
- #write_directive(dir)
- #write_loc_source(located)
- #write_member(member)
Constructor Details
.new(out:) ⇒ Writer
# File 'lib/rbs/writer.rb', line 8
def initialize(out:) @out = out @indentation = [] @preserve = false end
Instance Attribute Details
#indentation (readonly)
[ GitHub ]# File 'lib/rbs/writer.rb', line 6
attr_reader :indentation
#out (readonly)
[ GitHub ]# File 'lib/rbs/writer.rb', line 5
attr_reader :out
#preserve? ⇒ Boolean
(readonly)
[ GitHub ]
# File 'lib/rbs/writer.rb', line 14
def preserve? @preserve end
Instance Method Details
#attribute(kind, attr)
[ GitHub ]# File 'lib/rbs/writer.rb', line 361
def attribute(kind, attr) visibility = case attr.visibility when :public "public " when :private "private " else "" end var = case attr.ivar_name when nil "" when false "()" else "(#{attr.ivar_name})" end receiver = case attr.kind when :singleton "self." when :instance "" end "#{visibility}attr_#{kind} #{receiver}#{method_name(attr.name)}#{var}: #{attr.type}" end
#format_annotation(annotation)
[ GitHub ]# File 'lib/rbs/writer.rb', line 42
def format_annotation(annotation) string = annotation.string case when string !~ /\}/ "%a{#{string}}" when string !~ /\)/ "%a(#{string})" when string !~ /\]/ "%a[#{string}]" when string !~ /\>/ "%a<#{string}>" when string !~ /\|/ "%a|#{string}|" else raise end end
#indent(size = 2)
[ GitHub ]# File 'lib/rbs/writer.rb', line 23
def indent(size = 2) indentation.push(" " * size) yield ensure indentation.pop end
#method_name(name)
[ GitHub ]# File 'lib/rbs/writer.rb', line 288
def method_name(name) s = name.to_s case s when /\A(_?)[A-Za-z_]\w*(\?|!|=)?\Z/ s when *%w(| ^ & <=> == === =~ > >= < <= << >> + - * / % ** ~ +@ -@ [] []= ` ! != !~) s else "`#{s}`" end end
#name_and_args(name, args)
[ GitHub ]# File 'lib/rbs/writer.rb', line 214
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)
[ GitHub ]# File 'lib/rbs/writer.rb', line 202
def name_and_params(name, params) if params.empty? "#{name}" else ps = params.each.map do |param| param.to_s end "#{name}[#{ps.join(", ")}]" end end
#prefix
[ GitHub ]# File 'lib/rbs/writer.rb', line 30
def prefix indentation.join() end
#preserve!(preserve: true)
[ GitHub ]# File 'lib/rbs/writer.rb', line 18
def preserve!(preserve: true) @preserve = preserve self end
#preserve_empty_line(prev, decl)
[ GitHub ]# File 'lib/rbs/writer.rb', line 391
def preserve_empty_line(prev, decl) # @type var decl: _Located 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 # When the signature is not constructed by the parser, # it always inserts an empty line. puts end end
#put_lines(lines, leading_spaces:)
[ GitHub ]# File 'lib/rbs/writer.rb', line 224
def put_lines(lines, leading_spaces:) lines.each_line.with_index do |line, index| line.chomp! line.rstrip! line.sub!(/\A( {,#{leading_spaces}})/, '') if index > 0 puts line end end
#puts(string = "")
[ GitHub ]# File 'lib/rbs/writer.rb', line 34
def puts(string = "") if string.size > 0 @out.puts("#{prefix}#{string}") else @out.puts end end
#write(contents)
[ GitHub ]# File 'lib/rbs/writer.rb', line 79
def write(contents) dirs = contents.select {|c| c.is_a?(AST::Directives::Base) } #: Array[AST::Directives::t] decls = contents.select {|c| c.is_a?(AST::Declarations::Base) } #: Array[AST::Declarations::t] dirs.each do |dir| write_directive(dir) end puts unless dirs.empty? [nil, *decls].each_cons(2) do |prev, decl| raise unless decl preserve_empty_line(prev, decl) write_decl decl end end
#write_annotation(annotations)
[ GitHub ]# File 'lib/rbs/writer.rb', line 60
def write_annotation(annotations) annotations.each do |annotation| puts format_annotation(annotation) end end
#write_comment(comment)
[ GitHub ]#write_decl(decl)
[ GitHub ]# File 'lib/rbs/writer.rb', line 114
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::TypeAlias write_comment decl.comment write_annotation decl.annotations write_loc_source(decl) { puts "type #{name_and_params(decl.name, decl.type_params)} = #{decl.type}" } when AST::Declarations::ClassAlias write_comment decl.comment write_loc_source(decl) { puts "class #{decl.new_name} = #{decl.old_name}" } when AST::Declarations::ModuleAlias write_comment decl.comment write_loc_source(decl) { puts "module #{decl.new_name} = #{decl.old_name}" } 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)
[ GitHub ]# File 'lib/rbs/writer.rb', line 309
def write_def(member) visibility = case member.visibility when :public "public " when :private "private " else "" end 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 = "#{visibility}def #{name}:" padding = " " * (prefix.size-1) string << prefix member.overloads.each.with_index do |overload, index| if index > 0 string << padding string << "|" end overload.annotations.each do |annotation| string << " #{format_annotation(annotation)}" end string << " #{overload.method_type}\n" end if member.overloading? if member.overloads.size > 0 string << padding string << "|" end string << " ...\n" end string.each_line do |line| puts line.chomp end end
#write_directive(dir)
[ GitHub ]# File 'lib/rbs/writer.rb', line 97
def write_directive(dir) clauses = dir.clauses.map do |clause| case clause when AST::Directives::Use::SingleClause if clause.new_name "#{clause.type_name} as #{clause.new_name}" else "#{clause.type_name}" end when AST::Directives::Use::WildcardClause "#{clause.namespace}*" end end puts "use #{clauses.join(", ")}" end
#write_loc_source(located)
[ GitHub ]#write_member(member)
[ GitHub ]# File 'lib/rbs/writer.rb', line 234
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.#{method_name(member.new_name)}" : method_name(member.new_name) old_name = member.singleton? ? "self.#{method_name(member.old_name)}" : method_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_loc_source(member) { write_def member } else write_decl member end end