steep 0.43.0 → 0.45.0

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 (59) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +8 -0
  3. data/.github/workflows/ruby.yml +3 -2
  4. data/.gitignore +0 -1
  5. data/CHANGELOG.md +30 -0
  6. data/Gemfile +0 -1
  7. data/Gemfile.lock +77 -0
  8. data/bin/output_test.rb +8 -2
  9. data/lib/steep.rb +4 -1
  10. data/lib/steep/ast/builtin.rb +7 -1
  11. data/lib/steep/ast/types/factory.rb +19 -25
  12. data/lib/steep/diagnostic/ruby.rb +137 -60
  13. data/lib/steep/diagnostic/signature.rb +34 -0
  14. data/lib/steep/equatable.rb +21 -0
  15. data/lib/steep/index/source_index.rb +55 -5
  16. data/lib/steep/interface/block.rb +4 -0
  17. data/lib/steep/interface/function.rb +798 -579
  18. data/lib/steep/server/interaction_worker.rb +239 -20
  19. data/lib/steep/server/master.rb +40 -19
  20. data/lib/steep/server/type_check_worker.rb +68 -0
  21. data/lib/steep/services/file_loader.rb +26 -19
  22. data/lib/steep/services/goto_service.rb +322 -0
  23. data/lib/steep/services/hover_content.rb +131 -79
  24. data/lib/steep/services/type_check_service.rb +25 -0
  25. data/lib/steep/source.rb +7 -10
  26. data/lib/steep/type_construction.rb +496 -518
  27. data/lib/steep/type_inference/block_params.rb +2 -5
  28. data/lib/steep/type_inference/method_params.rb +483 -0
  29. data/lib/steep/type_inference/send_args.rb +610 -128
  30. data/lib/steep/typing.rb +46 -21
  31. data/lib/steep/version.rb +1 -1
  32. data/sig/steep/type_inference/send_args.rbs +42 -0
  33. data/smoke/array/test_expectations.yml +3 -3
  34. data/smoke/block/c.rb +0 -1
  35. data/smoke/class/test_expectations.yml +12 -15
  36. data/smoke/const/test_expectations.yml +0 -10
  37. data/smoke/diagnostics-rbs/mixin-class-error.rbs +6 -0
  38. data/smoke/diagnostics-rbs/test_expectations.yml +12 -0
  39. data/smoke/diagnostics-ruby-unsat/Steepfile +5 -0
  40. data/smoke/diagnostics-ruby-unsat/a.rbs +3 -0
  41. data/smoke/diagnostics-ruby-unsat/test_expectations.yml +27 -0
  42. data/smoke/{diagnostics → diagnostics-ruby-unsat}/unsatisfiable_constraint.rb +0 -1
  43. data/smoke/diagnostics/a.rbs +0 -4
  44. data/smoke/diagnostics/different_method_parameter_kind.rb +9 -0
  45. data/smoke/diagnostics/method_arity_mismatch.rb +2 -2
  46. data/smoke/diagnostics/method_parameter_mismatch.rb +10 -0
  47. data/smoke/diagnostics/test_expectations.yml +108 -57
  48. data/smoke/ensure/test_expectations.yml +3 -3
  49. data/smoke/enumerator/test_expectations.yml +1 -1
  50. data/smoke/literal/test_expectations.yml +2 -2
  51. data/smoke/method/test_expectations.yml +11 -10
  52. data/smoke/regression/issue_372.rb +8 -0
  53. data/smoke/regression/issue_372.rbs +4 -0
  54. data/smoke/regression/test_expectations.yml +0 -12
  55. data/smoke/rescue/test_expectations.yml +3 -3
  56. data/smoke/toplevel/test_expectations.yml +3 -3
  57. data/smoke/tsort/test_expectations.yml +2 -2
  58. data/steep.gemspec +2 -2
  59. metadata +24 -10
@@ -1,194 +1,676 @@
1
1
  module Steep
2
2
  module TypeInference
3
3
  class SendArgs
