class TypeProf::Core::EscapeBox::HashSplatBox::MethodCallBox
Attributes
mid[R]
recv[R]
ret[R]
Public Class Methods
new(node, genv, recv, mid, a_args, subclasses)
click to toggle source
Calls superclass method
TypeProf::Core::Box::new
# File typeprof-0.30.1/lib/typeprof/core/graph/box.rb, line 657 def initialize(node, genv, recv, mid, a_args, subclasses) raise mid.to_s unless mid super(node) @recv = recv.new_vertex(genv, node) @recv.add_edge(genv, self) @mid = mid @a_args = a_args.new_vertexes(genv, node) @a_args.positionals.each {|arg| arg.add_edge(genv, self) } @a_args.keywords.add_edge(genv, self) if @a_args.keywords @a_args.block.add_edge(genv, self) if @a_args.block @ret = Vertex.new(node) @subclasses = subclasses @generics = {} end
Public Instance Methods
resolve(genv, changes) { |me, ty, mid, orig_ty| ... }
click to toggle source
# File typeprof-0.30.1/lib/typeprof/core/graph/box.rb, line 734 def resolve(genv, changes, &blk) @recv.each_type do |orig_ty| next if orig_ty == Type::Bot.new(genv) if @mid == :"*super" mid = @node.lenv.cref.mid skip = true else mid = @mid skip = false end ty = orig_ty.base_type(genv) base_ty_env = Type.default_param_map(genv, ty) alias_limit = 0 while ty unless skip me = ty.mod.get_method(ty.is_a?(Type::Singleton), mid) changes.add_depended_method_entity(me) if changes if !me.aliases.empty? mid = me.aliases.values.first alias_limit += 1 redo if alias_limit < 5 end if me.exist? yield me, ty, mid, orig_ty break end end skip = false if ty.is_a?(Type::Singleton) # TODO: extended modules else break if resolve_included_modules(genv, changes, base_ty_env, ty, mid) do |me, ty, mid| yield me, ty, mid, orig_ty end end ty = genv.get_superclass_type(ty, changes, base_ty_env) end yield nil, nil, mid, orig_ty unless ty end end
resolve_included_modules(genv, changes, base_ty_env, ty, mid) { |me, self_ty, mid| ... }
click to toggle source
# File typeprof-0.30.1/lib/typeprof/core/graph/box.rb, line 782 def resolve_included_modules(genv, changes, base_ty_env, ty, mid, &blk) found = false alias_limit = 0 ty.mod.self_types.each do |(mdecl, idx), self_ty_mod| raise unless mdecl.is_a?(AST::SigModuleNode) if self_ty_mod.type_params self_ty = genv.get_instance_type(self_ty_mod, mdecl.self_type_args[idx], changes, base_ty_env, ty) else self_ty = Type::Instance.new(genv, self_ty_mod, []) end me = self_ty.mod.get_method(false, mid) changes.add_depended_method_entity(me) if changes if !me.aliases.empty? mid = me.aliases.values.first alias_limit += 1 redo if alias_limit < 5 end if me.exist? found = true yield me, self_ty, mid else found ||= resolve_included_modules(genv, changes, base_ty_env, self_ty, mid, &blk) end end alias_limit = 0 ty.mod.included_modules.each do |inc_decl, inc_mod| if inc_decl.is_a?(AST::SigIncludeNode) && inc_mod.type_params inc_ty = genv.get_instance_type(inc_mod, inc_decl.args, changes, base_ty_env, ty) else type_params = inc_mod.type_params.map {|ty_param| Source.new() } # TODO: better support inc_ty = Type::Instance.new(genv, inc_mod, type_params) end me = inc_ty.mod.get_method(false, mid) changes.add_depended_method_entity(me) if changes if !me.aliases.empty? mid = me.aliases.values.first alias_limit += 1 redo if alias_limit < 5 end if me.exist? found = true yield me, inc_ty, mid else found ||= resolve_included_modules(genv, changes, base_ty_env, inc_ty, mid, &blk) end end found end
resolve_subclasses(genv, changes) { |ty, me| ... }
click to toggle source
# File typeprof-0.30.1/lib/typeprof/core/graph/box.rb, line 835 def resolve_subclasses(genv, changes) # TODO: This does not follow new subclasses @recv.each_type do |ty| next if ty == Type::Bot.new(genv) base_ty = ty.base_type(genv) singleton = base_ty.is_a?(Type::Singleton) mod = base_ty.mod mod.each_descendant do |desc_mod| next if mod == desc_mod me = desc_mod.get_method(singleton, @mid) changes.add_depended_method_entity(me) if me && me.exist? yield ty, me end end end end
run0(genv, changes)
click to toggle source
# File typeprof-0.30.1/lib/typeprof/core/graph/box.rb, line 674 def run0(genv, changes) edges = Set[] called_mdefs = Set[] error_count = 0 resolve(genv, changes) do |me, ty, mid, orig_ty| if !me # TODO: undefined method error if error_count < 3 meth = @node.mid_code_range ? :mid_code_range : :code_range changes.add_diagnostic(meth, "undefined method: #{ orig_ty.show }##{ mid }") end error_count += 1 elsif me.builtin && me.builtin[changes, @node, orig_ty, @a_args, @ret] # do nothing elsif !me.decls.empty? # TODO: support "| ..." me.decls.each do |mdecl| # TODO: union type is ok? # TODO: add_depended_method_entity for types used to resolve overloads ty_env = Type.default_param_map(genv, orig_ty) if ty.is_a?(Type::Instance) ty.mod.type_params.zip(ty.args) do |param, arg| ty_env[param] = arg end end mdecl.resolve_overloads(changes, genv, @node, ty_env, @a_args, @ret) do |method_type| @generics[method_type] ||= method_type.type_params.map {|var| Vertex.new(@node) } end end elsif !me.defs.empty? me.defs.each do |mdef| next if called_mdefs.include?(mdef) called_mdefs << mdef mdef.call(changes, genv, @a_args, @ret) end else pp me raise end end if @subclasses resolve_subclasses(genv, changes) do |recv_ty, me| if !me.defs.empty? me.defs.each do |mdef| next if called_mdefs.include?(mdef) called_mdefs << mdef mdef.call(changes, genv, @a_args, @ret) end end end end edges.each do |src, dst| changes.add_edge(genv, src, dst) end if error_count > 3 meth = @node.mid_code_range ? :mid_code_range : :code_range changes.add_diagnostic(meth, "... and other #{ error_count - 3 } errors") end end