lib/steep/interface/shape.rb in steep-1.7.0.dev.2 vs lib/steep/interface/shape.rb in steep-1.7.0.dev.3
- old
+ new
@@ -1,18 +1,47 @@
module Steep
module Interface
class Shape
class Entry
- attr_reader :method_types
-
- def initialize(method_types:)
+ def initialize(method_types: nil, private_method:, &block)
@method_types = method_types
+ @generator = block
+ @private_method = private_method
end
+ def force
+ unless @method_types
+ @method_types = @generator&.call
+ @generator = nil
+ end
+ end
+
+ def method_types
+ force
+ @method_types or raise
+ end
+
+ def has_method_type?
+ force
+ @method_types ? true : false
+ end
+
def to_s
- "{ #{method_types.join(" || ")} }"
+ if @generator
+ "<< Lazy entry >>"
+ else
+ "{ #{method_types.join(" || ")} }"
+ end
end
+
+ def private_method?
+ @private_method
+ end
+
+ def public_method?
+ !private_method?
+ end
end
class Methods
attr_reader :substs, :methods, :resolved_methods
@@ -23,11 +52,15 @@
@methods = methods
@resolved_methods = methods.transform_values { nil }
end
def key?(name)
- methods.key?(name)
+ if entry = methods.fetch(name, nil)
+ entry.has_method_type?
+ else
+ false
+ end
end
def []=(name, entry)
resolved_methods[name] = nil
methods[name] = entry
@@ -35,32 +68,36 @@
def [](name)
return nil unless key?(name)
resolved_methods[name] ||= begin
+ entry = methods[name]
Entry.new(
- method_types: methods[name].method_types.map do |method_type|
+ method_types: entry.method_types.map do |method_type|
method_type.subst(subst)
- end
+ end,
+ private_method: entry.private_method?
)
end
end
def each(&block)
if block
methods.each_key do |name|
- entry = self[name] or raise
+ entry = self[name] or next
yield [name, entry]
end
else
enum_for :each
end
end
def each_name(&block)
if block
- methods.each_key(&block)
+ each do |name, _|
+ yield name
+ end
else
enum_for :each_name
end
end
@@ -74,23 +111,25 @@
def push_substitution(subst)
Methods.new(substs: [*substs, subst], methods: methods)
end
- def merge!(other)
+ def merge!(other, &block)
other.each do |name, entry|
- methods[name] = entry
+ if block && (old_entry = methods[name])
+ methods[name] = yield(name, old_entry, entry)
+ else
+ methods[name] = entry
+ end
end
end
- def +(other)
- methods = Methods.new(substs: [], methods: {})
-
- methods.merge!(self)
- methods.merge!(other)
-
- methods
+ def public_methods
+ Methods.new(
+ substs: substs,
+ methods: methods.reject {|_, entry| entry.private_method? }
+ )
end
end
attr_reader :type
attr_reader :methods
@@ -124,9 +163,21 @@
@private
end
def public?
!private?
+ end
+
+ def public_shape
+ if public?
+ self
+ else
+ @public_shape ||= Shape.new(
+ type: type,
+ private: false,
+ methods: methods.public_methods
+ )
+ end
end
end
end
end