4
- attr_reader :args
5
- attr_reader :block_pass_arg
4
+ class PositionalArgs
5
+ class NodeParamPair
6
+ attr_reader :node
7
+ attr_reader :param
6
8
 
7
- def initialize(args:, block_pass_arg:)
8
- @args = args
9
- @block_pass_arg = block_pass_arg
10
- end
9
+ def initialize(node:, param:)
10
+ @node = node
11
+ @param = param
12
+ end
13
+
14
+ include Equatable
11
15
 
12
- def self.from_nodes(nodes)
13
- nodes = nodes.dup
16
+ def to_ary
17
+ [node, param]
18
+ end
19
+ end
14
20
 
15
- args = []
16
- block_pass_arg = nil
21
+ class NodeTypePair
22
+ attr_reader :node
23
+ attr_reader :type
17
24
 
18
- if nodes.last&.type == :block_pass
19
- block_pass_arg = nodes.pop
25
+ def initialize(node:, type:)
26
+ @node = node
27
+ @type = type
28
+ end
29
+
30
+ include Equatable
31
+
32
+ def node_type
33
+ case node.type
34
+ when :splat
35
+ AST::Builtin::Array.instance_type(type)
36
+ else
37
+ type
38
+ end
39
+ end
20
40
  end
21
41
 
22
- nodes.each do |node|
23
- args << node
42
+ class SplatArg
43
+ attr_reader :node
44
+ attr_accessor :type
45
+
46
+ def initialize(node:)
47
+ @node = node
48
+ @type = nil
49
+ end
50
+
51
+ include Equatable
24
52
  end
25
53
 
26
- new(args: args, block_pass_arg: block_pass_arg)
27
- end
54
+ class UnexpectedArg
55
+ attr_reader :node
28
56
 
29
- def drop_first
30
- raise "Cannot drop first from empty args" if args.empty?
31
- self.class.new(args: args.drop(1), block_pass_arg: block_pass_arg)
32
- end
57
+ def initialize(node:)
58
+ @node = node
59
+ end
33
60
 
34
- def drop_last
35
- raise "Cannot drop last from empty args" if args.empty?
36
- self.class.new(args: args.take(args.size - 1), block_pass_arg: block_pass_arg)
37
- end
61
+ include Equatable
62
+ end
38
63
 
39
- def each_keyword_arg
40
- if block_given?
41
- if kw_args
42
- kw_args.children.each do |node|
43
- if node.type == :pair
44
- yield node
45
- end
46
- end
64
+ class MissingArg
65
+ attr_reader :params
66
+
67
+ def initialize(params:)
68
+ @params = params
47
69
  end
48
- else
49
- enum_for :each_keyword_arg
70
+
71
+ include Equatable
50
72
  end
51
- end
52
73
 
