class TypeProf::Core::ModuleEntity

Attributes

child_modules[R]
consts[R]
cpath[R]
cvar_reads[R]
cvars[R]
included_modules[R]
inner_modules[R]
ivar_reads[R]
ivars[R]
methods[R]
module_decls[R]
module_defs[R]
outer_module[R]
self_types[R]
static_reads[R]
subclass_checks[R]
superclass[R]
superclass_type_args[R]
type_aliases[R]
type_params[R]

Public Class Methods

new(cpath, outer_module = self) click to toggle source
# File typeprof-0.30.1/lib/typeprof/core/env/module_entity.rb, line 3
def initialize(cpath, outer_module = self)
  @cpath = cpath

  @module_decls = Set[]
  @module_defs = Set[]
  @include_decls = Set[]
  @include_defs = Set[]

  @inner_modules = {}
  @outer_module = outer_module

  # parent modules (superclass and all modules that I include)
  @superclass = nil
  @self_types = {}
  @included_modules = {}
  @basic_object = @cpath == [:BasicObject]

  # child modules (subclasses and all modules that include me)
  @child_modules = {}

  # class Foo[X, Y, Z] < Bar[A, B, C]
  @superclass_type_args = nil # A, B, C
  @type_params = [] # X, Y, Z

  @consts = {}
  @methods = { true => {}, false => {} }
  @ivars = { true => {}, false => {} }
  @cvars = {}
  @type_aliases = {}

  @static_reads = {}
  @subclass_checks = Set[]
  @ivar_reads = Set[] # should be handled in @ivars ??
  @cvar_reads = Set[]
end

Public Instance Methods

add_include_decl(genv, node) click to toggle source
# File typeprof-0.30.1/lib/typeprof/core/env/module_entity.rb, line 175
def add_include_decl(genv, node)
  @include_decls << node
  genv.add_static_eval_queue(:parent_modules_changed, self)
end
add_include_def(genv, node) click to toggle source
# File typeprof-0.30.1/lib/typeprof/core/env/module_entity.rb, line 185
def add_include_def(genv, node)
  @include_defs << node
  genv.add_static_eval_queue(:parent_modules_changed, self)
end
add_module_decl(genv, decl) click to toggle source
# File typeprof-0.30.1/lib/typeprof/core/env/module_entity.rb, line 108
def add_module_decl(genv, decl)
  on_module_added(genv)

  @module_decls << decl

  if @type_params
    update_type_params if @type_params != decl.params
  else
    @type_params = decl.params
  end

  if decl.is_a?(AST::SigClassNode) && !@superclass_type_args
    @superclass_type_args = decl.superclass_args
  end

  ce = @outer_module.get_const(get_cname)
  ce.add_decl(decl)
  ce
end
add_module_def(genv, node) click to toggle source
# File typeprof-0.30.1/lib/typeprof/core/env/module_entity.rb, line 161
def add_module_def(genv, node)
  on_module_added(genv)
  @module_defs << node
  ce = @outer_module.get_const(get_cname)
  ce.add_def(node)
  ce
end
each_descendant(base_mod = nil) { |self| ... } click to toggle source
# File typeprof-0.30.1/lib/typeprof/core/env/module_entity.rb, line 362
def each_descendant(base_mod = nil, &blk)
  return if base_mod == self
  yield self
  @child_modules.each_key do |child_mod|
    child_mod.each_descendant(base_mod || self, &blk)
  end
end
exist?() click to toggle source
# File typeprof-0.30.1/lib/typeprof/core/env/module_entity.rb, line 77
def exist?
  !@module_decls.empty? || !@module_defs.empty?
end
find_superclass_const_read() click to toggle source
# File typeprof-0.30.1/lib/typeprof/core/env/module_entity.rb, line 225
def find_superclass_const_read
  return nil if @basic_object

  if @module_decls.empty?
    @module_defs.each do |mdef|
      case mdef
      when AST::ClassNode
        if mdef.superclass_cpath
          const_read = mdef.superclass_cpath.static_ret
          return const_read ? const_read.cpath : []
        end
      when AST::SingletonClassNode
        next
      when AST::ModuleNode
        return nil
      else
        raise
      end
    end
  else
    @module_decls.each do |mdecl|
      case mdecl
      when AST::SigClassNode
        if mdecl.superclass_cpath
          const_read = mdecl.static_ret[:superclass_cpath].last
          return const_read ? const_read.cpath : []
        end
      when AST::SigModuleNode, AST::SigInterfaceNode
        return nil
      end
    end
  end

  return []
end
get_cname() click to toggle source
# File typeprof-0.30.1/lib/typeprof/core/env/module_entity.rb, line 73
def get_cname
  @cpath.empty? ? :Object : @cpath.last
end
get_const(cname) click to toggle source
# File typeprof-0.30.1/lib/typeprof/core/env/module_entity.rb, line 370
def get_const(cname)
  @consts[cname] ||= ValueEntity.new
