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,455 @@
1
+ module Steep
2
+ module Server
3
+ module LSPFormatter
4
+ include Services
5
+
6
+ LSP = LanguageServer::Protocol
7
+
8
+ module_function
9
+
10
+ def markup_content(string = nil, &block)
11
+ if block
12
+ string = yield()
13
+ end
14
+
15
+ if string
16
+ LSP::Interface::MarkupContent.new(kind: LSP::Constant::MarkupKind::MARKDOWN, value: string)
17
+ end
18
+ end
19
+
20
+ def format_hover_content(content)
21
+ case content
22
+ when HoverProvider::Ruby::VariableContent
23
+ local_variable(content.name, content.type)
24
+
25
+ when HoverProvider::Ruby::MethodCallContent
26
+ io = StringIO.new
27
+ call = content.method_call
28
+
29
+ case call
30
+ when TypeInference::MethodCall::Typed
31
+ io.puts <<~MD
32
+ ```rbs
33
+ #{call.actual_method_type.type.return_type}
34
+ ```
35
+
36
+ ----
37
+ MD
38
+
39
+ method_decls = call.method_decls.sort_by {|decl| decl.method_name.to_s }
40
+ method_types = method_decls.map(&:method_type)
41
+
42
+ if call.is_a?(TypeInference::MethodCall::Special)
43
+ method_types = [
44
+ call.actual_method_type.with(
45
+ type: call.actual_method_type.type.with(return_type: call.return_type)
46
+ )
47
+ ]
48
+
49
+ header = <<~MD
50
+ **💡 Custom typing rule applies**
51
+
52
+ ----
53
+ MD
54
+ end
55
+ when TypeInference::MethodCall::Error
56
+ method_decls = call.method_decls.sort_by {|decl| decl.method_name.to_s }
57
+ method_types = method_decls.map {|decl| decl.method_type }
58
+
59
+ header = <<~MD
60
+ **🚨 No compatible method type found**
61
+
62
+ ----
63
+ MD
64
+ end
65
+
66
+ method_names = method_decls.map {|decl| decl.method_name.relative }
67
+ docs = method_decls.map {|decl| [decl.method_name, decl.method_def.comment] }.to_h
68
+
69
+ if header
70
+ io.puts header
71
+ end
72
+
73
+ io.puts(
74
+ format_method_item_doc(method_types, method_names, docs)
75
+ )
76
+
77
+ io.string
78
+
79
+ when HoverProvider::Ruby::DefinitionContent
80
+ io = StringIO.new
81
+
82
+ method_name =
83
+ if content.method_name.is_a?(SingletonMethodName)
84
+ "self.#{content.method_name.method_name}"
85
+ else
86
+ content.method_name.method_name
87
+ end
88
+
89
+ prefix_size = "def ".size + method_name.size
90
+ method_types = content.definition.method_types
91
+
92
+ io.puts <<~MD
93
+ ```rbs
94
+ def #{method_name}: #{method_types.join("\n" + " "*prefix_size + "| ") }
95
+ ```
96
+
97
+ ----
98
+ MD
99
+
100
+ if content.definition.method_types.size > 1
101
+ io.puts "**Internal method type**"
102
+ io.puts <<~MD
103
+ ```rbs
104
+ #{content.method_type}
105
+ ```
106
+
107
+ ----
108
+ MD
109
+ end
110
+
111
+ io.puts format_comments(
112
+ content.definition.comments.map {|comment|
113
+ [content.method_name.relative.to_s, comment] #: [String, RBS::AST::Comment?]
114
+ }
115
+ )
116
+
117
+ io.string
118
+ when HoverProvider::Ruby::ConstantContent
119
+ io = StringIO.new
120
+
121
+ decl_summary =
122
+ case
123
+ when decl = content.class_decl
124
+ declaration_summary(decl.primary.decl)
125
+ when decl = content.constant_decl
126
+ declaration_summary(decl.decl)
127
+ when decl = content.class_alias
128
+ declaration_summary(decl.decl)
129
+ end
130
+
131
+ io.puts <<~MD
132
+ ```rbs
133
+ #{decl_summary}
134
+ ```
135
+ MD
136
+
137
+ comments = content.comments.map {|comment|
138
+ [content.full_name.relative!.to_s, comment] #: [String, RBS::AST::Comment?]
139
+ }
140
+
141
+ unless comments.all?(&:nil?)
142
+ io.puts "----"
143
+ io.puts format_comments(comments)
144
+ end
145
+
146
+ io.string
147
+ when HoverProvider::Ruby::TypeContent
148
+ <<~MD
149
+ ```rbs
150
+ #{content.type}
151
+ ```
152
+ MD
153
+
154
+ when HoverProvider::Ruby::TypeAssertionContent
155
+ <<~MD
156
+ ```rbs
157
+ #{content.asserted_type}
158
+ ```
159
+
160
+ ↑ Converted from `#{content.original_type.to_s}`
161
+ MD
162
+
163
+ when HoverProvider::RBS::TypeAliasContent, HoverProvider::RBS::InterfaceContent
164
+ io = StringIO.new()
165
+
166
+ io.puts <<~MD
167
+ ```rbs
168
+ #{declaration_summary(content.decl)}
169
+ ```
170
+ MD
171
+
172
+ if comment = content.decl.comment
173
+ io.puts
174
+ io.puts "----"
175
+
176
+ io.puts format_comment(comment, header: content.decl.name.relative!.to_s)
177
+ end
178
+
179
+ io.string
180
+
181
+ when HoverProvider::RBS::ClassContent
182
+ io = StringIO.new
183
+
184
+ io << <<~MD
185
+ ```rbs
186
+ #{declaration_summary(content.decl)}
187
+ ```
188
+ MD
189
+
190
+ if content.decl.comment
191
+ io.puts "----"
192
+
193
+ class_name =
194
+ case content.decl
195
+ when RBS::AST::Declarations::ModuleAlias, RBS::AST::Declarations::ClassAlias
196
+ content.decl.new_name
197
+ when RBS::AST::Declarations::Class, RBS::AST::Declarations::Module
198
+ content.decl.name
199
+ else
200
+ raise
201
+ end
202
+
203
+ io << format_comments([[class_name.relative!.to_s, content.decl.comment]])
204
+ end
205
+
206
+ io.string
207
+ else
208
+ raise content.class.to_s
209
+ end
210
+ end
211
+
212
+ def format_completion_docs(item)
213
+ case item
214
+ when Services::CompletionProvider::LocalVariableItem
215
+ local_variable(item.identifier, item.type)
216
+ when Services::CompletionProvider::ConstantItem
217
+ io = StringIO.new
218
+
219
+ io.puts <<~MD
220
+ ```rbs
221
+ #{declaration_summary(item.decl)}
222
+ ```
223
+ MD
224
+
225
+ unless item.comments.all?(&:nil?)
226
+ io.puts "----"
227
+ io.puts format_comments(
228
+ item.comments.map {|comment|
229
+ [item.full_name.relative!.to_s, comment] #: [String, RBS::AST::Comment?]
230
+ }
231
+ )
232
+ end
233
+
234
+ io.string
235
+ when Services::CompletionProvider::InstanceVariableItem
236
+ instance_variable(item.identifier, item.type)
237
+ when Services::CompletionProvider::SimpleMethodNameItem
238
+ format_method_item_doc(item.method_types, [], { item.method_name => item.method_member.comment })
239
+ when Services::CompletionProvider::ComplexMethodNameItem
240
+ method_names = item.method_names.map(&:relative).uniq
241
+ comments = item.method_definitions.transform_values {|member| member.comment }
242
+ format_method_item_doc(item.method_types, method_names, comments)
243
+ when Services::CompletionProvider::GeneratedMethodNameItem
244
+ format_method_item_doc(item.method_types, [], {}, "🤖 Generated method for receiver type")
245
+ when Services::CompletionProvider::TypeNameItem
246
+ io = StringIO.new
247
+
248
+ io.puts <<~MD
249
+ ```rbs
250
+ #{declaration_summary(item.decl)}
251
+ ```
252
+ MD
253
+
254
+ unless item.comments.empty?
255
+ io.puts "----"
256
+ io.puts format_comments(
257
+ item.comments.map {|comment|
258
+ [item.absolute_type_name.relative!.to_s, comment] #: [String, RBS::AST::Comment?]
259
+ }
260
+ )
261
+ end
262
+
263
+ io.string
264
+ when Services::CompletionProvider::KeywordArgumentItem
265
+ <<~MD
266
+ **Keyword argument**: `#{item.identifier}`
267
+ MD
268
+ else
269
+ raise
270
+ end
271
+ end
272
+
273
+ def format_rbs_completion_docs(type_name, decl, comments)
274
+ io = StringIO.new
275
+
276
+ io.puts <<~MD
277
+ ```rbs
278
+ #{declaration_summary(decl)}
279
+ ```
280
+ MD
281
+
282
+ unless comments.empty?
283
+ io.puts
284
+ io.puts "----"
285
+
286
+ io.puts format_comments(
287
+ comments.map {|comment|
288
+ [type_name.relative!.to_s, comment] #: [String, RBS::AST::Comment?]
289
+ }
290
+ )
291
+ end
292
+
293
+ io.string
294
+ end
295
+
296
+ def format_comments(comments)
297
+ io = StringIO.new
298
+
299
+ with_docs = [] #: Array[[String, RBS::AST::Comment]]
300
+ without_docs = [] #: Array[String]
301
+
302
+ comments.each do |title, comment|
303
+ if comment
304
+ with_docs << [title, comment]
305
+ else
306
+ without_docs << title
307
+ end
308
+ end
309
+
310
+ unless with_docs.empty?
311
+ with_docs.each do |title, comment|
312
+ io.puts format_comment(comment, header: title)
313
+ io.puts
314
+ end
315
+
316
+ unless without_docs.empty?
317
+ io.puts
318
+ io.puts "----"
319
+ if without_docs.size == 1
320
+ io.puts "🔍 One more definition without docs"
321
+ else
322
+ io.puts "🔍 #{without_docs.size} more definitions without docs"
323
+ end
324
+ end
325
+ end
326
+
327
+ io.string
328
+ end
329
+
330
+ def format_comment(comment, header: nil, &block)
331
+ return unless comment
332
+
333
+ io = StringIO.new
334
+ if header
335
+ io.puts "### 📚 #{header.gsub("_", "\\_")}"
336
+ io.puts
337
+ end
338
+ io.puts comment.string.rstrip.gsub(/^[ \t]*<!--(?~-->)-->\n/, "").gsub(/\A([ \t]*\n)+/, "")
339
+
340
+ if block
341
+ yield io.string
342
+ else
343
+ io.string
344
+ end
345
+ end
346
+
347
+ def local_variable(name, type)
348
+ <<~MD
349
+ **Local variable** `#{name}: #{type}`
350
+ MD
351
+ end
352
+
353
+ def instance_variable(name, type)
354
+ <<~MD
355
+ **Instance variable** `#{name}: #{type}`
356
+ MD
357
+ end
358
+
359
+ def name_and_params(name, params)
360
+ if params.empty?
361
+ "#{name}"
362
+ else
363
+ ps = params.each.map do |param|
364
+ s = +""
365
+ if param.unchecked?
366
+ s << "unchecked "
367
+ end
368
+ case param.variance
369
+ when :invariant
370
+ # nop
371
+ when :covariant
372
+ s << "out "
373
+ when :contravariant
374
+ s << "in "
375
+ end
376
+ s << param.name.to_s
377
+
378
+ if param.upper_bound_type
379
+ s << " < #{param.upper_bound_type.to_s}"
380
+ end
381
+
382
+ s
383
+ end
384
+
385
+ "#{name}[#{ps.join(", ")}]"
386
+ end
387
+ end
388
+
389
+ def name_and_args(name, args)
390
+ if args.empty?
391
+ "#{name}"
392
+ else
393
+ "#{name}[#{args.map(&:to_s).join(", ")}]"
394
+ end
395
+ end
396
+
397
+ def declaration_summary(decl)
398
+ # Note that all names in the declarations is absolute
399
+ case decl
400
+ when RBS::AST::Declarations::Class
401
+ super_class = if super_class = decl.super_class
402
+ " < #{name_and_args(super_class.name, super_class.args)}"
403
+ end
404
+ "class #{name_and_params(decl.name.relative!, decl.type_params)}#{super_class}"
405
+ when RBS::AST::Declarations::Module
406
+ self_type = unless decl.self_types.empty?
407
+ " : #{decl.self_types.map {|s| name_and_args(s.name, s.args) }.join(", ")}"
408
+ end
409
+ "module #{name_and_params(decl.name.relative!, decl.type_params)}#{self_type}"
410
+ when RBS::AST::Declarations::TypeAlias
411
+ "type #{name_and_params(decl.name.relative!, decl.type_params)} = #{decl.type}"
412
+ when RBS::AST::Declarations::Interface
413
+ "interface #{name_and_params(decl.name.relative!, decl.type_params)}"
414
+ when RBS::AST::Declarations::ClassAlias
415
+ "class #{decl.new_name.relative!} = #{decl.old_name}"
416
+ when RBS::AST::Declarations::ModuleAlias
417
+ "module #{decl.new_name.relative!} = #{decl.old_name}"
418
+ when RBS::AST::Declarations::Global
419
+ "#{decl.name}: #{decl.type}"
420
+ when RBS::AST::Declarations::Constant
421
+ "#{decl.name.relative!}: #{decl.type}"
422
+ end
423
+ end
424
+
425
+ def format_method_item_doc(method_types, method_names, comments, footer = "")
426
+ io = StringIO.new
427
+
428
+ io.puts "**Method type**:"
429
+ io.puts "```rbs"
430
+ if method_types.size == 1
431
+ io.puts method_types[0].to_s
432
+ else
433
+ io.puts " #{method_types.join("\n| ")}"
434
+ end
435
+ io.puts "```"
436
+
437
+ if method_names.size > 1
438
+ io.puts "**Possible methods**: #{method_names.map {|type| "`#{type.to_s}`" }.join(", ")}"
439
+ io.puts
440
+ end
441
+
442
+ unless comments.each_value.all?(&:nil?)
443
+ io.puts "----"
444
+ io.puts format_comments(comments.transform_keys {|name| name.relative.to_s }.entries)
445
+ end
446
+
447
+ unless footer.empty?
448
+ io.puts footer.rstrip
449
+ end
450
+
451
+ io.string
452
+ end
453
+ end
454
+ end
455
+ end