123456789_123456789_123456789_123456789_123456789_

Class: RBS::AST::TypeParam

Relationships & Source Files
Inherits: Object
Defined in: lib/rbs/ast/type_param.rb

Class Method Summary

Instance Attribute Summary

Instance Method Summary

Constructor Details

.new(name:, variance:, upper_bound:, location:, default_type: nil) ⇒ TypeParam

[ GitHub ]

  
# File 'lib/rbs/ast/type_param.rb', line 8

def initialize(name:, variance:, upper_bound:, location:, default_type: nil)
  @name = name
  @variance = variance
  @upper_bound_type = upper_bound
  @location = location
  @unchecked = false
  @default_type = default_type
end

Class Method Details

.application(params, args)

[ GitHub ]

  
# File 'lib/rbs/ast/type_param.rb', line 156

def self.application(params, args)
  if params.empty?
    return nil
  end

  optional_params, required_params = params.partition {|param| param.default_type }

  param_subst = Substitution.new()
  app_subst = Substitution.new()

  required_params.zip(args.take(required_params.size)).each do |param, arg|
    arg ||= Types::Bases::Any.new(location: nil)
    param_subst.add(from: param.name, to: arg)
    app_subst.add(from: param.name, to: arg)
  end

  optional_params.each do |param|
    param_subst.add(from: param.name, to: Types::Bases::Any.new(location: nil))
  end

  optional_params.zip(args.drop(required_params.size)).each do |param, arg|
    if arg
      app_subst.add(from: param.name, to: arg)
    else
      param.default_type or raise
      app_subst.add(from: param.name, to: param.default_type.sub(param_subst))
    end
  end

  app_subst
end

.normalize_args(params, args)

[ GitHub ]

  
# File 'lib/rbs/ast/type_param.rb', line 188

def self.normalize_args(params, args)
  app = application(params, args) or return []

  min_count = params.count { _1.default_type.nil? }
  unless min_count <= args.size && args.size <= params.size
    return args
  end

  params.zip(args).filter_map do |param, arg|
    if arg
      arg
    else
      if param.default_type
        param.default_type.sub(app)
      else
        Types::Bases::Any.new(location: nil)
      end
    end
  end
end

.rename(params, new_names:)

[ GitHub ]

  
# File 'lib/rbs/ast/type_param.rb', line 109

def self.rename(params, new_names:)
  raise unless params.size == new_names.size

  subst = Substitution.build(new_names, Types::Variable.build(new_names))

  params.map.with_index do |param, index|
    new_name = new_names[index]

    TypeParam.new(
      name: new_name,
      variance: param.variance,
      upper_bound: param.upper_bound_type&.map_type {|type| type.sub(subst) },
      location: param.location,
      default_type: param.default_type&.map_type {|type| type.sub(subst) }
    ).unchecked!(param.unchecked?)
  end
end

.resolve_variables(params)

[ GitHub ]

  
# File 'lib/rbs/ast/type_param.rb', line 87

def self.resolve_variables(params)
  return if params.empty?

  vars = Set.new(params.map(&:name))

  params.map! do |param|
    param.map_type {|bound| _ = subst_var(vars, bound) }
  end
end

.subst_var(vars, type)

[ GitHub ]

  
# File 'lib/rbs/ast/type_param.rb', line 97

def self.subst_var(vars, type)
  case type
  when Types::ClassInstance
    namespace = type.name.namespace
    if namespace.relative? && namespace.empty? && vars.member?(type.name.name)
      return Types::Variable.new(name: type.name.name, location: type.location)
    end
  end

  type.map_type {|t| subst_var(vars, t) }
end

.validate(type_params)

[ GitHub ]

  
# File 'lib/rbs/ast/type_param.rb', line 209

def self.validate(type_params)
  optionals = type_params.filter {|param| param.default_type }

  optional_param_names = optionals.map(&:name).sort

  optionals.filter! do |param|
    default_type = param.default_type or raise
    optional_param_names.any? { default_type.free_variables.include?(_1) }
  end

  unless optionals.empty?
    optionals
  end
