rbs 1.1.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +5 -1
  3. data/.gitignore +2 -0
  4. data/CHANGELOG.md +81 -0
  5. data/README.md +1 -1
  6. data/Rakefile +11 -0
  7. data/Steepfile +1 -0
  8. data/core/array.rbs +2 -2
  9. data/core/basic_object.rbs +1 -1
  10. data/core/enumerable.rbs +1 -1
  11. data/core/hash.rbs +13 -5
  12. data/core/io.rbs +4 -4
  13. data/core/kernel.rbs +2 -2
  14. data/core/marshal.rbs +4 -3
  15. data/core/module.rbs +1 -1
  16. data/core/numeric.rbs +10 -0
  17. data/core/proc.rbs +1 -1
  18. data/core/random.rbs +4 -2
  19. data/core/range.rbs +2 -2
  20. data/core/struct.rbs +3 -2
  21. data/core/thread.rbs +1 -1
  22. data/docs/CONTRIBUTING.md +5 -3
  23. data/docs/rbs_by_example.md +328 -0
  24. data/docs/sigs.md +21 -2
  25. data/docs/stdlib.md +1 -1
  26. data/docs/syntax.md +11 -14
  27. data/lib/rbs.rb +1 -0
  28. data/lib/rbs/ast/annotation.rb +2 -2
  29. data/lib/rbs/ast/comment.rb +2 -2
  30. data/lib/rbs/ast/declarations.rb +37 -22
  31. data/lib/rbs/ast/members.rb +26 -26
  32. data/lib/rbs/cli.rb +3 -0
  33. data/lib/rbs/constant_table.rb +4 -1
  34. data/lib/rbs/definition.rb +1 -1
  35. data/lib/rbs/definition_builder.rb +16 -18
  36. data/lib/rbs/definition_builder/ancestor_builder.rb +10 -2
  37. data/lib/rbs/definition_builder/method_builder.rb +4 -2
  38. data/lib/rbs/errors.rb +36 -0
  39. data/lib/rbs/location.rb +106 -2
  40. data/lib/rbs/locator.rb +205 -0
  41. data/lib/rbs/method_type.rb +2 -2
  42. data/lib/rbs/parser.rb +1315 -962
  43. data/lib/rbs/parser.y +411 -75
  44. data/lib/rbs/prototype/rb.rb +7 -3
  45. data/lib/rbs/prototype/runtime.rb +118 -42
  46. data/lib/rbs/test/hook.rb +8 -2
  47. data/lib/rbs/type_name.rb +2 -3
  48. data/lib/rbs/type_name_resolver.rb +1 -1
  49. data/lib/rbs/types.rb +36 -34
  50. data/lib/rbs/version.rb +1 -1
  51. data/lib/rbs/writer.rb +4 -2
  52. data/rbs.gemspec +1 -1
  53. data/sig/ancestor_builder.rbs +2 -0
  54. data/sig/annotation.rbs +1 -1
  55. data/sig/cli.rbs +31 -21
  56. data/sig/comment.rbs +1 -1
  57. data/sig/declarations.rbs +106 -21
  58. data/sig/environment.rbs +2 -2
  59. data/sig/errors.rbs +15 -0
  60. data/sig/location.rbs +84 -3
  61. data/sig/locator.rbs +44 -0
  62. data/sig/members.rbs +76 -12
  63. data/sig/method_builder.rbs +1 -1
  64. data/sig/method_types.rbs +1 -1
  65. data/sig/namespace.rbs +1 -1
  66. data/sig/polyfill.rbs +4 -17
  67. data/sig/rbs.rbs +8 -4
  68. data/sig/typename.rbs +1 -1
  69. data/sig/types.rbs +67 -20
  70. data/sig/util.rbs +0 -4
  71. data/sig/writer.rbs +8 -2
  72. data/stdlib/dbm/0/dbm.rbs +43 -30
  73. data/stdlib/mutex_m/0/mutex_m.rbs +1 -1
  74. data/stdlib/net-http/0/net-http.rbs +1846 -0
  75. data/stdlib/optparse/0/optparse.rbs +1214 -0
  76. data/stdlib/resolv/0/resolv.rbs +1504 -0
  77. data/stdlib/rubygems/0/requirement.rbs +84 -2
  78. data/stdlib/rubygems/0/rubygems.rbs +2 -2
  79. data/stdlib/rubygems/0/version.rbs +2 -1
  80. data/stdlib/shellwords/0/shellwords.rbs +252 -0
  81. data/stdlib/socket/0/addrinfo.rbs +469 -0
  82. data/stdlib/socket/0/basic_socket.rbs +503 -0
  83. data/stdlib/socket/0/ip_socket.rbs +72 -0
  84. data/stdlib/socket/0/socket.rbs +2687 -0
  85. data/stdlib/socket/0/tcp_server.rbs +177 -0
  86. data/stdlib/socket/0/tcp_socket.rbs +35 -0
  87. data/stdlib/socket/0/udp_socket.rbs +111 -0
  88. data/stdlib/socket/0/unix_server.rbs +154 -0
  89. data/stdlib/socket/0/unix_socket.rbs +132 -0
  90. data/stdlib/timeout/0/timeout.rbs +5 -0
  91. data/steep/Gemfile.lock +19 -16
  92. metadata +18 -11
  93. data/bin/annotate-with-rdoc +0 -153
  94. data/bin/console +0 -14
  95. data/bin/query-rdoc +0 -103
  96. data/bin/rbs-prof +0 -9
  97. data/bin/run_in_md.rb +0 -49
  98. data/bin/setup +0 -8
  99. data/bin/sort +0 -89
  100. data/bin/steep +0 -4
  101. data/bin/test_runner.rb +0 -29
