irb 1.8.3 → 1.9.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,1169 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'set'
4
+ require_relative 'types'
5
+ require_relative 'scope'
6
+ require 'prism'
7
+
8
+ module IRB
9
+ module TypeCompletion
10
+ class TypeAnalyzer
11
+ class DigTarget
12
+ def initialize(parents, receiver, &block)
13
+ @dig_ids = parents.to_h { [_1.__id__, true] }
14
+ @target_id = receiver.__id__
15
+ @block = block
16
+ end
17
+
18
+ def dig?(node) = @dig_ids[node.__id__]
19
+ def target?(node) = @target_id == node.__id__
20
+ def resolve(type, scope)
21
+ @block.call type, scope
22
+ end
23
+ end
24
+
25
+ OBJECT_METHODS = {
26
+ to_s: Types::STRING,
27
+ to_str: Types::STRING,
28
+ to_a: Types::ARRAY,
29
+ to_ary: Types::ARRAY,
30
+ to_h: Types::HASH,
31
+ to_hash: Types::HASH,
32
+ to_i: Types::INTEGER,
33
+ to_int: Types::INTEGER,
34
+ to_f: Types::FLOAT,
35
+ to_c: Types::COMPLEX,
36
+ to_r: Types::RATIONAL
37
+ }
38
+
39
+ def initialize(dig_targets)
40
+ @dig_targets = dig_targets
41
+ end
42
+
43
+ def evaluate(node, scope)
44
+ method = "evaluate_#{node.type}"
45
+ if respond_to? method
46
+ result = send method, node, scope
47
+ else
48
+ result = Types::NIL
49
+ end
50
+ @dig_targets.resolve result, scope if @dig_targets.target? node
51
+ result
52
+ end
53
+
54
+ def evaluate_program_node(node, scope)
55
+ evaluate node.statements, scope
56
+ end
57
+
58
+ def evaluate_statements_node(node, scope)
59
+ if node.body.empty?
60
+ Types::NIL
61
+ else
62
+ node.body.map { evaluate _1, scope }.last
63
+ end
64
+ end
65
+
66
+ def evaluate_def_node(node, scope)
67
+ if node.receiver
68
+ self_type = evaluate node.receiver, scope
69
+ else
70
+ current_self_types = scope.self_type.types
71
+ self_types = current_self_types.map do |type|
72
+ if type.is_a?(Types::SingletonType) && type.module_or_class.is_a?(Class)
73
+ Types::InstanceType.new type.module_or_class
74
+ else
75
+ type
76
+ end
77
+ end
78
+ self_type = Types::UnionType[*self_types]
79
+ end
80
+ if @dig_targets.dig?(node.body) || @dig_targets.dig?(node.parameters)
81
+ params_table = node.locals.to_h { [_1.to_s, Types::NIL] }
82
+ method_scope = Scope.new(
83
+ scope,
84
+ { **params_table, Scope::BREAK_RESULT => nil, Scope::NEXT_RESULT => nil, Scope::RETURN_RESULT => nil },
85
+ self_type: self_type,
86
+ trace_lvar: false,
87
+ trace_ivar: false
88
+ )
89
+ if node.parameters
90
+ # node.parameters is Prism::ParametersNode
91
+ assign_parameters node.parameters, method_scope, [], {}
92
+ end
93
+
94
+ if @dig_targets.dig?(node.body)
95
+ method_scope.conditional do |s|
96
+ evaluate node.body, s
97
+ end
98
+ end
99
+ method_scope.merge_jumps
100
+ scope.update method_scope
101
+ end
102
+ Types::SYMBOL
103
+ end
104
+
105
+ def evaluate_integer_node(_node, _scope) = Types::INTEGER
106
+
107
+ def evaluate_float_node(_node, _scope) = Types::FLOAT
108
+
109
+ def evaluate_rational_node(_node, _scope) = Types::RATIONAL
110
+
111
+ def evaluate_imaginary_node(_node, _scope) = Types::COMPLEX
112
+
113
+ def evaluate_string_node(_node, _scope) = Types::STRING
114
+
115
+ def evaluate_x_string_node(_node, _scope)
116
+ Types::UnionType[Types::STRING, Types::NIL]
117
+ end
118
+
119
+ def evaluate_symbol_node(_node, _scope) = Types::SYMBOL
120
+
121
+ def evaluate_regular_expression_node(_node, _scope) = Types::REGEXP
122
+
123
+ def evaluate_string_concat_node(node, scope)
124
+ evaluate node.left, scope
125
+ evaluate node.right, scope
126
+ Types::STRING
127
+ end
128
+
129
+ def evaluate_interpolated_string_node(node, scope)
130
+ node.parts.each { evaluate _1, scope }
131
+ Types::STRING
132
+ end
133
+
134
+ def evaluate_interpolated_x_string_node(node, scope)
135
+ node.parts.each { evaluate _1, scope }
136
+ Types::STRING
137
+ end
138
+
139
+ def evaluate_interpolated_symbol_node(node, scope)
140
+ node.parts.each { evaluate _1, scope }
141
+ Types::SYMBOL
142
+ end
143
+
144
+ def evaluate_interpolated_regular_expression_node(node, scope)
145
+ node.parts.each { evaluate _1, scope }
146
+ Types::REGEXP
147
+ end
148
+
149
+ def evaluate_embedded_statements_node(node, scope)
150
+ node.statements ? evaluate(node.statements, scope) : Types::NIL
151
+ Types::STRING
152
+ end
153
+
154
+ def evaluate_embedded_variable_node(node, scope)
155
+ evaluate node.variable, scope
156
+ Types::STRING
157
+ end
158
+
159
+ def evaluate_array_node(node, scope)
160
+ Types.array_of evaluate_list_splat_items(node.elements, scope)
161
+ end
162
+
163
+ def evaluate_hash_node(node, scope) = evaluate_hash(node, scope)
164
+ def evaluate_keyword_hash_node(node, scope) = evaluate_hash(node, scope)
165
+ def evaluate_hash(node, scope)
166
+ keys = []
167
+ values = []
168
+ node.elements.each do |assoc|
169
+ case assoc
170
+ when Prism::AssocNode
171
+ keys << evaluate(assoc.key, scope)
172
+ values << evaluate(assoc.value, scope)
173
+ when Prism::AssocSplatNode
174
+ next unless assoc.value # def f(**); {**}
175
+
176
+ hash = evaluate assoc.value, scope
177
+ unless hash.is_a?(Types::InstanceType) && hash.klass == Hash
178
+ hash = method_call hash, :to_hash, [], nil, nil, scope
179
+ end
180
+ if hash.is_a?(Types::InstanceType) && hash.klass == Hash
181
+ keys << hash.params[:K] if hash.params[:K]
182
+ values << hash.params[:V] if hash.params[:V]
183
+ end
184
+ end
185
+ end
186
+ if keys.empty? && values.empty?
187
+ Types::InstanceType.new Hash
188
+ else
189
+ Types::InstanceType.new Hash, K: Types::UnionType[*keys], V: Types::UnionType[*values]
190
+ end
191
+ end
192
+
193
+ def evaluate_parentheses_node(node, scope)
194
+ node.body ? evaluate(node.body, scope) : Types::NIL
195
+ end
196
+
197
+ def evaluate_constant_path_node(node, scope)
198
+ type, = evaluate_constant_node_info node, scope
199
+ type
200
+ end
201
+
202
+ def evaluate_self_node(_node, scope) = scope.self_type
203
+
204
+ def evaluate_true_node(_node, _scope) = Types::TRUE
205
+
206
+ def evaluate_false_node(_node, _scope) = Types::FALSE
207
+
208
+ def evaluate_nil_node(_node, _scope) = Types::NIL
209
+
210
+ def evaluate_source_file_node(_node, _scope) = Types::STRING
211
+
212
+ def evaluate_source_line_node(_node, _scope) = Types::INTEGER
213
+
214
+ def evaluate_source_encoding_node(_node, _scope) = Types::InstanceType.new(Encoding)
215
+
216
+ def evaluate_numbered_reference_read_node(_node, _scope)
217
+ Types::UnionType[Types::STRING, Types::NIL]
218
+ end
219
+
220
+ def evaluate_back_reference_read_node(_node, _scope)
221
+ Types::UnionType[Types::STRING, Types::NIL]
222
+ end
223
+
224
+ def evaluate_reference_read(node, scope)
225
+ scope[node.name.to_s] || Types::NIL
226
+ end
227
+ alias evaluate_constant_read_node evaluate_reference_read
228
+ alias evaluate_global_variable_read_node evaluate_reference_read
229
+ alias evaluate_local_variable_read_node evaluate_reference_read
230
+ alias evaluate_class_variable_read_node evaluate_reference_read
231
+ alias evaluate_instance_variable_read_node evaluate_reference_read
232
+
233
+
234
+ def evaluate_call_node(node, scope)
235
+ is_field_assign = node.name.match?(/[^<>=!\]]=\z/) || (node.name == :[]= && !node.call_operator)
236
+ receiver_type = node.receiver ? evaluate(node.receiver, scope) : scope.self_type
237
+ evaluate_method = lambda do |scope|
238
+ args_types, kwargs_types, block_sym_node, has_block = evaluate_call_node_arguments node, scope
239
+
240
+ if block_sym_node
241
+ block_sym = block_sym_node.value
242
+ if @dig_targets.target? block_sym_node
243
+ # method(args, &:completion_target)
244
+ call_block_proc = ->(block_args, _self_type) do
245
+ block_receiver = block_args.first || Types::OBJECT
246
+ @dig_targets.resolve block_receiver, scope
247
+ Types::OBJECT
248
+ end
249
+ else
250
+ call_block_proc = ->(block_args, _self_type) do
251
+ block_receiver, *rest = block_args
252
+ block_receiver ? method_call(block_receiver || Types::OBJECT, block_sym, rest, nil, nil, scope) : Types::OBJECT
253
+ end
254
+ end
255
+ elsif node.block.is_a? Prism::BlockNode
256
+ call_block_proc = ->(block_args, block_self_type) do
257
+ scope.conditional do |s|
258
+ numbered_parameters = node.block.locals.grep(/\A_[1-9]/).map(&:to_s)
259
+ params_table = node.block.locals.to_h { [_1.to_s, Types::NIL] }
260
+ table = { **params_table, Scope::BREAK_RESULT => nil, Scope::NEXT_RESULT => nil }
261
+ block_scope = Scope.new s, table, self_type: block_self_type, trace_ivar: !block_self_type
262
+ # TODO kwargs
263
+ if node.block.parameters&.parameters
264
+ # node.block.parameters is Prism::BlockParametersNode
265
+ assign_parameters node.block.parameters.parameters, block_scope, block_args, {}
266
+ elsif !numbered_parameters.empty?
267
+ assign_numbered_parameters numbered_parameters, block_scope, block_args, {}
268
+ end
269
+ result = node.block.body ? evaluate(node.block.body, block_scope) : Types::NIL
270
+ block_scope.merge_jumps
271
+ s.update block_scope
272
+ nexts = block_scope[Scope::NEXT_RESULT]
273
+ breaks = block_scope[Scope::BREAK_RESULT]
274
+ if block_scope.terminated?
275
+ [Types::UnionType[*nexts], breaks]
276
+ else
277
+ [Types::UnionType[result, *nexts], breaks]
278
+ end
279
+ end
280
+ end
281
+ elsif has_block
282
+ call_block_proc = ->(_block_args, _self_type) { Types::OBJECT }
283
+ end
284
+ result = method_call receiver_type, node.name, args_types, kwargs_types, call_block_proc, scope
285
+ if is_field_assign
286
+ args_types.last || Types::NIL
287
+ else
288
+ result
289
+ end
290
+ end
291
+ if node.call_operator == '&.'
292
+ result = scope.conditional { evaluate_method.call _1 }
293
+ if receiver_type.nillable?
294
+ Types::UnionType[result, Types::NIL]
295
+ else
296
+ result
297
+ end
298
+ else
299
+ evaluate_method.call scope
300
+ end
301
+ end
302
+
303
+ def evaluate_and_node(node, scope) = evaluate_and_or(node, scope, and_op: true)
304
+ def evaluate_or_node(node, scope) = evaluate_and_or(node, scope, and_op: false)
305
+ def evaluate_and_or(node, scope, and_op:)
306
+ left = evaluate node.left, scope
307
+ right = scope.conditional { evaluate node.right, _1 }
308
+ if and_op
309
+ Types::UnionType[right, Types::NIL, Types::FALSE]
310
+ else
311
+ Types::UnionType[left, right]
312
+ end
313
+ end
314
+
315
+ def evaluate_call_operator_write_node(node, scope) = evaluate_call_write(node, scope, :operator, node.write_name)
316
+ def evaluate_call_and_write_node(node, scope) = evaluate_call_write(node, scope, :and, node.write_name)
317
+ def evaluate_call_or_write_node(node, scope) = evaluate_call_write(node, scope, :or, node.write_name)
318
+ def evaluate_index_operator_write_node(node, scope) = evaluate_call_write(node, scope, :operator, :[]=)
319
+ def evaluate_index_and_write_node(node, scope) = evaluate_call_write(node, scope, :and, :[]=)
320
+ def evaluate_index_or_write_node(node, scope) = evaluate_call_write(node, scope, :or, :[]=)
321
+ def evaluate_call_write(node, scope, operator, write_name)
322
+ receiver_type = evaluate node.receiver, scope
323
+ if write_name == :[]=
324
+ args_types, kwargs_types, block_sym_node, has_block = evaluate_call_node_arguments node, scope
325
+ else
326
+ args_types = []
327
+ end
328
+ if block_sym_node
329
+ block_sym = block_sym_node.value
330
+ call_block_proc = ->(block_args, _self_type) do
331
+ block_receiver, *rest = block_args
332
+ block_receiver ? method_call(block_receiver || Types::OBJECT, block_sym, rest, nil, nil, scope) : Types::OBJECT
333
+ end
334
+ elsif has_block
335
+ call_block_proc = ->(_block_args, _self_type) { Types::OBJECT }
336
+ end
337
+ method = write_name.to_s.delete_suffix('=')
338
+ left = method_call receiver_type, method, args_types, kwargs_types, call_block_proc, scope
339
+ case operator
340
+ when :and
341
+ right = scope.conditional { evaluate node.value, _1 }
342
+ Types::UnionType[right, Types::NIL, Types::FALSE]
343
+ when :or
344
+ right = scope.conditional { evaluate node.value, _1 }
345
+ Types::UnionType[left, right]
346
+ else
347
+ right = evaluate node.value, scope
348
+ method_call left, node.operator, [right], nil, nil, scope, name_match: false
349
+ end
350
+ end
351
+
352
+ def evaluate_variable_operator_write(node, scope)
353
+ left = scope[node.name.to_s] || Types::OBJECT
354
+ right = evaluate node.value, scope
355
+ scope[node.name.to_s] = method_call left, node.operator, [right], nil, nil, scope, name_match: false
356
+ end
357
+ alias evaluate_global_variable_operator_write_node evaluate_variable_operator_write
358
+ alias evaluate_local_variable_operator_write_node evaluate_variable_operator_write
359
+ alias evaluate_class_variable_operator_write_node evaluate_variable_operator_write
360
+ alias evaluate_instance_variable_operator_write_node evaluate_variable_operator_write
361
+
362
+ def evaluate_variable_and_write(node, scope)
363
+ right = scope.conditional { evaluate node.value, scope }
364
+ scope[node.name.to_s] = Types::UnionType[right, Types::NIL, Types::FALSE]
365
+ end
366
+ alias evaluate_global_variable_and_write_node evaluate_variable_and_write
367
+ alias evaluate_local_variable_and_write_node evaluate_variable_and_write
368
+ alias evaluate_class_variable_and_write_node evaluate_variable_and_write
369
+ alias evaluate_instance_variable_and_write_node evaluate_variable_and_write
370
+
371
+ def evaluate_variable_or_write(node, scope)
372
+ left = scope[node.name.to_s] || Types::OBJECT
373
+ right = scope.conditional { evaluate node.value, scope }
374
+ scope[node.name.to_s] = Types::UnionType[left, right]
375
+ end
376
+ alias evaluate_global_variable_or_write_node evaluate_variable_or_write
377
+ alias evaluate_local_variable_or_write_node evaluate_variable_or_write
378
+ alias evaluate_class_variable_or_write_node evaluate_variable_or_write
379
+ alias evaluate_instance_variable_or_write_node evaluate_variable_or_write
380
+
381
+ def evaluate_constant_operator_write_node(node, scope)
382
+ left = scope[node.name.to_s] || Types::OBJECT
383
+ right = evaluate node.value, scope
384
+ scope[node.name.to_s] = method_call left, node.operator, [right], nil, nil, scope, name_match: false
385
+ end
386
+
387
+ def evaluate_constant_and_write_node(node, scope)
388
+ right = scope.conditional { evaluate node.value, scope }
389
+ scope[node.name.to_s] = Types::UnionType[right, Types::NIL, Types::FALSE]
390
+ end
391
+
392
+ def evaluate_constant_or_write_node(node, scope)
393
+ left = scope[node.name.to_s] || Types::OBJECT
394
+ right = scope.conditional { evaluate node.value, scope }
395
+ scope[node.name.to_s] = Types::UnionType[left, right]
396
+ end
397
+
398
+ def evaluate_constant_path_operator_write_node(node, scope)
399
+ left, receiver, _parent_module, name = evaluate_constant_node_info node.target, scope
400
+ right = evaluate node.value, scope
401
+ value = method_call left, node.operator, [right], nil, nil, scope, name_match: false
402
+ const_path_write receiver, name, value, scope
403
+ value
404
+ end
405
+
406
+ def evaluate_constant_path_and_write_node(node, scope)
407
+ _left, receiver, _parent_module, name = evaluate_constant_node_info node.target, scope
408
+ right = scope.conditional { evaluate node.value, scope }
409
+ value = Types::UnionType[right, Types::NIL, Types::FALSE]
410
+ const_path_write receiver, name, value, scope
411
+ value
412
+ end
413
+
414
+ def evaluate_constant_path_or_write_node(node, scope)
415
+ left, receiver, _parent_module, name = evaluate_constant_node_info node.target, scope
416
+ right = scope.conditional { evaluate node.value, scope }
417
+ value = Types::UnionType[left, right]
418
+ const_path_write receiver, name, value, scope
419
+ value
420
+ end
421
+
422
+ def evaluate_constant_path_write_node(node, scope)
423
+ receiver = evaluate node.target.parent, scope if node.target.parent
424
+ value = evaluate node.value, scope
425
+ const_path_write receiver, node.target.child.name.to_s, value, scope
426
+ value
427
+ end
428
+
429
+ def evaluate_lambda_node(node, scope)
430
+ local_table = node.locals.to_h { [_1.to_s, Types::OBJECT] }
431
+ block_scope = Scope.new scope, { **local_table, Scope::BREAK_RESULT => nil, Scope::NEXT_RESULT => nil, Scope::RETURN_RESULT => nil }
432
+ block_scope.conditional do |s|
433
+ assign_parameters node.parameters.parameters, s, [], {} if node.parameters&.parameters
434
+ evaluate node.body, s if node.body
435
+ end
436
+ block_scope.merge_jumps
437
+ scope.update block_scope
438
+ Types::PROC
439
+ end
440
+
441
+ def evaluate_reference_write(node, scope)
442
+ scope[node.name.to_s] = evaluate node.value, scope
443
+ end
444
+ alias evaluate_constant_write_node evaluate_reference_write
445
+ alias evaluate_global_variable_write_node evaluate_reference_write
446
+ alias evaluate_local_variable_write_node evaluate_reference_write
447
+ alias evaluate_class_variable_write_node evaluate_reference_write
448
+ alias evaluate_instance_variable_write_node evaluate_reference_write
449
+
450
+ def evaluate_multi_write_node(node, scope)
451
+ evaluated_receivers = {}
452
+ evaluate_multi_write_receiver node, scope, evaluated_receivers
453
+ value = (
454
+ if node.value.is_a? Prism::ArrayNode
455
+ if node.value.elements.any?(Prism::SplatNode)
456
+ evaluate node.value, scope
457
+ else
458
+ node.value.elements.map do |n|
459
+ evaluate n, scope
460
+ end
461
+ end
462
+ elsif node.value
463
+ evaluate node.value, scope
464
+ else
465
+ Types::NIL
466
+ end
467
+ )
468
+ evaluate_multi_write node, value, scope, evaluated_receivers
469
+ value.is_a?(Array) ? Types.array_of(*value) : value
470
+ end
471
+
472
+ def evaluate_if_node(node, scope) = evaluate_if_unless(node, scope)
473
+ def evaluate_unless_node(node, scope) = evaluate_if_unless(node, scope)
474
+ def evaluate_if_unless(node, scope)
475
+ evaluate node.predicate, scope
476
+ Types::UnionType[*scope.run_branches(
477
+ -> { node.statements ? evaluate(node.statements, _1) : Types::NIL },
478
+ -> { node.consequent ? evaluate(node.consequent, _1) : Types::NIL }
479
+ )]
480
+ end
481
+
482
+ def evaluate_else_node(node, scope)
483
+ node.statements ? evaluate(node.statements, scope) : Types::NIL
484
+ end
485
+
486
+ def evaluate_while_until(node, scope)
487
+ inner_scope = Scope.new scope, { Scope::BREAK_RESULT => nil }
488
+ evaluate node.predicate, inner_scope
489
+ if node.statements
490
+ inner_scope.conditional do |s|
491
+ evaluate node.statements, s
492
+ end
493
+ end
494
+ inner_scope.merge_jumps
495
+ scope.update inner_scope
496
+ breaks = inner_scope[Scope::BREAK_RESULT]
497
+ breaks ? Types::UnionType[breaks, Types::NIL] : Types::NIL
498
+ end
499
+ alias evaluate_while_node evaluate_while_until
500
+ alias evaluate_until_node evaluate_while_until
501
+
502
+ def evaluate_break_node(node, scope) = evaluate_jump(node, scope, :break)
503
+ def evaluate_next_node(node, scope) = evaluate_jump(node, scope, :next)
504
+ def evaluate_return_node(node, scope) = evaluate_jump(node, scope, :return)
505
+ def evaluate_jump(node, scope, mode)
506
+ internal_key = (
507
+ case mode
508
+ when :break
509
+ Scope::BREAK_RESULT
510
+ when :next
511
+ Scope::NEXT_RESULT
512
+ when :return
513
+ Scope::RETURN_RESULT
514
+ end
515
+ )
516
+ jump_value = (
517
+ arguments = node.arguments&.arguments
518
+ if arguments.nil? || arguments.empty?
519
+ Types::NIL
520
+ elsif arguments.size == 1 && !arguments.first.is_a?(Prism::SplatNode)
521
+ evaluate arguments.first, scope
522
+ else
523
+ Types.array_of evaluate_list_splat_items(arguments, scope)
524
+ end
525
+ )
526
+ scope.terminate_with internal_key, jump_value
527
+ Types::NIL
528
+ end
529
+
530
+ def evaluate_yield_node(node, scope)
531
+ evaluate_list_splat_items node.arguments.arguments, scope if node.arguments
532
+ Types::OBJECT
533
+ end
534
+
535
+ def evaluate_redo_node(_node, scope)
536
+ scope.terminate
537
+ Types::NIL
538
+ end
539
+
540
+ def evaluate_retry_node(_node, scope)
541
+ scope.terminate
542
+ Types::NIL
543
+ end
544
+
545
+ def evaluate_forwarding_super_node(_node, _scope) = Types::OBJECT
546
+
547
+ def evaluate_super_node(node, scope)
548
+ evaluate_list_splat_items node.arguments.arguments, scope if node.arguments
549
+ Types::OBJECT
550
+ end
551
+
552
+ def evaluate_begin_node(node, scope)
553
+ return_type = node.statements ? evaluate(node.statements, scope) : Types::NIL
554
+ if node.rescue_clause
555
+ if node.else_clause
556
+ return_types = scope.run_branches(
557
+ ->{ evaluate node.rescue_clause, _1 },
558
+ ->{ evaluate node.else_clause, _1 }
559
+ )
560
+ else
561
+ return_types = [
562
+ return_type,
563
+ scope.conditional { evaluate node.rescue_clause, _1 }
564
+ ]
565
+ end
566
+ return_type = Types::UnionType[*return_types]
567
+ end
568
+ if node.ensure_clause&.statements
569
+ # ensure_clause is Prism::EnsureNode
570
+ evaluate node.ensure_clause.statements, scope
571
+ end
572
+ return_type
573
+ end
574
+
575
+ def evaluate_rescue_node(node, scope)
576
+ run_rescue = lambda do |s|
577
+ if node.reference
578
+ error_classes_type = evaluate_list_splat_items node.exceptions, s
579
+ error_types = error_classes_type.types.filter_map do
580
+ Types::InstanceType.new _1.module_or_class if _1.is_a?(Types::SingletonType)
581
+ end
582
+ error_types << Types::InstanceType.new(StandardError) if error_types.empty?
583
+ error_type = Types::UnionType[*error_types]
584
+ case node.reference
585
+ when Prism::LocalVariableTargetNode, Prism::InstanceVariableTargetNode, Prism::ClassVariableTargetNode, Prism::GlobalVariableTargetNode, Prism::ConstantTargetNode
586
+ s[node.reference.name.to_s] = error_type
587
+ when Prism::CallNode
588
+ evaluate node.reference, s
589
+ end
590
+ end
591
+ node.statements ? evaluate(node.statements, s) : Types::NIL
592
+ end
593
+ if node.consequent # begin; rescue A; rescue B; end
594
+ types = scope.run_branches(
595
+ run_rescue,
596
+ -> { evaluate node.consequent, _1 }
597
+ )
598
+ Types::UnionType[*types]
599
+ else
600
+ run_rescue.call scope
601
+ end
602
+ end
603
+
604
+ def evaluate_rescue_modifier_node(node, scope)
605
+ a = evaluate node.expression, scope
606
+ b = scope.conditional { evaluate node.rescue_expression, _1 }
607
+ Types::UnionType[a, b]
608
+ end
609
+
610
+ def evaluate_singleton_class_node(node, scope)
611
+ klass_types = evaluate(node.expression, scope).types.filter_map do |type|
612
+ Types::SingletonType.new type.klass if type.is_a? Types::InstanceType
613
+ end
614
+ klass_types = [Types::CLASS] if klass_types.empty?
615
+ table = node.locals.to_h { [_1.to_s, Types::NIL] }
616
+ sclass_scope = Scope.new(
617
+ scope,
618
+ { **table, Scope::BREAK_RESULT => nil, Scope::NEXT_RESULT => nil, Scope::RETURN_RESULT => nil },
619
+ trace_ivar: false,
620
+ trace_lvar: false,
621
+ self_type: Types::UnionType[*klass_types]
622
+ )
623
+ result = node.body ? evaluate(node.body, sclass_scope) : Types::NIL
624
+ scope.update sclass_scope
625
+ result
626
+ end
627
+
628
+ def evaluate_class_node(node, scope) = evaluate_class_module(node, scope, true)
629
+ def evaluate_module_node(node, scope) = evaluate_class_module(node, scope, false)
630
+ def evaluate_class_module(node, scope, is_class)
631
+ unless node.constant_path.is_a?(Prism::ConstantReadNode) || node.constant_path.is_a?(Prism::ConstantPathNode)
632
+ # Incomplete class/module `class (statement[cursor_here])::Name; end`
633
+ evaluate node.constant_path, scope
634
+ return Types::NIL
635
+ end
636
+ const_type, _receiver, parent_module, name = evaluate_constant_node_info node.constant_path, scope
637
+ if is_class
638
+ select_class_type = -> { _1.is_a?(Types::SingletonType) && _1.module_or_class.is_a?(Class) }
639
+ module_types = const_type.types.select(&select_class_type)
640
+ module_types += evaluate(node.superclass, scope).types.select(&select_class_type) if node.superclass
641
+ module_types << Types::CLASS if module_types.empty?
642
+ else
643
+ module_types = const_type.types.select { _1.is_a?(Types::SingletonType) && !_1.module_or_class.is_a?(Class) }
644
+ module_types << Types::MODULE if module_types.empty?
645
+ end
646
+ return Types::NIL unless node.body
647
+
648
+ table = node.locals.to_h { [_1.to_s, Types::NIL] }
649
+ if !name.empty? && (parent_module.is_a?(Module) || parent_module.nil?)
650
+ value = parent_module.const_get name if parent_module&.const_defined? name
651
+ unless value
652
+ value_type = scope[name]
653
+ value = value_type.module_or_class if value_type.is_a? Types::SingletonType
654
+ end
655
+
656
+ if value.is_a? Module
657
+ nesting = [value, []]
658
+ else
659
+ if parent_module
660
+ nesting = [parent_module, [name]]
661
+ else
662
+ parent_nesting, parent_path = scope.module_nesting.first
663
+ nesting = [parent_nesting, parent_path + [name]]
664
+ end
665
+ nesting_key = [nesting[0].__id__, nesting[1]].join('::')
666
+ nesting_value = is_class ? Types::CLASS : Types::MODULE
667
+ end
668
+ else
669
+ # parent_module == :unknown
670
+ # TODO: dummy module
671
+ end
672
+ module_scope = Scope.new(
673
+ scope,
674
+ { **table, Scope::BREAK_RESULT => nil, Scope::NEXT_RESULT => nil, Scope::RETURN_RESULT => nil },
675
+ trace_ivar: false,
676
+ trace_lvar: false,
677
+ self_type: Types::UnionType[*module_types],
678
+ nesting: nesting
679
+ )
680
+ module_scope[nesting_key] = nesting_value if nesting_value
681
+ result = evaluate(node.body, module_scope)
682
+ scope.update module_scope
683
+ result
684
+ end
685
+
686
+ def evaluate_for_node(node, scope)
687
+ node.statements
688
+ collection = evaluate node.collection, scope
689
+ inner_scope = Scope.new scope, { Scope::BREAK_RESULT => nil }
690
+ ary_type = method_call collection, :to_ary, [], nil, nil, nil, name_match: false
691
+ element_types = ary_type.types.filter_map do |ary|
692
+ ary.params[:Elem] if ary.is_a?(Types::InstanceType) && ary.klass == Array
693
+ end
694
+ element_type = Types::UnionType[*element_types]
695
+ inner_scope.conditional do |s|
696
+ evaluate_write node.index, element_type, s, nil
697
+ evaluate node.statements, s if node.statements
698
+ end
699
+ inner_scope.merge_jumps
700
+ scope.update inner_scope
701
+ breaks = inner_scope[Scope::BREAK_RESULT]
702
+ breaks ? Types::UnionType[breaks, collection] : collection
703
+ end
704
+
705
+ def evaluate_case_node(node, scope)
706
+ target = evaluate(node.predicate, scope) if node.predicate
707
+ # TODO
708
+ branches = node.conditions.map do |condition|
709
+ ->(s) { evaluate_case_match target, condition, s }
710
+ end
711
+ if node.consequent
712
+ branches << ->(s) { evaluate node.consequent, s }
713
+ elsif node.conditions.any? { _1.is_a? Prism::WhenNode }
714
+ branches << ->(_s) { Types::NIL }
715
+ end
716
+ Types::UnionType[*scope.run_branches(*branches)]
717
+ end
718
+
719
+ def evaluate_match_required_node(node, scope)
720
+ value_type = evaluate node.value, scope
721
+ evaluate_match_pattern value_type, node.pattern, scope
722
+ Types::NIL # void value
723
+ end
724
+
725
+ def evaluate_match_predicate_node(node, scope)
726
+ value_type = evaluate node.value, scope
727
+ scope.conditional { evaluate_match_pattern value_type, node.pattern, _1 }
728
+ Types::BOOLEAN
729
+ end
730
+
731
+ def evaluate_range_node(node, scope)
732
+ beg_type = evaluate node.left, scope if node.left
733
+ end_type = evaluate node.right, scope if node.right
734
+ elem = (Types::UnionType[*[beg_type, end_type].compact]).nonnillable
735
+ Types::InstanceType.new Range, Elem: elem
736
+ end
737
+
738
+ def evaluate_defined_node(node, scope)
739
+ scope.conditional { evaluate node.value, _1 }
740
+ Types::UnionType[Types::STRING, Types::NIL]
741
+ end
742
+
743
+ def evaluate_flip_flop_node(node, scope)
744
+ scope.conditional { evaluate node.left, _1 } if node.left
745
+ scope.conditional { evaluate node.right, _1 } if node.right
746
+ Types::BOOLEAN
747
+ end
748
+
749
+ def evaluate_multi_target_node(node, scope)
750
+ # Raw MultiTargetNode, incomplete code like `a,b`, `*a`.
751
+ evaluate_multi_write_receiver node, scope, nil
752
+ Types::NIL
753
+ end
754
+
755
+ def evaluate_splat_node(node, scope)
756
+ # Raw SplatNode, incomplete code like `*a.`
757
+ evaluate_multi_write_receiver node.expression, scope, nil if node.expression
758
+ Types::NIL
759
+ end
760
+
761
+ def evaluate_implicit_node(node, scope)
762
+ evaluate node.value, scope
763
+ end
764
+
765
+ def evaluate_match_write_node(node, scope)
766
+ # /(?<a>)(?<b>)/ =~ string
767
+ evaluate node.call, scope
768
+ node.locals.each { scope[_1.to_s] = Types::UnionType[Types::STRING, Types::NIL] }
769
+ Types::BOOLEAN
770
+ end
771
+
772
+ def evaluate_match_last_line_node(_node, _scope)
773
+ Types::BOOLEAN
774
+ end
775
+
776
+ def evaluate_interpolated_match_last_line_node(node, scope)
777
+ node.parts.each { evaluate _1, scope }
778
+ Types::BOOLEAN
779
+ end
780
+
781
+ def evaluate_pre_execution_node(node, scope)
782
+ node.statements ? evaluate(node.statements, scope) : Types::NIL
783
+ end
784
+
785
+ def evaluate_post_execution_node(node, scope)
786
+ node.statements && @dig_targets.dig?(node.statements) ? evaluate(node.statements, scope) : Types::NIL
787
+ end
788
+
789
+ def evaluate_alias_method_node(_node, _scope) = Types::NIL
790
+ def evaluate_alias_global_variable_node(_node, _scope) = Types::NIL
791
+ def evaluate_undef_node(_node, _scope) = Types::NIL
792
+ def evaluate_missing_node(_node, _scope) = Types::NIL
793
+
794
+ def evaluate_call_node_arguments(call_node, scope)
795
+ # call_node.arguments is Prism::ArgumentsNode
796
+ arguments = call_node.arguments&.arguments&.dup || []
797
+ block_arg = call_node.block.expression if call_node.block.is_a?(Prism::BlockArgumentNode)
798
+ kwargs = arguments.pop.elements if arguments.last.is_a?(Prism::KeywordHashNode)
799
+ args_types = arguments.map do |arg|
800
+ case arg
801
+ when Prism::ForwardingArgumentsNode
802
+ # `f(a, ...)` treat like splat
803
+ nil
804
+ when Prism::SplatNode
805
+ evaluate arg.expression, scope if arg.expression
806
+ nil # TODO: splat
807
+ else
808
+ evaluate arg, scope
809
+ end
810
+ end
811
+ if kwargs
812
+ kwargs_types = kwargs.map do |arg|
813
+ case arg
814
+ when Prism::AssocNode
815
+ if arg.key.is_a?(Prism::SymbolNode)
816
+ [arg.key.value, evaluate(arg.value, scope)]
817
+ else
818
+ evaluate arg.key, scope
819
+ evaluate arg.value, scope
820
+ nil
821
+ end
822
+ when Prism::AssocSplatNode
823
+ evaluate arg.value, scope if arg.value
824
+ nil
825
+ end
826
+ end.compact.to_h
827
+ end
828
+ if block_arg.is_a? Prism::SymbolNode
829
+ block_sym_node = block_arg
830
+ elsif block_arg
831
+ evaluate block_arg, scope
832
+ end
833
+ [args_types, kwargs_types, block_sym_node, !!block_arg]
834
+ end
835
+
836
+ def const_path_write(receiver, name, value, scope)
837
+ if receiver # receiver::A = value
838
+ singleton_type = receiver.types.find { _1.is_a? Types::SingletonType }
839
+ scope.set_const singleton_type.module_or_class, name, value if singleton_type
840
+ else # ::A = value
841
+ scope.set_const Object, name, value
842
+ end
843
+ end
844
+
845
+ def assign_required_parameter(node, value, scope)
846
+ case node
847
+ when Prism::RequiredParameterNode
848
+ scope[node.name.to_s] = value || Types::OBJECT
849
+ when Prism::MultiTargetNode
850
+ parameters = [*node.lefts, *node.rest, *node.rights]
851
+ values = value ? sized_splat(value, :to_ary, parameters.size) : []
852
+ parameters.zip values do |n, v|
853
+ assign_required_parameter n, v, scope
854
+ end
855
+ when Prism::SplatNode
856
+ splat_value = value ? Types.array_of(value) : Types::ARRAY
857
+ assign_required_parameter node.expression, splat_value, scope if node.expression
858
+ end
859
+ end
860
+
861
+ def evaluate_constant_node_info(node, scope)
862
+ case node
863
+ when Prism::ConstantPathNode
864
+ name = node.child.name.to_s
865
+ if node.parent
866
+ receiver = evaluate node.parent, scope
867
+ if receiver.is_a? Types::SingletonType
868
+ parent_module = receiver.module_or_class
869
+ end
870
+ else
871
+ parent_module = Object
872
+ end
873
+ if parent_module
874
+ type = scope.get_const(parent_module, [name]) || Types::NIL
875
+ else
876
+ parent_module = :unknown
877
+ type = Types::NIL
878
+ end
879
+ when Prism::ConstantReadNode
880
+ name = node.name.to_s
881
+ type = scope[name]
882
+ end
883
+ @dig_targets.resolve type, scope if @dig_targets.target? node
884
+ [type, receiver, parent_module, name]
885
+ end
886
+
887
+
888
+ def assign_parameters(node, scope, args, kwargs)
889
+ args = args.dup
890
+ kwargs = kwargs.dup
891
+ size = node.requireds.size + node.optionals.size + (node.rest ? 1 : 0) + node.posts.size
892
+ args = sized_splat(args.first, :to_ary, size) if size >= 2 && args.size == 1
893
+ reqs = args.shift node.requireds.size
894
+ if node.rest
895
+ # node.rest is Prism::RestParameterNode
896
+ posts = []
897
+ opts = args.shift node.optionals.size
898
+ rest = args
899
+ else
900
+ posts = args.pop node.posts.size
901
+ opts = args
902
+ rest = []
903
+ end
904
+ node.requireds.zip reqs do |n, v|
905
+ assign_required_parameter n, v, scope
906
+ end
907
+ node.optionals.zip opts do |n, v|
908
+ # n is Prism::OptionalParameterNode
909
+ values = [v]
910
+ values << evaluate(n.value, scope) if n.value
911
+ scope[n.name.to_s] = Types::UnionType[*values.compact]
912
+ end
913
+ node.posts.zip posts do |n, v|
914
+ assign_required_parameter n, v, scope
915
+ end
916
+ if node.rest&.name
917
+ # node.rest is Prism::RestParameterNode
918
+ scope[node.rest.name.to_s] = Types.array_of(*rest)
919
+ end
920
+ node.keywords.each do |n|
921
+ name = n.name.to_s.delete(':')
922
+ values = [kwargs.delete(name)]
923
+ # n is Prism::OptionalKeywordParameterNode (has n.value) or Prism::RequiredKeywordParameterNode (does not have n.value)
924
+ values << evaluate(n.value, scope) if n.respond_to?(:value)
925
+ scope[name] = Types::UnionType[*values.compact]
926
+ end
927
+ # node.keyword_rest is Prism::KeywordRestParameterNode or Prism::ForwardingParameterNode or Prism::NoKeywordsParameterNode
928
+ if node.keyword_rest.is_a?(Prism::KeywordRestParameterNode) && node.keyword_rest.name
929
+ scope[node.keyword_rest.name.to_s] = Types::InstanceType.new(Hash, K: Types::SYMBOL, V: Types::UnionType[*kwargs.values])
930
+ end
931
+ if node.block&.name
932
+ # node.block is Prism::BlockParameterNode
933
+ scope[node.block.name.to_s] = Types::PROC
934
+ end
935
+ end
936
+
937
+ def assign_numbered_parameters(numbered_parameters, scope, args, _kwargs)
938
+ return if numbered_parameters.empty?
939
+ max_num = numbered_parameters.map { _1[1].to_i }.max
940
+ if max_num == 1
941
+ scope['_1'] = args.first || Types::NIL
942
+ else
943
+ args = sized_splat(args.first, :to_ary, max_num) if args.size == 1
944
+ numbered_parameters.each do |name|
945
+ index = name[1].to_i - 1
946
+ scope[name] = args[index] || Types::NIL
947
+ end
948
+ end
949
+ end
950
+
951
+ def evaluate_case_match(target, node, scope)
952
+ case node
953
+ when Prism::WhenNode
954
+ node.conditions.each { evaluate _1, scope }
955
+ node.statements ? evaluate(node.statements, scope) : Types::NIL
956
+ when Prism::InNode
957
+ pattern = node.pattern
958
+ if pattern.is_a?(Prism::IfNode) || pattern.is_a?(Prism::UnlessNode)
959
+ cond_node = pattern.predicate
960
+ pattern = pattern.statements.body.first
961
+ end
962
+ evaluate_match_pattern(target, pattern, scope)
963
+ evaluate cond_node, scope if cond_node # TODO: conditional branch
964
+ node.statements ? evaluate(node.statements, scope) : Types::NIL
965
+ end
966
+ end
967
+
968
+ def evaluate_match_pattern(value, pattern, scope)
969
+ # TODO: scope.terminate_with Scope::PATTERNMATCH_BREAK, Types::NIL
970
+ case pattern
971
+ when Prism::FindPatternNode
972
+ # TODO
973
+ evaluate_match_pattern Types::OBJECT, pattern.left, scope
974
+ pattern.requireds.each { evaluate_match_pattern Types::OBJECT, _1, scope }
975
+ evaluate_match_pattern Types::OBJECT, pattern.right, scope
976
+ when Prism::ArrayPatternNode
977
+ # TODO
978
+ pattern.requireds.each { evaluate_match_pattern Types::OBJECT, _1, scope }
979
+ evaluate_match_pattern Types::OBJECT, pattern.rest, scope if pattern.rest
980
+ pattern.posts.each { evaluate_match_pattern Types::OBJECT, _1, scope }
981
+ Types::ARRAY
982
+ when Prism::HashPatternNode
983
+ # TODO
984
+ pattern.elements.each { evaluate_match_pattern Types::OBJECT, _1, scope }
985
+ if pattern.respond_to?(:rest) && pattern.rest
986
+ evaluate_match_pattern Types::OBJECT, pattern.rest, scope
987
+ end
988
+ Types::HASH
989
+ when Prism::AssocNode
990
+ evaluate_match_pattern value, pattern.value, scope if pattern.value
991
+ Types::OBJECT
992
+ when Prism::AssocSplatNode
993
+ # TODO
994
+ evaluate_match_pattern Types::HASH, pattern.value, scope
995
+ Types::OBJECT
996
+ when Prism::PinnedVariableNode
997
+ evaluate pattern.variable, scope
998
+ when Prism::PinnedExpressionNode
999
+ evaluate pattern.expression, scope
1000
+ when Prism::LocalVariableTargetNode
1001
+ scope[pattern.name.to_s] = value
1002
+ when Prism::AlternationPatternNode
1003
+ Types::UnionType[evaluate_match_pattern(value, pattern.left, scope), evaluate_match_pattern(value, pattern.right, scope)]
1004
+ when Prism::CapturePatternNode
1005
+ capture_type = class_or_value_to_instance evaluate_match_pattern(value, pattern.value, scope)
1006
+ value = capture_type unless capture_type.types.empty? || capture_type.types == [Types::OBJECT]
1007
+ evaluate_match_pattern value, pattern.target, scope
1008
+ when Prism::SplatNode
1009
+ value = Types.array_of value
1010
+ evaluate_match_pattern value, pattern.expression, scope if pattern.expression
1011
+ value
1012
+ else
1013
+ # literal node
1014
+ type = evaluate(pattern, scope)
1015
+ class_or_value_to_instance(type)
1016
+ end
1017
+ end
1018
+
1019
+ def class_or_value_to_instance(type)
1020
+ instance_types = type.types.map do |t|
1021
+ t.is_a?(Types::SingletonType) ? Types::InstanceType.new(t.module_or_class) : t
1022
+ end
1023
+ Types::UnionType[*instance_types]
1024
+ end
1025
+
1026
+ def evaluate_write(node, value, scope, evaluated_receivers)
1027
+ case node
1028
+ when Prism::MultiTargetNode
1029
+ evaluate_multi_write node, value, scope, evaluated_receivers
1030
+ when Prism::CallNode
1031
+ evaluated_receivers&.[](node.receiver) || evaluate(node.receiver, scope) if node.receiver
1032
+ when Prism::SplatNode
1033
+ evaluate_write node.expression, Types.array_of(value), scope, evaluated_receivers if node.expression
1034
+ when Prism::LocalVariableTargetNode, Prism::GlobalVariableTargetNode, Prism::InstanceVariableTargetNode, Prism::ClassVariableTargetNode, Prism::ConstantTargetNode
1035
+ scope[node.name.to_s] = value
1036
+ when Prism::ConstantPathTargetNode
1037
+ receiver = evaluated_receivers&.[](node.parent) || evaluate(node.parent, scope) if node.parent
1038
+ const_path_write receiver, node.child.name.to_s, value, scope
1039
+ value
1040
+ end
1041
+ end
1042
+
1043
+ def evaluate_multi_write(node, values, scope, evaluated_receivers)
1044
+ pre_targets = node.lefts
1045
+ splat_target = node.rest
1046
+ post_targets = node.rights
1047
+ size = pre_targets.size + (splat_target ? 1 : 0) + post_targets.size
1048
+ values = values.is_a?(Array) ? values.dup : sized_splat(values, :to_ary, size)
1049
+ pre_pairs = pre_targets.zip(values.shift(pre_targets.size))
1050
+ post_pairs = post_targets.zip(values.pop(post_targets.size))
1051
+ splat_pairs = splat_target ? [[splat_target, Types::UnionType[*values]]] : []
1052
+ (pre_pairs + splat_pairs + post_pairs).each do |target, value|
1053
+ evaluate_write target, value || Types::NIL, scope, evaluated_receivers
1054
+ end
1055
+ end
1056
+
1057
+ def evaluate_multi_write_receiver(node, scope, evaluated_receivers)
1058
+ case node
1059
+ when Prism::MultiWriteNode, Prism::MultiTargetNode
1060
+ targets = [*node.lefts, *node.rest, *node.rights]
1061
+ targets.each { evaluate_multi_write_receiver _1, scope, evaluated_receivers }
1062
+ when Prism::CallNode
1063
+ if node.receiver
1064
+ receiver = evaluate(node.receiver, scope)
1065
+ evaluated_receivers[node.receiver] = receiver if evaluated_receivers
1066
+ end
1067
+ if node.arguments
1068
+ node.arguments.arguments&.each do |arg|
1069
+ if arg.is_a? Prism::SplatNode
1070
+ evaluate arg.expression, scope
1071
+ else
1072
+ evaluate arg, scope
1073
+ end
1074
+ end
1075
+ end
1076
+ when Prism::SplatNode
1077
+ evaluate_multi_write_receiver node.expression, scope, evaluated_receivers if node.expression
1078
+ end
1079
+ end
1080
+
1081
+ def evaluate_list_splat_items(list, scope)
1082
+ items = list.flat_map do |node|
1083
+ if node.is_a? Prism::SplatNode
1084
+ next unless node.expression # def f(*); [*]
1085
+
1086
+ splat = evaluate node.expression, scope
1087
+ array_elem, non_array = partition_to_array splat.nonnillable, :to_a
1088
+ [*array_elem, *non_array]
1089
+ else
1090
+ evaluate node, scope
1091
+ end
1092
+ end.compact.uniq
1093
+ Types::UnionType[*items]
1094
+ end
1095
+
1096
+ def sized_splat(value, method, size)
1097
+ array_elem, non_array = partition_to_array value, method
1098
+ values = [Types::UnionType[*array_elem, *non_array]]
1099
+ values += [array_elem] * (size - 1) if array_elem && size >= 1
1100
+ values
1101
+ end
1102
+
1103
+ def partition_to_array(value, method)
1104
+ arrays, non_arrays = value.types.partition { _1.is_a?(Types::InstanceType) && _1.klass == Array }
1105
+ non_arrays.select! do |type|
1106
+ to_array_result = method_call type, method, [], nil, nil, nil, name_match: false
1107
+ if to_array_result.is_a?(Types::InstanceType) && to_array_result.klass == Array
1108
+ arrays << to_array_result
1109
+ false
1110
+ else
1111
+ true
1112
+ end
1113
+ end
1114
+ array_elem = arrays.empty? ? nil : Types::UnionType[*arrays.map { _1.params[:Elem] || Types::OBJECT }]
1115
+ non_array = non_arrays.empty? ? nil : Types::UnionType[*non_arrays]
1116
+ [array_elem, non_array]
1117
+ end
1118
+
1119
+ def method_call(receiver, method_name, args, kwargs, block, scope, name_match: true)
1120
+ methods = Types.rbs_methods receiver, method_name.to_sym, args, kwargs, !!block
1121
+ block_called = false
1122
+ type_breaks = methods.map do |method, given_params, method_params|
1123
+ receiver_vars = receiver.is_a?(Types::InstanceType) ? receiver.params : {}
1124
+ free_vars = method.type.free_variables - receiver_vars.keys.to_set
1125
+ vars = receiver_vars.merge Types.match_free_variables(free_vars, method_params, given_params)
1126
+ if block && method.block
1127
+ params_type = method.block.type.required_positionals.map do |func_param|
1128
+ Types.from_rbs_type func_param.type, receiver, vars
1129
+ end
1130
+ self_type = Types.from_rbs_type method.block.self_type, receiver, vars if method.block.self_type
1131
+ block_response, breaks = block.call params_type, self_type
1132
+ block_called = true
1133
+ vars.merge! Types.match_free_variables(free_vars - vars.keys.to_set, [method.block.type.return_type], [block_response])
1134
+ end
1135
+ if Types.method_return_bottom?(method)
1136
+ [nil, breaks]
1137
+ else
1138
+ [Types.from_rbs_type(method.type.return_type, receiver, vars || {}), breaks]
1139
+ end
1140
+ end
1141
+ block&.call [], nil unless block_called
1142
+ terminates = !type_breaks.empty? && type_breaks.map(&:first).all?(&:nil?)
1143
+ types = type_breaks.map(&:first).compact
1144
+ breaks = type_breaks.map(&:last).compact
1145
+ types << OBJECT_METHODS[method_name.to_sym] if name_match && OBJECT_METHODS.has_key?(method_name.to_sym)
1146
+
1147
+ if method_name.to_sym == :new
1148
+ receiver.types.each do |type|
1149
+ if type.is_a?(Types::SingletonType) && type.module_or_class.is_a?(Class)
1150
+ types << Types::InstanceType.new(type.module_or_class)
1151
+ end
1152
+ end
1153
+ end
1154
+ scope&.terminate if terminates && breaks.empty?
1155
+ Types::UnionType[*types, *breaks]
1156
+ end
1157
+
1158
+ def self.calculate_target_type_scope(binding, parents, target)
1159
+ dig_targets = DigTarget.new(parents, target) do |type, scope|
1160
+ return type, scope
1161
+ end
1162
+ program = parents.first
1163
+ scope = Scope.from_binding(binding, program.locals)
1164
+ new(dig_targets).evaluate program, scope
1165
+ [Types::NIL, scope]
1166
+ end
1167
+ end
1168
+ end
1169
+ end