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,691 @@
1
+ module Steep
2
+ class Source
3
+ attr_reader :buffer
4
+ attr_reader :path
5
+ attr_reader :node
6
+ attr_reader :mapping
7
+ attr_reader :comments
8
+ attr_reader :ignores
9
+
10
+ extend NodeHelper
11
+ extend ModuleHelper
12
+
13
+ def initialize(buffer:, path:, node:, mapping:, comments:, ignores:)
14
+ @buffer = buffer
15
+ @path = path
16
+ @node = node
17
+ @mapping = mapping
18
+ @comments = comments
19
+ @ignores = ignores
20
+ end
21
+
22
+ class Builder < ::Parser::Builders::Default
23
+ def string_value(token)
24
+ value(token)
25
+ end
26
+
27
+ self.emit_lambda = true
28
+ self.emit_procarg0 = true
29
+ self.emit_kwargs = true
30
+ self.emit_forward_arg = true
31
+ end
32
+
33
+ def self.new_parser
34
+ ::Parser::Ruby33.new(Builder.new).tap do |parser|
35
+ parser.diagnostics.all_errors_are_fatal = true
36
+ parser.diagnostics.ignore_warnings = true
37
+ end
38
+ end
39
+
40
+ def self.parse(source_code, path:, factory:)
41
+ buffer = ::Parser::Source::Buffer.new(path.to_s, 1, source: source_code)
42
+ node, comments = new_parser().parse_with_comments(buffer)
43
+
44
+ # @type var annotations: Array[AST::Annotation::t]
45
+ annotations = []
46
+ # @type var type_comments: Hash[Integer, type_comment]
47
+ type_comments = {}
48
+
49
+ buffer = RBS::Buffer.new(name: path, content: source_code)
50
+ annotation_parser = AnnotationParser.new(factory: factory)
51
+
52
+ comments = comments.sort_by do |comment|
53
+ comment.loc.expression.begin_pos
54
+ end
55
+
56
+ comments.each do |comment|
57
+ if comment.inline?
58
+ content = comment.text.delete_prefix('#')
59
+ content.lstrip!
60
+ prefix = comment.text.size - content.size
61
+ content.rstrip!
62
+ suffix = comment.text.size - content.size - prefix
63
+
64
+ location = RBS::Location.new(
65
+ buffer: buffer,
66
+ start_pos: comment.location.expression.begin_pos + prefix,
67
+ end_pos: comment.location.expression.end_pos - suffix
68
+ )
69
+
70
+ case
71
+ when annotation = annotation_parser.parse(content, location: location)
72
+ annotations << annotation
73
+ when assertion = AST::Node::TypeAssertion.parse(location)
74
+ type_comments[assertion.line] = assertion
75
+ when tapp = AST::Node::TypeApplication.parse(location)
76
+ type_comments[tapp.line] = tapp
77
+ end
78
+ end
79
+ end
80
+
81
+ map = {} #: Hash[Parser::AST::Node, Array[AST::Annotation::t]]
82
+ map.compare_by_identity
83
+
84
+ if node
85
+ node = insert_type_node(node, type_comments)
86
+ construct_mapping(node: node, annotations: annotations, mapping: map)
87
+ end
88
+
89
+ annotations.each do |annot|
90
+ map[node] ||= []
91
+ map.fetch(node) << annot
92
+ end
93
+
94
+ ignores = comments.filter_map do |comment|
95
+ AST::Ignore.parse(comment, buffer)
96
+ end
97
+
98
+ new(buffer: buffer, path: path, node: node, mapping: map, comments: comments, ignores: ignores)
99
+ end
100
+
101
+ def self.construct_mapping(node:, annotations:, mapping:, line_range: nil)
102
+ case node.type
103
+ when :if
104
+ cond_node, truthy_node, falsy_node, loc = deconstruct_if_node!(node)
105
+
106
+ if node.loc.respond_to?(:question)
107
+ # Skip ternary operator
108
+
109
+ each_child_node node do |child|
110
+ construct_mapping(node: child, annotations: annotations, mapping: mapping, line_range: nil)
111
+ end
112
+ else
113
+ if_loc = loc #: NodeHelper::condition_loc
114
+
115
+ if if_loc.expression.begin_pos == if_loc.keyword.begin_pos
116
+ construct_mapping(node: cond_node,annotations: annotations, mapping: mapping, line_range: nil)
117
+
118
+ if truthy_node
119
+ if if_loc.keyword.source == "if" || if_loc.keyword.source == "elsif"
120
+ # if foo
121
+ # bar <=
122
+ # end
123
+ then_start = if_loc.begin&.last_line || cond_node.loc.last_line
124
+ then_end = if_loc.else&.line || if_loc.last_line
125
+ else
126
+ # unless foo
127
+ # else
128
+ # bar <=
129
+ # end
130
+ if_loc.else or raise
131
+ then_start = if_loc.else.last_line
132
+ then_end = loc.last_line
133
+ end
134
+ construct_mapping(node: truthy_node, annotations: annotations, mapping: mapping, line_range: then_start...then_end)
135
+ end
136
+
137
+ if falsy_node
138
+ if if_loc.keyword.source == "if" || if_loc.keyword.source == "elsif"
139
+ # if foo
140
+ # else
141
+ # bar <=
142
+ # end
143
+ if_loc.else or raise
144
+ else_start = if_loc.else.last_line
145
+ else_end = if_loc.last_line
146
+ else
147
+ # unless foo
148
+ # bar <=
149
+ # end
150
+ else_start = if_loc.begin&.last_line || cond_node.loc.last_line
151
+ else_end = if_loc.else&.line || if_loc.last_line
152
+ end
153
+ construct_mapping(node: falsy_node, annotations: annotations, mapping: mapping, line_range: else_start...else_end)
154
+ end
155
+
156
+ else
157
+ # postfix if/unless
158
+ each_child_node(node) do |child|
159
+ construct_mapping(node: child, annotations: annotations, mapping: mapping, line_range: nil)
160
+ end
161
+ end
162
+ end
163
+
164
+ when :while, :until
165
+ cond_node, body_node, loc = deconstruct_whileish_node!(node)
166
+
167
+ if loc.expression.begin_pos == loc.keyword.begin_pos
168
+ # prefix while
169
+ loc.end or raise
170
+ construct_mapping(node: cond_node, annotations: annotations, mapping: mapping, line_range: nil)
171
+
172
+ if body_node
173
+ body_start = cond_node.loc.last_line
174
+ body_end = loc.end.line
175
+
176
+ construct_mapping(node: body_node, annotations: annotations, mapping: mapping, line_range: body_start...body_end)
177
+ end
178
+ else
179
+ # postfix while
180
+ each_child_node(node) do |child|
181
+ construct_mapping(node: child, annotations: annotations, mapping: mapping, line_range: nil)
182
+ end
183
+ end
184
+
185
+ when :while_post, :until_post
186
+ cond_node, body_node, loc = deconstruct_whileish_node!(node)
187
+
188
+ construct_mapping(node: cond_node, annotations: annotations, mapping: mapping, line_range: nil)
189
+
190
+ if body_node
191
+ body_start = loc.expression.line
192
+ body_end = loc.keyword.line
193
+ construct_mapping(node: body_node, annotations: annotations, mapping: mapping, line_range: body_start...body_end)
194
+ end
195
+
196
+ when :case
197
+ cond_node, when_nodes, else_node, loc = deconstruct_case_node!(node)
198
+
199
+ if cond_node
200
+ construct_mapping(node: cond_node, annotations: annotations, mapping: mapping, line_range: nil)
201
+ end
202
+
203
+ if else_node
204
+ loc.else or raise
205
+ loc.end or raise
206
+
207
+ else_start = loc.else.last_line
208
+ else_end = loc.end.line
209
+
210
+ construct_mapping(node: else_node, annotations: annotations, mapping: mapping, line_range: else_start...else_end)
211
+ end
212
+
213
+ when_nodes.each do |child|
214
+ if child.type == :when
215
+ construct_mapping(node: child, annotations: annotations, mapping: mapping, line_range: nil)
216
+ end
217
+ end
218
+
219
+ when :when
220
+ operands, body, loc = deconstruct_when_node!(node)
221
+ last_cond = operands.last or raise
222
+
223
+ operands.each do |child|
224
+ construct_mapping(node: child, annotations: annotations, mapping: mapping, line_range: nil)
225
+ end
226
+
227
+ if body
228
+ cond_end = loc.begin&.last_line || last_cond.loc.last_line+1
229
+ body_end = body.loc.last_line
230
+ construct_mapping(node: body, annotations: annotations, mapping: mapping, line_range: cond_end...body_end)
231
+ end
232
+
233
+ when :rescue
234
+ body, resbodies, else_node, loc = deconstruct_rescue_node!(node)
235
+
236
+ if else_node
237
+ loc.else or raise
238
+
239
+ else_start = loc.else.last_line
240
+ else_end = loc.last_line
241
+
242
+ construct_mapping(node: else_node, annotations: annotations, mapping: mapping, line_range: else_start...else_end)
243
+ end
244
+
245
+ each_child_node(node) do |child|
246
+ construct_mapping(node: child, annotations: annotations, mapping: mapping, line_range: nil)
247
+ end
248
+
249
+ else
250
+ each_child_node(node) do |child|
251
+ construct_mapping(node: child, annotations: annotations, mapping: mapping, line_range: nil)
252
+ end
253
+ end
254
+
255
+ associated_annotations, other_annotations = annotations.partition do |annot|
256
+ location = node.loc
257
+ annot.line or next
258
+
259
+ case node.type
260
+ when :def, :module, :class, :block, :ensure, :defs, :resbody
261
+ location = node.loc
262
+ location.line <= annot.line && annot.line < location.last_line
263
+ else
264
+ if line_range
265
+ line_range.begin <= annot.line && annot.line < line_range.end
266
+ end
267
+ end
268
+ end
269
+
270
+ associated_annotations.each do |annot|
271
+ mapping[node] ||= []
272
+ mapping.fetch(node) << annot
273
+ end
274
+
275
+ annotations.replace(other_annotations)
276
+ end
277
+
278
+ def self.map_child_node(node, type = nil, skip: nil)
279
+ children = node.children.map do |child|
280
+ if child.is_a?(Parser::AST::Node)
281
+ if skip
282
+ if skip.member?(child)
283
+ child
284
+ else
285
+ yield child
286
+ end
287
+ else
288
+ yield child
289
+ end
290
+ else
291
+ child
292
+ end
293
+ end
294
+
295
+ node.updated(type, children)
296
+ end
297
+
298
+ def annotations(block:, factory:, context:)
299
+ annotations =
300
+ if block
301
+ mapping.fetch(block, [])
302
+ else
303
+ []
304
+ end #: Array[AST::Annotation::t]
305
+ AST::Annotation::Collection.new(
306
+ annotations: annotations,
307
+ factory: factory,
308
+ context: context
309
+ )
310
+ end
311
+
312
+ def each_annotation(&block)
313
+ if block_given?
314
+ mapping.each do |node, annots|
315
+ yield [node, annots]
316
+ end
317
+ else
318
+ enum_for :each_annotation
319
+ end
320
+ end
321
+
322
+ def each_heredoc_node(node = self.node, parents = [], &block)
323
+ if block
324
+ return unless node
325
+
326
+ case node.type
327
+ when :dstr, :str
328
+ if node.location.respond_to?(:heredoc_body)
329
+ yield [[node, *parents], _ = node.location]
330
+ end
331
+ end
332
+
333
+ parents.unshift(node)
334
+ Source.each_child_node(node) do |child|
335
+ each_heredoc_node(child, parents, &block)
336
+ end
337
+ parents.shift()
338
+ else
339
+ enum_for :each_heredoc_node, node
340
+ end
341
+ end
342
+
343
+ def find_heredoc_nodes(line, column, position)
344
+ each_heredoc_node() do |nodes, location|
345
+ node = nodes[0]
346
+ loc = location.heredoc_body #: Parser::Source::Range
347
+
348
+ if range = loc.to_range
349
+ if range.begin <= position && position <= range.end
350
+ return nodes
351
+ end
352
+ end
353
+ end
354
+
355
+ nil
356
+ end
357
+
358
+ def find_nodes_loc(node, position, parents)
359
+ range = node.location.expression&.to_range
360
+
361
+ if range
362
+ if range.begin <= position && position <= range.end
363
+ parents.unshift node
364
+
365
+ Source.each_child_node(node) do |child|
366
+ if ns = find_nodes_loc(child, position, parents)
367
+ return ns
368
+ end
369
+ end
370
+
371
+ parents
372
+ end
373
+ end
374
+ end
375
+
376
+ def find_nodes(line:, column:)
377
+ return [] unless node
378
+
379
+ position = buffer.loc_to_pos([line, column])
380
+
381
+ if heredoc_nodes = find_heredoc_nodes(line, column, position)
382
+ Source.each_child_node(heredoc_nodes.fetch(0)) do |child|
383
+ if nodes = find_nodes_loc(child, position, heredoc_nodes)
384
+ return nodes
385
+ end
386
+ end
387
+
388
+ return heredoc_nodes
389
+ else
390
+ find_nodes_loc(node, position, [])
391
+ end
392
+ end
393
+
394
+ def find_comment(line:, column:)
395
+ pos = buffer.loc_to_pos([line, column])
396
+
397
+ comment = comments.bsearch do |comment|
398
+ pos <= comment.loc.expression.end_pos
399
+ end
400
+
401
+ if comment
402
+ if comment.loc.expression.begin_pos < pos
403
+ comment
404
+ end
405
+ end
406
+ end
407
+
408
+ def self.delete_defs(node, allow_list)
409
+ case node.type
410
+ when :def
411
+ if allow_list.include?(node)
412
+ node
413
+ else
414
+ node.updated(:nil, [])
415
+ end
416
+ when :defs
417
+ if allow_list.include?(node)
418
+ node
419
+ else
420
+ delete_defs(node.children[0], allow_list)
421
+ end
422
+ else
423
+ map_child_node(node) do |child|
424
+ delete_defs(child, allow_list)
425
+ end
426
+ end
427
+ end
428
+
429
+ def without_unrelated_defs(line:, column:)
430
+ if node
431
+ nodes = find_nodes(line: line, column: column) || []
432
+ defs = Set[].compare_by_identity.merge(nodes.select {|node| node.type == :def || node.type == :defs })
433
+
434
+ node_ = Source.delete_defs(node, defs)
435
+
436
+ # @type var mapping: Hash[Parser::AST::Node, Array[AST::Annotation::t]]
437
+ mapping = {}
438
+ mapping.compare_by_identity
439
+
440
+ annotations = self.mapping.values.flatten
441
+ Source.construct_mapping(node: node_, annotations: annotations, mapping: mapping)
442
+
443
+ annotations.each do |annot|
444
+ mapping[node_] ||= []
445
+ mapping.fetch(node_) << annot
446
+ end
447
+
448
+ Source.new(buffer: buffer, path: path, node: node_, mapping: mapping, comments: comments, ignores: ignores)
449
+ else
450
+ self
451
+ end
452
+ end
453
+
454
+ def self.skip_arg_assertions(node)
455
+ send_node, _ = deconstruct_sendish_and_block_nodes(node)
456
+ return false unless send_node
457
+
458
+ if send_node.type == :send
459
+ receiver, method, args = deconstruct_send_node!(send_node)
460
+
461
+ return false unless receiver
462
+
463
+ if receiver.type == :const
464
+ if type_name = module_name_from_node(receiver.children[0], receiver.children[1])
465
+ if type_name.namespace.empty?
466
+ if type_name.name == :Data && method == :define
467
+ return true
468
+ end
469
+ if type_name.name == :Struct && method == :new
470
+ return true
471
+ end
472
+ end
473
+ end
474
+ end
475
+ end
476
+
477
+ false
478
+ end
479
+
480
+ def self.insert_type_node(node, comments)
481
+ if node.location.expression
482
+ first_line = node.location.expression.first_line
483
+ last_line = node.location.expression.last_line
484
+ last_comment = comments[last_line]
485
+
486
+ if (first_line..last_line).none? {|l| comments.key?(l) }
487
+ return node
488
+ end
489
+
490
+ case
491
+ when last_comment.is_a?(AST::Node::TypeAssertion)
492
+ case node.type
493
+ when :lvasgn, :ivasgn, :gvasgn, :cvasgn, :casgn
494
+ # Skip
495
+ when :return, :break, :next
496
+ # Skip
497
+ when :def, :defs
498
+ # Skip
499
+ when :kwargs
500
+ # skip
501
+ when :when
502
+ # skip
503
+ when :pair
504
+ key, value = node.children
505
+ key = insert_type_node(key, comments.except(last_line))
506
+ value = insert_type_node(value, comments)
507
+ node = node.updated(nil, [key, value])
508
+ return adjust_location(node)
509
+ when :masgn
510
+ lhs, rhs = node.children
511
+ node = node.updated(nil, [lhs, insert_type_node(rhs, comments)])
512
+ return adjust_location(node)
513
+ when :begin
514
+ location = node.loc #: Parser::Source::Map & Parser::AST::_Collection
515
+ if location.begin
516
+ # paren
517
+ child_assertions = comments.except(last_line)
518
+ node = map_child_node(node) {|child| insert_type_node(child, child_assertions) }
519
+ node = adjust_location(node)
520
+ return assertion_node(node, last_comment)
521
+ end
522
+ else
523
+ if (receiver, name, * = deconstruct_send_node(node))
524
+ if receiver.nil?
525
+ if name == :attr_reader || name == :attr_writer || name == :attr_accessor
526
+ child_assertions = comments.except(last_line)
527
+ node = map_child_node(node) {|child| insert_type_node(child, child_assertions) }
528
+ return adjust_location(node)
529
+ end
530
+ end
531
+ end
532
+ child_assertions = comments.except(last_line)
533
+ node = map_child_node(node) {|child| insert_type_node(child, child_assertions) }
534
+ node = adjust_location(node)
535
+ return assertion_node(node, last_comment)
536
+ end
537
+ when selector_line = sendish_node?(node)
538
+ if (comment = comments[selector_line]).is_a?(AST::Node::TypeApplication)
539
+ child_assertions = comments.except(selector_line)
540
+ case node.type
541
+ when :block
542
+ send, *children = node.children
543
+ node = node.updated(
544
+ nil,
545
+ [
546
+ map_child_node(send) {|child| insert_type_node(child, child_assertions) },
547
+ *children.map do |child|
548
+ if child
549
+ insert_type_node(child, child_assertions)
550
+ end
551
+ end
552
+ ]
553
+ )
554
+ when :numblock
555
+ send, size, body = node.children
556
+ node = node.updated(
557
+ nil,
558
+ [
559
+ map_child_node(send) {|child| insert_type_node(child, child_assertions) },
560
+ size,
561
+ insert_type_node(body, child_assertions)
562
+ ]
563
+ )
564
+ else
565
+ node = map_child_node(node) {|child| insert_type_node(child, child_assertions) }
566
+ end
567
+ node = adjust_location(node)
568
+ return type_application_node(node, comment)
569
+ end
570
+ end
571
+ end
572
+
573
+ case node.type
574
+ when :class
575
+ class_name, super_class, class_body = node.children
576
+ adjust_location(
577
+ node.updated(
578
+ nil,
579
+ [
580
+ class_name,
581
+ super_class,
582
+ class_body ? insert_type_node(class_body, comments) : nil
583
+ ]
584
+ )
585
+ )
586
+ when :module
587
+ module_name, module_body = node.children
588
+ adjust_location(
589
+ node.updated(
590
+ nil,
591
+ [
592
+ module_name,
593
+ module_body ? insert_type_node(module_body, comments) : nil
594
+ ]
595
+ )
596
+ )
597
+ when :def
598
+ name, args, body = node.children
599
+ assertion_location = args&.location&.expression || (_ = node.location).name
600
+ no_assertion_comments = comments.except(assertion_location.last_line)
601
+ args = insert_type_node(args, no_assertion_comments)
602
+ body = insert_type_node(body, comments) if body
603
+ return adjust_location(node.updated(nil, [name, args, body]))
604
+ when :defs
605
+ object, name, args, body = node.children
606
+ assertion_location = args&.location&.expression || (_ = node.location).name
607
+ no_assertion_comments = comments.except(assertion_location.last_line)
608
+ object = insert_type_node(object, no_assertion_comments)
609
+ args = insert_type_node(args, no_assertion_comments)
610
+ body = insert_type_node(body, comments) if body
611
+ return adjust_location(node.updated(nil, [object, name, args, body]))
612
+ else
613
+ if skip_arg_assertions(node)
614
+ # Data.define, Struct.new, ...??
615
+ if node.location.expression
616
+ first_line = node.location.expression.first_line
617
+ last_line = node.location.expression.last_line
618
+
619
+ child_assertions = comments.delete_if {|line, _ | first_line < line && line < last_line }
620
+ node = map_child_node(node) {|child| insert_type_node(child, child_assertions) }
621
+
622
+ return adjust_location(node)
623
+ end
624
+ end
625
+
626
+ adjust_location(
627
+ map_child_node(node, nil) {|child| insert_type_node(child, comments) }
628
+ )
629
+ end
630
+ end
631
+
632
+ def self.sendish_node?(node)
633
+ send_node =
634
+ case node.type
635
+ when :send, :csend
636
+ node
637
+ when :block, :numblock
638
+ send = node.children[0]
639
+ case send.type
640
+ when :send, :csend
641
+ send
642
+ end
643
+ end
644
+
645
+ if send_node
646
+ receiver_node, name, _, location = deconstruct_send_node!(send_node)
647
+
648
+ if receiver_node
649
+ if location.dot
650
+ location.selector.line
651
+ end
652
+ else
653
+ location.selector.line
654
+ end
655
+ end
656
+ end
657
+
658
+ def self.adjust_location(node)
659
+ if end_pos = node.location.expression&.end_pos
660
+ if last_pos = each_child_node(node).map {|node| node.location.expression&.end_pos }.compact.max
661
+ if last_pos > end_pos
662
+ props = { location: node.location.with_expression(node.location.expression.with(end_pos: last_pos)) }
663
+ end
664
+ end
665
+ end
666
+
667
+ if props
668
+ node.updated(nil, nil, props)
669
+ else
670
+ node
671
+ end
672
+ end
673
+
674
+ def self.assertion_node(node, type)
675
+ map = Parser::Source::Map.new(node.location.expression.with(end_pos: type.location.end_pos))
676
+ Parser::AST::Node.new(:assertion, [node, type], { location: map })
677
+ end
678
+
679
+ def self.type_application_node(node, tapp)
680
+ if node.location.expression.end_pos > tapp.location.end_pos
681
+ map = Parser::Source::Map.new(node.location.expression)
682
+ else
683
+ map = Parser::Source::Map.new(node.location.expression.with(end_pos: tapp.location.end_pos))
684
+ end
685
+
686
+ node = Parser::AST::Node.new(:tapp, [node, tapp], { location: map })
687
+ tapp.set_node(node)
688
+ node
689
+ end
690
+ end
691
+ end
@@ -0,0 +1,30 @@
1
+ module Steep
2
+ module Subtyping
3
+ class Cache
4
+ attr_reader :subtypes
5
+
6
+ def initialize
7
+ @subtypes = {}
8
+ end
9
+
10
+ def subtype(relation, self_type, instance_type, class_type, bounds)
11
+ key = [relation, self_type, instance_type, class_type, bounds]
12
+ subtypes[key]
13
+ end
14
+
15
+ def [](relation, self_type, instance_type, class_type, bounds)
16
+ key = [relation, self_type, instance_type, class_type, bounds]
17
+ subtypes[key]
18
+ end
19
+
20
+ def []=(relation, self_type, instance_type, class_type, bounds, value)
21
+ key = [relation, self_type, instance_type, class_type, bounds]
22
+ subtypes[key] = value
23
+ end
24
+
25
+ def no_subtype_cache?
26
+ @subtypes.empty?
27
+ end
28
+ end
29
+ end
30
+ end