@@ -0,0 +1,328 @@
1
+ # RBS By Example
2
+
3
+ ## Goal
4
+
5
+ The purpose of this doc is to teach you how to write RBS signatures by using the standard library's methods as a guide.
6
+
7
+ ## Examples
8
+
9
+ ### Zero argument methods
10
+
11
+ **Example:** `String#empty?`
12
+
13
+ ```ruby
14
+ # .rb
15
+ "".empty?
16
+ # => true
17
+ "hello".empty?
18
+ # => false
19
+ ```
20
+
21
+ ```ruby
22
+ # .rbs
23
+ class String
24
+ def empty?: () -> bool
25
+ end
26
+ ```
27
+
28
+ `String`'s `#empty` method takes no parameters, and returns a boolean value
29
+
30
+ ### Single argument methods
31
+
32
+ **Example:** `String#include?`
33
+
34
+ ```ruby
35
+ # .rb
36
+ "homeowner".include?("house")
37
+ # => false
38
+ "homeowner".include?("meow")
39
+ # => true
40
+ ```
41
+
42
+ ```ruby
43
+ class String
44
+ def include?: (String) -> bool
45
+ end
46
+ ```
47
+
48
+ `String`'s `include?` method takes one argument, a `String`, and returns a
49
+ boolean value
50
+
51
+ ### Variable argument methods
52
+
53
+ **Example:** `String#end_with?`
54
+
55
+ ```ruby
56
+ # .rb
57
+ "hello?".end_with?("!")
58
+ # => false
59
+ "hello?".end_with?("?")
60
+ # => true
61
+ "hello?".end_with?("?", "!")
62
+ # => true
63
+ "hello?".end_with?(".", "!")
64
+ # => false
65
+ ```
66
+
67
+ ```ruby
68
+ # .rbs
69
+ class String
70
+ def end_with?: (*String) -> bool
71
+ end
72
+ ```
73
+
74
+ `String`'s `#end_with?` method takes any number of `String` arguments, and
75
+ returns a boolean value.
76
+
77
+ ### Optional positional arguments
78
+
79
+ **Example:** `String#ljust`
80
+
81
+ ```ruby
82
+ # .rb
83
+ "hello".ljust(4)
84
+ #=> "hello"
85
+ "hello".ljust(20)
86
+ #=> "hello "
87
+ "hello".ljust(20, '1234')
88
+ #=> "hello123412341234123"
89
+ ```
90
+
91
+ ```ruby
92
+ # .rbs
93
+ class String
94
+ def ljust: (Integer, ?String) -> String
95
+ end
96
+ ```
97
+
98
+ `String`'s `ljust` takes one `Integer` argument, and an optional `String` argument, indicated by the the `?` prefix marker. It returns a `String`.
99
+
100
+ ### Multiple signatures for a single method
101
+
102
+ **Example:** `Array#*`
103
+
104
+ ```ruby
105
+ # .rb
106
+ [1, 2, 3] * ","
107
+ # => "1,2,3"
108
+ [1, 2, 3] * 2
109
+ # => [1, 2, 3, 1, 2, 3]
110
+ ```
111
+
112
+ *Note:* Some of the signatures after this point include type variables (e.g. `Elem`, `T`).
113
+ For now, it's safe to ignore them, but they're included for completeness.
114
+
115
+ ```ruby
116
+ # .rbs
117
+ class Array[Elem]
118
+ def *: (String) -> String
119
+ | (Integer) -> Array[Elem]
120
+ end
121
+ ```
122
+
123
+ `Array`'s `*` method, when given a `String` returns a `String`. When given an
124
+ `Integer`, it returns an `Array` of the same contained type `Elem` (in our example case, `Elem` corresponds to `Integer`).
125
+
126
+ ### Union types
127
+
128
+ **Example:** `String#<<`
129
+
130
+ ```ruby
131
+ # .rb
132
+ a = "hello "
133
+ a << "world"
134
+ #=> "hello world"
135
+ a << 33
136
+ #=> "hello world!"
137
+ ```
138
+
139
+ ```ruby
140
+ # .rbs
141
+ class String
142
+ def <<: (String | Integer) -> String
143
+ end
144
+ ```
145
+
146
+ `String`'s `<<` operator takes either a `String` or an `Integer`, and returns a `String`.
147
+
148
+ ### Nilable types
149
+
150
+ ```ruby
151
+ # .rb
152
+ [1, 2, 3].first
153
+ # => 1
154
+ [].first
155
+ # => nil
156
+ [1, 2, 3].first(2)
157
+ # => [1, 2]
158
+ [].first(2)
159
+ # => []
160
+ ```
161
+
162
+ ```ruby
163
+ # .rbs
164
+ class Enumerable[Elem]
165
+ def first: () -> Elem?
166
+ | (Integer) -> Array[Elem]
167
+ end
168
+ ```
169
+
170
+ `Enumerable`'s `#first` method has two different signatures.
171
+
172
+ When called with no arguments, the return value will either be an instance of
173
+ whatever type is contained in the enumerable, or `nil`. We represent that with
174
+ the type variable `Elem`, and the `?` suffix nilable marker.
175
+
176
+ When called with an `Integer` positional argument, the return value will be an
177
+ `Array` of whatever type is contained.
178
+
179
+ The `?` syntax is a convenient shorthand for a union with nil. An equivalent union type woould be `(Elem | nil)`.
180
+
181
+ ### Keyword Arguments
182
+
183
+ **Example**: `String#lines`
184
+
185
+ ```ruby
186
+ # .rb
187
+ "hello\nworld\n".lines
188
+ # => ["hello\n", "world\n"]
189
+ "hello world".lines(' ')
190
+ # => ["hello ", " ", "world"]
191
+ "hello\nworld\n".lines(chomp: true)
192
+ # => ["hello", "world"]
193
+ ```
194
+
195
+ ```ruby
196
+ # .rbs
197
+ class String
198
+ def lines: (?String, ?chomp: bool) -> Array[String]
199
+ end
200
+ ```
201
+
202
+ `String`'s `#lines` method take two arguments: one optional String argument, and another optional boolean keyword argument. It returns an `Array` of `String`s.
203
+
204
+ Keyword arguments are declared similar to in ruby, with the keyword immediately followed by a colon. Keyword arguments that are optional are indicated as optional using the same `?` prefix as positional arguments.
205
+
206
+
207
+ ### Class methods
208
+
209
+ **Example**: `Time.now`
210
+
211
+ ```ruby
212
+ # .rb
213
+ Time.now
214
+ # => 2009-06-24 12:39:54 +0900
215
+ ```
216
+
217
+ ```ruby
218
+ class Time
219
+ def self.now: () -> Time
220
+ end
221
+ ```
222
+
223
+ `Time`'s class method `now` takes no arguments, and returns an instance of the
224
+ `Time` class.
225
+
226
+ ### Block Arguments
227
+
228
+ **Example**: `Array#filter`
229
+
230
+ ```ruby
231
+ # .rb
232
+ [1,2,3,4,5].select {|num| num.even? }
233
+ # => [2, 4]
234
+ %w[ a b c d e f ].select {|v| v =~ /[aeiou]/ }
235
+ # => ["a", "e"]
236
+ [1,2,3,4,5].filter
237
+ ```
238
+
239
+ ```ruby
240
+ # .rbs
241
+ class Array[Elem]
242
+ def filter: () { (Elem) -> boolish } -> ::Array[Elem]
243
+ | () -> ::Enumerator[Elem, ::Array[Elem]]
244
+ end
245
+ ```
246
+
247
+ `Array`'s `#filter` method, when called with no arguments returns an Enumerator.
248
+
249
+ When called with a block, the method returns an `Array` of whatever type the original contained. The block will take one argument, of the type of the contained value, and the block will return a truthy or falsy value.
250
+
251
+ `boolish` is a special keyword for any type that will be treated as if it were a `bool`.
252
+
253
+ ### Type Variables
254
+
255
+ **Example**: `Hash`, `Hash#keys`
256
+
257
+ ```ruby
258
+ h = { "a" => 100, "b" => 200, "c" => 300, "d" => 400 }
259
+ h.keys
260
+ # => ["a", "b", "c", "d"]
261
+ ```
262
+
263
+ ```ruby
264
+ # .rbs
265
+ class Hash[K, V]
266
+ def keys: () -> Array[K]
267
+ end
268
+ ```
269
+
270
+ Generic types in RBS are parameterized at declaration time. These type variables are then available throughout all the methods contained in the `class` block.
271
+
272
+ `Hash`'s `#keys` method takes no arguments, and returns an `Array` of the first type parameter. In the above example, `a` is of concrete type `Hash[String, Integer]`, so `#keys` returns an `Array` for `String`.
273
+
274
+
275
+ ```ruby
276
+ # .rb
277
+ a = [ "a", "b", "c", "d" ]
278
+ a.collect {|x| x + "!"}
279
+ # => ["a!", "b!", "c!", "d!"]
280
+ a.collect.with_index {|x, i| x * i}
281
+ # => ["", "b", "cc", "ddd"]
282
+ ```
283
+
284
+ ```ruby
285
+ # .rbs
286
+ class Array[Elem]
287
+ def collect: [U] () { (Elem) -> U } -> Array[U]
288
+ | () -> Enumerator[Elem, Array[untyped]]
289
+ end
290
+ ```
291
+
292
+ Type variables can also be introduced in methods. Here, in `Array`'s `#collect` method, we introduce a type variable `U`. The block passed to `#collect` will receive a parameter of type `Elem`, and return a value of type `U`. Then `#collect` will return an `Array` of type `U`.
293
+
294
+ In this example, the method receives its signature from the inferred return type of the passed block. When then block is absent, as in when the method returns an `Enumerator`, we can't infer the type, and so the return value of the enumerator can only be described as `Array[untyped]`.
295
+
296
+ ### Tuples
297
+
298
+ **Examples**: `Enumerable#partition`, `Enumerable#to_h`
299
+
300
+ ```ruby
301
+ (1..6).partition { |v| v.even? }
302
+ # => [[2, 4, 6], [1, 3, 5]]
303
+ ```
304
+
305
+ ```ruby
306
+ class Enumerable[Elem]
307
+ def partition: () { (Elem) -> boolish } -> [Array[Elem], Array[Elem]]
308
+ | () -> ::Enumerator[Elem, [Array[Elem], Array[Elem] ]]
309
+ end
310
+ ```
311
+
312
+ `Enumerable`'s `partition` method, when given a block, returns a 2-item tuple of `Array`s containing the original type of the `Enumerable`.
313
+
314
+ Tuples can be of any size, and they can have mixed types.
315
+
316
+ ```ruby
317
+ (1..5).to_h {|x| [x, x ** 2]}
318
+ # => {1=>1, 2=>4, 3=>9, 4=>16, 5=>25}
319
+ ```
320
+
321
+ ```ruby
322
+ class Enumerable[Elem]
323
+ def to_h: () -> ::Hash[untyped, untyped]
324
+ | [T, U] () { (Elem) -> [T, U] } -> ::Hash[T, U]
325
+ end
326
+ ```
327
+
328
+ `Enumerable`'s `to_h` method, when given a block that returns a 2-item tuple, returns a `Hash` with keys the type of the first position in the tuple, and values the type of the second position in the tuple.
data/docs/sigs.md CHANGED
@@ -26,7 +26,7 @@ The test installs instrumentations to spy the method calls and check if argument
26
26
  If errors are reported by the test, you will fix the signature.
