steep 1.1.1 → 1.2.0.pre.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +20 -0
- data/Gemfile +0 -1
- data/Gemfile.lock +12 -11
- data/Gemfile.steep +1 -1
- data/Gemfile.steep.lock +9 -9
- data/README.md +3 -3
- data/Steepfile +23 -0
- data/bin/steep-prof +2 -1
- data/lib/steep/annotation_parser.rb +1 -1
- data/lib/steep/ast/types/class.rb +4 -0
- data/lib/steep/ast/types/factory.rb +86 -602
- data/lib/steep/ast/types/instance.rb +4 -0
- data/lib/steep/ast/types/literal.rb +1 -1
- data/lib/steep/ast/types/proc.rb +22 -8
- data/lib/steep/ast/types/self.rb +4 -0
- data/lib/steep/ast/types/union.rb +1 -1
- data/lib/steep/cli.rb +24 -1
- data/lib/steep/diagnostic/ruby.rb +17 -22
- data/lib/steep/drivers/checkfile.rb +205 -0
- data/lib/steep/drivers/validate.rb +3 -1
- data/lib/steep/equatable.rb +2 -0
- data/lib/steep/interface/block.rb +21 -11
- data/lib/steep/interface/builder.rb +756 -0
- data/lib/steep/interface/function.rb +32 -24
- data/lib/steep/interface/method_type.rb +191 -78
- data/lib/steep/interface/shape.rb +132 -0
- data/lib/steep/interface/substitution.rb +23 -12
- data/lib/steep/interface/type_param.rb +1 -2
- data/lib/steep/path_helper.rb +1 -1
- data/lib/steep/project.rb +5 -7
- data/lib/steep/server/base_worker.rb +2 -2
- data/lib/steep/server/change_buffer.rb +4 -3
- data/lib/steep/server/interaction_worker.rb +1 -1
- data/lib/steep/server/master.rb +69 -9
- data/lib/steep/server/type_check_worker.rb +13 -11
- data/lib/steep/server/worker_process.rb +9 -7
- data/lib/steep/services/completion_provider.rb +15 -3
- data/lib/steep/services/hover_provider/singleton_methods.rb +5 -6
- data/lib/steep/services/signature_service.rb +13 -8
- data/lib/steep/services/type_check_service.rb +2 -0
- data/lib/steep/signature/validator.rb +1 -1
- data/lib/steep/subtyping/check.rb +154 -103
- data/lib/steep/subtyping/relation.rb +3 -3
- data/lib/steep/subtyping/result.rb +20 -2
- data/lib/steep/subtyping/variable_variance.rb +9 -0
- data/lib/steep/type_construction.rb +558 -299
- data/lib/steep/type_inference/block_params.rb +169 -86
- data/lib/steep/type_inference/logic_type_interpreter.rb +9 -14
- data/lib/steep/type_inference/method_params.rb +12 -7
- data/lib/steep/type_inference/send_args.rb +41 -35
- data/lib/steep/type_inference/type_env_builder.rb +1 -1
- data/lib/steep/version.rb +1 -1
- data/lib/steep.rb +71 -2
- data/rbs_collection.steep.lock.yaml +18 -30
- data/rbs_collection.steep.yaml +1 -0
- data/sig/shims/language-server_protocol.rbs +20 -0
- data/sig/shims/tagged_logging.rbs +6 -0
- data/sig/steep/ast/annotation/collection.rbs +6 -6
- data/sig/steep/ast/types/class.rbs +3 -0
- data/sig/steep/ast/types/factory.rbs +38 -32
- data/sig/steep/ast/types/instance.rbs +3 -0
- data/sig/steep/ast/types/intersection.rbs +1 -1
- data/sig/steep/ast/types/literal.rbs +7 -7
- data/sig/steep/ast/types/name.rbs +14 -13
- data/sig/steep/ast/types/proc.rbs +3 -1
- data/sig/steep/ast/types/self.rbs +3 -0
- data/sig/steep/ast/types/var.rbs +1 -1
- data/sig/steep/diagnostic/ruby.rbs +30 -34
- data/sig/steep/drivers/annotations.rbs +17 -0
- data/sig/steep/drivers/check.rbs +33 -0
- data/sig/steep/drivers/checkfile.rbs +26 -0
- data/sig/steep/drivers/diagnostic_printer.rbs +25 -0
- data/sig/steep/drivers/init.rbs +19 -0
- data/sig/steep/drivers/langserver.rbs +35 -0
- data/sig/steep/drivers/print_project.rbs +15 -0
- data/sig/steep/drivers/stats.rbs +37 -0
- data/sig/steep/drivers/utils/driver_helper.rbs +23 -0
- data/sig/steep/drivers/utils/jobs_count.rbs +11 -0
- data/sig/steep/drivers/validate.rbs +15 -0
- data/sig/steep/drivers/vendor.rbs +19 -0
- data/sig/steep/drivers/watch.rbs +27 -0
- data/sig/steep/drivers/worker.rbs +31 -0
- data/sig/steep/equatable.rbs +11 -0
- data/sig/steep/index/rbs_index.rbs +91 -0
- data/sig/steep/index/signature_symbol_provider.rbs +29 -0
- data/sig/steep/index/source_index.rbs +63 -0
- data/sig/steep/interface/block.rbs +3 -1
- data/sig/steep/interface/builder.rbs +152 -0
- data/sig/steep/interface/function.rbs +67 -55
- data/sig/steep/interface/method_type.rbs +60 -12
- data/sig/steep/interface/shape.rbs +61 -0
- data/sig/steep/interface/substitution.rbs +18 -22
- data/sig/steep/interface/type_param.rbs +9 -1
- data/sig/steep/path_helper.rbs +7 -0
- data/sig/steep/project/pattern.rbs +10 -10
- data/sig/steep/project/target.rbs +2 -2
- data/sig/steep/project.rbs +15 -8
- data/sig/steep/server/base_worker.rbs +49 -0
- data/sig/steep/server/change_buffer.rbs +32 -0
- data/sig/steep/server/interaction_worker.rbs +41 -0
- data/sig/steep/server/lsp_formatter.rbs +29 -0
- data/sig/steep/server/master.rbs +260 -0
- data/sig/steep/server/type_check_worker.rbs +135 -0
- data/sig/steep/server/worker_process.rbs +29 -0
- data/sig/steep/services/completion_provider.rbs +5 -5
- data/sig/steep/services/content_change.rbs +14 -12
- data/sig/steep/services/file_loader.rbs +12 -4
- data/sig/steep/services/hover_provider/singleton_methods.rbs +1 -1
- data/sig/steep/services/path_assignment.rbs +7 -7
- data/sig/steep/services/signature_service.rbs +67 -40
- data/sig/steep/services/type_check_service.rbs +53 -39
- data/sig/steep/subtyping/check.rbs +80 -44
- data/sig/steep/subtyping/relation.rbs +24 -22
- data/sig/steep/subtyping/result.rbs +48 -30
- data/sig/steep/subtyping/variable_variance.rbs +2 -0
- data/sig/steep/type_construction.rbs +132 -23
- data/sig/steep/type_inference/block_params.rbs +120 -18
- data/sig/steep/type_inference/context.rbs +45 -20
- data/sig/steep/type_inference/context_array.rbs +37 -0
- data/sig/steep/type_inference/logic_type_interpreter.rbs +3 -1
- data/sig/steep/type_inference/method_params.rbs +13 -9
- data/sig/steep/type_inference/send_args.rbs +229 -0
- data/sig/steep/type_inference/type_env_builder.rbs +1 -1
- data/sig/steep/typing.rbs +4 -4
- data/sig/steep.rbs +4 -2
- data/smoke/block/e.rb +12 -0
- data/smoke/block/e.rbs +4 -0
- data/smoke/block/test_expectations.yml +12 -0
- data/smoke/regression/block_param_split.rb +7 -0
- data/smoke/regression/block_param_split.rbs +3 -0
- data/smoke/regression/empty_yield.rb +5 -0
- data/smoke/regression/empty_yield.rbs +3 -0
- data/smoke/regression/test_expectations.yml +12 -0
- data/smoke/yield/test_expectations.yml +4 -4
- data/steep.gemspec +2 -1
- metadata +61 -9
- data/lib/steep/interface/interface.rb +0 -34
- data/sig/steep/interface/interface.rbs +0 -23
- data/sig/version.rbs +0 -3
@@ -0,0 +1,756 @@
|
|
1
|
+
|
2
|
+
module Steep
|
3
|
+
module Interface
|
4
|
+
class Builder
|
5
|
+
class Config
|
6
|
+
attr_reader :self_type, :class_type, :instance_type, :variable_bounds
|
7
|
+
attr_reader :resolve_self, :resolve_instance, :resolve_class
|
8
|
+
|
9
|
+
def initialize(self_type:, class_type:, instance_type:, resolve_self: true, resolve_class: true, resolve_instance: true, variable_bounds:)
|
10
|
+
@self_type = self_type
|
11
|
+
@class_type = class_type
|
12
|
+
@instance_type = instance_type
|
13
|
+
@resolve_self = resolve_self
|
14
|
+
@resolve_class = resolve_class
|
15
|
+
@resolve_instance = resolve_instance
|
16
|
+
@variable_bounds = variable_bounds
|
17
|
+
end
|
18
|
+
|
19
|
+
def update(self_type: self.self_type, class_type: self.class_type, instance_type: self.instance_type, resolve_self: self.resolve_self, resolve_class: self.resolve_class, resolve_instance: self.resolve_instance, variable_bounds: self.variable_bounds)
|
20
|
+
_ = self.class.new(
|
21
|
+
self_type: self_type,
|
22
|
+
class_type: class_type,
|
23
|
+
instance_type: instance_type,
|
24
|
+
resolve_self: resolve_self,
|
25
|
+
resolve_class: resolve_class,
|
26
|
+
resolve_instance: resolve_instance,
|
27
|
+
variable_bounds: variable_bounds
|
28
|
+
)
|
29
|
+
end
|
30
|
+
|
31
|
+
def no_resolve
|
32
|
+
if resolve?
|
33
|
+
@no_resolve ||= update(resolve_self: false, resolve_class: false, resolve_instance: false)
|
34
|
+
else
|
35
|
+
self
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def resolve?
|
40
|
+
resolve_self || resolve_class || resolve_instance
|
41
|
+
end
|
42
|
+
|
43
|
+
def ==(other)
|
44
|
+
other.is_a?(Config) &&
|
45
|
+
other.self_type == self_type &&
|
46
|
+
other.class_type == class_type &&
|
47
|
+
other.instance_type == instance_type &&
|
48
|
+
other.resolve_self == resolve_self &&
|
49
|
+
other.resolve_class == resolve_class &&
|
50
|
+
other.resolve_instance == resolve_instance &&
|
51
|
+
other.variable_bounds == variable_bounds
|
52
|
+
end
|
53
|
+
|
54
|
+
alias eql? ==
|
55
|
+
|
56
|
+
def hash
|
57
|
+
self_type.hash ^ class_type.hash ^ instance_type.hash ^ resolve_self.hash ^ resolve_class.hash ^ resolve_instance.hash ^ variable_bounds.hash
|
58
|
+
end
|
59
|
+
|
60
|
+
def subst
|
61
|
+
@subst ||= begin
|
62
|
+
Substitution.build(
|
63
|
+
[],
|
64
|
+
[],
|
65
|
+
self_type: self_type,
|
66
|
+
module_type: class_type || AST::Types::Class.instance,
|
67
|
+
instance_type: instance_type || AST::Types::Instance.instance
|
68
|
+
)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
attr_reader :factory, :cache, :raw_object_cache
|
74
|
+
attr_reader :raw_instance_object_shape_cache, :raw_singleton_object_shape_cache, :raw_interface_object_shape_cache
|
75
|
+
|
76
|
+
def initialize(factory)
|
77
|
+
@factory = factory
|
78
|
+
@cache = {}
|
79
|
+
@raw_instance_object_shape_cache = {}
|
80
|
+
@raw_singleton_object_shape_cache = {}
|
81
|
+
@raw_interface_object_shape_cache = {}
|
82
|
+
end
|
83
|
+
|
84
|
+
def include_self?(type)
|
85
|
+
case type
|
86
|
+
when AST::Types::Self, AST::Types::Instance, AST::Types::Class
|
87
|
+
true
|
88
|
+
else
|
89
|
+
type.each_child.any? {|t| include_self?(t) }
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def fetch_cache(type, public_only, config)
|
94
|
+
has_self = include_self?(type)
|
95
|
+
fvs = type.free_variables
|
96
|
+
|
97
|
+
# @type var key: cache_key
|
98
|
+
key = [
|
99
|
+
type,
|
100
|
+
public_only,
|
101
|
+
has_self ? config.self_type : nil,
|
102
|
+
has_self ? config.class_type : nil,
|
103
|
+
has_self ? config.instance_type : nil,
|
104
|
+
config.resolve_self,
|
105
|
+
config.resolve_class,
|
106
|
+
config.resolve_instance,
|
107
|
+
if config.variable_bounds.each_key.any? {|var| fvs.include?(var)}
|
108
|
+
config.variable_bounds.select {|var, _| fvs.include?(var) }
|
109
|
+
else
|
110
|
+
nil
|
111
|
+
end
|
112
|
+
]
|
113
|
+
|
114
|
+
if cache.key?(key)
|
115
|
+
cache[key]
|
116
|
+
else
|
117
|
+
cache[key] = yield
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def shape(type, public_only:, config:)
|
122
|
+
fetch_cache(type, public_only, config) do
|
123
|
+
case type
|
124
|
+
when AST::Types::Self
|
125
|
+
self_type = config.self_type.subst(config.subst)
|
126
|
+
shape(self_type, public_only: public_only, config: config.update(resolve_self: false))
|
127
|
+
when AST::Types::Instance
|
128
|
+
if config.instance_type
|
129
|
+
instance_type = config.instance_type.subst(config.subst)
|
130
|
+
shape(instance_type, public_only: public_only, config: config.update(resolve_instance: false))
|
131
|
+
end
|
132
|
+
when AST::Types::Class
|
133
|
+
if config.class_type
|
134
|
+
class_type = config.class_type.subst(config.subst)
|
135
|
+
shape(class_type, public_only: public_only, config: config.update(resolve_class: false))
|
136
|
+
end
|
137
|
+
when AST::Types::Name::Instance, AST::Types::Name::Interface, AST::Types::Name::Singleton
|
138
|
+
object_shape(
|
139
|
+
type.subst(config.subst),
|
140
|
+
public_only,
|
141
|
+
!config.resolve_self,
|
142
|
+
!config.resolve_instance,
|
143
|
+
!config.resolve_class
|
144
|
+
)
|
145
|
+
when AST::Types::Name::Alias
|
146
|
+
if expanded = factory.deep_expand_alias(type)
|
147
|
+
shape(expanded, public_only: public_only, config: config)&.update(type: type)
|
148
|
+
end
|
149
|
+
when AST::Types::Any, AST::Types::Bot, AST::Types::Void, AST::Types::Top
|
150
|
+
nil
|
151
|
+
when AST::Types::Var
|
152
|
+
if bound = config.variable_bounds[type.name]
|
153
|
+
shape(bound, public_only: public_only, config: config)&.update(type: type)
|
154
|
+
end
|
155
|
+
when AST::Types::Union
|
156
|
+
if include_self?(type)
|
157
|
+
self_var = AST::Types::Var.fresh(:SELF)
|
158
|
+
class_var = AST::Types::Var.fresh(:CLASS)
|
159
|
+
instance_var = AST::Types::Var.fresh(:INSTANCE)
|
160
|
+
|
161
|
+
bounds = config.variable_bounds.merge({ self_var.name => config.self_type, instance_var.name => config.instance_type, class_var.name => config.class_type })
|
162
|
+
type_ = type.subst(Substitution.build([], [], self_type: self_var, instance_type: instance_var, module_type: class_var))
|
163
|
+
|
164
|
+
config_ = config.update(resolve_self: false, resolve_class: true, resolve_instance: true, variable_bounds: bounds)
|
165
|
+
|
166
|
+
shapes = type_.types.map do |type|
|
167
|
+
shape(type, public_only: public_only, config: config_) or return
|
168
|
+
end
|
169
|
+
|
170
|
+
if shape = union_shape(type, shapes, public_only)
|
171
|
+
shape.subst(
|
172
|
+
Substitution.build(
|
173
|
+
[self_var.name, class_var.name, instance_var.name],
|
174
|
+
[AST::Types::Self.instance, AST::Types::Class.instance, AST::Types::Instance.instance],
|
175
|
+
self_type: type,
|
176
|
+
instance_type: AST::Builtin.any_type,
|
177
|
+
module_type: AST::Builtin.any_type
|
178
|
+
),
|
179
|
+
type: type.subst(config.subst)
|
180
|
+
)
|
181
|
+
end
|
182
|
+
else
|
183
|
+
config_ = config.update(resolve_self: false)
|
184
|
+
|
185
|
+
shapes = type.types.map do |type|
|
186
|
+
shape(type, public_only: public_only, config: config_) or return
|
187
|
+
end
|
188
|
+
|
189
|
+
if shape = union_shape(type, shapes, public_only)
|
190
|
+
shape.subst(
|
191
|
+
Substitution.build(
|
192
|
+
[], [],
|
193
|
+
self_type: type,
|
194
|
+
instance_type: AST::Builtin.any_type,
|
195
|
+
module_type: AST::Builtin.any_type
|
196
|
+
)
|
197
|
+
)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
when AST::Types::Intersection
|
201
|
+
self_var = AST::Types::Var.fresh(:SELF)
|
202
|
+
class_var = AST::Types::Var.fresh(:CLASS)
|
203
|
+
instance_var = AST::Types::Var.fresh(:INSTANCE)
|
204
|
+
|
205
|
+
bounds = config.variable_bounds.merge({ self_var.name => config.self_type, instance_var.name => config.instance_type, class_var.name => config.class_type })
|
206
|
+
type_ = type.subst(Substitution.build([], [], self_type: self_var, instance_type: instance_var, module_type: class_var))
|
207
|
+
|
208
|
+
config_ = config.update(resolve_self: false, resolve_class: true, resolve_instance: true, variable_bounds: bounds)
|
209
|
+
|
210
|
+
shapes = type_.types.map do |type|
|
211
|
+
shape(type, public_only: public_only, config: config_) or return
|
212
|
+
end
|
213
|
+
|
214
|
+
if shape = intersection_shape(type, shapes, public_only)
|
215
|
+
shape.subst(
|
216
|
+
Substitution.build(
|
217
|
+
[self_var.name, class_var.name, instance_var.name],
|
218
|
+
[AST::Types::Self.instance, AST::Types::Class.instance, AST::Types::Instance.instance],
|
219
|
+
self_type: type,
|
220
|
+
instance_type: AST::Builtin.any_type,
|
221
|
+
module_type: AST::Builtin.any_type
|
222
|
+
),
|
223
|
+
type: type.subst(config.subst)
|
224
|
+
)
|
225
|
+
end
|
226
|
+
|
227
|
+
when AST::Types::Tuple
|
228
|
+
tuple_shape(type, public_only, config)
|
229
|
+
when AST::Types::Record
|
230
|
+
record_shape(type, public_only, config)
|
231
|
+
when AST::Types::Literal
|
232
|
+
if shape = shape(type.back_type, public_only: public_only, config: config.update(resolve_self: false))
|
233
|
+
shape.subst(Substitution.build([], [], self_type: type), type: type)
|
234
|
+
end
|
235
|
+
when AST::Types::Boolean, AST::Types::Logic::Base
|
236
|
+
shape = union_shape(
|
237
|
+
type,
|
238
|
+
[
|
239
|
+
object_shape(AST::Builtin::TrueClass.instance_type, public_only, true, true, true),
|
240
|
+
object_shape(AST::Builtin::FalseClass.instance_type, public_only, true, true, true)
|
241
|
+
],
|
242
|
+
public_only
|
243
|
+
)
|
244
|
+
|
245
|
+
if shape
|
246
|
+
shape.subst(Substitution.build([], [], self_type: type))
|
247
|
+
end
|
248
|
+
when AST::Types::Nil
|
249
|
+
if shape = object_shape(AST::Builtin::NilClass.instance_type, public_only, true, !config.resolve_instance, !config.resolve_class)
|
250
|
+
if config.resolve_self
|
251
|
+
shape.subst(Substitution.build([], [], self_type: type), type: type)
|
252
|
+
else
|
253
|
+
shape.update(type: type)
|
254
|
+
end
|
255
|
+
end
|
256
|
+
when AST::Types::Proc
|
257
|
+
proc_shape(type, public_only, config)
|
258
|
+
else
|
259
|
+
raise "Unknown type is given: #{type}"
|
260
|
+
end
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
def definition_builder
|
265
|
+
factory.definition_builder
|
266
|
+
end
|
267
|
+
|
268
|
+
def object_shape(type, public_only, keep_self, keep_instance, keep_singleton)
|
269
|
+
case type
|
270
|
+
when AST::Types::Name::Instance
|
271
|
+
definition = definition_builder.build_instance(type.name)
|
272
|
+
subst = Interface::Substitution.build(
|
273
|
+
definition.type_params,
|
274
|
+
type.args,
|
275
|
+
self_type: keep_self ? AST::Types::Self.instance : type,
|
276
|
+
module_type: keep_singleton ? AST::Types::Class.instance : AST::Types::Name::Singleton.new(name: type.name),
|
277
|
+
instance_type: keep_instance ? AST::Types::Instance.instance : factory.instance_type(type.name)
|
278
|
+
)
|
279
|
+
when AST::Types::Name::Interface
|
280
|
+
definition = definition_builder.build_interface(type.name)
|
281
|
+
subst = Interface::Substitution.build(
|
282
|
+
definition.type_params,
|
283
|
+
type.args,
|
284
|
+
self_type: keep_self ? AST::Types::Self.instance : type
|
285
|
+
)
|
286
|
+
when AST::Types::Name::Singleton
|
287
|
+
subst = Interface::Substitution.build(
|
288
|
+
[],
|
289
|
+
[],
|
290
|
+
self_type: keep_self ? AST::Types::Self.instance : type,
|
291
|
+
module_type: keep_singleton ? AST::Types::Class.instance : AST::Types::Name::Singleton.new(name: type.name),
|
292
|
+
instance_type: keep_instance ? AST::Types::Instance.instance : factory.instance_type(type.name)
|
293
|
+
)
|
294
|
+
end
|
295
|
+
|
296
|
+
raw_object_shape(type, public_only, subst)
|
297
|
+
end
|
298
|
+
|
299
|
+
def raw_object_shape(type, public_only, subst)
|
300
|
+
cache =
|
301
|
+
case type
|
302
|
+
when AST::Types::Name::Instance
|
303
|
+
raw_instance_object_shape_cache
|
304
|
+
when AST::Types::Name::Interface
|
305
|
+
raw_interface_object_shape_cache
|
306
|
+
when AST::Types::Name::Singleton
|
307
|
+
raw_singleton_object_shape_cache
|
308
|
+
end
|
309
|
+
|
310
|
+
raw_shape = cache[[type.name, public_only]] ||= begin
|
311
|
+
shape = Interface::Shape.new(type: AST::Builtin.bottom_type, private: !public_only)
|
312
|
+
|
313
|
+
case type
|
314
|
+
when AST::Types::Name::Instance
|
315
|
+
definition = definition_builder.build_instance(type.name)
|
316
|
+
when AST::Types::Name::Interface
|
317
|
+
definition = definition_builder.build_interface(type.name)
|
318
|
+
when AST::Types::Name::Singleton
|
319
|
+
definition = definition_builder.build_singleton(type.name)
|
320
|
+
end
|
321
|
+
|
322
|
+
definition.methods.each do |name, method|
|
323
|
+
next if method.private? && public_only
|
324
|
+
|
325
|
+
Steep.logger.tagged "method = #{type}##{name}" do
|
326
|
+
shape.methods[name] = Interface::Shape::Entry.new(
|
327
|
+
method_types: method.defs.map do |type_def|
|
328
|
+
method_name = method_name_for(type_def, name)
|
329
|
+
decl = TypeInference::MethodCall::MethodDecl.new(method_name: method_name, method_def: type_def)
|
330
|
+
method_type = factory.method_type(type_def.type, method_decls: Set[decl])
|
331
|
+
replace_primitive_method(method_name, type_def, method_type)
|
332
|
+
end
|
333
|
+
)
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
shape
|
338
|
+
end
|
339
|
+
|
340
|
+
raw_shape.subst(subst, type: type)
|
341
|
+
end
|
342
|
+
|
343
|
+
def method_name_for(type_def, name)
|
344
|
+
type_name = type_def.implemented_in || type_def.defined_in
|
345
|
+
|
346
|
+
if name == :new && type_def.member.is_a?(RBS::AST::Members::MethodDefinition) && type_def.member.name == :initialize
|
347
|
+
return SingletonMethodName.new(type_name: type_name, method_name: name)
|
348
|
+
end
|
349
|
+
|
350
|
+
case type_def.member.kind
|
351
|
+
when :instance
|
352
|
+
InstanceMethodName.new(type_name: type_name, method_name: name)
|
353
|
+
when :singleton
|
354
|
+
SingletonMethodName.new(type_name: type_name, method_name: name)
|
355
|
+
when :singleton_instance
|
356
|
+
# Assume it a instance method, because `module_function` methods are typically defined with `def`
|
357
|
+
InstanceMethodName.new(type_name: type_name, method_name: name)
|
358
|
+
else
|
359
|
+
raise
|
360
|
+
end
|
361
|
+
end
|
362
|
+
|
363
|
+
def subtyping
|
364
|
+
@subtyping ||= Subtyping::Check.new(builder: self)
|
365
|
+
end
|
366
|
+
|
367
|
+
def union_shape(shape_type, shapes, public_only)
|
368
|
+
shapes.inject do |shape1, shape2|
|
369
|
+
Interface::Shape.new(type: shape_type, private: !public_only).tap do |shape|
|
370
|
+
common_methods = Set.new(shape1.methods.each_name) & Set.new(shape2.methods.each_name)
|
371
|
+
common_methods.each do |name|
|
372
|
+
Steep.logger.tagged(name.to_s) do
|
373
|
+
types1 = shape1.methods[name]&.method_types or raise
|
374
|
+
types2 = shape2.methods[name]&.method_types or raise
|
375
|
+
|
376
|
+
if types1 == types2
|
377
|
+
shape.methods[name] = (shape1.methods[name] or raise)
|
378
|
+
else
|
379
|
+
method_types = {}
|
380
|
+
|
381
|
+
types1.each do |type1|
|
382
|
+
types2.each do |type2|
|
383
|
+
if type1 == type2
|
384
|
+
method_types[type1] = true
|
385
|
+
else
|
386
|
+
if type = MethodType.union(type1, type2, subtyping)
|
387
|
+
method_types[type] = true
|
388
|
+
end
|
389
|
+
end
|
390
|
+
end
|
391
|
+
end
|
392
|
+
|
393
|
+
unless method_types.empty?
|
394
|
+
shape.methods[name] = Interface::Shape::Entry.new(method_types: method_types.keys)
|
395
|
+
end
|
396
|
+
end
|
397
|
+
end
|
398
|
+
end
|
399
|
+
end
|
400
|
+
end
|
401
|
+
end
|
402
|
+
|
403
|
+
def intersection_shape(type, shapes, public_only)
|
404
|
+
shapes.inject do |shape1, shape2|
|
405
|
+
Interface::Shape.new(type: type, private: !public_only).tap do |shape|
|
406
|
+
shape.methods.merge!(shape1.methods)
|
407
|
+
shape.methods.merge!(shape2.methods)
|
408
|
+
end
|
409
|
+
end
|
410
|
+
end
|
411
|
+
|
412
|
+
def tuple_shape(tuple, public_only, config)
|
413
|
+
element_type = AST::Types::Union.build(types: tuple.types, location: nil)
|
414
|
+
array_type = AST::Builtin::Array.instance_type(element_type)
|
415
|
+
|
416
|
+
array_shape = shape(array_type, public_only: public_only, config: config.no_resolve) or raise
|
417
|
+
shape = Shape.new(type: tuple, private: !public_only)
|
418
|
+
shape.methods.merge!(array_shape.methods)
|
419
|
+
|
420
|
+
aref_entry = array_shape.methods[:[]].yield_self do |aref|
|
421
|
+
raise unless aref
|
422
|
+
|
423
|
+
Shape::Entry.new(
|
424
|
+
method_types: tuple.types.map.with_index {|elem_type, index|
|
425
|
+
MethodType.new(
|
426
|
+
type_params: [],
|
427
|
+
type: Function.new(
|
428
|
+
params: Function::Params.build(required: [AST::Types::Literal.new(value: index)]),
|
429
|
+
return_type: elem_type,
|
430
|
+
location: nil
|
431
|
+
),
|
432
|
+
block: nil,
|
433
|
+
method_decls: Set[]
|
434
|
+
)
|
435
|
+
} + aref.method_types
|
436
|
+
)
|
437
|
+
end
|
438
|
+
|
439
|
+
aref_update_entry = array_shape.methods[:[]=].yield_self do |update|
|
440
|
+
raise unless update
|
441
|
+
|
442
|
+
Shape::Entry.new(
|
443
|
+
method_types: tuple.types.map.with_index {|elem_type, index|
|
444
|
+
MethodType.new(
|
445
|
+
type_params: [],
|
446
|
+
type: Function.new(
|
447
|
+
params: Function::Params.build(required: [AST::Types::Literal.new(value: index), elem_type]),
|
448
|
+
return_type: elem_type,
|
449
|
+
location: nil
|
450
|
+
),
|
451
|
+
block: nil,
|
452
|
+
method_decls: Set[]
|
453
|
+
)
|
454
|
+
} + update.method_types
|
455
|
+
)
|
456
|
+
end
|
457
|
+
|
458
|
+
fetch_entry = array_shape.methods[:fetch].yield_self do |fetch|
|
459
|
+
raise unless fetch
|
460
|
+
|
461
|
+
Shape::Entry.new(
|
462
|
+
method_types: tuple.types.flat_map.with_index {|elem_type, index|
|
463
|
+
[
|
464
|
+
MethodType.new(
|
465
|
+
type_params: [],
|
466
|
+
type: Function.new(
|
467
|
+
params: Function::Params.build(required: [AST::Types::Literal.new(value: index)]),
|
468
|
+
return_type: elem_type,
|
469
|
+
location: nil
|
470
|
+
),
|
471
|
+
block: nil,
|
472
|
+
method_decls: Set[]
|
473
|
+
),
|
474
|
+
MethodType.new(
|
475
|
+
type_params: [TypeParam.new(name: :T, upper_bound: nil, variance: :invariant, unchecked: false)],
|
476
|
+
type: Function.new(
|
477
|
+
params: Function::Params.build(
|
478
|
+
required: [
|
479
|
+
AST::Types::Literal.new(value: index),
|
480
|
+
AST::Types::Var.new(name: :T)
|
481
|
+
]
|
482
|
+
),
|
483
|
+
return_type: AST::Types::Union.build(types: [elem_type, AST::Types::Var.new(name: :T)]),
|
484
|
+
location: nil
|
485
|
+
),
|
486
|
+
block: nil,
|
487
|
+
method_decls: Set[]
|
488
|
+
),
|
489
|
+
MethodType.new(
|
490
|
+
type_params: [TypeParam.new(name: :T, upper_bound: nil, variance: :invariant, unchecked: false)],
|
491
|
+
type: Function.new(
|
492
|
+
params: Function::Params.build(required: [AST::Types::Literal.new(value: index)]),
|
493
|
+
return_type: AST::Types::Union.build(types: [elem_type, AST::Types::Var.new(name: :T)]),
|
494
|
+
location: nil
|
495
|
+
),
|
496
|
+
block: Block.new(
|
497
|
+
type: Function.new(
|
498
|
+
params: Function::Params.build(required: [AST::Builtin::Integer.instance_type]),
|
499
|
+
return_type: AST::Types::Var.new(name: :T),
|
500
|
+
location: nil
|
501
|
+
),
|
502
|
+
optional: false,
|
503
|
+
self_type: nil
|
504
|
+
),
|
505
|
+
method_decls: Set[]
|
506
|
+
)
|
507
|
+
]
|
508
|
+
} + fetch.method_types
|
509
|
+
)
|
510
|
+
end
|
511
|
+
|
512
|
+
first_entry = array_shape.methods[:first].yield_self do |first|
|
513
|
+
Shape::Entry.new(
|
514
|
+
method_types: [
|
515
|
+
MethodType.new(
|
516
|
+
type_params: [],
|
517
|
+
type: Function.new(
|
518
|
+
params: Function::Params.empty,
|
519
|
+
return_type: tuple.types[0] || AST::Builtin.nil_type,
|
520
|
+
location: nil
|
521
|
+
),
|
522
|
+
block: nil,
|
523
|
+
method_decls: Set[]
|
524
|
+
)
|
525
|
+
]
|
526
|
+
)
|
527
|
+
end
|
528
|
+
|
529
|
+
last_entry = array_shape.methods[:last].yield_self do |last|
|
530
|
+
Shape::Entry.new(
|
531
|
+
method_types: [
|
532
|
+
MethodType.new(
|
533
|
+
type_params: [],
|
534
|
+
type: Function.new(
|
535
|
+
params: Function::Params.empty,
|
536
|
+
return_type: tuple.types.last || AST::Builtin.nil_type,
|
537
|
+
location: nil
|
538
|
+
),
|
539
|
+
block: nil,
|
540
|
+
method_decls: Set[]
|
541
|
+
)
|
542
|
+
]
|
543
|
+
)
|
544
|
+
end
|
545
|
+
|
546
|
+
shape.methods[:[]] = aref_entry
|
547
|
+
shape.methods[:[]=] = aref_update_entry
|
548
|
+
shape.methods[:fetch] = fetch_entry
|
549
|
+
shape.methods[:first] = first_entry
|
550
|
+
shape.methods[:last] = last_entry
|
551
|
+
|
552
|
+
shape.subst(
|
553
|
+
Substitution.build(
|
554
|
+
[], [],
|
555
|
+
self_type: config.resolve_self ? tuple : AST::Types::Self.instance,
|
556
|
+
instance_type: AST::Builtin::Array.instance_type(fill_untyped: true),
|
557
|
+
module_type: AST::Builtin::Array.module_type
|
558
|
+
)
|
559
|
+
)
|
560
|
+
end
|
561
|
+
|
562
|
+
def record_shape(record, public_only, config)
|
563
|
+
all_key_type = AST::Types::Union.build(
|
564
|
+
types: record.elements.each_key.map {|value| AST::Types::Literal.new(value: value, location: nil) },
|
565
|
+
location: nil
|
566
|
+
)
|
567
|
+
all_value_type = AST::Types::Union.build(types: record.elements.values, location: nil)
|
568
|
+
hash_type = AST::Builtin::Hash.instance_type(all_key_type, all_value_type)
|
569
|
+
|
570
|
+
hash_shape = shape(hash_type, public_only: public_only, config: config.no_resolve) or raise
|
571
|
+
shape = Shape.new(type: record, private: !public_only)
|
572
|
+
shape.methods.merge!(hash_shape.methods)
|
573
|
+
|
574
|
+
shape.methods[:[]] = hash_shape.methods[:[]].yield_self do |aref|
|
575
|
+
aref or raise
|
576
|
+
Shape::Entry.new(
|
577
|
+
method_types: record.elements.map do |key_value, value_type|
|
578
|
+
key_type = AST::Types::Literal.new(value: key_value, location: nil)
|
579
|
+
|
580
|
+
MethodType.new(
|
581
|
+
type_params: [],
|
582
|
+
type: Function.new(
|
583
|
+
params: Function::Params.build(required: [key_type]),
|
584
|
+
return_type: value_type,
|
585
|
+
location: nil
|
586
|
+
),
|
587
|
+
block: nil,
|
588
|
+
method_decls: Set[]
|
589
|
+
)
|
590
|
+
end + aref.method_types
|
591
|
+
)
|
592
|
+
end
|
593
|
+
|
594
|
+
shape.methods[:[]=] = hash_shape.methods[:[]=].yield_self do |update|
|
595
|
+
update or raise
|
596
|
+
|
597
|
+
Shape::Entry.new(
|
598
|
+
method_types: record.elements.map do |key_value, value_type|
|
599
|
+
key_type = AST::Types::Literal.new(value: key_value, location: nil)
|
600
|
+
MethodType.new(
|
601
|
+
type_params: [],
|
602
|
+
type: Function.new(
|
603
|
+
params: Function::Params.build(required: [key_type, value_type]),
|
604
|
+
return_type: value_type,
|
605
|
+
location: nil),
|
606
|
+
block: nil,
|
607
|
+
method_decls: Set[]
|
608
|
+
)
|
609
|
+
end + update.method_types
|
610
|
+
)
|
611
|
+
end
|
612
|
+
|
613
|
+
shape.methods[:fetch] = hash_shape.methods[:fetch].yield_self do |update|
|
614
|
+
update or raise
|
615
|
+
|
616
|
+
Shape::Entry.new(
|
617
|
+
method_types: record.elements.flat_map {|key_value, value_type|
|
618
|
+
key_type = AST::Types::Literal.new(value: key_value, location: nil)
|
619
|
+
|
620
|
+
[
|
621
|
+
MethodType.new(
|
622
|
+
type_params: [],
|
623
|
+
type: Function.new(
|
624
|
+
params: Function::Params.build(required: [key_type]),
|
625
|
+
return_type: value_type,
|
626
|
+
location: nil
|
627
|
+
),
|
628
|
+
block: nil,
|
629
|
+
method_decls: Set[]
|
630
|
+
),
|
631
|
+
MethodType.new(
|
632
|
+
type_params: [TypeParam.new(name: :T, upper_bound: nil, variance: :invariant, unchecked: false)],
|
633
|
+
type: Function.new(
|
634
|
+
params: Function::Params.build(required: [key_type, AST::Types::Var.new(name: :T)]),
|
635
|
+
return_type: AST::Types::Union.build(types: [value_type, AST::Types::Var.new(name: :T)]),
|
636
|
+
location: nil
|
637
|
+
),
|
638
|
+
block: nil,
|
639
|
+
method_decls: Set[]
|
640
|
+
),
|
641
|
+
MethodType.new(
|
642
|
+
type_params: [TypeParam.new(name: :T, upper_bound: nil, variance: :invariant, unchecked: false)],
|
643
|
+
type: Function.new(
|
644
|
+
params: Function::Params.build(required: [key_type]),
|
645
|
+
return_type: AST::Types::Union.build(types: [value_type, AST::Types::Var.new(name: :T)]),
|
646
|
+
location: nil
|
647
|
+
),
|
648
|
+
block: Block.new(
|
649
|
+
type: Function.new(
|
650
|
+
params: Function::Params.build(required: [all_key_type]),
|
651
|
+
return_type: AST::Types::Var.new(name: :T),
|
652
|
+
location: nil
|
653
|
+
),
|
654
|
+
optional: false,
|
655
|
+
self_type: nil
|
656
|
+
),
|
657
|
+
method_decls: Set[]
|
658
|
+
)
|
659
|
+
]
|
660
|
+
} + update.method_types
|
661
|
+
)
|
662
|
+
end
|
663
|
+
|
664
|
+
shape.subst(
|
665
|
+
Substitution.build(
|
666
|
+
[], [],
|
667
|
+
self_type: config.resolve_self ? record : AST::Types::Self.instance,
|
668
|
+
instance_type: AST::Builtin::Hash.instance_type(fill_untyped: true),
|
669
|
+
module_type: AST::Builtin::Hash.module_type
|
670
|
+
)
|
671
|
+
)
|
672
|
+
end
|
673
|
+
|
674
|
+
def proc_shape(proc, public_only, config)
|
675
|
+
proc_shape = shape(AST::Builtin::Proc.instance_type, public_only: public_only, config: config.no_resolve) or raise
|
676
|
+
|
677
|
+
shape = Shape.new(type: proc, private: !public_only)
|
678
|
+
shape.methods.merge!(proc_shape.methods)
|
679
|
+
|
680
|
+
shape.methods[:[]] = shape.methods[:call] = Shape::Entry.new(
|
681
|
+
method_types: [MethodType.new(type_params: [], type: proc.type, block: proc.block, method_decls: Set[])]
|
682
|
+
)
|
683
|
+
|
684
|
+
shape.subst(
|
685
|
+
Substitution.build(
|
686
|
+
[], [],
|
687
|
+
self_type: config.resolve_self ? proc : AST::Types::Self.instance,
|
688
|
+
instance_type: AST::Builtin::Proc.instance_type(fill_untyped: true),
|
689
|
+
module_type: AST::Builtin::Proc.module_type
|
690
|
+
)
|
691
|
+
)
|
692
|
+
end
|
693
|
+
|
694
|
+
def replace_primitive_method(method_name, method_def, method_type)
|
695
|
+
defined_in = method_def.defined_in
|
696
|
+
member = method_def.member
|
697
|
+
|
698
|
+
if member.is_a?(RBS::AST::Members::MethodDefinition)
|
699
|
+
case method_name.method_name
|
700
|
+
when :is_a?, :kind_of?, :instance_of?
|
701
|
+
if defined_in == RBS::BuiltinNames::Object.name && member.instance?
|
702
|
+
return method_type.with(
|
703
|
+
type: method_type.type.with(
|
704
|
+
return_type: AST::Types::Logic::ReceiverIsArg.new(location: method_type.type.return_type.location)
|
705
|
+
)
|
706
|
+
)
|
707
|
+
end
|
708
|
+
|
709
|
+
when :nil?
|
710
|
+
case defined_in
|
711
|
+
when RBS::BuiltinNames::Object.name, AST::Builtin::NilClass.module_name
|
712
|
+
return method_type.with(
|
713
|
+
type: method_type.type.with(
|
714
|
+
return_type: AST::Types::Logic::ReceiverIsNil.new(location: method_type.type.return_type.location)
|
715
|
+
)
|
716
|
+
)
|
717
|
+
end
|
718
|
+
|
719
|
+
when :!
|
720
|
+
case defined_in
|
721
|
+
when RBS::BuiltinNames::BasicObject.name,
|
722
|
+
RBS::BuiltinNames::TrueClass.name,
|
723
|
+
RBS::BuiltinNames::FalseClass.name,
|
724
|
+
AST::Builtin::NilClass.module_name
|
725
|
+
return method_type.with(
|
726
|
+
type: method_type.type.with(
|
727
|
+
return_type: AST::Types::Logic::Not.new(location: method_type.type.return_type.location)
|
728
|
+
)
|
729
|
+
)
|
730
|
+
end
|
731
|
+
|
732
|
+
when :===
|
733
|
+
case defined_in
|
734
|
+
when RBS::BuiltinNames::Module.name
|
735
|
+
return method_type.with(
|
736
|
+
type: method_type.type.with(
|
737
|
+
return_type: AST::Types::Logic::ArgIsReceiver.new(location: method_type.type.return_type.location)
|
738
|
+
)
|
739
|
+
)
|
740
|
+
when RBS::BuiltinNames::Object.name, RBS::BuiltinNames::String.name, RBS::BuiltinNames::Integer.name, RBS::BuiltinNames::Symbol.name,
|
741
|
+
RBS::BuiltinNames::TrueClass.name, RBS::BuiltinNames::FalseClass.name, TypeName("::NilClass")
|
742
|
+
# Value based type-case works on literal types which is available for String, Integer, Symbol, TrueClass, FalseClass, and NilClass
|
743
|
+
return method_type.with(
|
744
|
+
type: method_type.type.with(
|
745
|
+
return_type: AST::Types::Logic::ArgEqualsReceiver.new(location: method_type.type.return_type.location)
|
746
|
+
)
|
747
|
+
)
|
748
|
+
end
|
749
|
+
end
|
750
|
+
end
|
751
|
+
|
752
|
+
method_type
|
753
|
+
end
|
754
|
+
end
|
755
|
+
end
|
756
|
+
end
|