# File typeprof-0.12.0/lib/typeprof/import.rb, line 362
def attr_method_def(kind, name, ty, visibility)
{
kind: kind,
ivar: name,
ty: ty,
visibility: visibility,
}
end
# File typeprof-0.12.0/lib/typeprof/import.rb, line 371
def conv_block(rbs_block)
type = rbs_block.type
# XXX
raise NotImplementedError unless type.optional_keywords.empty?
raise NotImplementedError unless type.required_keywords.empty?
raise NotImplementedError if type.rest_keywords
req = rbs_block.required
lead_tys = type.required_positionals.map do |type|
conv_type(type.type)
end
opt_tys = type.optional_positionals.map do |type|
conv_type(type.type)
end
ret_ty = conv_type(type.return_type)
[req, lead_tys, opt_tys, ret_ty]
end
# File typeprof-0.12.0/lib/typeprof/import.rb, line 119
def conv_classes
json = {}
each_class_decl do |name, decls|
klass = conv_type_name(name)
super_class_name, super_class_args = get_super_class(name, decls)
if super_class_name
name = conv_type_name(super_class_name)
type_args = super_class_args.map {|type| conv_type(type) }
superclass = [name, type_args]
end
type_params = nil
modules = { include: [], extend: [], prepend: [] }
methods = {}
attr_methods = {}
ivars = {}
cvars = {}
rbs_sources = {}
visibility = true
decls.each do |decl|
decl = decl.decl
type_params2 = decl.type_params.params.map {|param| [param.name, param.variance] }
raise "inconsistent type parameter declaration" if type_params && type_params != type_params2
type_params = type_params2
decl.members.each do |member|
case member
when RBS::AST::Members::MethodDefinition
name = member.name
method_types = member.types.map do |method_type|
case method_type
when RBS::MethodType then method_type
when :super then raise NotImplementedError
end
end
method_def = conv_method_def(method_types, visibility)
rbs_source = [(member.kind == :singleton ? "self." : "") + member.name.to_s, member.types.map {|type| type.location.source }]
if member.instance?
methods[[false, name]] = method_def
rbs_sources[[false, name]] = rbs_source
end
if member.singleton?
methods[[true, name]] = method_def
rbs_sources[[true, name]] = rbs_source
end
when RBS::AST::Members::AttrReader
ty = conv_type(member.type)
attr_methods[[false, member.name]] = attr_method_def(:reader, member.name, ty, visibility)
when RBS::AST::Members::AttrWriter
ty = conv_type(member.type)
attr_methods[[false, member.name]] = attr_method_def(:writer, member.name, ty, visibility)
when RBS::AST::Members::AttrAccessor
ty = conv_type(member.type)
attr_methods[[false, member.name]] = attr_method_def(:accessor, member.name, ty, visibility)
when RBS::AST::Members::Alias
# XXX: an alias to attr methods?
if member.instance?
method_def = methods[[false, member.old_name]]
methods[[false, member.new_name]] = method_def if method_def
end
if member.singleton?
method_def = methods[[true, member.old_name]]
methods[[true, member.new_name]] = method_def if method_def
end
when RBS::AST::Members::Include
name = member.name
if name.kind == :class
mod = conv_type_name(name)
type_args = member.args.map {|type| conv_type(type) }
modules[:include] << [mod, type_args]
else
# including an interface is not supported yet
end
when RBS::AST::Members::Extend
name = member.name
if name.kind == :class
mod = conv_type_name(name)
type_args = member.args.map {|type| conv_type(type) }
modules[:extend] << [mod, type_args]
else
# extending a module with an interface is not supported yet
end
when RBS::AST::Members::Prepend
name = member.name
if name.kind == :class
mod = conv_type_name(name)
type_args = member.args.map {|type| conv_type(type) }
modules[:prepend] << [mod, type_args]
else
# extending a module with an interface is not supported yet
end
when RBS::AST::Members::InstanceVariable
ivars[member.name] = conv_type(member.type)
when RBS::AST::Members::ClassVariable
cvars[member.name] = conv_type(member.type)
when RBS::AST::Members::Public
visibility = true
when RBS::AST::Members::Private
visibility = false
# The following declarations are ignoreable because they are handled in other level
when RBS::AST::Declarations::Constant
when RBS::AST::Declarations::Alias # type alias
when RBS::AST::Declarations::Class, RBS::AST::Declarations::Module
when RBS::AST::Declarations::Interface
else
warn "Importing #{ member.class.name } is not supported yet"
end
end
end
json[klass] = {
type_params: type_params,
superclass: superclass,
members: {
modules: modules,
methods: methods,
attr_methods: attr_methods,
ivars: ivars,
cvars: cvars,
rbs_sources: rbs_sources,
},
}
end
json
end
constant_name = [Symbol]
{ constant_name => type }
# File typeprof-0.12.0/lib/typeprof/import.rb, line 98
def conv_constants
constants = {}
@cur_env.constant_decls.each do |name, decl|
klass = conv_type_name(name)
constants[klass] = conv_type(decl.decl.type)
end
constants
end
# File typeprof-0.12.0/lib/typeprof/import.rb, line 335
def conv_func(type_params, func, block)
blk = block ? conv_block(block) : nil
lead_tys = func.required_positionals.map {|type| conv_type(type.type) }
opt_tys = func.optional_positionals.map {|type| conv_type(type.type) }
rest_ty = func.rest_positionals
rest_ty = conv_type(rest_ty.type) if rest_ty
opt_kw_tys = func.optional_keywords.to_h {|key, type| [key, conv_type(type.type)] }
req_kw_tys = func.required_keywords.to_h {|key, type| [key, conv_type(type.type)] }
rest_kw_ty = func.rest_keywords
rest_kw_ty = conv_type(rest_kw_ty.type) if rest_kw_ty
ret_ty = conv_type(func.return_type)
{
type_params: type_params,
lead_tys: lead_tys,
opt_tys: opt_tys,
rest_ty: rest_ty,
req_kw_tys: req_kw_tys,
opt_kw_tys: opt_kw_tys,
rest_kw_ty: rest_kw_ty,
blk: blk,
ret_ty: ret_ty,
}
end
gvar_name = Symbol (:$gvar)
{ gvar_name => type }
# File typeprof-0.12.0/lib/typeprof/import.rb, line 110
def conv_globals
gvars = {}
@cur_env.global_decls.each do |name, decl|
decl = decl.decl
gvars[name] = conv_type(decl.type)
end
gvars
end
# File typeprof-0.12.0/lib/typeprof/import.rb, line 325
def conv_method_def(rbs_method_types, visibility)
sig_rets = rbs_method_types.map do |method_type|
conv_func(method_type.type_params, method_type.type, method_type.block)
end
{
sig_rets: sig_rets,
visibility: visibility,
}
end
# File typeprof-0.12.0/lib/typeprof/import.rb, line 393
def conv_type(ty)
case ty
when RBS::Types::ClassSingleton
[:class, conv_type_name(ty.name)]
when RBS::Types::ClassInstance
klass = conv_type_name(ty.name)
case klass
when [:Array]
raise if ty.args.size != 1
[:array, [:Array], [], conv_type(ty.args.first)]
when [:Hash]
raise if ty.args.size != 2
key, val = ty.args
[:hash, [:Hash], [conv_type(key), conv_type(val)]]
when [:Enumerator]
raise if ty.args.size != 2
[:array, [:Enumerator], [], conv_type(ty.args.first)]
else
if ty.args.empty?
[:instance, klass]
else
[:cell, [:instance, klass], ty.args.map {|ty| conv_type(ty) }]
end
end
when RBS::Types::Bases::Bool then [:bool]
when RBS::Types::Bases::Any then [:any]
when RBS::Types::Bases::Top then [:any]
when RBS::Types::Bases::Void then [:void]
when RBS::Types::Bases::Self then [:self]
when RBS::Types::Bases::Nil then [:nil]
when RBS::Types::Bases::Bottom then [:union, []]
when RBS::Types::Variable then [:var, ty.name]
when RBS::Types::Tuple
tys = ty.types.map {|ty2| conv_type(ty2) }
[:array, [:Array], tys, [:union, []]]
when RBS::Types::Literal
case ty.literal
when Integer then [:int]
when String then [:str]
when true then [:true]
when false then [:false]
when Symbol then [:sym, ty.literal]
else
p ty.literal
raise NotImplementedError
end
when RBS::Types::Alias
if @alias_resolution_stack[ty.name]
[:any]
else
begin
@alias_resolution_stack[ty.name] = true
alias_decl = @all_env.alias_decls[ty.name]
alias_decl ? conv_type(alias_decl.decl.type) : [:any]
ensure
@alias_resolution_stack.delete(ty.name)
end
end
when RBS::Types::Union
[:union, ty.types.map {|ty2| conv_type(ty2) }.compact]
when RBS::Types::Optional
[:optional, conv_type(ty.type)]
when RBS::Types::Interface
# XXX: Currently, only a few builtin interfaces are supported
case ty.to_s
when "::_ToStr" then [:str]
when "::_ToInt" then [:int]
when "::_ToAry[U]" then [:array, [:Array], [], [:var, :U]]
else
[:instance, conv_type_name(ty.name)]
end
when RBS::Types::Bases::Instance then [:any] # XXX: not implemented yet
when RBS::Types::Record
[:hash_record, [:Hash], ty.fields.map {|key, ty| [key, conv_type(ty)] }]
when RBS::Types::Proc
[:proc, conv_func(nil, ty.type, nil)]
else
warn "unknown RBS type: %p" % ty.class
[:any]
end
end
# File typeprof-0.12.0/lib/typeprof/import.rb, line 475
def conv_type_name(name)
name.namespace.path + [name.name]
end
# File typeprof-0.12.0/lib/typeprof/import.rb, line 87
def dump_json
{
classes: conv_classes,
constants: conv_constants,
globals: conv_globals,
}
end
# File typeprof-0.12.0/lib/typeprof/import.rb, line 258
def each_class_decl
# topological sort
# * superclasses and modules appear earlier than their subclasses (Object is earlier than String)
# * namespace module appers earlier than its children (Process is earlier than Process::Status)
visited = {}
queue = @cur_env.class_decls.keys.map {|name| [:visit, name] }.reverse
until queue.empty?
event, name = queue.pop
case event
when :visit
if !visited[name]
visited[name] = true
queue << [:new, name]
@all_env.class_decls[name].decls.each do |decl|
decl = decl.decl
next if decl.is_a?(RBS::AST::Declarations::Module)
each_reference(decl) {|name| queue << [:visit, name] }
end
queue << [:visit, name.namespace.to_type_name] if !name.namespace.empty?
end
when :new
decls = @cur_env.class_decls[name]
yield name, decls.decls if decls
end
end
@cur_env.interface_decls.each do |name, decl|
yield name, [decl]
end
end
# File typeprof-0.12.0/lib/typeprof/import.rb, line 289
def each_reference(decl, &blk)
yield decl.name
if decl.super_class
name = decl.super_class.name
else
name = RBS::BuiltinNames::Object.name
end
return if decl.name == RBS::BuiltinNames::BasicObject.name
return if decl.name == name
decls = @all_env.class_decls[name]
if decls
decls.decls.each do |decl|
each_reference(decl.decl, &blk)
end
end
end
# File typeprof-0.12.0/lib/typeprof/import.rb, line 306
def get_super_class(name, decls)
return nil if name == RBS::BuiltinNames::BasicObject.name
decls.each do |decl|
decl = decl.decl
case decl
when RBS::AST::Declarations::Class
super_class = decl.super_class
return super_class.name, super_class.args if super_class
when RBS::AST::Declarations::Module, RBS::AST::Declarations::Interface
return nil
else
raise "unknown declaration: %p" % decl.class
end
end
return RBS::BuiltinNames::Object.name, []
end