steep-relaxed 1.9.3.3

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 (165) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +13 -0
  3. data/.gitmodules +0 -0
  4. data/CHANGELOG.md +1032 -0
  5. data/LICENSE +21 -0
  6. data/README.md +260 -0
  7. data/Rakefile +227 -0
  8. data/STDGEM_DEPENDENCIES.txt +59 -0
  9. data/Steepfile +68 -0
  10. data/bin/console +14 -0
  11. data/bin/generate-diagnostics-docs.rb +112 -0
  12. data/bin/mem_graph.rb +67 -0
  13. data/bin/mem_prof.rb +102 -0
  14. data/bin/output_rebaseline.rb +34 -0
  15. data/bin/output_test.rb +60 -0
  16. data/bin/rbs +20 -0
  17. data/bin/rbs-inline +19 -0
  18. data/bin/setup +9 -0
  19. data/bin/stackprof_test.rb +19 -0
  20. data/bin/steep +19 -0
  21. data/bin/steep-check.rb +251 -0
  22. data/bin/steep-prof +16 -0
  23. data/doc/narrowing.md +195 -0
  24. data/doc/shape.md +194 -0
  25. data/exe/steep +18 -0
  26. data/guides/README.md +5 -0
  27. data/guides/src/gem-rbs-collection/gem-rbs-collection.md +126 -0
  28. data/guides/src/getting-started/getting-started.md +163 -0
  29. data/guides/src/nil-optional/nil-optional.md +195 -0
  30. data/lib/steep/annotation_parser.rb +199 -0
  31. data/lib/steep/ast/annotation/collection.rb +172 -0
  32. data/lib/steep/ast/annotation.rb +137 -0
  33. data/lib/steep/ast/builtin.rb +104 -0
  34. data/lib/steep/ast/ignore.rb +148 -0
  35. data/lib/steep/ast/node/type_application.rb +88 -0
  36. data/lib/steep/ast/node/type_assertion.rb +81 -0
  37. data/lib/steep/ast/types/any.rb +35 -0
  38. data/lib/steep/ast/types/boolean.rb +45 -0
  39. data/lib/steep/ast/types/bot.rb +35 -0
  40. data/lib/steep/ast/types/class.rb +43 -0
  41. data/lib/steep/ast/types/factory.rb +557 -0
  42. data/lib/steep/ast/types/helper.rb +40 -0
  43. data/lib/steep/ast/types/instance.rb +42 -0
  44. data/lib/steep/ast/types/intersection.rb +93 -0
  45. data/lib/steep/ast/types/literal.rb +59 -0
  46. data/lib/steep/ast/types/logic.rb +84 -0
  47. data/lib/steep/ast/types/name.rb +128 -0
  48. data/lib/steep/ast/types/nil.rb +41 -0
  49. data/lib/steep/ast/types/proc.rb +117 -0
  50. data/lib/steep/ast/types/record.rb +79 -0
  51. data/lib/steep/ast/types/self.rb +43 -0
  52. data/lib/steep/ast/types/shared_instance.rb +11 -0
  53. data/lib/steep/ast/types/top.rb +35 -0
  54. data/lib/steep/ast/types/tuple.rb +60 -0
  55. data/lib/steep/ast/types/union.rb +97 -0
  56. data/lib/steep/ast/types/var.rb +65 -0
  57. data/lib/steep/ast/types/void.rb +35 -0
  58. data/lib/steep/cli.rb +401 -0
  59. data/lib/steep/diagnostic/deprecated/else_on_exhaustive_case.rb +20 -0
  60. data/lib/steep/diagnostic/deprecated/unknown_constant_assigned.rb +28 -0
  61. data/lib/steep/diagnostic/helper.rb +18 -0
  62. data/lib/steep/diagnostic/lsp_formatter.rb +78 -0
  63. data/lib/steep/diagnostic/result_printer2.rb +48 -0
  64. data/lib/steep/diagnostic/ruby.rb +1221 -0
  65. data/lib/steep/diagnostic/signature.rb +570 -0
  66. data/lib/steep/drivers/annotations.rb +52 -0
  67. data/lib/steep/drivers/check.rb +339 -0
  68. data/lib/steep/drivers/checkfile.rb +210 -0
  69. data/lib/steep/drivers/diagnostic_printer.rb +105 -0
  70. data/lib/steep/drivers/init.rb +66 -0
  71. data/lib/steep/drivers/langserver.rb +56 -0
  72. data/lib/steep/drivers/print_project.rb +113 -0
  73. data/lib/steep/drivers/stats.rb +203 -0
  74. data/lib/steep/drivers/utils/driver_helper.rb +143 -0
  75. data/lib/steep/drivers/utils/jobs_option.rb +26 -0
  76. data/lib/steep/drivers/vendor.rb +27 -0
  77. data/lib/steep/drivers/watch.rb +194 -0
  78. data/lib/steep/drivers/worker.rb +58 -0
  79. data/lib/steep/equatable.rb +23 -0
  80. data/lib/steep/expectations.rb +228 -0
  81. data/lib/steep/index/rbs_index.rb +350 -0
  82. data/lib/steep/index/signature_symbol_provider.rb +185 -0
  83. data/lib/steep/index/source_index.rb +167 -0
  84. data/lib/steep/interface/block.rb +103 -0
  85. data/lib/steep/interface/builder.rb +843 -0
  86. data/lib/steep/interface/function.rb +1090 -0
  87. data/lib/steep/interface/method_type.rb +330 -0
  88. data/lib/steep/interface/shape.rb +239 -0
  89. data/lib/steep/interface/substitution.rb +159 -0
  90. data/lib/steep/interface/type_param.rb +115 -0
  91. data/lib/steep/located_value.rb +20 -0
  92. data/lib/steep/method_name.rb +42 -0
  93. data/lib/steep/module_helper.rb +24 -0
  94. data/lib/steep/node_helper.rb +273 -0
  95. data/lib/steep/path_helper.rb +30 -0
  96. data/lib/steep/project/dsl.rb +268 -0
  97. data/lib/steep/project/group.rb +31 -0
  98. data/lib/steep/project/options.rb +63 -0
  99. data/lib/steep/project/pattern.rb +59 -0
  100. data/lib/steep/project/target.rb +92 -0
  101. data/lib/steep/project.rb +78 -0
  102. data/lib/steep/rake_task.rb +132 -0
  103. data/lib/steep/range_extension.rb +29 -0
  104. data/lib/steep/server/base_worker.rb +97 -0
  105. data/lib/steep/server/change_buffer.rb +73 -0
  106. data/lib/steep/server/custom_methods.rb +77 -0
  107. data/lib/steep/server/delay_queue.rb +45 -0
  108. data/lib/steep/server/interaction_worker.rb +492 -0
  109. data/lib/steep/server/lsp_formatter.rb +455 -0
  110. data/lib/steep/server/master.rb +922 -0
  111. data/lib/steep/server/target_group_files.rb +205 -0
  112. data/lib/steep/server/type_check_controller.rb +366 -0
  113. data/lib/steep/server/type_check_worker.rb +303 -0
  114. data/lib/steep/server/work_done_progress.rb +64 -0
  115. data/lib/steep/server/worker_process.rb +176 -0
  116. data/lib/steep/services/completion_provider.rb +802 -0
  117. data/lib/steep/services/content_change.rb +61 -0
  118. data/lib/steep/services/file_loader.rb +74 -0
  119. data/lib/steep/services/goto_service.rb +441 -0
  120. data/lib/steep/services/hover_provider/rbs.rb +88 -0
  121. data/lib/steep/services/hover_provider/ruby.rb +221 -0
  122. data/lib/steep/services/hover_provider/singleton_methods.rb +20 -0
  123. data/lib/steep/services/path_assignment.rb +46 -0
  124. data/lib/steep/services/signature_help_provider.rb +202 -0
  125. data/lib/steep/services/signature_service.rb +428 -0
  126. data/lib/steep/services/stats_calculator.rb +68 -0
  127. data/lib/steep/services/type_check_service.rb +394 -0
  128. data/lib/steep/services/type_name_completion.rb +236 -0
  129. data/lib/steep/signature/validator.rb +651 -0
  130. data/lib/steep/source/ignore_ranges.rb +69 -0
  131. data/lib/steep/source.rb +691 -0
  132. data/lib/steep/subtyping/cache.rb +30 -0
  133. data/lib/steep/subtyping/check.rb +1113 -0
  134. data/lib/steep/subtyping/constraints.rb +341 -0
  135. data/lib/steep/subtyping/relation.rb +101 -0
  136. data/lib/steep/subtyping/result.rb +324 -0
  137. data/lib/steep/subtyping/variable_variance.rb +89 -0
  138. data/lib/steep/test.rb +9 -0
  139. data/lib/steep/thread_waiter.rb +43 -0
  140. data/lib/steep/type_construction.rb +5183 -0
  141. data/lib/steep/type_inference/block_params.rb +416 -0
  142. data/lib/steep/type_inference/case_when.rb +303 -0
  143. data/lib/steep/type_inference/constant_env.rb +56 -0
  144. data/lib/steep/type_inference/context.rb +195 -0
  145. data/lib/steep/type_inference/logic_type_interpreter.rb +613 -0
  146. data/lib/steep/type_inference/method_call.rb +193 -0
  147. data/lib/steep/type_inference/method_params.rb +531 -0
  148. data/lib/steep/type_inference/multiple_assignment.rb +194 -0
  149. data/lib/steep/type_inference/send_args.rb +712 -0
  150. data/lib/steep/type_inference/type_env.rb +341 -0
  151. data/lib/steep/type_inference/type_env_builder.rb +138 -0
  152. data/lib/steep/typing.rb +321 -0
  153. data/lib/steep/version.rb +3 -0
  154. data/lib/steep.rb +369 -0
  155. data/manual/annotations.md +181 -0
  156. data/manual/ignore.md +20 -0
  157. data/manual/ruby-diagnostics.md +1879 -0
  158. data/sample/Steepfile +22 -0
  159. data/sample/lib/conference.rb +49 -0
  160. data/sample/lib/length.rb +35 -0
  161. data/sample/sig/conference.rbs +42 -0
  162. data/sample/sig/generics.rbs +15 -0
  163. data/sample/sig/length.rbs +34 -0
  164. data/steep-relaxed.gemspec +56 -0
  165. metadata +340 -0
