class ReplTypeCompletor::Types::SingletonType - repl_type_completor: Ruby Standard Library Documentation

# class ReplTypeCompletor::Types::SingletonType

### Attributes

module_or_class[R]

### Public Class Methods

new(module_or_class) click to toggle source

    # File repl_type_completor-0.1.9/lib/repl_type_completor/types.rb, line 182
    def initialize(module_or_class)
      @module_or_class = module_or_class
    end

### Public Instance Methods

all_methods() click to toggle source

    # File repl_type_completor-0.1.9/lib/repl_type_completor/types.rb, line 187
      def all_methods() = methods | @module_or_class.private_methods
      def constants() = @module_or_class.constants
      def types() = [self]
      def nillable?() = false
      def nonnillable() = self
      def inspect
        "#{module_or_class}.itself"
      end
    end

    class InstanceType
      attr_reader :klass, :params
      def initialize(klass, params = {})
        @klass = klass
        @params = params
      end
      def transform() = yield(self)
      def methods() = rbs_methods.select { _2.public? }.keys | @klass.instance_methods
      def all_methods() = rbs_methods.keys | @klass.instance_methods | @klass.private_instance_methods
      def constants() = []
      def types() = [self]
      def nillable?() = (@klass == NilClass)
      def nonnillable() = self
      def rbs_methods
        name = Types.class_name_of(@klass)
        return {} unless name && Types.rbs_builder

        type_name = RBS::TypeName(name).absolute!
        Types.rbs_builder.build_instance(type_name).methods rescue {}
      end
      def inspect
        if params.empty?
          inspect_without_params
        else
          params_string = "[#{params.map { "#{_1}: #{_2.inspect}" }.join(', ')}]"
          "#{inspect_without_params}#{params_string}"
        end
      end
      def inspect_without_params
        if klass == NilClass
          'nil'
        elsif klass == TrueClass
          'true'
        elsif klass == FalseClass
          'false'
        else
          klass.singleton_class? ? klass.superclass.to_s : klass.to_s
        end
      end
    end

    NIL = InstanceType.new NilClass
    OBJECT = InstanceType.new Object
    TRUE = InstanceType.new TrueClass
    FALSE = InstanceType.new FalseClass
    SYMBOL = InstanceType.new Symbol
    STRING = InstanceType.new String
    INTEGER = InstanceType.new Integer
    RANGE = InstanceType.new Range
    REGEXP = InstanceType.new Regexp
    FLOAT = InstanceType.new Float
    RATIONAL = InstanceType.new Rational
    COMPLEX = InstanceType.new Complex
    ARRAY = InstanceType.new Array
    HASH = InstanceType.new Hash
    CLASS = InstanceType.new Class
    MODULE = InstanceType.new Module
    PROC = InstanceType.new Proc

    class UnionType
      attr_reader :types

      def initialize(*types)
        @types = []
        singletons = []
        instances = {}
        collect = -> type do
          case type
          in UnionType
            type.types.each(&collect)
          in InstanceType
            params = (instances[type.klass] ||= {})
            type.params.each do |k, v|
              (params[k] ||= []) << v
            end
          in SingletonType
            singletons << type
          end
        end
        types.each(&collect)
        @types = singletons.uniq + instances.map do |klass, params|
          InstanceType.new(klass, params.transform_values { |v| UnionType[*v] })
        end
      end

      def transform(&block)
        UnionType[*types.map(&block)]
      end

      def nillable?
        types.any?(&:nillable?)
      end

      def nonnillable
        UnionType[*types.reject { _1.is_a?(InstanceType) && _1.klass == NilClass }]
      end

      def self.[](*types)
        type = new(*types)
        if type.types.empty?
          OBJECT
        elsif type.types.size == 1
          type.types.first
        else
          type
        end
      end

      def methods() = @types.flat_map(&:methods).uniq
      def all_methods() = @types.flat_map(&:all_methods).uniq
      def constants() = @types.flat_map(&:constants).uniq
      def inspect() = @types.map(&:inspect).join(' | ')
    end

    BOOLEAN = UnionType[TRUE, FALSE]

    def self.array_of(*types)
      type = types.size >= 2 ? UnionType[*types] : types.first || OBJECT
      InstanceType.new Array, Elem: type
    end

    def self.from_rbs_type(return_type, self_type, extra_vars = {})
      case return_type
      when RBS::Types::Bases::Self
        self_type
      when RBS::Types::Bases::Bottom, RBS::Types::Bases::Nil
        NIL
      when RBS::Types::Bases::Any, RBS::Types::Bases::Void
        OBJECT
      when RBS::Types::Bases::Class
        self_type.transform do |type|
          case type
          in SingletonType
            InstanceType.new(self_type.module_or_class.is_a?(Class) ? Class : Module)
          in InstanceType
            SingletonType.new type.klass
          end
        end
        UnionType[*types]
      when RBS::Types::Bases::Bool
        BOOLEAN
      when RBS::Types::Bases::Instance
        self_type.transform do |type|
          if type.is_a?(SingletonType) && type.module_or_class.is_a?(Class)
            InstanceType.new type.module_or_class
          elsif type.is_a?(InstanceType)
            InstanceType.new type.klass
          else
            OBJECT
          end
        end
      when RBS::Types::Union
        UnionType[*return_type.types.map { from_rbs_type _1, self_type, extra_vars }]
      when RBS::Types::Proc
        PROC
      when RBS::Types::Tuple
        elem = UnionType[*return_type.types.map { from_rbs_type _1, self_type, extra_vars }]
        InstanceType.new Array, Elem: elem
      when RBS::Types::Record
        InstanceType.new Hash, K: SYMBOL, V: OBJECT
      when RBS::Types::Literal
        InstanceType.new return_type.literal.class
      when RBS::Types::Variable
        if extra_vars.key? return_type.name
          extra_vars[return_type.name]
        elsif self_type.is_a? InstanceType
          self_type.params[return_type.name] || OBJECT
        elsif self_type.is_a? UnionType
          types = self_type.types.filter_map do |t|
            t.params[return_type.name] if t.is_a? InstanceType
          end
          UnionType[*types]
        else
          OBJECT
        end
      when RBS::Types::Optional
        UnionType[from_rbs_type(return_type.type, self_type, extra_vars), NIL]
      when RBS::Types::Alias
        case return_type.name.name
        when :int
          INTEGER
        when :boolish
          BOOLEAN
        when :string
          STRING
        else
          # TODO: ???
          OBJECT
        end
      when RBS::Types::Interface
        # unimplemented
        OBJECT
      when RBS::Types::ClassInstance
        klass = return_type.name.to_namespace.path.reduce(Object) { _1.const_get _2 }
        if return_type.args
          args = return_type.args.map { from_rbs_type _1, self_type, extra_vars }
          names = rbs_builder.build_singleton(return_type.name).type_params
          params = names.map.with_index { [_1, args[_2] || OBJECT] }.to_h
        end
        InstanceType.new klass, params || {}
      end
    end

    def self.method_return_bottom?(method)
      method.type.return_type.is_a? RBS::Types::Bases::Bottom
    end

    def self.match_free_variables(vars, types, values)
      accumulator = {}
      types.zip values do |t, v|
        _match_free_variable(vars, t, v, accumulator) if v
      end
      accumulator.transform_values { UnionType[*_1] }
    end

    def self._match_free_variable(vars, rbs_type, value, accumulator)
      case [rbs_type, value]
      in [RBS::Types::Variable,]
        (accumulator[rbs_type.name] ||= []) << value if vars.include? rbs_type.name
      in [RBS::Types::ClassInstance, InstanceType]
        names = rbs_builder.build_singleton(rbs_type.name).type_params
        names.zip(rbs_type.args).each do |name, arg|
          v = value.params[name]
          _match_free_variable vars, arg, v, accumulator if v
        end
      in [RBS::Types::Tuple, InstanceType] if value.klass == Array
        v = value.params[:Elem]
        rbs_type.types.each do |t|
          _match_free_variable vars, t, v, accumulator
        end
      in [RBS::Types::Record, InstanceType] if value.klass == Hash
        # TODO
      in [RBS::Types::Interface,]
        definition = rbs_builder.build_interface rbs_type.name
        convert = {}
        definition.type_params.zip(rbs_type.args).each do |from, arg|
          convert[from] = arg.name if arg.is_a? RBS::Types::Variable
        end
        return if convert.empty?
        ac = {}
        definition.methods.each do |method_name, method|
          return_type = method_return_type value, method_name
          method.defs.each do |method_def|
            interface_return_type = method_def.type.type.return_type
            _match_free_variable convert, interface_return_type, return_type, ac
          end
        end
        convert.each do |from, to|
          values = ac[from]
          (accumulator[to] ||= []

constants() click to toggle source

    # File repl_type_completor-0.1.9/lib/repl_type_completor/types.rb, line 188
      def constants() = @module_or_class.constants
      def types() = [self]
      def nillable?() = false
      def nonnillable() = self
      def inspect
        "#{module_or_class}.itself"
      end
    end

    class InstanceType
      attr_reader :klass, :params
      def initialize(klass, params = {})
        @klass = klass
        @params = params
      end
      def transform() = yield(self)
      def methods() = rbs_methods.select { _2.public? }.keys | @klass.instance_methods
      def all_methods() = rbs_methods.keys | @klass.instance_methods | @klass.private_instance_methods
      def constants() = []
      def types() = [self]
      def nillable?() = (@klass == NilClass)
      def nonnillable() = self
      def rbs_methods
        name = Types.class_name_of(@klass)
        return {} unless name && Types.rbs_builder

        type_name = RBS::TypeName(name).absolute!
        Types.rbs_builder.build_instance(type_name).methods rescue {}
      end
      def inspect
        if params.empty?
          inspect_without_params
        else
          params_string = "[#{params.map { "#{_1}: #{_2.inspect}" }.join(', ')}]"
          "#{inspect_without_params}#{params_string}"
        end
      end
      def inspect_without_params
        if klass == NilClass
          'nil'
        elsif klass == TrueClass
          'true'
        elsif klass == FalseClass
          'false'
        else
          klass.singleton_class? ? klass.superclass.to_s : klass.to_s
        end
      end
    end

    NIL = InstanceType.new NilClass
    OBJECT = InstanceType.new Object
    TRUE = InstanceType.new TrueClass
    FALSE = InstanceType.new FalseClass
    SYMBOL = InstanceType.new Symbol
    STRING = InstanceType.new String
    INTEGER = InstanceType.new Integer
    RANGE = InstanceType.new Range
    REGEXP = InstanceType.new Regexp
    FLOAT = InstanceType.new Float
    RATIONAL = InstanceType.new Rational
    COMPLEX = InstanceType.new Complex
    ARRAY = InstanceType.new Array
    HASH = InstanceType.new Hash
    CLASS = InstanceType.new Class
    MODULE = InstanceType.new Module
    PROC = InstanceType.new Proc

    class UnionType
      attr_reader :types

      def initialize(*types)
        @types = []
        singletons = []
        instances = {}
        collect = -> type do
          case type
          in UnionType
            type.types.each(&collect)
          in InstanceType
            params = (instances[type.klass] ||= {})
            type.params.each do |k, v|
              (params[k] ||= []) << v
            end
          in SingletonType
            singletons << type
          end
        end
        types.each(&collect)
        @types = singletons.uniq + instances.map do |klass, params|
          InstanceType.new(klass, params.transform_values { |v| UnionType[*v] })
        end
      end

      def transform(&block)
        UnionType[*types.map(&block)]
      end

      def nillable?
        types.any?(&:nillable?)
      end

      def nonnillable
        UnionType[*types.reject { _1.is_a?(InstanceType) && _1.klass == NilClass }]
      end

      def self.[](*types)
        type = new(*types)
        if type.types.empty?
          OBJECT
        elsif type.types.size == 1
          type.types.first
        else
          type
        end
      end

      def methods() = @types.flat_map(&:methods).uniq
      def all_methods() = @types.flat_map(&:all_methods).uniq
      def constants() = @types.flat_map(&:constants).uniq
      def inspect() = @types.map(&:inspect).join(' | ')
    end

    BOOLEAN = UnionType[TRUE, FALSE]

    def self.array_of(*types)
      type = types.size >= 2 ? UnionType[*types] : types.first || OBJECT
      InstanceType.new Array, Elem: type
    end

    def self.from_rbs_type(return_type, self_type, extra_vars = {})
      case return_type
      when RBS::Types::Bases::Self
        self_type
      when RBS::Types::Bases::Bottom, RBS::Types::Bases::Nil
        NIL
      when RBS::Types::Bases::Any, RBS::Types::Bases::Void
        OBJECT
      when RBS::Types::Bases::Class
        self_type.transform do |type|
          case type
          in SingletonType
            InstanceType.new(self_type.module_or_class.is_a?(Class) ? Class : Module)
          in InstanceType
            SingletonType.new type.klass
          end
        end
        UnionType[*types]
      when RBS::Types::Bases::Bool
        BOOLEAN
      when RBS::Types::Bases::Instance
        self_type.transform do |type|
          if type.is_a?(SingletonType) && type.module_or_class.is_a?(Class)
            InstanceType.new type.module_or_class
          elsif type.is_a?(InstanceType)
            InstanceType.new type.klass
          else
            OBJECT
          end
        end
      when RBS::Types::Union
        UnionType[*return_type.types.map { from_rbs_type _1, self_type, extra_vars }]
      when RBS::Types::Proc
        PROC
      when RBS::Types::Tuple
        elem = UnionType[*return_type.types.map { from_rbs_type _1, self_type, extra_vars }]
        InstanceType.new Array, Elem: elem
      when RBS::Types::Record
        InstanceType.new Hash, K: SYMBOL, V: OBJECT
      when RBS::Types::Literal
        InstanceType.new return_type.literal.class
      when RBS::Types::Variable
        if extra_vars.key? return_type.name
          extra_vars[return_type.name]
        elsif self_type.is_a? InstanceType
          self_type.params[return_type.name] || OBJECT
        elsif self_type.is_a? UnionType
          types = self_type.types.filter_map do |t|
            t.params[return_type.name] if t.is_a? InstanceType
          end
          UnionType[*types]
        else
          OBJECT
        end
      when RBS::Types::Optional
        UnionType[from_rbs_type(return_type.type, self_type, extra_vars), NIL]
      when RBS::Types::Alias
        case return_type.name.name
        when :int
          INTEGER
        when :boolish
          BOOLEAN
        when :string
          STRING
        else
          # TODO: ???
          OBJECT
        end
      when RBS::Types::Interface
        # unimplemented
        OBJECT
      when RBS::Types::ClassInstance
        klass = return_type.name.to_namespace.path.reduce(Object) { _1.const_get _2 }
        if return_type.args
          args = return_type.args.map { from_rbs_type _1, self_type, extra_vars }
          names = rbs_builder.build_singleton(return_type.name).type_params
          params = names.map.with_index { [_1, args[_2] || OBJECT] }.to_h
        end
        InstanceType.new klass, params || {}
      end
    end

    def self.method_return_bottom?(method)
      method.type.return_type.is_a? RBS::Types::Bases::Bottom
    end

    def self.match_free_variables(vars, types, values)
      accumulator = {}
      types.zip values do |t, v|
        _match_free_variable(vars, t, v, accumulator) if v
      end
      accumulator.transform_values { UnionType[*_1] }
    end

    def self._match_free_variable(vars, rbs_type, value, accumulator)
      case [rbs_type, value]
      in [RBS::Types::Variable,]
        (accumulator[rbs_type.name] ||= []) << value if vars.include? rbs_type.name
      in [RBS::Types::ClassInstance, InstanceType]
        names = rbs_builder.build_singleton(rbs_type.name).type_params
        names.zip(rbs_type.args).each do |name, arg|
          v = value.params[name]
          _match_free_variable vars, arg, v, accumulator if v
        end
      in [RBS::Types::Tuple, InstanceType] if value.klass == Array
        v = value.params[:Elem]
        rbs_type.types.each do |t|
          _match_free_variable vars, t, v, accumulator
        end
      in [RBS::Types::Record, InstanceType] if value.klass == Hash
        # TODO
      in [RBS::Types::Interface,]
        definition = rbs_builder.build_interface rbs_type.name
        convert = {}
        definition.type_params.zip(rbs_type.args).each do |from, arg|
          convert[from] = arg.name if arg.is_a? RBS::Types::Variable
        end
        return if convert.empty?
        ac = {}
        definition.methods.each do |method_name, method|
          return_type = method_return_type value, method_name
          method.defs.each do |method_def|
            interface_return_type = method_def.type.type.return_type
            _match_free_variable convert, interface_return_type, return_type, ac
          end
        end
        convert.each do |from, to|
          values = ac[from]
          (accumulator[to] ||= []).

inspect() click to toggle source

    # File repl_type_completor-0.1.9/lib/repl_type_completor/types.rb, line 192
    def inspect
      "#{module_or_class}.itself"
    end

methods() click to toggle source

    # File repl_type_completor-0.1.9/lib/repl_type_completor/types.rb, line 186
      def methods() = @module_or_class.methods
      def all_methods() = methods | @module_or_class.private_methods
      def constants() = @module_or_class.constants
      def types() = [self]
      def nillable?() = false
      def nonnillable() = self
      def inspect
        "#{module_or_class}.itself"
      end
    end

    class InstanceType
      attr_reader :klass, :params
      def initialize(klass, params = {})
        @klass = klass
        @params = params
      end
      def transform() = yield(self)
      def methods() = rbs_methods.select { _2.public? }.keys | @klass.instance_methods
      def all_methods() = rbs_methods.keys | @klass.instance_methods | @klass.private_instance_methods
      def constants() = []
      def types() = [self]
      def nillable?() = (@klass == NilClass)
      def nonnillable() = self
      def rbs_methods
        name = Types.class_name_of(@klass)
        return {} unless name && Types.rbs_builder

        type_name = RBS::TypeName(name).absolute!
        Types.rbs_builder.build_instance(type_name).methods rescue {}
      end
      def inspect
        if params.empty?
          inspect_without_params
        else
          params_string = "[#{params.map { "#{_1}: #{_2.inspect}" }.join(', ')}]"
          "#{inspect_without_params}#{params_string}"
        end
      end
      def inspect_without_params
        if klass == NilClass
          'nil'
        elsif klass == TrueClass
          'true'
        elsif klass == FalseClass
          'false'
        else
          klass.singleton_class? ? klass.superclass.to_s : klass.to_s
        end
      end
    end

    NIL = InstanceType.new NilClass
    OBJECT = InstanceType.new Object
    TRUE = InstanceType.new TrueClass
    FALSE = InstanceType.new FalseClass
    SYMBOL = InstanceType.new Symbol
    STRING = InstanceType.new String
    INTEGER = InstanceType.new Integer
    RANGE = InstanceType.new Range
    REGEXP = InstanceType.new Regexp
    FLOAT = InstanceType.new Float
    RATIONAL = InstanceType.new Rational
    COMPLEX = InstanceType.new Complex
    ARRAY = InstanceType.new Array
    HASH = InstanceType.new Hash
    CLASS = InstanceType.new Class
    MODULE = InstanceType.new Module
    PROC = InstanceType.new Proc

    class UnionType
      attr_reader :types

      def initialize(*types)
        @types = []
        singletons = []
        instances = {}
        collect = -> type do
          case type
          in UnionType
            type.types.each(&collect)
          in InstanceType
            params = (instances[type.klass] ||= {})
            type.params.each do |k, v|
              (params[k] ||= []) << v
            end
          in SingletonType
            singletons << type
          end
        end
        types.each(&collect)
        @types = singletons.uniq + instances.map do |klass, params|
          InstanceType.new(klass, params.transform_values { |v| UnionType[*v] })
        end
      end

      def transform(&block)
        UnionType[*types.map(&block)]
      end

      def nillable?
        types.any?(&:nillable?)
      end

      def nonnillable
        UnionType[*types.reject { _1.is_a?(InstanceType) && _1.klass == NilClass }]
      end

      def self.[](*types)
        type = new(*types)
        if type.types.empty?
          OBJECT
        elsif type.types.size == 1
          type.types.first
        else
          type
        end
      end

      def methods() = @types.flat_map(&:methods).uniq
      def all_methods() = @types.flat_map(&:all_methods).uniq
      def constants() = @types.flat_map(&:constants).uniq
      def inspect() = @types.map(&:inspect).join(' | ')
    end

    BOOLEAN = UnionType[TRUE, FALSE]

    def self.array_of(*types)
      type = types.size >= 2 ? UnionType[*types] : types.first || OBJECT
      InstanceType.new Array, Elem: type
    end

    def self.from_rbs_type(return_type, self_type, extra_vars = {})
      case return_type
      when RBS::Types::Bases::Self
        self_type
      when RBS::Types::Bases::Bottom, RBS::Types::Bases::Nil
        NIL
      when RBS::Types::Bases::Any, RBS::Types::Bases::Void
        OBJECT
      when RBS::Types::Bases::Class
        self_type.transform do |type|
          case type
          in SingletonType
            InstanceType.new(self_type.module_or_class.is_a?(Class) ? Class : Module)
          in InstanceType
            SingletonType.new type.klass
          end
        end
        UnionType[*types]
      when RBS::Types::Bases::Bool
        BOOLEAN
      when RBS::Types::Bases::Instance
        self_type.transform do |type|
          if type.is_a?(SingletonType) && type.module_or_class.is_a?(Class)
            InstanceType.new type.module_or_class
          elsif type.is_a?(InstanceType)
            InstanceType.new type.klass
          else
            OBJECT
          end
        end
      when RBS::Types::Union
        UnionType[*return_type.types.map { from_rbs_type _1, self_type, extra_vars }]
      when RBS::Types::Proc
        PROC
      when RBS::Types::Tuple
        elem = UnionType[*return_type.types.map { from_rbs_type _1, self_type, extra_vars }]
        InstanceType.new Array, Elem: elem
      when RBS::Types::Record
        InstanceType.new Hash, K: SYMBOL, V: OBJECT
      when RBS::Types::Literal
        InstanceType.new return_type.literal.class
      when RBS::Types::Variable
        if extra_vars.key? return_type.name
          extra_vars[return_type.name]
        elsif self_type.is_a? InstanceType
          self_type.params[return_type.name] || OBJECT
        elsif self_type.is_a? UnionType
          types = self_type.types.filter_map do |t|
            t.params[return_type.name] if t.is_a? InstanceType
          end
          UnionType[*types]
        else
          OBJECT
        end
      when RBS::Types::Optional
        UnionType[from_rbs_type(return_type.type, self_type, extra_vars), NIL]
      when RBS::Types::Alias
        case return_type.name.name
        when :int
          INTEGER
        when :boolish
          BOOLEAN
        when :string
          STRING
        else
          # TODO: ???
          OBJECT
        end
      when RBS::Types::Interface
        # unimplemented
        OBJECT
      when RBS::Types::ClassInstance
        klass = return_type.name.to_namespace.path.reduce(Object) { _1.const_get _2 }
        if return_type.args
          args = return_type.args.map { from_rbs_type _1, self_type, extra_vars }
          names = rbs_builder.build_singleton(return_type.name).type_params
          params = names.map.with_index { [_1, args[_2] || OBJECT] }.to_h
        end
        InstanceType.new klass, params || {}
      end
    end

    def self.method_return_bottom?(method)
      method.type.return_type.is_a? RBS::Types::Bases::Bottom
    end

    def self.match_free_variables(vars, types, values)
      accumulator = {}
      types.zip values do |t, v|
        _match_free_variable(vars, t, v, accumulator) if v
      end
      accumulator.transform_values { UnionType[*_1] }
    end

    def self._match_free_variable(vars, rbs_type, value, accumulator)
      case [rbs_type, value]
      in [RBS::Types::Variable,]
        (accumulator[rbs_type.name] ||= []) << value if vars.include? rbs_type.name
      in [RBS::Types::ClassInstance, InstanceType]
        names = rbs_builder.build_singleton(rbs_type.name).type_params
        names.zip(rbs_type.args).each do |name, arg|
          v = value.params[name]
          _match_free_variable vars, arg, v, accumulator if v
        end
      in [RBS::Types::Tuple, InstanceType] if value.klass == Array
        v = value.params[:Elem]
        rbs_type.types.each do |t|
          _match_free_variable vars, t, v, accumulator
        end
      in [RBS::Types::Record, InstanceType] if value.klass == Hash
        # TODO
      in [RBS::Types::Interface,]
        definition = rbs_builder.build_interface rbs_type.name
        convert = {}
        definition.type_params.zip(rbs_type.args).each do |from, arg|
          convert[from] = arg.name if arg.is_a? RBS::Types::Variable
        end
        return if convert.empty?
        ac = {}
        definition.methods.each do |method_name, method|
          return_type = method_return_type value, method_name
          method.defs.each do |method_def|
            interface_return_type = method_def.type.type.return_type
            _match_free_variable convert, interface_return_type, return_type, ac
          end
        end
        convert.each do |from, to|
          values = ac[from]
          (accumulator[to] ||=

nillable?() click to toggle source

    # File repl_type_completor-0.1.9/lib/repl_type_completor/types.rb, line 190
      def nillable?() = false
      def nonnillable() = self
      def inspect
        "#{module_or_class}.itself"
      end
    end

    class InstanceType
      attr_reader :klass, :params
      def initialize(klass, params = {})
        @klass = klass
        @params = params
      end
      def transform() = yield(self)
      def methods() = rbs_methods.select { _2.public? }.keys | @klass.instance_methods
      def all_methods() = rbs_methods.keys | @klass.instance_methods | @klass.private_instance_methods
      def constants() = []
      def types() = [self]
      def nillable?() = (@klass == NilClass)
      def nonnillable() = self
      def rbs_methods
        name = Types.class_name_of(@klass)
        return {} unless name && Types.rbs_builder

        type_name = RBS::TypeName(name).absolute!
        Types.rbs_builder.build_instance(type_name).methods rescue {}
      end
      def inspect
        if params.empty?
          inspect_without_params
        else
          params_string = "[#{params.map { "#{_1}: #{_2.inspect}" }.join(', ')}]"
          "#{inspect_without_params}#{params_string}"
        end
      end
      def inspect_without_params
        if klass == NilClass
          'nil'
        elsif klass == TrueClass
          'true'
        elsif klass == FalseClass
          'false'
        else
          klass.singleton_class? ? klass.superclass.to_s : klass.to_s
        end
      end
    end

    NIL = InstanceType.new NilClass
    OBJECT = InstanceType.new Object
    TRUE = InstanceType.new TrueClass
    FALSE = InstanceType.new FalseClass
    SYMBOL = InstanceType.new Symbol
    STRING = InstanceType.new String
    INTEGER = InstanceType.new Integer
    RANGE = InstanceType.new Range
    REGEXP = InstanceType.new Regexp
    FLOAT = InstanceType.new Float
    RATIONAL = InstanceType.new Rational
    COMPLEX = InstanceType.new Complex
    ARRAY = InstanceType.new Array
    HASH = InstanceType.new Hash
    CLASS = InstanceType.new Class
    MODULE = InstanceType.new Module
    PROC = InstanceType.new Proc

    class UnionType
      attr_reader :types

      def initialize(*types)
        @types = []
        singletons = []
        instances = {}
        collect = -> type do
          case type
          in UnionType
            type.types.each(&collect)
          in InstanceType
            params = (instances[type.klass] ||= {})
            type.params.each do |k, v|
              (params[k] ||= []) << v
            end
          in SingletonType
            singletons << type
          end
        end
        types.each(&collect)
        @types = singletons.uniq + instances.map do |klass, params|
          InstanceType.new(klass, params.transform_values { |v| UnionType[*v] })
        end
      end

      def transform(&block)
        UnionType[*types.map(&block)]
      end

      def nillable?
        types.any?(&:nillable?)
      end

      def nonnillable
        UnionType[*types.reject { _1.is_a?(InstanceType) && _1.klass == NilClass }]
      end

      def self.[](*types)
        type = new(*types)
        if type.types.empty?
          OBJECT
        elsif type.types.size == 1
          type.types.first
        else
          type
        end
      end

      def methods() = @types.flat_map(&:methods).uniq
      def all_methods() = @types.flat_map(&:all_methods).uniq
      def constants() = @types.flat_map(&:constants).uniq
      def inspect() = @types.map(&:inspect).join(' | ')
    end

    BOOLEAN = UnionType[TRUE, FALSE]

    def self.array_of(*types)
      type = types.size >= 2 ? UnionType[*types] : types.first || OBJECT
      InstanceType.new Array, Elem: type
    end

    def self.from_rbs_type(return_type, self_type, extra_vars = {})
      case return_type
      when RBS::Types::Bases::Self
        self_type
      when RBS::Types::Bases::Bottom, RBS::Types::Bases::Nil
        NIL
      when RBS::Types::Bases::Any, RBS::Types::Bases::Void
        OBJECT
      when RBS::Types::Bases::Class
        self_type.transform do |type|
          case type
          in SingletonType
            InstanceType.new(self_type.module_or_class.is_a?(Class) ? Class : Module)
          in InstanceType
            SingletonType.new type.klass
          end
        end
        UnionType[*types]
      when RBS::Types::Bases::Bool
        BOOLEAN
      when RBS::Types::Bases::Instance
        self_type.transform do |type|
          if type.is_a?(SingletonType) && type.module_or_class.is_a?(Class)
            InstanceType.new type.module_or_class
          elsif type.is_a?(InstanceType)
            InstanceType.new type.klass
          else
            OBJECT
          end
        end
      when RBS::Types::Union
        UnionType[*return_type.types.map { from_rbs_type _1, self_type, extra_vars }]
      when RBS::Types::Proc
        PROC
      when RBS::Types::Tuple
        elem = UnionType[*return_type.types.map { from_rbs_type _1, self_type, extra_vars }]
        InstanceType.new Array, Elem: elem
      when RBS::Types::Record
        InstanceType.new Hash, K: SYMBOL, V: OBJECT
      when RBS::Types::Literal
        InstanceType.new return_type.literal.class
      when RBS::Types::Variable
        if extra_vars.key? return_type.name
          extra_vars[return_type.name]
        elsif self_type.is_a? InstanceType
          self_type.params[return_type.name] || OBJECT
        elsif self_type.is_a? UnionType
          types = self_type.types.filter_map do |t|
            t.params[return_type.name] if t.is_a? InstanceType
          end
          UnionType[*types]
        else
          OBJECT
        end
      when RBS::Types::Optional
        UnionType[from_rbs_type(return_type.type, self_type, extra_vars), NIL]
      when RBS::Types::Alias
        case return_type.name.name
        when :int
          INTEGER
        when :boolish
          BOOLEAN
        when :string
          STRING
        else
          # TODO: ???
          OBJECT
        end
      when RBS::Types::Interface
        # unimplemented
        OBJECT
      when RBS::Types::ClassInstance
        klass = return_type.name.to_namespace.path.reduce(Object) { _1.const_get _2 }
        if return_type.args
          args = return_type.args.map { from_rbs_type _1, self_type, extra_vars }
          names = rbs_builder.build_singleton(return_type.name).type_params
          params = names.map.with_index { [_1, args[_2] || OBJECT] }.to_h
        end
        InstanceType.new klass, params || {}
      end
    end

    def self.method_return_bottom?(method)
      method.type.return_type.is_a? RBS::Types::Bases::Bottom
    end

    def self.match_free_variables(vars, types, values)
      accumulator = {}
      types.zip values do |t, v|
        _match_free_variable(vars, t, v, accumulator) if v
      end
      accumulator.transform_values { UnionType[*_1] }
    end

    def self._match_free_variable(vars, rbs_type, value, accumulator)
      case [rbs_type, value]
      in [RBS::Types::Variable,]
        (accumulator[rbs_type.name] ||= []) << value if vars.include? rbs_type.name
      in [RBS::Types::ClassInstance, InstanceType]
        names = rbs_builder.build_singleton(rbs_type.name).type_params
        names.zip(rbs_type.args).each do |name, arg|
          v = value.params[name]
          _match_free_variable vars, arg, v, accumulator if v
        end
      in [RBS::Types::Tuple, InstanceType] if value.klass == Array
        v = value.params[:Elem]
        rbs_type.types.each do |t|
          _match_free_variable vars, t, v, accumulator
        end
      in [RBS::Types::Record, InstanceType] if value.klass == Hash
        # TODO
      in [RBS::Types::Interface,]
        definition = rbs_builder.build_interface rbs_type.name
        convert = {}
        definition.type_params.zip(rbs_type.args).each do |from, arg|
          convert[from] = arg.name if arg.is_a? RBS::Types::Variable
        end
        return if convert.empty?
        ac = {}
        definition.methods.each do |method_name, method|
          return_type = method_return_type value, method_name
          method.defs.each do |method_def|
            interface_return_type = method_def.type.type.return_type
            _match_free_variable convert, interface_return_type, return_type, ac
          end
        end
        convert.each do |from, to|
          values = ac[from]
          (accumulator[to] ||= []).concat values

nonnillable() click to toggle source

    # File repl_type_completor-0.1.9/lib/repl_type_completor/types.rb, line 191
      def nonnillable() = self
      def inspect
        "#{module_or_class}.itself"
      end
    end

transform() { |self| ... } click to toggle source

    # File repl_type_completor-0.1.9/lib/repl_type_completor/types.rb, line 185
      def transform() = yield(self)
      def methods() = @module_or_class.methods
      def all_methods() = methods | @module_or_class.private_methods
      def constants() = @module_or_class.constants
      def types() = [self]
      def nillable?() = false
      def nonnillable() = self
      def inspect
        "#{module_or_class}.itself"
      end
    end

    class InstanceType
      attr_reader :klass, :params
      def initialize(klass, params = {})
        @klass = klass
        @params = params
      end
      def transform() = yield(self)
      def methods() = rbs_methods.select { _2.public? }.keys | @klass.instance_methods
      def all_methods() = rbs_methods.keys | @klass.instance_methods | @klass.private_instance_methods
      def constants() = []
      def types() = [self]
      def nillable?() = (@klass == NilClass)
      def nonnillable() = self
      def rbs_methods
        name = Types.class_name_of(@klass)
        return {} unless name && Types.rbs_builder

        type_name = RBS::TypeName(name).absolute!
        Types.rbs_builder.build_instance(type_name).methods rescue {}
      end
      def inspect
        if params.empty?
          inspect_without_params
        else
          params_string = "[#{params.map { "#{_1}: #{_2.inspect}" }.join(', ')}]"
          "#{inspect_without_params}#{params_string}"
        end
      end
      def inspect_without_params
        if klass == NilClass
          'nil'
        elsif klass == TrueClass
          'true'
        elsif klass == FalseClass
          'false'
        else
          klass.singleton_class? ? klass.superclass.to_s : klass.to_s
        end
      end
    end

    NIL = InstanceType.new NilClass
    OBJECT = InstanceType.new Object
    TRUE = InstanceType.new TrueClass
    FALSE = InstanceType.new FalseClass
    SYMBOL = InstanceType.new Symbol
    STRING = InstanceType.new String
    INTEGER = InstanceType.new Integer
    RANGE = InstanceType.new Range
    REGEXP = InstanceType.new Regexp
    FLOAT = InstanceType.new Float
    RATIONAL = InstanceType.new Rational
    COMPLEX = InstanceType.new Complex
    ARRAY = InstanceType.new Array
    HASH = InstanceType.new Hash
    CLASS = InstanceType.new Class
    MODULE = InstanceType.new Module
    PROC = InstanceType.new Proc

    class UnionType
      attr_reader :types

      def initialize(*types)
        @types = []
        singletons = []
        instances = {}
        collect = -> type do
          case type
          in UnionType
            type.types.each(&collect)
          in InstanceType
            params = (instances[type.klass] ||= {})
            type.params.each do |k, v|
              (params[k] ||= []) << v
            end
          in SingletonType
            singletons << type
          end
        end
        types.each(&collect)
        @types = singletons.uniq + instances.map do |klass, params|
          InstanceType.new(klass, params.transform_values { |v| UnionType[*v] })
        end
      end

      def transform(&block)
        UnionType[*types.map(&block)]
      end

      def nillable?
        types.any?(&:nillable?)
      end

      def nonnillable
        UnionType[*types.reject { _1.is_a?(InstanceType) && _1.klass == NilClass }]
      end

      def self.[](*types)
        type = new(*types)
        if type.types.empty?
          OBJECT
        elsif type.types.size == 1
          type.types.first
        else
          type
        end
      end

      def methods() = @types.flat_map(&:methods).uniq
      def all_methods() = @types.flat_map(&:all_methods).uniq
      def constants() = @types.flat_map(&:constants).uniq
      def inspect() = @types.map(&:inspect).join(' | ')
    end

    BOOLEAN = UnionType[TRUE, FALSE]

    def self.array_of(*types)
      type = types.size >= 2 ? UnionType[*types] : types.first || OBJECT
      InstanceType.new Array, Elem: type
    end

    def self.from_rbs_type(return_type, self_type, extra_vars = {})
      case return_type
      when RBS::Types::Bases::Self
        self_type
      when RBS::Types::Bases::Bottom, RBS::Types::Bases::Nil
        NIL
      when RBS::Types::Bases::Any, RBS::Types::Bases::Void
        OBJECT
      when RBS::Types::Bases::Class
        self_type.transform do |type|
          case type
          in SingletonType
            InstanceType.new(self_type.module_or_class.is_a?(Class) ? Class : Module)
          in InstanceType
            SingletonType.new type.klass
          end
        end
        UnionType[*types]
      when RBS::Types::Bases::Bool
        BOOLEAN
      when RBS::Types::Bases::Instance
        self_type.transform do |type|
          if type.is_a?(SingletonType) && type.module_or_class.is_a?(Class)
            InstanceType.new type.module_or_class
          elsif type.is_a?(InstanceType)
            InstanceType.new type.klass
          else
            OBJECT
          end
        end
      when RBS::Types::Union
        UnionType[*return_type.types.map { from_rbs_type _1, self_type, extra_vars }]
      when RBS::Types::Proc
        PROC
      when RBS::Types::Tuple
        elem = UnionType[*return_type.types.map { from_rbs_type _1, self_type, extra_vars }]
        InstanceType.new Array, Elem: elem
      when RBS::Types::Record
        InstanceType.new Hash, K: SYMBOL, V: OBJECT
      when RBS::Types::Literal
        InstanceType.new return_type.literal.class
      when RBS::Types::Variable
        if extra_vars.key? return_type.name
          extra_vars[return_type.name]
        elsif self_type.is_a? InstanceType
          self_type.params[return_type.name] || OBJECT
        elsif self_type.is_a? UnionType
          types = self_type.types.filter_map do |t|
            t.params[return_type.name] if t.is_a? InstanceType
          end
          UnionType[*types]
        else
          OBJECT
        end
      when RBS::Types::Optional
        UnionType[from_rbs_type(return_type.type, self_type, extra_vars), NIL]
      when RBS::Types::Alias
        case return_type.name.name
        when :int
          INTEGER
        when :boolish
          BOOLEAN
        when :string
          STRING
        else
          # TODO: ???
          OBJECT
        end
      when RBS::Types::Interface
        # unimplemented
        OBJECT
      when RBS::Types::ClassInstance
        klass = return_type.name.to_namespace.path.reduce(Object) { _1.const_get _2 }
        if return_type.args
          args = return_type.args.map { from_rbs_type _1, self_type, extra_vars }
          names = rbs_builder.build_singleton(return_type.name).type_params
          params = names.map.with_index { [_1, args[_2] || OBJECT] }.to_h
        end
        InstanceType.new klass, params || {}
      end
    end

    def self.method_return_bottom?(method)
      method.type.return_type.is_a? RBS::Types::Bases::Bottom
    end

    def self.match_free_variables(vars, types, values)
      accumulator = {}
      types.zip values do |t, v|
        _match_free_variable(vars, t, v, accumulator) if v
      end
      accumulator.transform_values { UnionType[*_1] }
    end

    def self._match_free_variable(vars, rbs_type, value, accumulator)
      case [rbs_type, value]
      in [RBS::Types::Variable,]
        (accumulator[rbs_type.name] ||= []) << value if vars.include? rbs_type.name
      in [RBS::Types::ClassInstance, InstanceType]
        names = rbs_builder.build_singleton(rbs_type.name).type_params
        names.zip(rbs_type.args).each do |name, arg|
          v = value.params[name]
          _match_free_variable vars, arg, v, accumulator if v
        end
      in [RBS::Types::Tuple, InstanceType] if value.klass == Array
        v = value.params[:Elem]
        rbs_type.types.each do |t|
          _match_free_variable vars, t, v, accumulator
        end
      in [RBS::Types::Record, InstanceType] if value.klass == Hash
        # TODO
      in [RBS::Types::Interface,]
        definition = rbs_builder.build_interface rbs_type.name
        convert = {}
        definition.type_params.zip(rbs_type.args).each do |from, arg|
          convert[from] = arg.name if arg.is_a? RBS::Types::Variable
        end
        return if convert.empty?
        ac = {}
        definition.methods.each do |method_name, method|
          return_type = method_return_type value, method_name
          method.defs.each do |method_def|
            interface_return_type = method_def.type.type.return_type
            _match_free_variable convert, interface_return_type, return_type, ac
          end
        end
        convert.each do |from, to|
          values = ac[from]
          (accumulator[to]

types() click to toggle source

    # File repl_type_completor-0.1.9/lib/repl_type_completor/types.rb, line 189
      def types() = [self]
      def nillable?() = false
      def nonnillable() = self
      def inspect
        "#{module_or_class}.itself"
      end
    end

    class InstanceType
      attr_reader :klass, :params
      def initialize(klass, params = {})
        @klass = klass
        @params = params
      end
      def transform() = yield(self)
      def methods() = rbs_methods.select { _2.public? }.keys | @klass.instance_methods
      def all_methods() = rbs_methods.keys | @klass.instance_methods | @klass.private_instance_methods
      def constants() = []
      def types() = [self]
      def nillable?() = (@klass == NilClass)
      def nonnillable() = self
      def rbs_methods
        name = Types.class_name_of(@klass)
        return {} unless name && Types.rbs_builder

        type_name = RBS::TypeName(name).absolute!
        Types.rbs_builder.build_instance(type_name).methods rescue {}
      end
      def inspect
        if params.empty?
          inspect_without_params
        else
          params_string = "[#{params.map { "#{_1}: #{_2.inspect}" }.join(', ')}]"
          "#{inspect_without_params}#{params_string}"
        end
      end
      def inspect_without_params
        if klass == NilClass
          'nil'
        elsif klass == TrueClass
          'true'
        elsif klass == FalseClass
          'false'
        else
          klass.singleton_class? ? klass.superclass.to_s : klass.to_s
        end
      end
    end

    NIL = InstanceType.new NilClass
    OBJECT = InstanceType.new Object
    TRUE = InstanceType.new TrueClass
    FALSE = InstanceType.new FalseClass
    SYMBOL = InstanceType.new Symbol
    STRING = InstanceType.new String
    INTEGER = InstanceType.new Integer
    RANGE = InstanceType.new Range
    REGEXP = InstanceType.new Regexp
    FLOAT = InstanceType.new Float
    RATIONAL = InstanceType.new Rational
    COMPLEX = InstanceType.new Complex
    ARRAY = InstanceType.new Array
    HASH = InstanceType.new Hash
    CLASS = InstanceType.new Class
    MODULE = InstanceType.new Module
    PROC = InstanceType.new Proc

    class UnionType
      attr_reader :types

      def initialize(*types)
        @types = []
        singletons = []
        instances = {}
        collect = -> type do
          case type
          in UnionType
            type.types.each(&collect)
          in InstanceType
            params = (instances[type.klass] ||= {})
            type.params.each do |k, v|
              (params[k] ||= []) << v
            end
          in SingletonType
            singletons << type
          end
        end
        types.each(&collect)
        @types = singletons.uniq + instances.map do |klass, params|
          InstanceType.new(klass, params.transform_values { |v| UnionType[*v] })
        end
      end

      def transform(&block)
        UnionType[*types.map(&block)]
      end

      def nillable?
        types.any?(&:nillable?)
      end

      def nonnillable
        UnionType[*types.reject { _1.is_a?(InstanceType) && _1.klass == NilClass }]
      end

      def self.[](*types)
        type = new(*types)
        if type.types.empty?
          OBJECT
        elsif type.types.size == 1
          type.types.first
        else
          type
        end
      end

      def methods() = @types.flat_map(&:methods).uniq
      def all_methods() = @types.flat_map(&:all_methods).uniq
      def constants() = @types.flat_map(&:constants).uniq
      def inspect() = @types.map(&:inspect).join(' | ')
    end

    BOOLEAN = UnionType[TRUE, FALSE]

    def self.array_of(*types)
      type = types.size >= 2 ? UnionType[*types] : types.first || OBJECT
      InstanceType.new Array, Elem: type
    end

    def self.from_rbs_type(return_type, self_type, extra_vars = {})
      case return_type
      when RBS::Types::Bases::Self
        self_type
      when RBS::Types::Bases::Bottom, RBS::Types::Bases::Nil
        NIL
      when RBS::Types::Bases::Any, RBS::Types::Bases::Void
        OBJECT
      when RBS::Types::Bases::Class
        self_type.transform do |type|
          case type
          in SingletonType
            InstanceType.new(self_type.module_or_class.is_a?(Class) ? Class : Module)
          in InstanceType
            SingletonType.new type.klass
          end
        end
        UnionType[*types]
      when RBS::Types::Bases::Bool
        BOOLEAN
      when RBS::Types::Bases::Instance
        self_type.transform do |type|
          if type.is_a?(SingletonType) && type.module_or_class.is_a?(Class)
            InstanceType.new type.module_or_class
          elsif type.is_a?(InstanceType)
            InstanceType.new type.klass
          else
            OBJECT
          end
        end
      when RBS::Types::Union
        UnionType[*return_type.types.map { from_rbs_type _1, self_type, extra_vars }]
      when RBS::Types::Proc
        PROC
      when RBS::Types::Tuple
        elem = UnionType[*return_type.types.map { from_rbs_type _1, self_type, extra_vars }]
        InstanceType.new Array, Elem: elem
      when RBS::Types::Record
        InstanceType.new Hash, K: SYMBOL, V: OBJECT
      when RBS::Types::Literal
        InstanceType.new return_type.literal.class
      when RBS::Types::Variable
        if extra_vars.key? return_type.name
          extra_vars[return_type.name]
        elsif self_type.is_a? InstanceType
          self_type.params[return_type.name] || OBJECT
        elsif self_type.is_a? UnionType
          types = self_type.types.filter_map do |t|
            t.params[return_type.name] if t.is_a? InstanceType
          end
          UnionType[*types]
        else
          OBJECT
        end
      when RBS::Types::Optional
        UnionType[from_rbs_type(return_type.type, self_type, extra_vars), NIL]
      when RBS::Types::Alias
        case return_type.name.name
        when :int
          INTEGER
        when :boolish
          BOOLEAN
        when :string
          STRING
        else
          # TODO: ???
          OBJECT
        end
      when RBS::Types::Interface
        # unimplemented
        OBJECT
      when RBS::Types::ClassInstance
        klass = return_type.name.to_namespace.path.reduce(Object) { _1.const_get _2 }
        if return_type.args
          args = return_type.args.map { from_rbs_type _1, self_type, extra_vars }
          names = rbs_builder.build_singleton(return_type.name).type_params
          params = names.map.with_index { [_1, args[_2] || OBJECT] }.to_h
        end
        InstanceType.new klass, params || {}
      end
    end

    def self.method_return_bottom?(method)
      method.type.return_type.is_a? RBS::Types::Bases::Bottom
    end

    def self.match_free_variables(vars, types, values)
      accumulator = {}
      types.zip values do |t, v|
        _match_free_variable(vars, t, v, accumulator) if v
      end
      accumulator.transform_values { UnionType[*_1] }
    end

    def self._match_free_variable(vars, rbs_type, value, accumulator)
      case [rbs_type, value]
      in [RBS::Types::Variable,]
        (accumulator[rbs_type.name] ||= []) << value if vars.include? rbs_type.name
      in [RBS::Types::ClassInstance, InstanceType]
        names = rbs_builder.build_singleton(rbs_type.name).type_params
        names.zip(rbs_type.args).each do |name, arg|
          v = value.params[name]
          _match_free_variable vars, arg, v, accumulator if v
        end
      in [RBS::Types::Tuple, InstanceType] if value.klass == Array
        v = value.params[:Elem]
        rbs_type.types.each do |t|
          _match_free_variable vars, t, v, accumulator
        end
      in [RBS::Types::Record, InstanceType] if value.klass == Hash
        # TODO
      in [RBS::Types::Interface,]
        definition = rbs_builder.build_interface rbs_type.name
        convert = {}
        definition.type_params.zip(rbs_type.args).each do |from, arg|
          convert[from] = arg.name if arg.is_a? RBS::Types::Variable
        end
        return if convert.empty?
        ac = {}
        definition.methods.each do |method_name, method|
          return_type = method_return_type value, method_name
          method.defs.each do |method_def|
            interface_return_type = method_def.type.type.return_type
            _match_free_variable convert, interface_return_type, return_type, ac
          end
        end
        convert.each do |from, to|
          values = ac[from]
          (accumulator[to] ||= []).concat