53
- def kwsplat_nodes
54
- if kw_args
55
- kw_args.children.select do |node|
56
- node.type == :kwsplat
74
+ attr_reader :args
75
+ attr_reader :index
76
+ attr_reader :positional_params
77
+ attr_reader :uniform
78
+
79
+ def initialize(args:, index:, positional_params:, uniform: false)
80
+ @args = args
81
+ @index = index
82
+ @positional_params = positional_params
83
+ @uniform = uniform
84
+ end
85
+
86
+ def node
87
+ args[index]
88
+ end
89
+
90
+ def following_args
91
+ args[index..]
92
+ end
93
+
94
+ def param
95
+ positional_params&.head
96
+ end
97
+
98
+ def update(index: self.index, positional_params: self.positional_params, uniform: self.uniform)
99
+ PositionalArgs.new(args: args, index: index, positional_params: positional_params, uniform: uniform)
100
+ end
101
+
102
+ def uniform!
103
+ update(uniform: true)
104
+ end
105
+
106
+ def next()
107
+ if uniform
108
+ if node
109
+ return [node, uniform_type, update(index: index+1)]
110
+ else
111
+ return
112
+ end
113
+ end
114
+
115
+ case
116
+ when !node && param.is_a?(Interface::Function::Params::PositionalParams::Required)
117
+ [
118
+ MissingArg.new(params: positional_params),
119
+ update(index: index, positional_params: nil)
120
+ ]
121
+ when !node && param.is_a?(Interface::Function::Params::PositionalParams::Optional)
122
+ nil
123
+ when !node && param.is_a?(Interface::Function::Params::PositionalParams::Rest)
124
+ nil
125
+ when !node && !param
126
+ nil
127
+ when node && node.type != :splat && param.is_a?(Interface::Function::Params::PositionalParams::Required)
128
+ [
129
+ NodeParamPair.new(node: node, param: param),
130
+ update(index: index+1, positional_params: positional_params.tail)
131
+ ]
132
+ when node && node.type != :splat && param.is_a?(Interface::Function::Params::PositionalParams::Optional)
133
+ [
134
+ NodeParamPair.new(node: node, param: param),
135
+ update(index: index+1, positional_params: positional_params.tail)
136
+ ]
137
+ when node && node.type != :splat && param.is_a?(Interface::Function::Params::PositionalParams::Rest)
138
+ [
139
+ NodeParamPair.new(node: node, param: param),
140
+ update(index: index+1)
141
+ ]
142
+ when node && node.type != :splat && !param
143
+ [
144
+ UnexpectedArg.new(node: node),
145
+ update(index: index + 1)
146
+ ]
147
+ when node && node.type == :splat
148
+ [
149
+ SplatArg.new(node: node),
150
+ self
151
+ ]
57
152
  end
58
- else
59
- []
60
153
  end
61
- end
62
154
 
63
- def zips(params, block_type)
64
- zip0(params, block_type).map do |pairs|
65
- group_pairs(pairs)
155
+ def uniform_type
156
+ if positional_params.each.any? {|param| param.is_a?(Interface::Function::Params::PositionalParams::Rest) }
157
+ AST::Types::Intersection.build(types: positional_params.each.map(&:type))
158
+ end
66
159
  end
67
- end
68
160
 
69
- def group_pairs(pairs)
70
- types = pairs.each_with_object({}) do |pair, hash|
71
- case pair
72
- when Array
73
- node, type = pair
74
- hash[node.__id__] ||= [node]
75
- hash[node.__id__] << type
161
+ def consume(n, node:)
162
+ ps = []
163
+ params = consume0(n, node: node, params: positional_params, ps: ps)
164
+ case params
165
+ when UnexpectedArg
166
+ [
167
+ params,
168
+ update(index: index+1, positional_params: nil)
169
+ ]
76
170
  else
77
- hash[node.__id__] = pair
171
+ [ps, update(index: index+1, positional_params: params)]
78
172
  end
79
173
  end
80
174
 
81
- types.map do |_, array|
82
- case array
83
- when Array
84
- node, *types_ = array
85
- [node, AST::Types::Intersection.build(types: types_)]
175
+ def consume0(n, node:, params:, ps:)
176
+ case n
177
+ when 0
178
+ params
86
179
  else
87
- array
180
+ head = params&.head
181
+ case head
182
+ when nil
183
+ UnexpectedArg.new(node: node)
184
+ when Interface::Function::Params::PositionalParams::Required, Interface::Function::Params::PositionalParams::Optional
185
+ ps << head
186
+ consume0(n-1, node: node, params: params.tail, ps: ps)
187
+ when Interface::Function::Params::PositionalParams::Rest
188
+ ps << head
189
+ consume0(n-1, node: node, params: params, ps: ps)
190
+ end
88
191
  end
89
192
  end
90
193
  end
91
194
 
92
- def add_pair(pairs, pair)
93
- pairs.map do |ps|
94
- if block_given?
95
- yield ps, pair
96
- else
97
- [pair] + ps
195
+ class KeywordArgs
196
+ class ArgTypePairs
197
+ attr_reader :pairs
198
+
199
+ def initialize(pairs:)
200
+ @pairs = pairs
201
+ end
202
+
203
+ include Equatable
204
+
205
+ def [](index)
206
+ pairs[index]
207
+ end
208
+
209
+ def size
210
+ pairs.size
98
211
  end
