rbs 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (132) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/ruby.yml +28 -0
  3. data/.gitignore +12 -0
  4. data/.rubocop.yml +15 -0
  5. data/BSDL +22 -0
  6. data/CHANGELOG.md +9 -0
  7. data/COPYING +56 -0
  8. data/Gemfile +6 -0
  9. data/README.md +93 -0
  10. data/Rakefile +142 -0
  11. data/bin/annotate-with-rdoc +157 -0
  12. data/bin/console +14 -0
  13. data/bin/query-rdoc +103 -0
  14. data/bin/setup +10 -0
  15. data/bin/sort +89 -0
  16. data/bin/test_runner.rb +16 -0
  17. data/docs/CONTRIBUTING.md +97 -0
  18. data/docs/sigs.md +148 -0
  19. data/docs/stdlib.md +152 -0
  20. data/docs/syntax.md +528 -0
  21. data/exe/rbs +7 -0
  22. data/lib/rbs.rb +64 -0
  23. data/lib/rbs/ast/annotation.rb +27 -0
  24. data/lib/rbs/ast/comment.rb +27 -0
  25. data/lib/rbs/ast/declarations.rb +395 -0
  26. data/lib/rbs/ast/members.rb +362 -0
  27. data/lib/rbs/buffer.rb +50 -0
  28. data/lib/rbs/builtin_names.rb +55 -0
  29. data/lib/rbs/cli.rb +558 -0
  30. data/lib/rbs/constant.rb +26 -0
  31. data/lib/rbs/constant_table.rb +150 -0
  32. data/lib/rbs/definition.rb +170 -0
  33. data/lib/rbs/definition_builder.rb +919 -0
  34. data/lib/rbs/environment.rb +281 -0
  35. data/lib/rbs/environment_loader.rb +136 -0
  36. data/lib/rbs/environment_walker.rb +124 -0
  37. data/lib/rbs/errors.rb +187 -0
  38. data/lib/rbs/location.rb +102 -0
  39. data/lib/rbs/method_type.rb +123 -0
  40. data/lib/rbs/namespace.rb +91 -0
  41. data/lib/rbs/parser.y +1344 -0
  42. data/lib/rbs/prototype/rb.rb +553 -0
  43. data/lib/rbs/prototype/rbi.rb +587 -0
  44. data/lib/rbs/prototype/runtime.rb +381 -0
  45. data/lib/rbs/substitution.rb +46 -0
  46. data/lib/rbs/test.rb +26 -0
  47. data/lib/rbs/test/errors.rb +61 -0
  48. data/lib/rbs/test/hook.rb +294 -0
  49. data/lib/rbs/test/setup.rb +58 -0
  50. data/lib/rbs/test/spy.rb +325 -0
  51. data/lib/rbs/test/test_helper.rb +183 -0
  52. data/lib/rbs/test/type_check.rb +254 -0
  53. data/lib/rbs/type_name.rb +70 -0
  54. data/lib/rbs/types.rb +936 -0
  55. data/lib/rbs/variance_calculator.rb +138 -0
  56. data/lib/rbs/vendorer.rb +47 -0
  57. data/lib/rbs/version.rb +3 -0
  58. data/lib/rbs/writer.rb +269 -0
  59. data/lib/ruby/signature.rb +7 -0
  60. data/rbs.gemspec +46 -0
  61. data/stdlib/abbrev/abbrev.rbs +60 -0
  62. data/stdlib/base64/base64.rbs +71 -0
  63. data/stdlib/benchmark/benchmark.rbs +372 -0
  64. data/stdlib/builtin/array.rbs +1997 -0
  65. data/stdlib/builtin/basic_object.rbs +280 -0
  66. data/stdlib/builtin/binding.rbs +177 -0
  67. data/stdlib/builtin/builtin.rbs +45 -0
  68. data/stdlib/builtin/class.rbs +145 -0
  69. data/stdlib/builtin/comparable.rbs +116 -0
  70. data/stdlib/builtin/complex.rbs +400 -0
  71. data/stdlib/builtin/constants.rbs +37 -0
  72. data/stdlib/builtin/data.rbs +5 -0
  73. data/stdlib/builtin/deprecated.rbs +2 -0
  74. data/stdlib/builtin/dir.rbs +413 -0
  75. data/stdlib/builtin/encoding.rbs +607 -0
  76. data/stdlib/builtin/enumerable.rbs +404 -0
  77. data/stdlib/builtin/enumerator.rbs +260 -0
  78. data/stdlib/builtin/errno.rbs +781 -0
  79. data/stdlib/builtin/errors.rbs +582 -0
  80. data/stdlib/builtin/exception.rbs +194 -0
  81. data/stdlib/builtin/false_class.rbs +40 -0
  82. data/stdlib/builtin/fiber.rbs +68 -0
  83. data/stdlib/builtin/fiber_error.rbs +12 -0
  84. data/stdlib/builtin/file.rbs +1076 -0
  85. data/stdlib/builtin/file_test.rbs +59 -0
  86. data/stdlib/builtin/float.rbs +696 -0
  87. data/stdlib/builtin/gc.rbs +243 -0
  88. data/stdlib/builtin/hash.rbs +1029 -0
  89. data/stdlib/builtin/integer.rbs +707 -0
  90. data/stdlib/builtin/io.rbs +683 -0
  91. data/stdlib/builtin/kernel.rbs +576 -0
  92. data/stdlib/builtin/marshal.rbs +161 -0
  93. data/stdlib/builtin/match_data.rbs +271 -0
  94. data/stdlib/builtin/math.rbs +369 -0
  95. data/stdlib/builtin/method.rbs +185 -0
  96. data/stdlib/builtin/module.rbs +1104 -0
  97. data/stdlib/builtin/nil_class.rbs +82 -0
  98. data/stdlib/builtin/numeric.rbs +409 -0
  99. data/stdlib/builtin/object.rbs +824 -0
  100. data/stdlib/builtin/proc.rbs +429 -0
  101. data/stdlib/builtin/process.rbs +1227 -0
  102. data/stdlib/builtin/random.rbs +267 -0
  103. data/stdlib/builtin/range.rbs +226 -0
  104. data/stdlib/builtin/rational.rbs +424 -0
  105. data/stdlib/builtin/rb_config.rbs +57 -0
  106. data/stdlib/builtin/regexp.rbs +1083 -0
  107. data/stdlib/builtin/ruby_vm.rbs +14 -0
  108. data/stdlib/builtin/signal.rbs +55 -0
  109. data/stdlib/builtin/string.rbs +1901 -0
  110. data/stdlib/builtin/string_io.rbs +284 -0
  111. data/stdlib/builtin/struct.rbs +40 -0
  112. data/stdlib/builtin/symbol.rbs +228 -0
  113. data/stdlib/builtin/thread.rbs +1108 -0
  114. data/stdlib/builtin/thread_group.rbs +23 -0
  115. data/stdlib/builtin/time.rbs +1047 -0
  116. data/stdlib/builtin/trace_point.rbs +290 -0
  117. data/stdlib/builtin/true_class.rbs +46 -0
  118. data/stdlib/builtin/unbound_method.rbs +153 -0
  119. data/stdlib/builtin/warning.rbs +17 -0
  120. data/stdlib/coverage/coverage.rbs +62 -0
  121. data/stdlib/csv/csv.rbs +773 -0
  122. data/stdlib/erb/erb.rbs +392 -0
  123. data/stdlib/find/find.rbs +40 -0
  124. data/stdlib/ipaddr/ipaddr.rbs +247 -0
  125. data/stdlib/json/json.rbs +335 -0
  126. data/stdlib/pathname/pathname.rbs +1093 -0
  127. data/stdlib/prime/integer-extension.rbs +23 -0
  128. data/stdlib/prime/prime.rbs +188 -0
  129. data/stdlib/securerandom/securerandom.rbs +9 -0
  130. data/stdlib/set/set.rbs +301 -0
  131. data/stdlib/tmpdir/tmpdir.rbs +53 -0
  132. metadata +292 -0
