irb 1.9.0 → 1.10.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,1169 +0,0 @@
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