99
212
  end
100
- end
101
213
 
102
- def zip0(params, block_type)
103
- case
104
- when params.empty? && args.empty?
105
- [[]]
214
+ class SplatArg
215
+ attr_reader :node
216
+ attr_accessor :type
106
217
 
107
- when params.required.any?
108
- if args.any?
109
- first_arg = args[0]
218
+ def initialize(node:)
219
+ @node = node
220
+ @type = nil
221
+ end
110
222
 
111
- case first_arg.type
112
- when :splat
113
- []
114
- else
115
- rest = drop_first.zip0(params.drop_first, block_type)
116
- pair = [first_arg, params.required[0]]
223
+ include Equatable
224
+ end
225
+
226
+ class UnexpectedKeyword
227
+ attr_reader :keyword
228
+ attr_reader :node
229
+
230
+ include Equatable
231
+
232
+ def initialize(keyword:, node:)
233
+ @keyword = keyword
234
+ @node = node
235
+ end
117
236
 
118
- add_pair(rest, pair)
237
+ def key_node
238
+ if node.type == :pair
239
+ node.children[0]
240
+ end
241
+ end
242
+
243
+ def value_node
244
+ if node.type == :pair
245
+ node.children[1]
119
246
  end
120
- else
121
- []
122
247
  end
248
+ end
249
+
250
+ class MissingKeyword
251
+ attr_reader :keywords
123
252
 
124
- when params.has_keywords? && params.required_keywords.any?
125
- if args.any?
126
- rest = drop_last.zip0(params.without_keywords, block_type)
127
- last_arg = args.last
253
+ include Equatable
128
254
 
129
- return [] if last_arg.type == :splat
255
+ def initialize(keywords:)
256
+ @keywords = keywords
257
+ end
258
+ end
259
+
260
+ attr_reader :kwarg_nodes
261
+ attr_reader :keyword_params
262
+ attr_reader :index
263
+ attr_reader :consumed_keywords
264
+
265
+ def initialize(kwarg_nodes:, keyword_params:, index: 0, consumed_keywords: Set[])
266
+ @kwarg_nodes = kwarg_nodes
267
+ @keyword_params = keyword_params
268
+ @index = index
269
+ @consumed_keywords = consumed_keywords
270
+ end
271
+
272
+ def update(index: self.index, consumed_keywords: self.consumed_keywords)
273
+ KeywordArgs.new(
274
+ kwarg_nodes: kwarg_nodes,
275
+ keyword_params: keyword_params,
276
+ index: index,
277
+ consumed_keywords: consumed_keywords
278
+ )
279
+ end
280
+
281
+ def keyword_pair
282
+ kwarg_nodes[index]
283
+ end
284
+
285
+ def required_keywords
286
+ keyword_params.requireds
287
+ end
288
+
289
+ def optional_keywords
290
+ keyword_params.optionals
291
+ end
292
+
293
+ def rest_type
294
+ keyword_params.rest
295
+ end
130
296
 