27
27
  You will be sure that you ship a correct signature finally.
28
28
 
29
- The instrumentations are implemneted using `Module#prepend`.
29
+ The instrumentations are implemented using `Module#prepend`.
30
30
  It defines a module with same name of methods, which asserts the type of arguments/return values and calls `super`.
31
31
 
32
32
  ## Type errors
@@ -70,6 +70,23 @@ ERROR -- : [Kaigi::Conference#speakers] UnexpectedBlockError: unexpected block i
70
70
  The error means there is a type error on overloaded methods.
71
71
  The `rbs` test framework tries to the best error message for overloaded methods too, but it reports the `UnresolvedOverloadingError` when it fails.
72
72
 
73
+ ### DuplicatedMethodDefinitionError
74
+
75
+ The error is reported when a method is defined multiple times, as RBS does not allow duplicate method definitions. When you need to overload a method, use the `...` syntax:
76
+
77
+ ```ruby
78
+ # First definition
79
+ class C
80
+ def foo: () -> untyped
81
+ end
82
+
83
+ # Second definition, use `...` syntax to tell RBS that we're overloading the method
84
+ class C
85
+ def foo: () -> untyped
86
+ | ...
87
+ end
88
+ ```
89
+
73
90
  ## Setting up the test
74
91
 
75
92
  The design of the signature testing aims to be non-intrusive. The setup is done in two steps:
@@ -114,9 +131,11 @@ You may need to specify `-r` or `-I` to load signatures.
114
131
  The default is `-I sig`.
115
132
 
116
133
  ```
117
- RBS_TEST_OPT='-r set -r pathname -I sig'
134
+ RBS_TEST_OPT='-r pathname -I sig'
118
135
  ```
119
136
 
137
+ Replacing `pathname` with the `stdlib` you want to include. For example, if you need to load `Set` and `BigDecimal` in `stdlib`, you would need to have `RBS_TEST_OPT='-r set -r bigdecimal -I sig'`
138
+
120
139
  `RBS_TEST_LOGLEVEL` can be used to configure log level. Defaults to `info`.
121
140
 
122
141
  `RBS_TEST_RAISE` may help to debug the type signatures.
data/docs/stdlib.md CHANGED
@@ -57,7 +57,7 @@ But it will help you to have an overview of the signatures you are trying to wri
57
57
 
58
58
  ### What to do with existing RBS files
59
59
 
60
- Generating prototypes will override everything, so the problem is if there is a RBS files already.
60
+ Generating prototypes will overwrite existing RBS files, which might be undesirable.
61
61
  You can try to find missing parts, or you can start from the scratch.
62
62
 
63
63
  One non-trivial but absolutely better solution is to make a tool:
data/docs/syntax.md CHANGED
@@ -11,8 +11,8 @@ _type_ ::= _class-name_ _type-arguments_ (Class instance type)
11
11
  | _type_ `|` _type_ (Union type)
12
12
  | _type_ `&` _type_ (Intersection type)
13
13
  | _type_ `?` (Optional type)
14
- | `{` _record-name_ `:` _type_ `,` ... `}` (Record type)
15
- | `[]` | `[` _type_ `,` ... `]` (Tuples)
14
+ | `{` _record-name_ `:` _type_ `,` etc. `}` (Record type)
15
+ | `[]` | `[` _type_ `,` etc. `]` (Tuples)
16
16
  | _type-variable_ (Type variables)
17
17
  | `^(` _parameters_ `) ->` _type_ (Proc type)
18
18
  | `self`
@@ -36,7 +36,7 @@ _namespace_ ::= (Empty namespace)
36
36
  | _namespace_ /[A-Z]\w*/ `::` (Namespace)
37
37
 
38
38
  _type-arguments_ ::= (No application)
39
- | `[` _type_ `,` ... `]` (Type application)
39
+ | `[` _type_ `,` etc. `]` (Type application)
40
40
 
41
41
  _literal_ ::= _string-literal_
42
42
  | _symbol-literal_
@@ -203,7 +203,6 @@ We can see an example at the definition of `Enumerable#find`:
203
203
  ```
204
204
  module Enumerable[Elem, Return]
205
205
  def find: () { (Elem) -> boolish } -> Elem?
206
- ...
207
206
  end
208
207
  ```
209
208
 
@@ -233,11 +232,11 @@ _parameters_ ::= _required-positionals_ _optional-positionals_ _rest-positional_
233
232
 
234
233
  _parameter_ ::= _type_ _var-name_ # Parameter with var name
235
234
  | _type_ # Parameter without var name
236
- _required-positionals_ ::= _parameter_ `,` ...
237
- _optional-positionals_ ::= `?` _parameter_ `,` ...
235
+ _required-positionals_ ::= _parameter_ `,` etc.
236
+ _optional-positionals_ ::= `?` _parameter_ `,` etc.
238
237
  _rest-positional_ ::= # Empty
239
238
  | `*` _parameter_
240
- _trailing-positionals_ ::= _parameter_ `,` ...
239
+ _trailing-positionals_ ::= _parameter_ `,` etc.
241
240
  _keywords_ ::= # Empty
242
241
  | `**` _parameter_ # Rest keyword
243
242
  | _keyword_ `:` _parameter_ `,` _keywords_ # Required keyword
@@ -292,9 +291,10 @@ _method-member_ ::= `def` _method-name_ `:` _method-types_ # Instance
292
291
  _method-types_ ::= # Empty
293
292
  | `super` # `super` overloading
294
293
  | _type-parameters_ _method-type_ `|` _method-types_ # Overloading types
294
+ | `...` # Overloading for duplicate definitions
295
295
 
296
296
  _type-parameters_ ::= # Empty
297
- | `[` _type-variable_ `,` ... `]`
297
+ | `[` _type-variable_ `,` etc. `]`
298
298
 
299
299
  _attribute-member_ ::= _attribute-type_ _method-name_ `:` _type_ # Attribute
300
300
  | _attribute-type_ _method-name_ `(` _ivar-name_ `) :` _type_ # Attribute with variable name specification
@@ -352,9 +352,6 @@ def +: (Float | Integer) -> (Float | Integer)
352
352
  | (Numeric) -> Numeric
353
353
  ```
354
354
 
355
- Method types can end with `super` which means the methods from existing definitions.
356
- This is useful to define an _extension_, which adds a new variation to the existing method preserving the original behavior.
357
-
358
355
  ### Attribute definition
359
356
 
360
357
  Attribute definitions help to define methods and instance variables based on the convention of `attr_reader`, `attr_writer` and `attr_accessor` methods in Ruby.
@@ -450,7 +447,7 @@ _const-name_ ::= _namespace_ /[A-Z]\w*/
450
447
  _global-name_ ::= /$[a-zA-Z]\w+/ | ...
451
448
 
452
449
  _module-type-parameters_ ::= # Empty
453
- | `[` _module-type-parameter_ `,` ... `]`
450
+ | `[` _module-type-parameter_ `,` etc. `]`
454
451
 
455
452
  _module-type-parameter_ ::= _check_ _variance_ _type-variable_
456
453
  _variance_ ::= `out` | `in`
@@ -475,7 +472,7 @@ For example, an `Array` of `String` can almost be considered to be an `Array` of
475
472
 
476
473
  ```
477
474
  class Array[out T]
478
- # ...
475
+ # etc.
479
476
  end
480
477
  ```
481
478
 
@@ -486,7 +483,7 @@ In those cases, one must use the `unchecked` keyword:
486
483
 
487
484
  ```
488
485
  class Array[unchecked out T]
489
- # ...
486
+ # etc.
490
487
  end
491
488
  ```
492
489