rbs 0.2.0

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 (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,183 @@
1
+ module RBS
2
+ module Test
3
+ module TypeAssertions
4
+ module ClassMethods
5
+ attr_reader :target
6
+
7
+ def library(*libs)
8
+ @libs = libs
9
+ @env = nil
10
+ @target = nil
11
+ end
12
+
13
+ def env
14
+ @env ||= begin
15
+ loader = RBS::EnvironmentLoader.new
16
+ (@libs || []).each do |lib|
17
+ loader.add library: lib
18
+ end
19
+
20
+ RBS::Environment.new.tap do |env|
21
+ loader.load(env: env)
22
+ end
23
+ end
24
+ end
25
+
26
+ def builder
27
+ @builder ||= DefinitionBuilder.new(env: env)
28
+ end
29
+
30
+ def testing(type_or_string)
31
+ type = case type_or_string
32
+ when String
33
+ RBS::Parser.parse_type(type_or_string, variables: [])
34
+ else
35
+ type_or_string
36
+ end
37
+
38
+ definition = case type
39
+ when Types::ClassInstance
40
+ builder.build_instance(type.name)
41
+ when Types::ClassSingleton
42
+ builder.build_singleton(type.name)
43
+ else
44
+ raise "Test target should be class instance or class singleton: #{type}"
45
+ end
46
+
47
+ @target = [type, definition]
48
+ end
49
+ end
50
+
51
+ def self.included(base)
52
+ base.extend ClassMethods
53
+ end
54
+
55
+ def env
56
+ self.class.env
57
+ end
58
+
59
+ def builder
60
+ self.class.builder
61
+ end
62
+
63
+ def targets
64
+ @targets ||= []
65
+ end
66
+
67
+ def target
68
+ targets.last || self.class.target
69
+ end
70
+
71
+ def testing(type_or_string)
72
+ type = case type_or_string
73
+ when String
74
+ RBS::Parser.parse_type(type_or_string, variables: [])
75
+ else
76
+ type_or_string
77
+ end
78
+
79
+ definition = case type
80
+ when Types::ClassInstance
81
+ builder.build_instance(type.name)
82
+ when Types::ClassSingleton
83
+ builder.build_singleton(type.name)
84
+ else
85
+ raise "Test target should be class instance or class singleton: #{type}"
86
+ end
87
+
88
+ targets.push [type, definition]
89
+
90
+ if block_given?
91
+ begin
92
+ yield
93
+ ensure
94
+ targets.pop
95
+ end
96
+ else
97
+ [type, definition]
98
+ end
99
+ end
100
+
101
+ ruby2_keywords def assert_send_type(method_type, receiver, method, *args, &block)
102
+ trace = []
103
+ spy = Spy.wrap(receiver, method)
104
+ spy.callback = -> (result) { trace << result }
105
+
106
+ exception = nil
107
+
108
+ begin
109
+ spy.wrapped_object.__send__(method, *args, &block)
110
+ rescue => exn
111
+ exception = exn
112
+ end
113
+
114
+ mt = case method_type
115
+ when String
116
+ RBS::Parser.parse_method_type(method_type, variables: [])
117
+ when RBS::MethodType
118
+ method_type
119
+ end
120
+
121
+ typecheck = TypeCheck.new(self_class: receiver.class, builder: builder)
122
+ errors = typecheck.method_call(method, mt, trace.last, errors: [])
123
+
124
+ assert_empty errors.map {|x| RBS::Test::Errors.to_string(x) }, "Call trace does not match with given method type: #{trace.last.inspect}"
125
+
126
+ type, definition = target
127
+ method_types = case
128
+ when definition.instance_type?
129
+ subst = Substitution.build(definition.declaration.type_params.each.map(&:name),
130
+ type.args)
131
+ definition.methods[method].method_types.map do |method_type|
132
+ method_type.sub(subst)
133
+ end
134
+ when definition.class_type?
135
+ definition.methods[method].method_types
136
+ end
137
+
138
+ all_errors = method_types.map {|t| typecheck.method_call(method, t, trace.last, errors: []) }
139
+ assert all_errors.any? {|es| es.empty? }, "Call trace does not match one of method definitions:\n #{trace.last.inspect}\n #{method_types.join(" | ")}"
140
+
141
+ if exception
142
+ raise exception
143
+ end
144
+ end
145
+
146
+ ruby2_keywords def refute_send_type(method_type, receiver, method, *args, &block)
147
+ trace = []
148
+ spy = Spy.wrap(receiver, method)
149
+ spy.callback = -> (result) { trace << result }
150
+
151
+ exception = nil
152
+ begin
153
+ spy.wrapped_object.__send__(method, *args, &block)
154
+ rescue Exception => exn
155
+ exception = exn
156
+ end
157
+
158
+ mt = case method_type
159
+ when String
160
+ RBS::Parser.parse_method_type(method_type, variables: [])
161
+ when RBS::MethodType
162
+ method_type
163
+ end
164
+
165
+ mt = mt.update(block: if mt.block
166
+ MethodType::Block.new(
167
+ type: mt.block.type.with_return_type(Types::Bases::Any.new(location: nil)),
168
+ required: mt.block.required
169
+ )
170
+ end,
171
+ type: mt.type.with_return_type(Types::Bases::Any.new(location: nil)))
172
+
173
+ typecheck = TypeCheck.new(self_class: receiver.class, builder: builder)
174
+ errors = typecheck.method_call(method, mt, trace.last, errors: [])
175
+
176
+ assert_operator exception, :is_a?, ::Exception
177
+ assert_empty errors.map {|x| RBS::Test::Errors.to_string(x) }
178
+
179
+ exception
180
+ end
181
+ end
182
+ end
183
+ end
@@ -0,0 +1,254 @@
1
+ module RBS
2
+ module Test
3
+ class TypeCheck
4
+ attr_reader :self_class
5
+ attr_reader :builder
6
+
7
+ def initialize(self_class:, builder:)
8
+ @self_class = self_class
9
+ @builder = builder
10
+ end
11
+
12
+ def method_call(method_name, method_type, call, errors:)
13
+ args(method_name, method_type, method_type.type, call.method_call, errors, type_error: Errors::ArgumentTypeError, argument_error: Errors::ArgumentError)
14
+ self.return(method_name, method_type, method_type.type, call.method_call, errors, return_error: Errors::ReturnTypeError)
15
+
16
+ if method_type.block
17
+ case
18
+ when !call.block_calls.empty?
19
+ call.block_calls.each do |block_call|
20
+ args(method_name, method_type, method_type.block.type, block_call, errors, type_error: Errors::BlockArgumentTypeError, argument_error: Errors::BlockArgumentError)
21
+ self.return(method_name, method_type, method_type.block.type, block_call, errors, return_error: Errors::BlockReturnTypeError)
22
+ end
23
+ when !call.block_given
24
+ # Block is not given
25
+ if method_type.block.required
26
+ errors << Errors::MissingBlockError.new(klass: self_class, method_name: method_name, method_type: method_type)
27
+ end
28
+ else
29
+ # Block is given, but not yielded
30
+ end
31
+ else
32
+ if call.block_given
33
+ errors << Errors::UnexpectedBlockError.new(klass: self_class, method_name: method_name, method_type: method_type)
34
+ end
35
+ end
36
+
37
+ errors
38
+ end
39
+
40
+ def args(method_name, method_type, fun, call, errors, type_error:, argument_error:)
41
+ test = zip_args(call.arguments, fun) do |val, param|
42
+ unless self.value(val, param.type)
43
+ errors << type_error.new(klass: self_class,
44
+ method_name: method_name,
45
+ method_type: method_type,
46
+ param: param,
47
+ value: val)
48
+ end
49
+ end
50
+
51
+ unless test
52
+ errors << argument_error.new(klass: self_class,
53
+ method_name: method_name,
54
+ method_type: method_type)
55
+ end
56
+ end
57
+
58
+ def return(method_name, method_type, fun, call, errors, return_error:)
59
+ unless call.exception
60
+ unless value(call.return_value, fun.return_type)
61
+ errors << return_error.new(klass: self_class,
62
+ method_name: method_name,
63
+ method_type: method_type,
64
+ type: fun.return_type,
65
+ value: call.return_value)
66
+ end
67
+ end
68
+ end
69
+
70
+ def zip_keyword_args(hash, fun)
71
+ fun.required_keywords.each do |name, param|
72
+ if hash.key?(name)
73
+ yield(hash[name], param)
74
+ else
75
+ return false
76
+ end
77
+ end
78
+
79
+ fun.optional_keywords.each do |name, param|
80
+ if hash.key?(name)
81
+ yield(hash[name], param)
82
+ end
83
+ end
84
+
85
+ hash.each do |name, value|
86
+ next if fun.required_keywords.key?(name)
87
+ next if fun.optional_keywords.key?(name)
88
+
89
+ if fun.rest_keywords
90
+ yield value, fun.rest_keywords
91
+ else
92
+ return false
93
+ end
94
+ end
95
+
96
+ true
97
+ end
98
+
99
+ def keyword?(value)
100
+ value.is_a?(Hash) && value.keys.all? {|key| key.is_a?(Symbol) }
101
+ end
102
+
103
+ def zip_args(args, fun, &block)
104
+ case
105
+ when args.empty?
106
+ if fun.required_positionals.empty? && fun.trailing_positionals.empty? && fun.required_keywords.empty?
107
+ true
108
+ else
109
+ false
110
+ end
111
+ when !fun.required_positionals.empty?
112
+ yield_self do
113
+ param, fun_ = fun.drop_head
114
+ yield(args.first, param)
115
+ zip_args(args.drop(1), fun_, &block)
116
+ end
117
+ when fun.has_keyword?
118
+ yield_self do
119
+ hash = args.last
120
+ if keyword?(hash)
121
+ zip_keyword_args(hash, fun, &block) &&
122
+ zip_args(args.take(args.size - 1),
123
+ fun.update(required_keywords: {}, optional_keywords: {}, rest_keywords: nil),
124
+ &block)
125
+ else
126
+ fun.required_keywords.empty? &&
127
+ zip_args(args,
128
+ fun.update(required_keywords: {}, optional_keywords: {}, rest_keywords: nil),
129
+ &block)
130
+ end
131
+ end
132
+ when !fun.trailing_positionals.empty?
133
+ yield_self do
134
+ param, fun_ = fun.drop_tail
135
+ yield(args.last, param)
136
+ zip_args(args.take(args.size - 1), fun_, &block)
137
+ end
138
+ when !fun.optional_positionals.empty?
139
+ yield_self do
140
+ param, fun_ = fun.drop_head
141
+ yield(args.first, param)
142
+ zip_args(args.drop(1), fun_, &block)
143
+ end
144
+ when fun.rest_positionals
145
+ yield_self do
146
+ yield(args.first, fun.rest_positionals)
147
+ zip_args(args.drop(1), fun, &block)
148
+ end
149
+ else
150
+ false
151
+ end
152
+ end
153
+
154
+ def value(val, type)
155
+ case type
156
+ when Types::Bases::Any
157
+ true
158
+ when Types::Bases::Bool
159
+ true
160
+ when Types::Bases::Top
161
+ true
162
+ when Types::Bases::Bottom
163
+ false
164
+ when Types::Bases::Void
165
+ true
166
+ when Types::Bases::Self
167
+ Test.call(val, IS_AP, self_class)
168
+ when Types::Bases::Nil
169
+ Test.call(val, IS_AP, ::NilClass)
170
+ when Types::Bases::Class
171
+ Test.call(val, IS_AP, Class)
172
+ when Types::Bases::Instance
173
+ Test.call(val, IS_AP, self_class)
174
+ when Types::ClassInstance
175
+ klass = Object.const_get(type.name.to_s)
176
+ case
177
+ when klass == ::Array
178
+ Test.call(val, IS_AP, klass) && val.all? {|v| value(v, type.args[0]) }
179
+ when klass == ::Hash
180
+ Test.call(val, IS_AP, klass) && val.all? {|k, v| value(k, type.args[0]) && value(v, type.args[1]) }
181
+ when klass == ::Range
182
+ Test.call(val, IS_AP, klass) && value(val.begin, type.args[0]) && value(val.end, type.args[0])
183
+ when klass == ::Enumerator
184
+ if Test.call(val, IS_AP, klass)
185
+ case val.size
186
+ when Float::INFINITY
187
+ values = []
188
+ ret = self
189
+ val.lazy.take(10).each do |*args|
190
+ values << args
191
+ nil
192
+ end
193
+ else
194
+ values = []
195
+ ret = val.each do |*args|
196
+ values << args
197
+ nil
198
+ end
199
+ end
200
+
201
+ values.all? do |v|
202
+ if v.size == 1
203
+ # Only one block argument.
204
+ value(v[0], type.args[0]) || value(v, type.args[0])
205
+ else
206
+ value(v, type.args[0])
207
+ end
208
+ end &&
209
+ if ret.equal?(self)
210
+ type.args[1].is_a?(Types::Bases::Bottom)
211
+ else
212
+ value(ret, type.args[1])
213
+ end
214
+ end
215
+ else
216
+ Test.call(val, IS_AP, klass)
217
+ end
218
+ when Types::ClassSingleton
219
+ klass = Object.const_get(type.name.to_s)
220
+ val == klass
221
+ when Types::Interface
222
+ methods = Set.new(Test.call(val, METHODS))
223
+ decl = builder.env.find_class(type.name)
224
+ if (definition = builder.build_interface(type.name, decl))
225
+ definition.methods.each_key.all? do |method_name|
226
+ methods.member?(method_name)
227
+ end
228
+ end
229
+ when Types::Variable
230
+ true
231
+ when Types::Literal
232
+ val == type.literal
233
+ when Types::Union
234
+ type.types.any? {|type| value(val, type) }
235
+ when Types::Intersection
236
+ type.types.all? {|type| value(val, type) }
237
+ when Types::Optional
238
+ Test.call(val, IS_AP, ::NilClass) || value(val, type.type)
239
+ when Types::Alias
240
+ value(val, builder.expand_alias(type.name))
241
+ when Types::Tuple
242
+ Test.call(val, IS_AP, ::Array) &&
243
+ type.types.map.with_index {|ty, index| value(val[index], ty) }.all?
244
+ when Types::Record
245
+ Test::call(val, IS_AP, ::Hash)
246
+ when Types::Proc
247
+ Test::call(val, IS_AP, ::Proc)
248
+ else
249
+ false
250
+ end
251
+ end
252
+ end
253
+ end
254
+ end
@@ -0,0 +1,70 @@
1
+ module RBS
2
+ class TypeName
3
+ attr_reader :namespace
4
+ attr_reader :name
5
+ attr_reader :kind
6
+
7
+ def initialize(namespace:, name:)
8
+ @namespace = namespace
9
+ @name = name
10
+ @kind = case name.to_s[0,1]
11
+ when /[A-Z]/
12
+ :class
13
+ when /[a-z]/
14
+ :alias
15
+ when "_"
16
+ :interface
17
+ end
18
+ end
19
+
20
+ def ==(other)
21
+ other.is_a?(self.class) && other.namespace == namespace && other.name == name
22
+ end
23
+
24
+ alias eql? ==
25
+
26
+ def hash
27
+ self.class.hash ^ namespace.hash ^ name.hash
28
+ end
29
+
30
+ def to_s
31
+ "#{namespace.to_s}#{name}"
32
+ end
33
+
34
+ def to_json(*a)
35
+ to_s.to_json(*a)
36
+ end
37
+
38
+ def to_namespace
39
+ namespace.append(self.name)
40
+ end
41
+
42
+ def class?
43
+ kind == :class
44
+ end
45
+
46
+ def alias?
47
+ kind == :alias
48
+ end
49
+
50
+ def absolute!
51
+ self.class.new(namespace: namespace.absolute!, name: name)
52
+ end
53
+
54
+ def absolute?
55
+ namespace.absolute?
56
+ end
57
+
58
+ def relative!
59
+ self.class.new(namespace: namespace.relative!, name: name)
60
+ end
61
+
62
+ def interface?
63
+ kind == :interface
64
+ end
65
+
66
+ def with_prefix(namespace)
67
+ self.class.new(namespace: namespace + self.namespace, name: name)
68
+ end
69
+ end
70
+ end