131
- add_pair(rest, last_arg) do |ps, p|
132
- ps + [p]
297
+ def keyword_type(key)
298
+ required_keywords[key] || optional_keywords[key]
299
+ end
300
+
301
+ def all_keys
302
+ keys = Set.new
303
+ keys.merge(required_keywords.each_key)
304
+ keys.merge(optional_keywords.each_key)
305
+ keys.sort_by(&:to_s).to_a
306
+ end
307
+
308
+ def all_values
309
+ keys = Set.new
310
+ keys.merge(required_keywords.each_value)
311
+ keys.merge(optional_keywords.each_value)
312
+ keys.sort_by(&:to_s).to_a
313
+ end
314
+
315
+ def possible_key_type
316
+ key_types = all_keys.map {|key| AST::Types::Literal.new(value: key) }
317
+ key_types << AST::Builtin::Symbol.instance_type if rest_type
318
+
319
+ AST::Types::Union.build(types: key_types)
320
+ end
321
+
322
+ def possible_value_type
323
+ value_types = all_values
324
+ value_types << rest_type if rest_type
325
+
326
+ AST::Types::Intersection.build(types: value_types)
327
+ end
328
+
329
+ def next()
330
+ node = keyword_pair
331
+
332
+ if node
333
+ case node.type
334
+ when :pair
335
+ key_node, value_node = node.children
336
+
337
+ if key_node.type == :sym
338
+ key = key_node.children[0]
339
+
340
+ case
341
+ when value_type = keyword_type(key)
342
+ [
343
+ ArgTypePairs.new(
344
+ pairs: [
345
+ [key_node, AST::Types::Literal.new(value: key)],
346
+ [value_node, value_type]
347
+ ]
348
+ ),
349
+ update(
350
+ index: index+1,
351
+ consumed_keywords: consumed_keywords + [key]
352
+ )
353
+ ]
354
+ when value_type = rest_type
355
+ [
356
+ ArgTypePairs.new(
357
+ pairs: [
358
+ [key_node, AST::Builtin::Symbol.instance_type],
359
+ [value_node, value_type]
360
+ ]
361
+ ),
362
+ update(
363
+ index: index+1,
364
+ consumed_keywords: consumed_keywords + [key]
365
+ )
366
+ ]
367
+ else
368
+ [
369
+ UnexpectedKeyword.new(keyword: key, node: node),
370
+ update(index: index+1)
371
+ ]
372
+ end
373
+ else
374
+ if !all_keys.empty? || rest_type
375
+ [
376
+ ArgTypePairs.new(
377
+ pairs: [
378
+ [key_node, possible_key_type],
379
+ [value_node, possible_value_type]
380
+ ]
381
+ ),
382
+ update(index: index+1)
383
+ ]
384
+ else
385
+ [
386
+ UnexpectedKeyword.new(keyword: nil, node: node),
387
+ update(index: index+1)
388
+ ]
389
+ end
390
+ end
391
+ when :kwsplat
392
+ [
393
+ SplatArg.new(node: node),
394
+ self
395
+ ]
133
396
  end
134
397
  else
135
- []
398
+ left = Set.new(required_keywords.keys) - consumed_keywords
399
+ unless left.empty?
400
+ [
401
+ MissingKeyword.new(keywords: left),
402
+ update(consumed_keywords: consumed_keywords + left)
403
+ ]
404
+ end
136
405
  end
406
+ end
137
407
 
138
- when params.has_keywords? && params.required_keywords.empty?
139
- if args.any?
140
- rest = drop_last.zip0(params.without_keywords, block_type)
141
- last_arg = args.last
408
+ def consume_keys(keys, node:)
409
+ consumed_keys = []
410
+ types = []
142
411
 
143
- no_keyword = zip0(params.without_keywords, block_type)
412
+ unexpected_keyword = nil
144
413
 
145
- if last_arg.type == :splat
146
- no_keyword
414
+ keys.each do |key|
415
+ case
416
+ when type = keyword_type(key)
417
+ consumed_keys << key
418
+ types << type
419
+ when rest_type
420
+ types << rest_type
147
421
  else
148
- add_pair(rest, last_arg) do |ps, p|
149
- ps + [p]
150
- end + no_keyword
422
+ unexpected_keyword = key
151
423
  end
424
+ end
425
+
426
+ [
427
+ if unexpected_keyword
428
+ UnexpectedKeyword.new(keyword: unexpected_keyword, node: node)
429
+ else
430
+ types
431
+ end,
432
+ update(index: index + 1, consumed_keywords: consumed_keywords + consumed_keys)
433
+ ]
434
+ end
435
+ end
436
+
437
+ class BlockPassArg
438
+ attr_reader :node
439
+ attr_reader :block
440
+
441
+ def initialize(node:, block:)
442
+ @node = node
443
+ @block = block
444
+ end
445
+
446
+ include Equatable
447
+
448
+ def no_block?
449
+ !node && !block
450
+ end
451
+
452
+ def compatible?
453
+ if node
454
+ block ? true : false
152
455
  else