end
get_cvar(name) click to toggle source
# File typeprof-0.30.1/lib/typeprof/core/env/module_entity.rb, line 382
def get_cvar(name)
  @cvars[name] ||= ValueEntity.new
end
get_ivar(singleton, name) click to toggle source
# File typeprof-0.30.1/lib/typeprof/core/env/module_entity.rb, line 378
def get_ivar(singleton, name)
  @ivars[singleton][name] ||= ValueEntity.new
end
get_method(singleton, mid) click to toggle source
# File typeprof-0.30.1/lib/typeprof/core/env/module_entity.rb, line 374
def get_method(singleton, mid)
  @methods[singleton][mid] ||= MethodEntity.new
end
get_type_alias(name) click to toggle source
# File typeprof-0.30.1/lib/typeprof/core/env/module_entity.rb, line 386
def get_type_alias(name)
  @type_aliases[name] ||= TypeAliasEntity.new
end
get_vertexes(vtxs) click to toggle source
# File typeprof-0.30.1/lib/typeprof/core/env/module_entity.rb, line 390
def get_vertexes(vtxs)
  @inner_modules.each_value do |mod|
    next if self.equal?(mod) # for Object
    mod.get_vertexes(vtxs)
  end
  @consts.each_value do |cdef|
    vtxs << cdef.vtx
  end
end
interface?() click to toggle source
# File typeprof-0.30.1/lib/typeprof/core/env/module_entity.rb, line 69
def interface?
  @cpath.last && @cpath.last.start_with?("_")
end
module?() click to toggle source
# File typeprof-0.30.1/lib/typeprof/core/env/module_entity.rb, line 65
def module?
  !@superclass && !@basic_object
end
on_ancestors_updated(genv, base_mod) click to toggle source
# File typeprof-0.30.1/lib/typeprof/core/env/module_entity.rb, line 344
def on_ancestors_updated(genv, base_mod)
  @child_modules.each_key {|child_mod| child_mod.on_ancestors_updated(genv, base_mod || self) }
  @static_reads.each_value do |static_reads|
    static_reads.each do |static_read|
      genv.add_static_eval_queue(:static_read_changed, static_read)
    end
  end
  @methods.each do |_, methods|
    methods.each_value do |me|
      me.method_call_boxes.each do |box|
        genv.add_run(box)
      end
    end
  end
  @ivar_reads.each {|ivar_read| genv.add_run(ivar_read) }
  @cvar_reads.each {|cvar_read| genv.add_run(cvar_read) }
end
on_inner_modules_changed(genv, changed_cname) click to toggle source
# File typeprof-0.30.1/lib/typeprof/core/env/module_entity.rb, line 81
def on_inner_modules_changed(genv, changed_cname)
  @child_modules.each_key do |child_mod|
    child_mod.on_inner_modules_changed(genv, changed_cname)
  end
  if @static_reads[changed_cname]
    @static_reads[changed_cname].each do |static_read|
      genv.add_static_eval_queue(:static_read_changed, static_read)
    end
  end
end
on_module_added(genv) click to toggle source
# File typeprof-0.30.1/lib/typeprof/core/env/module_entity.rb, line 92
def on_module_added(genv)
  return if @cpath.empty?
  unless exist?
    genv.add_static_eval_queue(:inner_modules_changed, [@outer_module, get_cname])
  end
  genv.add_static_eval_queue(:parent_modules_changed, self)
end
on_module_removed(genv) click to toggle source
# File typeprof-0.30.1/lib/typeprof/core/env/module_entity.rb, line 100
def on_module_removed(genv)
  return if @cpath.empty?
  genv.add_static_eval_queue(:parent_modules_changed, self)
  unless exist?
    genv.add_static_eval_queue(:inner_modules_changed, [@outer_module, get_cname])
  end
