steep 0.44.1 → 0.47.1

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