153
- zip0(params.without_keywords, block_type)
456
+ !block || block.optional?
154
457
  end
458
+ end
155
459
 
156
- when params.optional.any?
157
- if args.any?
158
- first_arg = args[0]
460
+ def block_missing?
461
+ !node && block&.required?
462
+ end
159
463
 
160
- case first_arg.type
161
- when :splat
162
- rest = zip0(params.drop_first, block_type)
163
- pair = [args[0], AST::Builtin::Array.instance_type(params.optional[0])]
164
- else
165
- rest = drop_first.zip0(params.drop_first, block_type)
166
- pair = [args[0], params.optional[0]]
464
+ def unexpected_block?
465
+ node && !block
466
+ end
467
+
468
+ def pair
469
+ raise unless compatible?
470
+
471
+ if node && block
472
+ [
473
+ node,
474
+ block.type
475
+ ]
476
+ end
477
+ end
478
+
479
+ def node_type
480
+ type = AST::Types::Proc.new(type: block.type, block: nil)
481
+
482
+ if block.optional?
483
+ type = AST::Types::Union.build(types: [type, AST::Builtin.nil_type])
484
+ end
485
+
486
+ type
487
+ end
488
+ end
489
+
490
+ attr_reader :node
491
+ attr_reader :arguments
492
+ attr_reader :method_type
493
+ attr_reader :method_name
494
+
495
+ def initialize(node:, arguments:, method_name:, method_type:)
496
+ @node = node
497
+ @arguments = arguments
498
+ @method_type = method_type
499
+ @method_name = method_name
500
+ end
501
+
502
+ def positional_params
503
+ method_type.type.params.positional_params
504
+ end
505
+
506
+ def keyword_params
507
+ method_type.type.params.keyword_params
508
+ end
509
+
510
+ def kwargs_node
511
+ unless keyword_params.empty?
512
+ arguments.find {|node| node.type == :kwargs }
513
+ end
514
+ end
515
+
516
+ def positional_arg
517
+ args = if keyword_params.empty?
518
+ arguments.take_while {|node| node.type != :block_pass }
519
+ else
520
+ arguments.take_while {|node| node.type != :kwargs && node.type != :block_pass }
521
+ end
522
+ PositionalArgs.new(args: args, index: 0, positional_params: positional_params)
523
+ end
524
+
525
+ def keyword_args
526
+ KeywordArgs.new(
527
+ kwarg_nodes: kwargs_node&.children || [],
528
+ keyword_params: keyword_params
529
+ )
530
+ end
531
+
532
+ def block_pass_arg
533
+ node = arguments.find {|node| node.type == :block_pass }
534
+ block = method_type.block
535
+
536
+ BlockPassArg.new(node: node, block: block)
537
+ end
538
+
539
+ def each
540
+ if block_given?
541
+ errors = []
542
+ positional_count = 0
543
+
544
+ positional_arg.tap do |args|
545
+ while (value, args = args.next())
546
+ yield value
547
+
548
+ case value
549
+ when PositionalArgs::SplatArg
550
+ type = value.type
551
+
552
+ case type
553
+ when nil
554
+ raise
555
+ when AST::Types::Tuple
556
+ ts, args = args.consume(type.types.size, node: value.node)
557
+
558
+ case ts
559
+ when Array
560
+ ty = AST::Types::Tuple.new(types: ts.map(&:type))
561
+ yield PositionalArgs::NodeTypePair.new(node: value.node, type: ty)
562
+ when PositionalArgs::UnexpectedArg
563
+ errors << ts
564
+ yield ts
565
+ end
566
+ else
567
+ if t = args.uniform_type
568
+ args.following_args.each do |node|
569
+ yield PositionalArgs::NodeTypePair.new(node: node, type: t)
570
+ end
571
+ else
572
+ args.following_args.each do |node|
573
+ arg = PositionalArgs::UnexpectedArg.new(node: node)
574
+ yield arg
575
+ errors << arg
576
+ end
577
+ end
578
+
579
+ break
580
+ end
581
+ when PositionalArgs::UnexpectedArg, PositionalArgs::MissingArg
582
+ errors << value
583
+ end
167
584
  end
