class TypeProf::Core::ModuleEntity - typeprof: Ruby Standard Library Documentation

# 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