@@ -0,0 +1,712 @@
1
+ module Steep
2
+ module TypeInference
3
+ class SendArgs
4
+ class PositionalArgs
5
+ class NodeParamPair
6
+ attr_reader :node
7
+ attr_reader :param
8
+
9
+ def initialize(node:, param:)
10
+ @node = node
11
+ @param = param
12
+ end
13
+
14
+ include Equatable
15
+
16
+ def to_ary
17
+ [node, param]
18
+ end
19
+ end
20
+
21
+ class NodeTypePair
22
+ attr_reader :node
23
+ attr_reader :type
24
+
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
40
+ end
41
+
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
52
+ end
53
+
54
+ class UnexpectedArg
55
+ attr_reader :node
56
+
57
+ def initialize(node:)
58
+ @node = node
59
+ end
60
+
61
+ include Equatable
62
+ end
63
+
64
+ class MissingArg
65
+ attr_reader :params
66
+
67
+ def initialize(params:)
68
+ @params = params
69
+ end
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]
88
+ end
89
+
90
+ def following_args
91
+ args[index..] or raise
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 && node.type == :forwarded_args
105
+ # If the node is a `:forwarded_args`, abort
106
+ nil
107
+ when !node && param.is_a?(Interface::Function::Params::PositionalParams::Required)
108
+ [
109
+ MissingArg.new(params: positional_params),
110
+ update(index: index, positional_params: nil)
111
+ ]
112
+ when !node && param.is_a?(Interface::Function::Params::PositionalParams::Optional)
113
+ nil
114
+ when !node && param.is_a?(Interface::Function::Params::PositionalParams::Rest)
115
+ nil
116
+ when !node && !param
117
+ nil
118
+ when node && node.type != :splat && param.is_a?(Interface::Function::Params::PositionalParams::Required)
119
+ [
120
+ NodeParamPair.new(node: node, param: param),
121
+ update(index: index+1, positional_params: positional_params&.tail)
122
+ ]
123
+ when node && node.type != :splat && param.is_a?(Interface::Function::Params::PositionalParams::Optional)
124
+ [
125
+ NodeParamPair.new(node: node, param: param),
126
+ update(index: index+1, positional_params: positional_params&.tail)
127
+ ]
128
+ when node && node.type != :splat && param.is_a?(Interface::Function::Params::PositionalParams::Rest)
129
+ [
130
+ NodeParamPair.new(node: node, param: param),
131
+ update(index: index+1)
132
+ ]
133
+ when node && node.type != :splat && !param
134
+ [
135
+ UnexpectedArg.new(node: node),
136
+ update(index: index + 1)
137
+ ]
138
+ when node && node.type == :splat
139
+ [
140
+ SplatArg.new(node: node),
141
+ self
142
+ ]
143
+ end
144
+ end
145
+
146
+ def uniform_type
147
+ return nil unless positional_params
148
+ if positional_params.each.any? {|param| param.is_a?(Interface::Function::Params::PositionalParams::Rest) }
149
+ AST::Types::Intersection.build(types: positional_params.each.map(&:type))
150
+ end
151
+ end
152
+
153
+ def consume(n, node:)
154
+ # @type var ps: Array[Interface::Function::Params::PositionalParams::param]
155
+ ps = []
156
+ params = consume0(n, node: node, params: positional_params, ps: ps)
157
+ case params
158
+ when UnexpectedArg
159
+ [
160
+ params,
161
+ update(index: index+1, positional_params: nil)
162
+ ]
163
+ else
164
+ [ps, update(index: index+1, positional_params: params)]
165
+ end
166
+ end
167
+
168
+ def consume0(n, node:, params:, ps:)
169
+ case n
170
+ when 0
171
+ params
172
+ else
173
+ head = params&.head
174
+ case head
175
+ when nil
176
+ UnexpectedArg.new(node: node)
177
+ when Interface::Function::Params::PositionalParams::Required, Interface::Function::Params::PositionalParams::Optional
178
+ ps << head
179
+ consume0(n-1, node: node, params: params&.tail, ps: ps)
180
+ when Interface::Function::Params::PositionalParams::Rest
181
+ ps << head
182
+ consume0(n-1, node: node, params: params, ps: ps)
183
+ end
184
+ end
185
+ end
186
+ end
187
+
188
+ class KeywordArgs
189
+ class ArgTypePairs
190
+ attr_reader :pairs
191
+
192
+ def initialize(pairs:)
193
+ @pairs = pairs
194
+ end
195
+
196
+ include Equatable
197
+
198
+ def [](index)
199
+ pairs[index]
200
+ end
201
+
202
+ def size
203
+ pairs.size
204
+ end
205
+ end
206
+
207
+ class SplatArg
208
+ attr_reader :node
209
+ attr_accessor :type
210
+
211
+ def initialize(node:)
212
+ @node = node
213
+ @type = nil
214
+ end
215
+
216
+ include Equatable
217
+ end
218
+
219
+ class UnexpectedKeyword
220
+ attr_reader :keyword
221
+ attr_reader :node
222
+
223
+ include Equatable
224
+
225
+ def initialize(keyword:, node:)
226
+ @keyword = keyword
227
+ @node = node
228
+ end
229
+
230
+ def key_node
231
+ if node.type == :pair
232
+ node.children[0]
233
+ end
234
+ end
235
+
236
+ def value_node
237
+ if node.type == :pair
238
+ node.children[1]
239
+ end
240
+ end
241
+ end
242
+
243
+ class MissingKeyword
244
+ attr_reader :keywords
245
+
246
+ include Equatable
247
+
248
+ def initialize(keywords:)
249
+ @keywords = keywords
250
+ end
251
+ end
252
+
253
+ attr_reader :kwarg_nodes
254
+ attr_reader :keyword_params
255
+ attr_reader :index
256
+ attr_reader :consumed_keywords
257
+
258
+ def initialize(kwarg_nodes:, keyword_params:, index: 0, consumed_keywords: Set[])
259
+ @kwarg_nodes = kwarg_nodes
260
+ @keyword_params = keyword_params
261
+ @index = index
262
+ @consumed_keywords = consumed_keywords
263
+ end
264
+
265
+ def update(index: self.index, consumed_keywords: self.consumed_keywords)
266
+ KeywordArgs.new(
267
+ kwarg_nodes: kwarg_nodes,
268
+ keyword_params: keyword_params,
269
+ index: index,
270
+ consumed_keywords: consumed_keywords
271
+ )
272
+ end
273
+
274
+ def keyword_pair
275
+ kwarg_nodes[index]
276
+ end
277
+
278
+ def required_keywords
279
+ keyword_params.requireds
280
+ end
281
+
282
+ def optional_keywords
283
+ keyword_params.optionals
284
+ end
285
+
286
+ def rest_type
287
+ keyword_params.rest
288
+ end
289
+
290
+ def keyword_type(key)
291
+ required_keywords[key] || optional_keywords[key]
292
+ end
293
+
294
+ def all_keys
295
+ keys = Set.new
296
+ keys.merge(required_keywords.each_key)
297
+ keys.merge(optional_keywords.each_key)
298
+ keys.sort_by(&:to_s).to_a
299
+ end
300
+
301
+ def all_values
302
+ keys = Set.new
303
+ keys.merge(required_keywords.each_value)
304
+ keys.merge(optional_keywords.each_value)
305
+ keys.sort_by(&:to_s).to_a
306
+ end
307
+
308
+ def possible_key_type
309
+ # @type var key_types: Array[AST::Types::t]
310
+ key_types = all_keys.map {|key| AST::Types::Literal.new(value: key) }
311
+ key_types << AST::Builtin::Symbol.instance_type if rest_type
312
+
313
+ AST::Types::Union.build(types: key_types)
314
+ end
315
+
316
+ def possible_value_type
317
+ value_types = all_values
318
+ value_types << rest_type if rest_type
319
+
320
+ AST::Types::Intersection.build(types: value_types)
321
+ end
322
+
323
+ def next()
324
+ node = keyword_pair
325
+
326
+ if node
327
+ case node.type
328
+ when :pair
329
+ key_node, value_node = node.children
330
+
331
+ if key_node.type == :sym
332
+ key = key_node.children[0]
333
+
334
+ case
335
+ when value_type = keyword_type(key)
336
+ [
337
+ ArgTypePairs.new(
338
+ pairs: [
339
+ [key_node, AST::Types::Literal.new(value: key)],
340
+ [value_node, value_type]
341
+ ]
342
+ ),
343
+ update(
344
+ index: index+1,
345
+ consumed_keywords: consumed_keywords + [key]
346
+ )
347
+ ]
348
+ when value_type = rest_type
349
+ [
350
+ ArgTypePairs.new(
351
+ pairs: [
352
+ [key_node, AST::Builtin::Symbol.instance_type],
353
+ [value_node, value_type]
354
+ ]
355
+ ),
356
+ update(
357
+ index: index+1,
358
+ consumed_keywords: consumed_keywords + [key]
359
+ )
360
+ ]
361
+ else
362
+ [
363
+ UnexpectedKeyword.new(keyword: key, node: node),
364
+ update(index: index+1)
365
+ ]
366
+ end
367
+ else
368
+ if !all_keys.empty? || rest_type
369
+ [
370
+ ArgTypePairs.new(
371
+ pairs: [
372
+ [key_node, possible_key_type],
373
+ [value_node, possible_value_type]
374
+ ]
375
+ ),
376
+ update(index: index+1)
377
+ ]
378
+ else
379
+ [
380
+ UnexpectedKeyword.new(keyword: nil, node: node),
381
+ update(index: index+1)
382
+ ]
383
+ end
384
+ end
385
+ when :kwsplat
386
+ [
387
+ SplatArg.new(node: node),
388
+ self
389
+ ]
390
+ end
391
+ else
392
+ left = Set.new(required_keywords.keys) - consumed_keywords
393
+ unless left.empty?
394
+ [
395
+ MissingKeyword.new(keywords: left),
396
+ update(consumed_keywords: consumed_keywords + left)
397
+ ]
398
+ end
399
+ end
400
+ end
401
+
402
+ def consume_keys(keys, node:)
403
+ # @type var consumed_keys: Array[Symbol]
404
+ consumed_keys = []
405
+ # @type var types: Array[AST::Types::t]
406
+ types = []
407
+
408
+ # @type var unexpected_keyword: Symbol?
409
+ unexpected_keyword = nil
410
+
411
+ keys.each do |key|
412
+ case
413
+ when type = keyword_type(key)
414
+ consumed_keys << key
415
+ types << type
416
+ when type = rest_type()
417
+ types << type
418
+ else
419
+ unexpected_keyword = key
420
+ end
421
+ end
422
+
423
+ [
424
+ if unexpected_keyword
425
+ UnexpectedKeyword.new(keyword: unexpected_keyword, node: node)
426
+ else
427
+ types
428
+ end,
429
+ update(index: index + 1, consumed_keywords: consumed_keywords + consumed_keys)
430
+ ]
431
+ end
432
+ end
433
+
434
+ class BlockPassArg
435
+ attr_reader :node
436
+ attr_reader :block
437
+
438
+ def initialize(node:, block:)
439
+ @node = node
440
+ @block = block
441
+ end
442
+
443
+ include Equatable
444
+
445
+ def no_block?
446
+ !node && !block
447
+ end
448
+
449
+ def compatible?
450
+ if node
451
+ block ? true : false
452
+ else
453
+ !block || block.optional?
454
+ end
455
+ end
456
+
457
+ def block_missing?
458
+ !node && block&.required?
459
+ end
460
+
461
+ def unexpected_block?
462
+ node && !block
463
+ end
464
+
465
+ def pair
466
+ raise unless compatible?
467
+
468
+ if node && block
469
+ [
470
+ node,
471
+ block.type
472
+ ]
473
+ end
474
+ end
475
+
476
+ def node_type
477
+ raise unless block
478
+
479
+ type = AST::Types::Proc.new(type: block.type, block: nil, self_type: block.self_type)
480
+
481
+ if block.optional?
482
+ type = AST::Types::Union.build(types: [type, AST::Builtin.nil_type])
483
+ end
484
+
485
+ type
486
+ end
487
+ end
488
+
489
+ class ForwardedArgs
490
+ attr_reader :node, :params
491
+
492
+ def initialize(node:, params:)
493
+ @node = node
494
+ @params = params
495
+ end
496
+ end
497
+
498
+ attr_reader :node
499
+ attr_reader :arguments
500
+ attr_reader :type
501
+
502
+ def initialize(node:, arguments:, type:)
503
+ raise "Untyped function is not supported" unless type.type.params
504
+ @node = node
505
+ @arguments = arguments
506
+ @type = type
507
+ end
508
+
509
+ def params
510
+ case type
511
+ when Interface::MethodType
512
+ type.type.params or raise
513
+ when AST::Types::Proc
514
+ type.type.params or raise
515
+ else
516
+ raise
517
+ end
518
+ end
519
+
520
+ def block
521
+ case type
522
+ when Interface::MethodType
523
+ type.block
524
+ when AST::Types::Proc
525
+ type.block
526
+ end
527
+ end
528
+
529
+ def positional_params
530
+ params or raise
531
+ params.positional_params
532
+ end
533
+
534
+ def keyword_params
535
+ params or raise
536
+ params.keyword_params
537
+ end
538
+
539
+ def kwargs_node
540
+ unless keyword_params.empty?
541
+ arguments.find {|node| node.type == :kwargs }
542
+ end
543
+ end
544
+
545
+ def positional_arg
546
+ args =
547
+ if keyword_params.empty?
548
+ arguments.take_while {|node| node.type != :block_pass }
549
+ else
550
+ arguments.take_while {|node| node.type != :kwargs && node.type != :block_pass }
551
+ end
552
+
553
+ PositionalArgs.new(args: args, index: 0, positional_params: positional_params)
554
+ end
555
+
556
+ def forwarded_args_node
557
+ arguments.find {|node| node.type == :forwarded_args }
558
+ end
559
+
560
+ def keyword_args
561
+ KeywordArgs.new(
562
+ kwarg_nodes: kwargs_node&.children || [],
563
+ keyword_params: keyword_params
564
+ )
565
+ end
566
+
567
+ def block_pass_arg
568
+ node = arguments.find {|node| node.type == :block_pass }
569
+
570
+ BlockPassArg.new(node: node, block: block)
571
+ end
572
+
573
+ def each
574
+ if block_given?
575
+ errors = [] #: Array[PositionalArgs::error_arg | KeywordArgs::error_arg]
576
+
577
+ last_positional_args = positional_arg
578
+
579
+ positional_arg.tap do |args|
580
+ while (value, args = args.next())
581
+ yield value
582
+
583
+ case value
584
+ when PositionalArgs::SplatArg
585
+ type = value.type
586
+
587
+ case type
588
+ when nil
589
+ raise
590
+ when AST::Types::Tuple
591
+ ts, args = args.consume(type.types.size, node: value.node)
592
+
593
+ case ts
594
+ when Array
595
+ ty = AST::Types::Tuple.new(types: ts.map(&:type))
596
+ yield PositionalArgs::NodeTypePair.new(node: value.node, type: ty)
597
+ when PositionalArgs::UnexpectedArg
598
+ errors << ts
599
+ yield ts
600
+ end
601
+ else
602
+ if t = args.uniform_type
603
+ args.following_args.each do |node|
604
+ yield PositionalArgs::NodeTypePair.new(node: node, type: t)
605
+ end
606
+ else
607
+ args.following_args.each do |node|
608
+ arg = PositionalArgs::UnexpectedArg.new(node: node)
609
+ yield arg
610
+ errors << arg
611
+ end
612
+ end
613
+
614
+ break
615
+ end
616
+ when PositionalArgs::UnexpectedArg, PositionalArgs::MissingArg
617
+ errors << value
618
+ end
619
+
620
+ last_positional_args = args
621
+ end
622
+ end
623
+
624
+ if fag = forwarded_args_node
625
+ forward_params = Interface::Function::Params.new(
626
+ positional_params: last_positional_args.positional_params,
627
+ keyword_params: keyword_params
628
+ )
629
+
630
+ forwarded_args = ForwardedArgs.new(node: fag, params: forward_params)
631
+ else
632
+ keyword_args.tap do |args|
633
+ while (a, args = args.next)
634
+ case a
635
+ when KeywordArgs::MissingKeyword
636
+ errors << a
637
+ when KeywordArgs::UnexpectedKeyword
638
+ errors << a
639
+ end
640
+
641
+ yield a
642
+
643
+ case a
644
+ when KeywordArgs::SplatArg
645
+ case type = a.type
646
+ when nil
647
+ raise
648
+ when AST::Types::Record
649
+ # @type var keys: Array[Symbol]
650
+ keys = _ = type.elements.keys
651
+ ts, args = args.consume_keys(keys, node: a.node)
652
+
653
+ case ts
654
+ when KeywordArgs::UnexpectedKeyword
655
+ yield ts
656
+ errors << ts
657
+ when Array
658
+ pairs = keys.zip(ts) #: Array[[Symbol, AST::Types::t]]
659
+ record = AST::Types::Record.new(elements: Hash[pairs], required_keys: Set.new(keys))
660
+ yield KeywordArgs::ArgTypePairs.new(pairs: [[a.node, record]])
661
+ end
662
+ else
663
+ args = args.update(index: args.index + 1)
664
+
665
+ if args.rest_type
666
+ type = AST::Builtin::Hash.instance_type(AST::Builtin::Symbol.instance_type, args.possible_value_type)
667
+ yield KeywordArgs::ArgTypePairs.new(pairs: [[a.node, type]])
668
+ else
669
+ yield KeywordArgs::UnexpectedKeyword.new(keyword: nil, node: a.node)
670
+ end
671
+ end
672
+ end
673
+ end
674
+ end
675
+ end
676
+
677
+ diagnostics = [] #: Array[Diagnostic::Ruby::Base]
678
+
679
+ missing_keywords = [] #: Array[Symbol]
680
+ errors.each do |error|
681
+ case error
682
+ when KeywordArgs::UnexpectedKeyword
683
+ diagnostics << Diagnostic::Ruby::UnexpectedKeywordArgument.new(node: error.node, params: params)
684
+ when KeywordArgs::MissingKeyword
685
+ missing_keywords.push(*error.keywords.to_a)
686
+ when PositionalArgs::UnexpectedArg
687
+ if error.node.type == :kwargs
688
+ error.node.children.each do |kwarg|
689
+ if kwarg.type == :pair
690
+ diagnostics << Diagnostic::Ruby::UnexpectedKeywordArgument.new(node: kwarg, params: params)
691
+ end
692
+ end
693
+ else
694
+ diagnostics << Diagnostic::Ruby::UnexpectedPositionalArgument.new(node: error.node, params: params)
695
+ end
696
+ when PositionalArgs::MissingArg
697
+ diagnostics << Diagnostic::Ruby::InsufficientPositionalArguments.new(node: node, params: params)
698
+ end
699
+ end
700
+
701
+ unless missing_keywords.empty?
702
+ diagnostics << Diagnostic::Ruby::InsufficientKeywordArguments.new(node: node, params: params, missing_keywords: missing_keywords)
703
+ end
704
+
705
+ [forwarded_args, diagnostics]
706
+ else
707
+ enum_for :each
708
+ end
709
+ end
710
+ end
711
+ end
712
+ end