end
on_parent_modules_changed(genv) click to toggle source
# File typeprof-0.30.1/lib/typeprof/core/env/module_entity.rb, line 261
def on_parent_modules_changed(genv)
  any_updated = false

  unless @basic_object
    new_superclass_cpath = find_superclass_const_read

    new_superclass, updated = update_parent(genv, :superclass, @superclass, new_superclass_cpath)
    if updated
      @superclass = new_superclass
      any_updated = true
    end
  end

  @module_decls.each do |mdecl|
    case mdecl
    when AST::SigModuleNode
      mdecl.static_ret[:self_types].each_with_index do |const_reads, i|
        key = [mdecl, i]
        new_parent_cpath = const_reads.last.cpath
        new_self_type, updated = update_parent(genv, key, @self_types[key], new_parent_cpath)
        if updated
          if new_self_type
            @self_types[key] = new_self_type
          else
            @self_types.delete(key) || raise
          end
          any_updated = true
        end
      end
    end
  end
  @self_types.delete_if do |(origin_mdecl, origin_idx), old_mod|
    if @module_decls.include?(origin_mdecl)
      false
    else
      _new_self_type, updated = update_parent(genv, [origin_mdecl, origin_idx], old_mod, nil)
      any_updated ||= updated
      true
    end
  end

  @include_decls.each do |idecl|
    new_parent_cpath = idecl.static_ret.last.cpath
    new_parent, updated = update_parent(genv, idecl, @included_modules[idecl], new_parent_cpath)
    if updated
      if new_parent
        @included_modules[idecl] = new_parent
      else
        @included_modules.delete(idecl) || raise
      end
      any_updated = true
    end
  end
  @include_defs.each do |idef|
    new_parent_cpath = idef.static_ret ? idef.static_ret.cpath : nil
    new_parent, updated = update_parent(genv, idef, @included_modules[idef], new_parent_cpath)
    if updated
      if new_parent
        @included_modules[idef] = new_parent
      else
        @included_modules.delete(idef) || raise
      end
      any_updated = true
    end
  end
  @included_modules.delete_if do |origin, old_mod|
    if @include_decls.include?(origin) || @include_defs.include?(origin)
      false
    else
      _new_parent, updated = update_parent(genv, origin, old_mod, nil)
      any_updated ||= updated
      true
    end
  end

  if any_updated
    @subclass_checks.each do |mcall_box|
      genv.add_run(mcall_box)
    end
    on_ancestors_updated(genv, nil)
  end
end
pretty_print(q) click to toggle source
# File typeprof-0.30.1/lib/typeprof/core/env/module_entity.rb, line 404
def pretty_print(q)
  q.text "#<ModuleEntity[::#{ @cpath.empty? ? "Object" : @cpath.join("::") }]>"
end
remove_include_decl(genv, node) click to toggle source
# File typeprof-0.30.1/lib/typeprof/core/env/module_entity.rb, line 180
def remove_include_decl(genv, node)
  @include_decls.delete(node) || raise
  genv.add_static_eval_queue(:parent_modules_changed, self)
end
remove_include_def(genv, node) click to toggle source
# File typeprof-0.30.1/lib/typeprof/core/env/module_entity.rb, line 190
def remove_include_def(genv, node)
  @include_defs.delete(node) || raise
  genv.add_static_eval_queue(:parent_modules_changed, self)
end
remove_module_decl(genv, decl) click to toggle source
# File typeprof-0.30.1/lib/typeprof/core/env/module_entity.rb, line 128
def remove_module_decl(genv, decl)
  @outer_module.get_const(get_cname).remove_decl(decl)
  @module_decls.delete(decl) || raise

  update_type_params if @type_params == decl.params
  if decl.is_a?(AST::SigClassNode) && @superclass_type_args == decl.superclass_args
    @superclass_type_args = nil
    @module_decls.each do |decl|
      if decl.superclass_args
        @superclass_type_args = decl.superclass_args
        break
      end
    end
  end

  on_module_removed(genv)
end
remove_module_def(genv, node) click to toggle source
# File typeprof-0.30.1/lib/typeprof/core/env/module_entity.rb, line 169
def remove_module_def(genv, node)
  @outer_module.get_const(get_cname).remove_def(node)
  @module_defs.delete(node) || raise
  on_module_removed(genv)
end
show_cpath() click to toggle source
# File typeprof-0.30.1/lib/typeprof/core/env/module_entity.rb, line 400
def show_cpath
  @cpath.empty? ? "Object" : @cpath.join("::" )
end
update_parent(genv, origin, old_parent, new_parent_cpath) click to toggle source
# File typeprof-0.30.1/lib/typeprof/core/env/module_entity.rb, line 195
def update_parent(genv, origin, old_parent, new_parent_cpath)
  new_parent = new_parent_cpath ? genv.resolve_cpath(new_parent_cpath) : nil
  if old_parent != new_parent
    # check circular inheritance
    mod = new_parent
    while mod
      if mod == self
        # TODO: report an "circular inheritance" error
        new_parent = nil
        break
      end
      mod = mod.superclass
    end

    if old_parent != new_parent
      if old_parent
        set = old_parent.child_modules[self]
        set.delete(origin)
        old_parent.child_modules.delete(self) if set.empty?
      end
      if new_parent
        set = new_parent.child_modules[self] ||= Set[]
        set << origin
      end
      return [new_parent, true]
    end
  end
  return [new_parent, false]
end
update_type_params() click to toggle source
# File typeprof-0.30.1/lib/typeprof/core/env/module_entity.rb, line 146
def update_type_params
  @type_params = nil
  @module_decls.each do |decl|
    params = decl.params
    next unless params
    if @type_params
      @type_params = params if (@type_params <=> params) > 0
    else
      @type_params = params
    end
  end
  @type_params ||= []
  # TODO: report an error if there are multiple inconsistent declarations
end