steep-activesupport-4 1.9.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (164) 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/Steepfile +68 -0
  9. data/bin/console +14 -0
  10. data/bin/generate-diagnostics-docs.rb +112 -0
  11. data/bin/mem_graph.rb +67 -0
  12. data/bin/mem_prof.rb +102 -0
  13. data/bin/output_rebaseline.rb +34 -0
  14. data/bin/output_test.rb +60 -0
  15. data/bin/rbs +20 -0
  16. data/bin/rbs-inline +19 -0
  17. data/bin/setup +9 -0
  18. data/bin/stackprof_test.rb +19 -0
  19. data/bin/steep +19 -0
  20. data/bin/steep-check.rb +251 -0
  21. data/bin/steep-prof +16 -0
  22. data/doc/narrowing.md +195 -0
  23. data/doc/shape.md +194 -0
  24. data/exe/steep +18 -0
  25. data/guides/README.md +5 -0
  26. data/guides/src/gem-rbs-collection/gem-rbs-collection.md +126 -0
  27. data/guides/src/getting-started/getting-started.md +163 -0
  28. data/guides/src/nil-optional/nil-optional.md +195 -0
  29. data/lib/steep/annotation_parser.rb +199 -0
  30. data/lib/steep/ast/annotation/collection.rb +172 -0
  31. data/lib/steep/ast/annotation.rb +137 -0
  32. data/lib/steep/ast/builtin.rb +104 -0
  33. data/lib/steep/ast/ignore.rb +148 -0
  34. data/lib/steep/ast/node/type_application.rb +88 -0
  35. data/lib/steep/ast/node/type_assertion.rb +81 -0
  36. data/lib/steep/ast/types/any.rb +35 -0
  37. data/lib/steep/ast/types/boolean.rb +45 -0
  38. data/lib/steep/ast/types/bot.rb +35 -0
  39. data/lib/steep/ast/types/class.rb +43 -0
  40. data/lib/steep/ast/types/factory.rb +557 -0
  41. data/lib/steep/ast/types/helper.rb +40 -0
  42. data/lib/steep/ast/types/instance.rb +42 -0
  43. data/lib/steep/ast/types/intersection.rb +93 -0
  44. data/lib/steep/ast/types/literal.rb +59 -0
  45. data/lib/steep/ast/types/logic.rb +84 -0
  46. data/lib/steep/ast/types/name.rb +128 -0
  47. data/lib/steep/ast/types/nil.rb +41 -0
  48. data/lib/steep/ast/types/proc.rb +117 -0
  49. data/lib/steep/ast/types/record.rb +79 -0
  50. data/lib/steep/ast/types/self.rb +43 -0
  51. data/lib/steep/ast/types/shared_instance.rb +11 -0
  52. data/lib/steep/ast/types/top.rb +35 -0
  53. data/lib/steep/ast/types/tuple.rb +60 -0
  54. data/lib/steep/ast/types/union.rb +97 -0
  55. data/lib/steep/ast/types/var.rb +65 -0
  56. data/lib/steep/ast/types/void.rb +35 -0
  57. data/lib/steep/cli.rb +401 -0
  58. data/lib/steep/diagnostic/deprecated/else_on_exhaustive_case.rb +20 -0
  59. data/lib/steep/diagnostic/deprecated/unknown_constant_assigned.rb +28 -0
  60. data/lib/steep/diagnostic/helper.rb +18 -0
  61. data/lib/steep/diagnostic/lsp_formatter.rb +78 -0
  62. data/lib/steep/diagnostic/result_printer2.rb +48 -0
  63. data/lib/steep/diagnostic/ruby.rb +1221 -0
  64. data/lib/steep/diagnostic/signature.rb +570 -0
  65. data/lib/steep/drivers/annotations.rb +52 -0
  66. data/lib/steep/drivers/check.rb +339 -0
  67. data/lib/steep/drivers/checkfile.rb +210 -0
  68. data/lib/steep/drivers/diagnostic_printer.rb +105 -0
  69. data/lib/steep/drivers/init.rb +66 -0
  70. data/lib/steep/drivers/langserver.rb +56 -0
  71. data/lib/steep/drivers/print_project.rb +113 -0
  72. data/lib/steep/drivers/stats.rb +203 -0
  73. data/lib/steep/drivers/utils/driver_helper.rb +143 -0
  74. data/lib/steep/drivers/utils/jobs_option.rb +26 -0
  75. data/lib/steep/drivers/vendor.rb +27 -0
  76. data/lib/steep/drivers/watch.rb +194 -0
  77. data/lib/steep/drivers/worker.rb +58 -0
  78. data/lib/steep/equatable.rb +23 -0
  79. data/lib/steep/expectations.rb +228 -0
  80. data/lib/steep/index/rbs_index.rb +350 -0
  81. data/lib/steep/index/signature_symbol_provider.rb +185 -0
  82. data/lib/steep/index/source_index.rb +167 -0
  83. data/lib/steep/interface/block.rb +103 -0
  84. data/lib/steep/interface/builder.rb +843 -0
  85. data/lib/steep/interface/function.rb +1090 -0
  86. data/lib/steep/interface/method_type.rb +330 -0
  87. data/lib/steep/interface/shape.rb +239 -0
  88. data/lib/steep/interface/substitution.rb +159 -0
  89. data/lib/steep/interface/type_param.rb +115 -0
  90. data/lib/steep/located_value.rb +20 -0
  91. data/lib/steep/method_name.rb +42 -0
  92. data/lib/steep/module_helper.rb +24 -0
  93. data/lib/steep/node_helper.rb +273 -0
  94. data/lib/steep/path_helper.rb +30 -0
  95. data/lib/steep/project/dsl.rb +268 -0
  96. data/lib/steep/project/group.rb +31 -0
  97. data/lib/steep/project/options.rb +63 -0
  98. data/lib/steep/project/pattern.rb +59 -0
  99. data/lib/steep/project/target.rb +92 -0
  100. data/lib/steep/project.rb +78 -0
  101. data/lib/steep/rake_task.rb +132 -0
  102. data/lib/steep/range_extension.rb +29 -0
  103. data/lib/steep/server/base_worker.rb +97 -0
  104. data/lib/steep/server/change_buffer.rb +73 -0
  105. data/lib/steep/server/custom_methods.rb +77 -0
  106. data/lib/steep/server/delay_queue.rb +45 -0
  107. data/lib/steep/server/interaction_worker.rb +492 -0
  108. data/lib/steep/server/lsp_formatter.rb +455 -0
  109. data/lib/steep/server/master.rb +912 -0
  110. data/lib/steep/server/target_group_files.rb +205 -0
  111. data/lib/steep/server/type_check_controller.rb +366 -0
  112. data/lib/steep/server/type_check_worker.rb +303 -0
  113. data/lib/steep/server/work_done_progress.rb +64 -0
  114. data/lib/steep/server/worker_process.rb +176 -0
  115. data/lib/steep/services/completion_provider.rb +802 -0
  116. data/lib/steep/services/content_change.rb +61 -0
  117. data/lib/steep/services/file_loader.rb +74 -0
  118. data/lib/steep/services/goto_service.rb +441 -0
  119. data/lib/steep/services/hover_provider/rbs.rb +88 -0
  120. data/lib/steep/services/hover_provider/ruby.rb +221 -0
  121. data/lib/steep/services/hover_provider/singleton_methods.rb +20 -0
  122. data/lib/steep/services/path_assignment.rb +46 -0
  123. data/lib/steep/services/signature_help_provider.rb +202 -0
  124. data/lib/steep/services/signature_service.rb +428 -0
  125. data/lib/steep/services/stats_calculator.rb +68 -0
  126. data/lib/steep/services/type_check_service.rb +394 -0
  127. data/lib/steep/services/type_name_completion.rb +236 -0
  128. data/lib/steep/signature/validator.rb +651 -0
  129. data/lib/steep/source/ignore_ranges.rb +69 -0
  130. data/lib/steep/source.rb +691 -0
  131. data/lib/steep/subtyping/cache.rb +30 -0
  132. data/lib/steep/subtyping/check.rb +1113 -0
  133. data/lib/steep/subtyping/constraints.rb +341 -0
  134. data/lib/steep/subtyping/relation.rb +101 -0
  135. data/lib/steep/subtyping/result.rb +324 -0
  136. data/lib/steep/subtyping/variable_variance.rb +89 -0
  137. data/lib/steep/test.rb +9 -0
  138. data/lib/steep/thread_waiter.rb +43 -0
  139. data/lib/steep/type_construction.rb +5183 -0
  140. data/lib/steep/type_inference/block_params.rb +416 -0
  141. data/lib/steep/type_inference/case_when.rb +303 -0
  142. data/lib/steep/type_inference/constant_env.rb +56 -0
  143. data/lib/steep/type_inference/context.rb +195 -0
  144. data/lib/steep/type_inference/logic_type_interpreter.rb +613 -0
  145. data/lib/steep/type_inference/method_call.rb +193 -0
  146. data/lib/steep/type_inference/method_params.rb +531 -0
  147. data/lib/steep/type_inference/multiple_assignment.rb +194 -0
  148. data/lib/steep/type_inference/send_args.rb +712 -0
  149. data/lib/steep/type_inference/type_env.rb +341 -0
  150. data/lib/steep/type_inference/type_env_builder.rb +138 -0
  151. data/lib/steep/typing.rb +321 -0
  152. data/lib/steep/version.rb +3 -0
  153. data/lib/steep.rb +369 -0
  154. data/manual/annotations.md +181 -0
  155. data/manual/ignore.md +20 -0
  156. data/manual/ruby-diagnostics.md +1879 -0
  157. data/sample/Steepfile +22 -0
  158. data/sample/lib/conference.rb +49 -0
  159. data/sample/lib/length.rb +35 -0
  160. data/sample/sig/conference.rbs +42 -0
  161. data/sample/sig/generics.rbs +15 -0
  162. data/sample/sig/length.rbs +34 -0
  163. data/steep-activesupport-4.gemspec +55 -0
  164. metadata +437 -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