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.
Files changed (140) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +20 -0
  3. data/Gemfile +0 -1
  4. data/Gemfile.lock +12 -11
  5. data/Gemfile.steep +1 -1
  6. data/Gemfile.steep.lock +9 -9
  7. data/README.md +3 -3
  8. data/Steepfile +23 -0
  9. data/bin/steep-prof +2 -1
  10. data/lib/steep/annotation_parser.rb +1 -1
  11. data/lib/steep/ast/types/class.rb +4 -0
  12. data/lib/steep/ast/types/factory.rb +86 -602
  13. data/lib/steep/ast/types/instance.rb +4 -0
  14. data/lib/steep/ast/types/literal.rb +1 -1
  15. data/lib/steep/ast/types/proc.rb +22 -8
  16. data/lib/steep/ast/types/self.rb +4 -0
  17. data/lib/steep/ast/types/union.rb +1 -1
  18. data/lib/steep/cli.rb +24 -1
  19. data/lib/steep/diagnostic/ruby.rb +17 -22
  20. data/lib/steep/drivers/checkfile.rb +205 -0
  21. data/lib/steep/drivers/validate.rb +3 -1
  22. data/lib/steep/equatable.rb +2 -0
  23. data/lib/steep/interface/block.rb +21 -11
  24. data/lib/steep/interface/builder.rb +756 -0
  25. data/lib/steep/interface/function.rb +32 -24
  26. data/lib/steep/interface/method_type.rb +191 -78
  27. data/lib/steep/interface/shape.rb +132 -0
  28. data/lib/steep/interface/substitution.rb +23 -12
  29. data/lib/steep/interface/type_param.rb +1 -2
  30. data/lib/steep/path_helper.rb +1 -1
  31. data/lib/steep/project.rb +5 -7
  32. data/lib/steep/server/base_worker.rb +2 -2
  33. data/lib/steep/server/change_buffer.rb +4 -3
  34. data/lib/steep/server/interaction_worker.rb +1 -1
  35. data/lib/steep/server/master.rb +69 -9
  36. data/lib/steep/server/type_check_worker.rb +13 -11
  37. data/lib/steep/server/worker_process.rb +9 -7
  38. data/lib/steep/services/completion_provider.rb +15 -3
  39. data/lib/steep/services/hover_provider/singleton_methods.rb +5 -6
  40. data/lib/steep/services/signature_service.rb +13 -8
  41. data/lib/steep/services/type_check_service.rb +2 -0
  42. data/lib/steep/signature/validator.rb +1 -1
  43. data/lib/steep/subtyping/check.rb +154 -103
  44. data/lib/steep/subtyping/relation.rb +3 -3
  45. data/lib/steep/subtyping/result.rb +20 -2
  46. data/lib/steep/subtyping/variable_variance.rb +9 -0
  47. data/lib/steep/type_construction.rb +558 -299
  48. data/lib/steep/type_inference/block_params.rb +169 -86
  49. data/lib/steep/type_inference/logic_type_interpreter.rb +9 -14
  50. data/lib/steep/type_inference/method_params.rb +12 -7
  51. data/lib/steep/type_inference/send_args.rb +41 -35
  52. data/lib/steep/type_inference/type_env_builder.rb +1 -1
  53. data/lib/steep/version.rb +1 -1
  54. data/lib/steep.rb +71 -2
  55. data/rbs_collection.steep.lock.yaml +18 -30
  56. data/rbs_collection.steep.yaml +1 -0
  57. data/sig/shims/language-server_protocol.rbs +20 -0
  58. data/sig/shims/tagged_logging.rbs +6 -0
  59. data/sig/steep/ast/annotation/collection.rbs +6 -6
  60. data/sig/steep/ast/types/class.rbs +3 -0
  61. data/sig/steep/ast/types/factory.rbs +38 -32
  62. data/sig/steep/ast/types/instance.rbs +3 -0
  63. data/sig/steep/ast/types/intersection.rbs +1 -1
  64. data/sig/steep/ast/types/literal.rbs +7 -7
  65. data/sig/steep/ast/types/name.rbs +14 -13
  66. data/sig/steep/ast/types/proc.rbs +3 -1
  67. data/sig/steep/ast/types/self.rbs +3 -0
  68. data/sig/steep/ast/types/var.rbs +1 -1
  69. data/sig/steep/diagnostic/ruby.rbs +30 -34
  70. data/sig/steep/drivers/annotations.rbs +17 -0
  71. data/sig/steep/drivers/check.rbs +33 -0
  72. data/sig/steep/drivers/checkfile.rbs +26 -0
  73. data/sig/steep/drivers/diagnostic_printer.rbs +25 -0
  74. data/sig/steep/drivers/init.rbs +19 -0
  75. data/sig/steep/drivers/langserver.rbs +35 -0
  76. data/sig/steep/drivers/print_project.rbs +15 -0
  77. data/sig/steep/drivers/stats.rbs +37 -0
  78. data/sig/steep/drivers/utils/driver_helper.rbs +23 -0
  79. data/sig/steep/drivers/utils/jobs_count.rbs +11 -0
  80. data/sig/steep/drivers/validate.rbs +15 -0
  81. data/sig/steep/drivers/vendor.rbs +19 -0
  82. data/sig/steep/drivers/watch.rbs +27 -0
  83. data/sig/steep/drivers/worker.rbs +31 -0
  84. data/sig/steep/equatable.rbs +11 -0
  85. data/sig/steep/index/rbs_index.rbs +91 -0
  86. data/sig/steep/index/signature_symbol_provider.rbs +29 -0
  87. data/sig/steep/index/source_index.rbs +63 -0
  88. data/sig/steep/interface/block.rbs +3 -1
  89. data/sig/steep/interface/builder.rbs +152 -0
  90. data/sig/steep/interface/function.rbs +67 -55
  91. data/sig/steep/interface/method_type.rbs +60 -12
  92. data/sig/steep/interface/shape.rbs +61 -0
  93. data/sig/steep/interface/substitution.rbs +18 -22
  94. data/sig/steep/interface/type_param.rbs +9 -1
  95. data/sig/steep/path_helper.rbs +7 -0
  96. data/sig/steep/project/pattern.rbs +10 -10
  97. data/sig/steep/project/target.rbs +2 -2
  98. data/sig/steep/project.rbs +15 -8
  99. data/sig/steep/server/base_worker.rbs +49 -0
  100. data/sig/steep/server/change_buffer.rbs +32 -0
  101. data/sig/steep/server/interaction_worker.rbs +41 -0
  102. data/sig/steep/server/lsp_formatter.rbs +29 -0
  103. data/sig/steep/server/master.rbs +260 -0
  104. data/sig/steep/server/type_check_worker.rbs +135 -0
  105. data/sig/steep/server/worker_process.rbs +29 -0
  106. data/sig/steep/services/completion_provider.rbs +5 -5
  107. data/sig/steep/services/content_change.rbs +14 -12
  108. data/sig/steep/services/file_loader.rbs +12 -4
  109. data/sig/steep/services/hover_provider/singleton_methods.rbs +1 -1
  110. data/sig/steep/services/path_assignment.rbs +7 -7
  111. data/sig/steep/services/signature_service.rbs +67 -40
  112. data/sig/steep/services/type_check_service.rbs +53 -39
  113. data/sig/steep/subtyping/check.rbs +80 -44
  114. data/sig/steep/subtyping/relation.rbs +24 -22
  115. data/sig/steep/subtyping/result.rbs +48 -30
  116. data/sig/steep/subtyping/variable_variance.rbs +2 -0
  117. data/sig/steep/type_construction.rbs +132 -23
  118. data/sig/steep/type_inference/block_params.rbs +120 -18
  119. data/sig/steep/type_inference/context.rbs +45 -20
  120. data/sig/steep/type_inference/context_array.rbs +37 -0
  121. data/sig/steep/type_inference/logic_type_interpreter.rbs +3 -1
  122. data/sig/steep/type_inference/method_params.rbs +13 -9
  123. data/sig/steep/type_inference/send_args.rbs +229 -0
  124. data/sig/steep/type_inference/type_env_builder.rbs +1 -1
  125. data/sig/steep/typing.rbs +4 -4
  126. data/sig/steep.rbs +4 -2
  127. data/smoke/block/e.rb +12 -0
  128. data/smoke/block/e.rbs +4 -0
  129. data/smoke/block/test_expectations.yml +12 -0
  130. data/smoke/regression/block_param_split.rb +7 -0
  131. data/smoke/regression/block_param_split.rbs +3 -0
  132. data/smoke/regression/empty_yield.rb +5 -0
  133. data/smoke/regression/empty_yield.rbs +3 -0
  134. data/smoke/regression/test_expectations.yml +12 -0
  135. data/smoke/yield/test_expectations.yml +4 -4
  136. data/steep.gemspec +2 -1
  137. metadata +61 -9
  138. data/lib/steep/interface/interface.rb +0 -34
  139. data/sig/steep/interface/interface.rbs +0 -23
  140. 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