end

Instance Attribute Details

#default_type (readonly)

[ GitHub ]

  
# File 'lib/rbs/ast/type_param.rb', line 6

attr_reader :name, :variance, :location, :upper_bound_type, :default_type

#location (readonly)

[ GitHub ]

  
# File 'lib/rbs/ast/type_param.rb', line 6

attr_reader :name, :variance, :location, :upper_bound_type, :default_type

#name (readonly)

[ GitHub ]

  
# File 'lib/rbs/ast/type_param.rb', line 6

attr_reader :name, :variance, :location, :upper_bound_type, :default_type

#unchecked?Boolean (readonly)

[ GitHub ]

  
# File 'lib/rbs/ast/type_param.rb', line 29

def unchecked?
  @unchecked
end

#upper_bound_type (readonly)

[ GitHub ]

  
# File 'lib/rbs/ast/type_param.rb', line 6

attr_reader :name, :variance, :location, :upper_bound_type, :default_type

#variance (readonly)

[ GitHub ]

  
# File 'lib/rbs/ast/type_param.rb', line 6

attr_reader :name, :variance, :location, :upper_bound_type, :default_type

Instance Method Details

#==(other) Also known as: #eql?

[ GitHub ]

  
# File 'lib/rbs/ast/type_param.rb', line 33

def ==(other)
  other.is_a?(TypeParam) &&
    other.name == name &&
    other.variance == variance &&
    other.upper_bound_type == upper_bound_type &&
    other.default_type == default_type &&
    other.unchecked? == unchecked?
end

#eql?(other)

Alias for #==.

[ GitHub ]

  
# File 'lib/rbs/ast/type_param.rb', line 42

alias eql? ==

#hash

[ GitHub ]

  
# File 'lib/rbs/ast/type_param.rb', line 44

def hash
  self.class.hash ^ name.hash ^ variance.hash ^ upper_bound_type.hash ^ unchecked?.hash ^ default_type.hash
end

#map_type(&block)

[ GitHub ]

  
# File 'lib/rbs/ast/type_param.rb', line 69

def map_type(&block)
  if b = upper_bound_type
    _upper_bound_type = yield(b)
  end

  if dt = default_type
    _default_type = yield(dt)
  end

  TypeParam.new(
    name: name,
    variance: variance,
    upper_bound: _upper_bound_type,
    location: location,
    default_type: _default_type
  ).unchecked!(unchecked?)
end

#rename(name)

[ GitHub ]

  
# File 'lib/rbs/ast/type_param.rb', line 59

def rename(name)
  TypeParam.new(
    name: name,
    variance: variance,
    upper_bound: upper_bound_type,
    location: location,
    default_type: default_type
  ).unchecked!(unchecked?)
end

#to_json(state = JSON::State.new)

[ GitHub ]

  
# File 'lib/rbs/ast/type_param.rb', line 48

def to_json(state = JSON::State.new)
  {
    name: name,
    variance: variance,
    unchecked: unchecked?,
    location: location,
    upper_bound: upper_bound_type,
    default_type: default_type
  }.to_json(state)
end

#to_s

[ GitHub ]

  
# File 'lib/rbs/ast/type_param.rb', line 127

def to_s
  s = +""

  if unchecked?
    s << "unchecked "
  end

  case variance
  when :invariant
    # nop
  when :covariant
    s << "out "
  when :contravariant
    s << "in "
  end

  s << name.to_s

  if type = upper_bound_type
    s << " < #{type}"
  end

  if dt = default_type
    s << " = #{dt}"
  end

  s
end

#unchecked!(value = true)

[ GitHub ]

  
# File 'lib/rbs/ast/type_param.rb', line 24

def unchecked!(value = true)
  @unchecked = value ? true : false
  self
end

#upper_bound

[ GitHub ]

  
# File 'lib/rbs/ast/type_param.rb', line 17

def upper_bound
  case upper_bound_type
  when Types::ClassInstance, Types::ClassSingleton, Types::Interface
    upper_bound_type
  end
end