585
+ end
168
586
 
169
- add_pair(rest, pair)
170
- else
171
- zip0(params.drop_first, block_type)
587
+ keyword_args.tap do |args|
588
+ while (a, args = args.next)
589
+ case a
590
+ when KeywordArgs::MissingKeyword
591
+ errors << a
592
+ when KeywordArgs::UnexpectedKeyword
593
+ errors << a
594
+ end
595
+
596
+ yield a
597
+
598
+ case a
599
+ when KeywordArgs::SplatArg
600
+ case type = a.type
601
+ when nil
602
+ raise
603
+ when AST::Types::Record
604
+ keys = type.elements.keys
605
+ ts, args = args.consume_keys(keys, node: a.node)
606
+
607
+ case ts
608
+ when KeywordArgs::UnexpectedKeyword
609
+ yield ts
610
+ errors << ts
611
+ when Array
612
+ record = AST::Types::Record.new(elements: Hash[keys.zip(ts)])
613
+ yield KeywordArgs::ArgTypePairs.new(pairs: [[a.node, record]])
614
+ end
615
+ else
616
+ args = args.update(index: args.index + 1)
617
+
618
+ if args.rest_type
619
+ type = AST::Builtin::Hash.instance_type(AST::Builtin::Symbol.instance_type, args.possible_value_type)
620
+ yield KeywordArgs::ArgTypePairs.new(pairs: [[a.node, type]])
621
+ else
622
+ yield KeywordArgs::UnexpectedKeyword.new(keyword: nil, node: a.node)
623
+ end
624
+ end
625
+ end
626
+ end
172
627
  end
173
628
 
174
- when params.rest
175
- if args.any?
176
- rest = drop_first.zip0(params, block_type)
177
- first_arg = args[0]
629
+ pass = block_pass_arg
630
+ # if pass.node
631
+ # yield pass
632
+ # end
178
633
 
179
- case first_arg.type
180
- when :splat
181
- pair = [first_arg, AST::Builtin::Array.instance_type(params.rest)]
182
- else
183
- pair = [first_arg, params.rest]
634
+ diagnostics = []
635
+
636
+ missing_keywords = []
637
+ errors.each do |error|
638
+ case error
639
+ when KeywordArgs::UnexpectedKeyword
640
+ diagnostics << Diagnostic::Ruby::UnexpectedKeywordArgument.new(
641
+ node: error.node,
642
+ method_type: method_type,
643
+ method_name: method_name
644
+ )
645
+ when KeywordArgs::MissingKeyword
646
+ missing_keywords.push(*error.keywords)
647
+ when PositionalArgs::UnexpectedArg
648
+ diagnostics << Diagnostic::Ruby::UnexpectedPositionalArgument.new(
649
+ node: error.node,
650
+ method_type: method_type,
651
+ method_name: method_name
652
+ )
653
+ when PositionalArgs::MissingArg
654
+ diagnostics << Diagnostic::Ruby::InsufficientPositionalArguments.new(
655
+ node: node,
656
+ method_name: method_name,
657
+ method_type: method_type
658
+ )
184
659
  end
660
+ end
185
661
 
186
- add_pair(rest, pair)
187
- else
188
- zip0(params.drop_first, block_type)
662
+ unless missing_keywords.empty?
663
+ diagnostics << Diagnostic::Ruby::InsufficientKeywordArguments.new(
664
+ node: node,
665
+ method_name: method_name,
666
+ method_type: method_type,
667
+ missing_keywords: missing_keywords
668
+ )
189
669
  end
670
+
671
+ diagnostics
190
672
  else
191
- []
673
+ enum_for :each
192
674
  end
193
675
  end
194
676
  end