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,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