Class: Steep::Interface::Instantiated

Inherits:
Object
  • Object
show all
Defined in:
lib/steep/interface/instantiated.rb

Defined Under Namespace

Classes: InvalidIvarOverrideError, InvalidMethodOverrideError, PrivateOverrideError

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(type:, methods:, ivar_chains:) ⇒ Instantiated

Returns a new instance of Instantiated.



8
9
10
11
12
# File 'lib/steep/interface/instantiated.rb', line 8

def initialize(type:, methods:, ivar_chains:)
  @type = type
  @methods = methods
  @ivar_chains = ivar_chains
end

Instance Attribute Details

#ivar_chainsObject (readonly)

Returns the value of attribute ivar_chains.



6
7
8
# File 'lib/steep/interface/instantiated.rb', line 6

def ivar_chains
  @ivar_chains
end

#methodsObject (readonly)

Returns the value of attribute methods.



5
6
7
# File 'lib/steep/interface/instantiated.rb', line 5

def methods
  @methods
end

#typeObject (readonly)

Returns the value of attribute type.



4
5
6
# File 'lib/steep/interface/instantiated.rb', line 4

def type
  @type
end

Instance Method Details

#==(other) ⇒ Object



18
19
20
# File 'lib/steep/interface/instantiated.rb', line 18

def ==(other)
  other.is_a?(self.class) && other.type == type && other.params == params && other.methods == methods && other.ivars == ivars
end

#ivarsObject



14
15
16
# File 'lib/steep/interface/instantiated.rb', line 14

def ivars
  @ivars ||= ivar_chains.transform_values(&:type)
end

#select_method_type(&block) ⇒ Object



144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/steep/interface/instantiated.rb', line 144

def select_method_type(&block)
  self.class.new(
    type: type,
    methods: methods.each.with_object({}) do |(name, method), methods|
      methods[name] = Method.new(
        type_name: method.type_name,
        name: method.name,
        types: method.types.select(&block),
        super_method: method.super_method,
        attributes: method.attributes,
      )
    end.reject do |_, method|
      method.types.empty?
    end,
    ivar_chains: ivar_chains
  )
end

#subst(s) ⇒ Object



22
23
24
25
26
27
28
# File 'lib/steep/interface/instantiated.rb', line 22

def subst(s)
  self.class.new(
    type: type,
    methods: methods.transform_values {|type| type.subst(s) },
    ivar_chains: ivar_chains.transform_values {|chain| chain.subst(s) }
  )
end

#validate(check) ⇒ Object



76
77
78
79
80
81
82
83
84
85
# File 'lib/steep/interface/instantiated.rb', line 76

def validate(check)
  methods.each do |_, method|
    validate_method_type(check, method)
    validate_method_visibility method
  end

  ivar_chains.each do |name, chain|
    validate_chain(check, name, chain)
  end
end

#validate_chain(check, name, chain) ⇒ Object



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/steep/interface/instantiated.rb', line 87

def validate_chain(check, name, chain)
  return unless chain.parent

  this_type = chain.type
  super_type = chain.parent.type

  case
  when this_type.is_a?(AST::Types::Any) && super_type.is_a?(AST::Types::Any)
    # ok
  else
    relation = Subtyping::Relation.new(sub_type: this_type, super_type: super_type)

    result1 = check.check(relation, constraints: Subtyping::Constraints.empty)
    result2 = check.check(relation.flip, constraints: Subtyping::Constraints.empty)

    if result1.failure? || result2.failure? || this_type.is_a?(AST::Types::Any) || super_type.is_a?(AST::Types::Any)
      raise InvalidIvarOverrideError.new(type: self.type, ivar_name: name, current_ivar_type: this_type, super_ivar_type: super_type)
    end
  end

  validate_chain(check, name, chain.parent)
end

#validate_method_type(check, method) ⇒ Object



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/steep/interface/instantiated.rb', line 110

def validate_method_type(check, method)
  if method.super_method && !method.incompatible?
    result = check.check_method(method.name,
                                method,
                                method.super_method,
                                assumption: Set.new,
                                trace: Subtyping::Trace.new,
                                constraints: Subtyping::Constraints.empty)

    if result.success?
      validate_method_type(check, method.super_method)
    else
      raise InvalidMethodOverrideError.new(type: type,
                                           current_method: method,
                                           super_method: method.super_method,
                                           result: result)
    end
  end
end

#validate_method_visibility(method) ⇒ Object



130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/steep/interface/instantiated.rb', line 130

def validate_method_visibility(method)
  if (super_method = method.super_method)
    if method.private? && !super_method.private?
      raise PrivateOverrideError.new(
        child_type: method.type_name,
        super_type: super_method.type_name,
        method_name: method.name
      )
    end

    validate_method_visibility(super_method)
  end
end