@@ -0,0 +1,381 @@
1
+ module RBS
2
+ module Prototype
3
+ class Runtime
4
+ attr_reader :patterns
5
+ attr_reader :env
6
+ attr_reader :merge
7
+ attr_reader :owners_included
8
+
9
+ def initialize(patterns:, env:, merge:, owners_included: [])
10
+ @patterns = patterns
11
+ @decls = nil
12
+ @env = env
13
+ @merge = merge
14
+ @owners_included = owners_included.map do |name|
15
+ Object.const_get(name)
16
+ end
17
+ end
18
+
19
+ def target?(const)
20
+ patterns.any? do |pattern|
21
+ if pattern.end_with?("*")
22
+ (const.name || "").start_with?(pattern.chop)
23
+ else
24
+ const.name == pattern
25
+ end
26
+ end
27
+ end
28
+
29
+ def builder
30
+ @builder ||= DefinitionBuilder.new(env: env)
31
+ end
32
+
33
+ def parse(file)
34
+ require file
35
+ end
36
+
37
+ def decls
38
+ unless @decls
39
+ @decls = []
40
+ ObjectSpace.each_object(Module).select {|mod| target?(mod) }.sort_by(&:name).each do |mod|
41
+ case mod
42
+ when Class
43
+ generate_class mod
44
+ when Module
45
+ generate_module mod
46
+ end
47
+ end
48
+ end
49
+ @decls
50
+ end
51
+
52
+ def to_type_name(name)
53
+ *prefix, last = name.split(/::/)
54
+
55
+ if prefix.empty?
56
+ TypeName.new(name: last.to_sym, namespace: Namespace.empty)
57
+ else
58
+ TypeName.new(name: last.to_sym, namespace: Namespace.parse(prefix.join("::")))
59
+ end
60
+ end
61
+
62
+ def each_mixin(mixins, *super_mixes)
63
+ supers = Set.new(super_mixes)
64
+ mixins.each do |mix|
65
+ unless supers.include?(mix)
66
+ yield mix
67
+ end
68
+ end
69
+ end
70
+
71
+ def method_type(method)
72
+ untyped = Types::Bases::Any.new(location: nil)
73
+
74
+ required_positionals = []
75
+ optional_positionals = []
76
+ rest = nil
77
+ trailing_positionals = []
78
+ required_keywords = {}
79
+ optional_keywords = {}
80
+ rest_keywords = nil
81
+
82
+ requireds = required_positionals
83
+
84
+ block = nil
85
+
86
+ method.parameters.each do |kind, name|
87
+ case kind
88
+ when :req
89
+ requireds << Types::Function::Param.new(name: name, type: untyped)
90
+ when :opt
91
+ requireds = trailing_positionals
92
+ optional_positionals << Types::Function::Param.new(name: name, type: untyped)
93
+ when :rest
94
+ requireds = trailing_positionals
95
+ rest = Types::Function::Param.new(name: name, type: untyped)
96
+ when :keyreq
97
+ required_keywords[name] = Types::Function::Param.new(name: nil, type: untyped)
98
+ when :key
99
+ optional_keywords[name] = Types::Function::Param.new(name: nil, type: untyped)
100
+ when :keyrest
101
+ rest_keywords = Types::Function::Param.new(name: nil, type: untyped)
102
+ when :block
103
+ block = MethodType::Block.new(
104
+ type: Types::Function.empty(untyped).update(rest_positionals: Types::Function::Param.new(name: nil, type: untyped)),
105
+ required: true
106
+ )
107
+ end
108
+ end
109
+
110
+ method_type = Types::Function.new(
111
+ required_positionals: required_positionals,
112
+ optional_positionals: optional_positionals,
113
+ rest_positionals: rest,
114
+ trailing_positionals: trailing_positionals,
115
+ required_keywords: required_keywords,
116
+ optional_keywords: optional_keywords,
117
+ rest_keywords: rest_keywords,
118
+ return_type: untyped
119
+ )
120
+
121
+ MethodType.new(
122
+ location: nil,
123
+ type_params: [],
124
+ type: method_type,
125
+ block: block
126
+ )
127
+ end
128
+
129
+ def merge_rbs(module_name, members, instance: nil, singleton: nil)
130
+ if merge
131
+ if env.class?(module_name.absolute!)
132
+ case
133
+ when instance
134
+ method = builder.build_instance(module_name.absolute!).methods[instance]
135
+ method_name = instance
136
+ kind = :instance
137
+ when singleton
138
+ method = builder.build_singleton(module_name.absolute!).methods[singleton]
139
+ method_name = singleton
140
+ kind = :singleton
141
+ end
142
+
143
+ if method
144
+ members << AST::Members::MethodDefinition.new(
145
+ name: method_name,
146
+ types: method.method_types.map {|type|
147
+ type.update.tap do |ty|
148
+ def ty.to_s
149
+ location.source
150
+ end
151
+ end
152
+ },
153
+ kind: kind,
154
+ location: nil,
155
+ comment: method.comment,
156
+ annotations: method.annotations,
157
+ attributes: method.attributes
158
+ )
159
+ return
160
+ end
161
+ end
162
+
163
+ yield
164
+ else
165
+ yield
166
+ end
167
+ end
168
+
169
+ def target_method?(mod, instance: nil, singleton: nil)
170
+ case
171
+ when instance
172
+ method = mod.instance_method(instance)
173
+ method.owner == mod || owners_included.any? {|m| method.owner == m }
174
+ when singleton
175
+ method = mod.singleton_class.instance_method(singleton)
176
+ method.owner == mod.singleton_class || owners_included.any? {|m| method.owner == m.singleton_class }
177
+ end
178
+ end
179
+
180
+ def generate_methods(mod, module_name, members)
181
+ mod.singleton_methods.select {|name| target_method?(mod, singleton: name) }.sort.each do |name|
182
+ method = mod.singleton_class.instance_method(name)
183
+
184
+ if method.name == method.original_name
185
+ merge_rbs(module_name, members, singleton: name) do
186
+ RBS.logger.info "missing #{module_name}.#{name} #{method.source_location}"
187
+
188
+ members << AST::Members::MethodDefinition.new(
189
+ name: method.name,
190
+ types: [method_type(method)],
191
+ kind: :singleton,
192
+ location: nil,
193
+ comment: nil,
194
+ annotations: [],
195
+ attributes: []
196
+ )
197
+ end
198
+ else
199
+ members << AST::Members::Alias.new(
200
+ new_name: method.name,
201
+ old_name: method.original_name,
202
+ kind: :singleton,
203
+ location: nil,
204
+ comment: nil,
205
+ annotations: [],
206
+ )
207
+ end
208
+ end
209
+
210
+ public_instance_methods = mod.public_instance_methods.select {|name| target_method?(mod, instance: name) }
211
+ unless public_instance_methods.empty?
212
+ members << AST::Members::Public.new(location: nil)
213
+
214
+ public_instance_methods.sort.each do |name|
215
+ method = mod.instance_method(name)
216
+
217
+ if method.name == method.original_name
218
+ merge_rbs(module_name, members, instance: name) do
219
+ RBS.logger.info "missing #{module_name}##{name} #{method.source_location}"
220
+
221
+ members << AST::Members::MethodDefinition.new(
222
+ name: method.name,
223
+ types: [method_type(method)],
224
+ kind: :instance,
225
+ location: nil,
226
+ comment: nil,
227
+ annotations: [],
228
+ attributes: []
229
+ )
230
+ end
231
+ else
232
+ members << AST::Members::Alias.new(
233
+ new_name: method.name,
234
+ old_name: method.original_name,
235
+ kind: :instance,
236
+ location: nil,
237
+ comment: nil,
238
+ annotations: [],
239
+ )
240
+ end
241
+ end
242
+ end
243
+
244
+ private_instance_methods = mod.private_instance_methods.select {|name| target_method?(mod, instance: name) }
245
+ unless private_instance_methods.empty?
246
+ members << AST::Members::Private.new(location: nil)
247
+
248
+ private_instance_methods.sort.each do |name|
249
+ method = mod.instance_method(name)
250
+
251
+ if method.name == method.original_name
252
+ merge_rbs(module_name, members, instance: name) do
253
+ RBS.logger.info "missing #{module_name}##{name} #{method.source_location}"
254
+
255
+ members << AST::Members::MethodDefinition.new(
256
+ name: method.name,
257
+ types: [method_type(method)],
258
+ kind: :instance,
259
+ location: nil,
260
+ comment: nil,
261
+ annotations: [],
262
+ attributes: []
263
+ )
264
+ end
265
+ else
266
+ members << AST::Members::Alias.new(
267
+ new_name: method.name,
268
+ old_name: method.original_name,
269
+ kind: :instance,
270
+ location: nil,
271
+ comment: nil,
272
+ annotations: [],
273
+ )
274
+ end
275
+ end
276
+ end
277
+ end
278
+
279
+ def generate_constants(mod)
280
+ mod.constants(false).sort.each do |name|
281
+ value = mod.const_get(name)
282
+
283
+ next if value.is_a?(Class) || value.is_a?(Module)
284
+ type = case value
285
+ when true, false
286
+ Types::Bases::Bool.new(location: nil)
287
+ when nil
288
+ Types::Optional.new(
289
+ type: Types::Bases::Any.new(location: nil),
290
+ location: nil
291
+ )
292
+ else
293
+ Types::ClassInstance.new(name: to_type_name(value.class.to_s), args: [], location: nil)
294
+ end
295
+
296
+ @decls << AST::Declarations::Constant.new(
297
+ name: "#{mod.to_s}::#{name}",
298
+ type: type,
299
+ location: nil,
300
+ comment: nil
301
+ )
302
+ end
303
+ end
304
+
305
+ def generate_class(mod)
306
+ type_name = to_type_name(mod.name)
307
+ super_class = if mod.superclass == ::Object
308
+ nil
309
+ else
310
+ AST::Declarations::Class::Super.new(name: to_type_name(mod.superclass.name), args: [])
311
+ end
312
+
313
+ decl = AST::Declarations::Class.new(
314
+ name: type_name,
315
+ type_params: AST::Declarations::ModuleTypeParams.empty,
316
+ super_class: super_class,
317
+ members: [],
318
+ annotations: [],
319
+ location: nil,
320
+ comment: nil
321
+ )
322
+
323
+ each_mixin(mod.included_modules, *mod.superclass.included_modules, *mod.included_modules.flat_map(&:included_modules)) do |included_module|
324
+ module_name = to_type_name(included_module.name)
325
+ if module_name.namespace == type_name.namespace
326
+ module_name = TypeName.new(name: module_name.name, namespace: Namespace.empty)
327
+ end
328
+
329
+ decl.members << AST::Members::Include.new(
330
+ name: module_name,
331
+ args: [],
332
+ location: nil,
333
+ comment: nil,
334
+ annotations: []
335
+ )
336
+ end
337
+
338
+ generate_methods(mod, type_name, decl.members)
339
+
340
+ @decls << decl
341
+
342
+ generate_constants mod
343
+ end
344
+
345
+ def generate_module(mod)
346
+ type_name = to_type_name(mod.name)
347
+
348
+ decl = AST::Declarations::Module.new(
349
+ name: type_name,
350
+ type_params: AST::Declarations::ModuleTypeParams.empty,
351
+ self_type: nil,
352
+ members: [],
353
+ annotations: [],
354
+ location: nil,
355
+ comment: nil
356
+ )
357
+
358
+ each_mixin(mod.included_modules, *mod.included_modules.flat_map(&:included_modules), namespace: type_name.namespace) do |included_module|
359
+ module_name = to_type_name(included_module.name)
360
+ if module_name.namespace == type_name.namespace
361
+ module_name = TypeName.new(name: module_name.name, namespace: Namespace.empty)
362
+ end
363
+
364
+ decl.members << AST::Members::Include.new(
365
+ name: module_name,
366
+ args: [],
367
+ location: nil,
368
+ comment: nil,
369
+ annotations: []
370
+ )
371
+ end
372
+
373
+ generate_methods(mod, type_name, decl.members)
374
+
375
+ @decls << decl
376
+
377
+ generate_constants mod
378
+ end
379
+ end
380
+ end
381
+ end
@@ -0,0 +1,46 @@
1
+ module RBS
2
+ class Substitution
3
+ attr_reader :mapping
4
+
5
+ def initialize()
6
+ @mapping = {}
7
+ end
8
+
9
+ def add(from:, to:)
10
+ mapping[from] = to
11
+ end
12
+
13
+ def self.build(variables, types, &block)
14
+ unless variables.size == types.size
15
+ raise "Broken substitution: variables=#{variables}, types=#{types}"
16
+ end
17
+
18
+ mapping = variables.zip(types).to_h
19
+
20
+ self.new.tap do |subst|
21
+ mapping.each do |v, t|
22
+ type = block_given? ? yield(t) : t
23
+ subst.add(from: v, to: type)
24
+ end
25
+ end
26
+ end
27
+
28
+ def apply(ty)
29
+ case ty
30
+ when Types::Variable
31
+ mapping[ty.name] || ty
32
+ else
33
+ ty
34
+ end
35
+ end
36
+
37
+ def without(*vars)
38
+ self.class.new.tap do |subst|
39
+ subst.mapping.merge!(mapping)
40
+ vars.each do |var|
41
+ subst.mapping.delete(var)
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,26 @@
1
+ require "rbs/test/spy"
2
+ require "rbs/test/errors"
3
+ require "rbs/test/type_check"
4
+ require "rbs/test/hook"
5
+
6
+ module RBS
7
+ module Test
8
+ IS_AP = Kernel.instance_method(:is_a?)
9
+ DEFINE_METHOD = Module.instance_method(:define_method)
10
+ INSTANCE_EVAL = BasicObject.instance_method(:instance_eval)
11
+ INSTANCE_EXEC = BasicObject.instance_method(:instance_exec)
12
+ METHOD = Kernel.instance_method(:method)
13
+ CLASS = Kernel.instance_method(:class)
14
+ SINGLETON_CLASS = Kernel.instance_method(:singleton_class)
15
+ PP = Kernel.instance_method(:pp)
16
+ INSPECT = Kernel.instance_method(:inspect)
17
+ METHODS = Kernel.instance_method(:methods)
18
+
19
+ ArgumentsReturn = Struct.new(:arguments, :return_value, :exception, keyword_init: true)
20
+ CallTrace = Struct.new(:method_name, :method_call, :block_calls, :block_given, keyword_init: true)
21
+
22
+ def self.call(receiver, method, *args, **kwargs, &block)
23
+ method.bind_call(receiver, *args, **kwargs, &block)
24
+ end
25
+ end
26
+ end