rbs 4.1.0.pre.1 → 4.1.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.
- checksums.yaml +4 -4
- data/.dockerignore +37 -0
- data/.github/workflows/bundle-update.yml +1 -1
- data/.github/workflows/c-check.yml +14 -6
- data/.github/workflows/comments.yml +2 -2
- data/.github/workflows/dependabot.yml +2 -2
- data/.github/workflows/jruby.yml +79 -0
- data/.github/workflows/milestone.yml +13 -2
- data/.github/workflows/ruby.yml +16 -4
- data/.github/workflows/rust.yml +13 -8
- data/.github/workflows/truffleruby.yml +54 -0
- data/.github/workflows/typecheck.yml +5 -2
- data/.github/workflows/wasm.yml +55 -0
- data/.github/workflows/windows.yml +8 -2
- data/.gitignore +8 -0
- data/CHANGELOG.md +88 -0
- data/Dockerfile.jruby +53 -0
- data/README.md +3 -3
- data/Rakefile +103 -1
- data/Steepfile +9 -0
- data/core/array.rbs +243 -180
- data/core/builtin.rbs +6 -6
- data/core/enumerable.rbs +109 -109
- data/core/enumerator/product.rbs +5 -5
- data/core/enumerator.rbs +28 -28
- data/core/file.rbs +24 -1018
- data/core/file_constants.rbs +463 -0
- data/core/file_stat.rbs +534 -0
- data/core/float.rbs +0 -24
- data/core/hash.rbs +117 -101
- data/core/integer.rbs +21 -58
- data/core/io.rbs +25 -7
- data/core/match_data.rbs +1 -1
- data/core/module.rbs +88 -74
- data/core/numeric.rbs +3 -0
- data/core/object_space/weak_key_map.rbs +7 -7
- data/core/pathname.rbs +0 -10
- data/core/ractor.rbs +0 -10
- data/core/range.rbs +23 -23
- data/core/rbs/ops.rbs +154 -0
- data/core/rbs/unnamed/argf.rbs +3 -3
- data/core/rubygems/errors.rbs +4 -1
- data/core/rubygems/requirement.rbs +0 -10
- data/core/rubygems/rubygems.rbs +4 -1
- data/core/rubygems/specification.rbs +8 -0
- data/core/rubygems/version.rbs +0 -160
- data/core/set.rbs +3 -3
- data/core/struct.rbs +16 -16
- data/core/thread.rbs +9 -14
- data/docs/CONTRIBUTING.md +2 -1
- data/docs/inline.md +36 -6
- data/docs/rbs_by_example.md +20 -20
- data/docs/release.md +69 -0
- data/docs/syntax.md +2 -2
- data/docs/wasm_serialization.md +80 -0
- data/ext/rbs_extension/ast_translation.c +1294 -973
- data/ext/rbs_extension/ast_translation.h +4 -0
- data/ext/rbs_extension/legacy_location.c +11 -6
- data/ext/rbs_extension/main.c +139 -4
- data/include/rbs/ast.h +9 -1
- data/include/rbs/serialize.h +39 -0
- data/lib/rbs/ast/ruby/comment_block.rb +6 -4
- data/lib/rbs/ast/ruby/helpers/location_helper.rb +1 -1
- data/lib/rbs/ast/ruby/members.rb +12 -1
- data/lib/rbs/buffer.rb +48 -11
- data/lib/rbs/collection/sources/git.rb +6 -0
- data/lib/rbs/definition_builder/method_builder.rb +12 -6
- data/lib/rbs/environment.rb +4 -3
- data/lib/rbs/inline_parser.rb +5 -3
- data/lib/rbs/namespace.rb +47 -11
- data/lib/rbs/parser_aux.rb +4 -2
- data/lib/rbs/prototype/rbi.rb +193 -25
- data/lib/rbs/prototype/runtime.rb +2 -0
- data/lib/rbs/resolver/type_name_resolver.rb +12 -14
- data/lib/rbs/type_name.rb +33 -13
- data/lib/rbs/unit_test/type_assertions.rb +9 -0
- data/lib/rbs/version.rb +1 -1
- data/lib/rbs/wasm/deserializer.rb +213 -0
- data/lib/rbs/wasm/location.rb +61 -0
- data/lib/rbs/wasm/parser.rb +137 -0
- data/lib/rbs/wasm/runtime.rb +196 -0
- data/lib/rbs/wasm/serialization_schema.rb +110 -0
- data/lib/rbs.rb +13 -2
- data/lib/rbs_jars.rb +39 -0
- data/lib/rdoc_plugin/parser.rb +5 -0
- data/rbs.gemspec +32 -2
- data/sig/ast/ruby/members.rbs +6 -1
- data/sig/buffer.rbs +19 -1
- data/sig/namespace.rbs +20 -0
- data/sig/parser.rbs +10 -0
- data/sig/prototype/rbi.rbs +33 -4
- data/sig/resolver/type_name_resolver.rbs +2 -4
- data/sig/typename.rbs +15 -0
- data/sig/unit_test/type_assertions.rbs +4 -0
- data/sig/wasm/deserializer.rbs +66 -0
- data/sig/wasm/serialization_schema.rbs +13 -0
- data/src/ast.c +78 -78
- data/src/lexer.c +97 -93
- data/src/lexer.re +1 -1
- data/src/lexstate.c +9 -1
- data/src/serialize.c +958 -0
- data/src/util/rbs_allocator.c +14 -8
- data/stdlib/abbrev/0/array.rbs +1 -1
- data/stdlib/csv/0/csv.rbs +5 -5
- data/stdlib/delegate/0/delegator.rbs +2 -1
- data/stdlib/digest/0/digest.rbs +11 -5
- data/stdlib/erb/0/erb.rbs +1 -1
- data/stdlib/etc/0/etc.rbs +18 -4
- data/stdlib/fileutils/0/fileutils.rbs +21 -21
- data/stdlib/ipaddr/0/ipaddr.rbs +0 -5
- data/stdlib/json/0/json.rbs +6 -6
- data/stdlib/monitor/0/monitor.rbs +2 -2
- data/stdlib/openssl/0/openssl.rbs +44 -38
- data/stdlib/resolv/0/resolv.rbs +1 -1
- data/stdlib/shellwords/0/shellwords.rbs +1 -1
- data/stdlib/stringio/0/stringio.rbs +32 -10
- data/stdlib/strscan/0/string_scanner.rbs +74 -55
- data/stdlib/tempfile/0/manifest.yaml +3 -0
- data/stdlib/timeout/0/timeout.rbs +0 -5
- data/stdlib/tsort/0/cyclic.rbs +1 -1
- data/stdlib/tsort/0/interfaces.rbs +8 -8
- data/stdlib/tsort/0/tsort.rbs +9 -9
- data/stdlib/uri/0/generic.rbs +0 -5
- data/stdlib/zlib/0/gzip_reader.rbs +2 -2
- data/stdlib/zlib/0/zstream.rbs +0 -1
- data/wasm/README.md +60 -0
- data/wasm/rbs_wasm.c +423 -0
- metadata +26 -5
- data/.vscode/extensions.json +0 -5
- data/.vscode/settings.json +0 -19
data/core/thread.rbs
CHANGED
|
@@ -1565,10 +1565,10 @@ class Thread::Mutex < Object
|
|
|
1565
1565
|
|
|
1566
1566
|
# <!--
|
|
1567
1567
|
# rdoc-file=thread_sync.rb
|
|
1568
|
-
# - mutex.
|
|
1568
|
+
# - mutex.unlock -> self
|
|
1569
1569
|
# -->
|
|
1570
|
-
#
|
|
1571
|
-
#
|
|
1570
|
+
# Releases the lock. Raises `ThreadError` if `mutex` wasn't locked by the
|
|
1571
|
+
# current thread.
|
|
1572
1572
|
#
|
|
1573
1573
|
def unlock: () -> self
|
|
1574
1574
|
end
|
|
@@ -1604,7 +1604,7 @@ end
|
|
|
1604
1604
|
#
|
|
1605
1605
|
# consumer.join
|
|
1606
1606
|
#
|
|
1607
|
-
class Thread::Queue[
|
|
1607
|
+
class Thread::Queue[E = untyped] < Object
|
|
1608
1608
|
# <!-- rdoc-file=thread_sync.c -->
|
|
1609
1609
|
# Pushes the given `object` to the queue.
|
|
1610
1610
|
#
|
|
@@ -1719,7 +1719,7 @@ class Thread::Queue[Elem = untyped] < Object
|
|
|
1719
1719
|
# If `timeout` seconds have passed and no data is available `nil` is returned.
|
|
1720
1720
|
# If `timeout` is `0` it returns immediately.
|
|
1721
1721
|
#
|
|
1722
|
-
def pop: (?boolish non_block, ?timeout: _ToF?) ->
|
|
1722
|
+
def pop: (?boolish non_block, ?timeout: _ToF?) -> E?
|
|
1723
1723
|
|
|
1724
1724
|
# <!--
|
|
1725
1725
|
# rdoc-file=thread_sync.c
|
|
@@ -1729,7 +1729,7 @@ class Thread::Queue[Elem = untyped] < Object
|
|
|
1729
1729
|
# -->
|
|
1730
1730
|
# Pushes the given `object` to the queue.
|
|
1731
1731
|
#
|
|
1732
|
-
def push: (
|
|
1732
|
+
def push: (E obj) -> void
|
|
1733
1733
|
|
|
1734
1734
|
# <!--
|
|
1735
1735
|
# rdoc-file=thread_sync.rb
|
|
@@ -1750,12 +1750,7 @@ end
|
|
|
1750
1750
|
#
|
|
1751
1751
|
# See Thread::Queue for an example of how a Thread::SizedQueue works.
|
|
1752
1752
|
#
|
|
1753
|
-
class Thread::SizedQueue[
|
|
1754
|
-
# <!--
|
|
1755
|
-
# rdoc-file=thread_sync.rb
|
|
1756
|
-
# - <<(object, non_block = false, timeout: nil)
|
|
1757
|
-
# -->
|
|
1758
|
-
#
|
|
1753
|
+
class Thread::SizedQueue[E = untyped] < Thread::Queue[E]
|
|
1759
1754
|
alias << push
|
|
1760
1755
|
|
|
1761
1756
|
# <!--
|
|
@@ -1813,8 +1808,8 @@ class Thread::SizedQueue[Elem = untyped] < Thread::Queue[Elem]
|
|
|
1813
1808
|
# If `timeout` seconds have passed and no space is available `nil` is returned.
|
|
1814
1809
|
# If `timeout` is `0` it returns immediately. Otherwise it returns `self`.
|
|
1815
1810
|
#
|
|
1816
|
-
def push: (
|
|
1817
|
-
| (
|
|
1811
|
+
def push: (E obj, ?boolish non_block) -> void
|
|
1812
|
+
| (E obj, timeout: _ToF?) -> self?
|
|
1818
1813
|
end
|
|
1819
1814
|
|
|
1820
1815
|
class ConditionVariable = Thread::ConditionVariable
|
data/docs/CONTRIBUTING.md
CHANGED
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
The RBS repository contains the type definitions of Core API and Standard Libraries.
|
|
13
13
|
There are some discussions whether if it is the best to have them in this repository, but we have them and continue updating the files meanwhile.
|
|
14
14
|
|
|
15
|
-
The target version of the bundled type definitions is the latest _release_ of Ruby -- `
|
|
15
|
+
The target version of the bundled type definitions is the [latest _release_ of Ruby](https://www.ruby-lang.org/en/downloads/branches/) -- `4.0` as of 2026.
|
|
16
|
+
Note, however, that the CI runs the tests on every non-EOL Ruby -- `3.3` and later as of 2026.
|
|
16
17
|
|
|
17
18
|
**The core API** type definitions are in `core` directory.
|
|
18
19
|
You will find the familiar class names in the directory, like `string.rbs` or `array.rbs`.
|
data/docs/inline.md
CHANGED
|
@@ -163,6 +163,8 @@ Inline RBS supports methods defined using the `def` syntax in Ruby.
|
|
|
163
163
|
```ruby
|
|
164
164
|
class Calculator
|
|
165
165
|
def add(x, y) = x+y
|
|
166
|
+
|
|
167
|
+
def self.zero = 0
|
|
166
168
|
end
|
|
167
169
|
```
|
|
168
170
|
|
|
@@ -233,6 +235,18 @@ The type of both methods is `(Integer, Integer) -> Integer | (Float, Float) -> F
|
|
|
233
235
|
> The `@rbs METHOD-TYPE` syntax allows overloads with the `|` operator, just like in RBS files.
|
|
234
236
|
> Multiple `: METHOD-TYPE` declarations are required for overloads.
|
|
235
237
|
|
|
238
|
+
The `#:` syntax can also be used as a trailing annotation to declare the return type of a method:
|
|
239
|
+
|
|
240
|
+
```ruby
|
|
241
|
+
class Calculator
|
|
242
|
+
def add(x, y) #: Integer
|
|
243
|
+
x + y
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
def subtract(x, y) = x - y #: Integer
|
|
247
|
+
end
|
|
248
|
+
```
|
|
249
|
+
|
|
236
250
|
The `@rbs METHOD-TYPE` syntax allows having `...` at the last part.
|
|
237
251
|
|
|
238
252
|
```ruby
|
|
@@ -337,9 +351,10 @@ end
|
|
|
337
351
|
|
|
338
352
|
### Current Limitations
|
|
339
353
|
|
|
340
|
-
- Class methods and singleton methods are not supported
|
|
341
|
-
- Only positional and keyword parameters are supported. Splat parameters (`*x`, `**y`) and block parameter (`&block`) are not supported yet.
|
|
342
354
|
- Method visibility declaration is not supported yet
|
|
355
|
+
- The `class << self` syntax is not supported
|
|
356
|
+
- Top-level method definitions (outside any class/module) are not supported
|
|
357
|
+
- Method definitions with a non-self receiver (e.g. `def obj.foo`) are not supported
|
|
343
358
|
|
|
344
359
|
## Attributes
|
|
345
360
|
|
|
@@ -417,6 +432,7 @@ The attribute definitions are ignored because the names are given by string lite
|
|
|
417
432
|
### Current Limitations
|
|
418
433
|
|
|
419
434
|
- Attribute visibility is not supported yet. All attributes are _public_
|
|
435
|
+
- Top-level attribute definitions (outside any class/module) are not supported
|
|
420
436
|
|
|
421
437
|
## Mixin
|
|
422
438
|
|
|
@@ -515,7 +531,7 @@ end
|
|
|
515
531
|
```
|
|
516
532
|
|
|
517
533
|
The `@rbs @VAR-NAME: TYPE` syntax enclosed in `class`/`module` syntax declares instance variables.
|
|
518
|
-
You can add the documentation of the variable followed by two
|
|
534
|
+
You can add the documentation of the variable followed by two hyphens (`--`).
|
|
519
535
|
|
|
520
536
|
Instance variable declarations must be under the `class`/`module` syntax, and they are ignored if written inside method definitions.
|
|
521
537
|
|
|
@@ -547,14 +563,16 @@ The types of constants may be automatically inferred when the right-hand side co
|
|
|
547
563
|
- **Floats**: `RATE = 3.14` → `Float`
|
|
548
564
|
- **Booleans**: `ENABLED = true` → `bool`
|
|
549
565
|
- **Strings**: `NAME = "test"` → `String`
|
|
550
|
-
- **Symbols**: `STATUS = :ready` →
|
|
566
|
+
- **Symbols**: `STATUS = :ready` → `Symbol`
|
|
567
|
+
- **Nil**: `EMPTY = nil` → `nil`
|
|
551
568
|
|
|
552
569
|
```ruby
|
|
553
570
|
MAX_SIZE = 100 # Inferred as Integer
|
|
554
571
|
PI = 3.14159 # Inferred as Float
|
|
555
572
|
DEBUG = false # Inferred as bool
|
|
556
573
|
APP_NAME = "MyApp" # Inferred as String
|
|
557
|
-
DEFAULT_MODE = :strict # Inferred as
|
|
574
|
+
DEFAULT_MODE = :strict # Inferred as Symbol
|
|
575
|
+
NONE = nil # Inferred as nil
|
|
558
576
|
```
|
|
559
577
|
|
|
560
578
|
### Explicit Type Annotations
|
|
@@ -595,10 +613,22 @@ MyKernel = Kernel #: module-alias
|
|
|
595
613
|
|
|
596
614
|
This creates new type names that refer to the same class or module as the original.
|
|
597
615
|
|
|
598
|
-
The annotations can have optional type name to specify the class/module name, for the case it cannot be
|
|
616
|
+
The annotations can have optional type name to specify the class/module name, for the case it cannot be inferred through the right-hand-side of the constant declaration.
|
|
599
617
|
|
|
600
618
|
```ruby
|
|
601
619
|
MyObject = object #: class-alias Object
|
|
602
620
|
|
|
603
621
|
MyKernel = kernel #: module-alias Kernel
|
|
604
622
|
```
|
|
623
|
+
|
|
624
|
+
## Skip Annotation
|
|
625
|
+
|
|
626
|
+
The `@rbs skip` annotation makes inline RBS ignore the following declaration.
|
|
627
|
+
|
|
628
|
+
```ruby
|
|
629
|
+
class Calculator
|
|
630
|
+
# @rbs skip
|
|
631
|
+
def debug_internal
|
|
632
|
+
end
|
|
633
|
+
end
|
|
634
|
+
```
|
data/docs/rbs_by_example.md
CHANGED
|
@@ -107,14 +107,14 @@ end
|
|
|
107
107
|
For now, it's safe to ignore them, but they're included for completeness.
|
|
108
108
|
|
|
109
109
|
```rbs
|
|
110
|
-
class Array[
|
|
110
|
+
class Array[E]
|
|
111
111
|
def *: (String) -> String
|
|
112
|
-
| (Integer) -> Array[
|
|
112
|
+
| (Integer) -> Array[E]
|
|
113
113
|
end
|
|
114
114
|
```
|
|
115
115
|
|
|
116
116
|
`Array`'s `*` method, when given a `String` returns a `String`. When given an
|
|
117
|
-
`Integer`, it returns an `Array` of the same contained type `
|
|
117
|
+
`Integer`, it returns an `Array` of the same contained type `E` (in our example case, `E` corresponds to `Integer`).
|
|
118
118
|
|
|
119
119
|
### Union types
|
|
120
120
|
|
|
@@ -150,9 +150,9 @@ end
|
|
|
150
150
|
```
|
|
151
151
|
|
|
152
152
|
```rbs
|
|
153
|
-
class Enumerable[
|
|
154
|
-
def first: () ->
|
|
155
|
-
| (Integer) -> Array[
|
|
153
|
+
class Enumerable[E]
|
|
154
|
+
def first: () -> E?
|
|
155
|
+
| (Integer) -> Array[E]
|
|
156
156
|
end
|
|
157
157
|
```
|
|
158
158
|
|
|
@@ -160,12 +160,12 @@ end
|
|
|
160
160
|
|
|
161
161
|
When called with no arguments, the return value will either be an instance of
|
|
162
162
|
whatever type is contained in the enumerable, or `nil`. We represent that with
|
|
163
|
-
the type variable `
|
|
163
|
+
the type variable `E`, and the `?` suffix nilable marker.
|
|
164
164
|
|
|
165
165
|
When called with an `Integer` positional argument, the return value will be an
|
|
166
166
|
`Array` of whatever type is contained.
|
|
167
167
|
|
|
168
|
-
The `?` syntax is a convenient shorthand for a union with nil. An equivalent union type would be `(
|
|
168
|
+
The `?` syntax is a convenient shorthand for a union with nil. An equivalent union type would be `(E | nil)`.
|
|
169
169
|
|
|
170
170
|
### Keyword Arguments
|
|
171
171
|
|
|
@@ -222,9 +222,9 @@ end
|
|
|
222
222
|
```
|
|
223
223
|
|
|
224
224
|
```rbs
|
|
225
|
-
class Array[
|
|
226
|
-
def filter: () { (
|
|
227
|
-
| () -> ::Enumerator[
|
|
225
|
+
class Array[E]
|
|
226
|
+
def filter: () { (E) -> boolish } -> ::Array[E]
|
|
227
|
+
| () -> ::Enumerator[E, ::Array[E]]
|
|
228
228
|
end
|
|
229
229
|
```
|
|
230
230
|
|
|
@@ -264,13 +264,13 @@ a.collect.with_index {|x, i| x * i}
|
|
|
264
264
|
```
|
|
265
265
|
|
|
266
266
|
```rbs
|
|
267
|
-
class Array[
|
|
268
|
-
def collect: [U] () { (
|
|
269
|
-
| () -> Enumerator[
|
|
267
|
+
class Array[E]
|
|
268
|
+
def collect: [U] () { (E) -> U } -> Array[U]
|
|
269
|
+
| () -> Enumerator[E, Array[untyped]]
|
|
270
270
|
end
|
|
271
271
|
```
|
|
272
272
|
|
|
273
|
-
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 `
|
|
273
|
+
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 `E`, and return a value of type `U`. Then `#collect` will return an `Array` of type `U`.
|
|
274
274
|
|
|
275
275
|
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]`.
|
|
276
276
|
|
|
@@ -284,9 +284,9 @@ In this example, the method receives its signature from the inferred return type
|
|
|
284
284
|
```
|
|
285
285
|
|
|
286
286
|
```rbs
|
|
287
|
-
class Enumerable[
|
|
288
|
-
def partition: () { (
|
|
289
|
-
| () -> ::Enumerator[
|
|
287
|
+
class Enumerable[E]
|
|
288
|
+
def partition: () { (E) -> boolish } -> [Array[E], Array[E]]
|
|
289
|
+
| () -> ::Enumerator[E, [Array[E], Array[E] ]]
|
|
290
290
|
end
|
|
291
291
|
```
|
|
292
292
|
|
|
@@ -300,9 +300,9 @@ Tuples can be of any size, and they can have mixed types.
|
|
|
300
300
|
```
|
|
301
301
|
|
|
302
302
|
```rbs
|
|
303
|
-
class Enumerable[
|
|
303
|
+
class Enumerable[E]
|
|
304
304
|
def to_h: () -> ::Hash[untyped, untyped]
|
|
305
|
-
| [T, U] () { (
|
|
305
|
+
| [T, U] () { (E) -> [T, U] } -> ::Hash[T, U]
|
|
306
306
|
end
|
|
307
307
|
```
|
|
308
308
|
|
data/docs/release.md
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Releasing RBS
|
|
2
|
+
|
|
3
|
+
Each release ships **two gems**:
|
|
4
|
+
|
|
5
|
+
| Gem | Platform | Parser | How it is built |
|
|
6
|
+
| --- | --- | --- | --- |
|
|
7
|
+
| `rbs-X.Y.Z.gem` | `ruby` (MRI) | C extension | `rake release` (re-builds it) |
|
|
8
|
+
| `rbs-X.Y.Z-java.gem` | `java` (JRuby) | WebAssembly (`lib/rbs/wasm`) | Docker image, pushed manually |
|
|
9
|
+
|
|
10
|
+
The `-java` gem contains no native code — just `rbs_parser.wasm`. The Chicory/ASM
|
|
11
|
+
jars it needs are not shipped in the gem; they are declared as `jar-dependencies`
|
|
12
|
+
requirements and fetched from Maven when the gem is installed. So the gem can be
|
|
13
|
+
built once in any environment and runs on every JRuby.
|
|
14
|
+
|
|
15
|
+
## Prerequisites
|
|
16
|
+
|
|
17
|
+
- Push rights to the `rbs` gem on RubyGems (`gem signin`). If your account has
|
|
18
|
+
MFA enabled, `gem push` / `rake release` will prompt for an OTP.
|
|
19
|
+
- Docker, for the `-java` gem. The WASI SDK is baked into the image, so there is
|
|
20
|
+
nothing to install on the host.
|
|
21
|
+
|
|
22
|
+
## Steps
|
|
23
|
+
|
|
24
|
+
### 1. Release the `ruby` gem
|
|
25
|
+
|
|
26
|
+
Once the version is bumped and committed, run on CRuby:
|
|
27
|
+
|
|
28
|
+
```console
|
|
29
|
+
$ bundle exec rake release
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
This re-builds the `ruby`-platform gem and then:
|
|
33
|
+
|
|
34
|
+
- creates the tag `vX.Y.Z`,
|
|
35
|
+
- pushes the current branch and the tag to `origin`,
|
|
36
|
+
- pushes the gem to RubyGems,
|
|
37
|
+
- runs `release:note`, which opens a GitHub **draft** release (with
|
|
38
|
+
`--prerelease` for `*.pre.*` versions) and prints the remaining manual steps.
|
|
39
|
+
|
|
40
|
+
### 2. Build and push the `java` gem
|
|
41
|
+
|
|
42
|
+
The `java` gem is not built by `rake release`, so build and push it manually:
|
|
43
|
+
|
|
44
|
+
```console
|
|
45
|
+
# Build from the committed state (the gemspec's file list comes from `git ls-files`).
|
|
46
|
+
$ docker build -f Dockerfile.jruby -t rbs-jruby .
|
|
47
|
+
|
|
48
|
+
# Build rbs_parser.wasm and the -java gem into ./pkg on the host. The Chicory/ASM
|
|
49
|
+
# jars are not bundled; they are fetched from Maven when the gem is installed.
|
|
50
|
+
$ docker run --rm -e RBS_PLATFORM=java -v "$PWD/pkg:/out" rbs-jruby \
|
|
51
|
+
gem build rbs.gemspec -o /out/rbs-X.Y.Z-java.gem
|
|
52
|
+
|
|
53
|
+
$ gem push pkg/rbs-X.Y.Z-java.gem
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Optionally confirm it installs and runs on JRuby before pushing:
|
|
57
|
+
|
|
58
|
+
```console
|
|
59
|
+
$ docker run --rm -v "$PWD/pkg:/pkg" -w /tmp rbs-jruby bash -c \
|
|
60
|
+
'gem install /pkg/rbs-X.Y.Z-java.gem && ruby -e "require %q{rbs}; puts [RUBY_ENGINE, RBS::VERSION].join(%q{ })"'
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Notes
|
|
64
|
+
|
|
65
|
+
- Prereleases (`X.Y.Z.pre.N`) are only installed with `gem install rbs --pre`;
|
|
66
|
+
a plain `gem install rbs` is unaffected. On JRuby, `gem install rbs [--pre]`
|
|
67
|
+
resolves to the `-java` gem automatically.
|
|
68
|
+
- The Dockerfile pins the WASI SDK / Chicory / ASM versions to match the
|
|
69
|
+
`wasm` and `jruby` CI workflows. Keep them in sync when bumping.
|
data/docs/syntax.md
CHANGED
|
@@ -196,8 +196,8 @@ It is an alias of `top` type, and you can use `boolish` if we want to allow any
|
|
|
196
196
|
We can see an example at the definition of `Enumerable#find`:
|
|
197
197
|
|
|
198
198
|
```rbs
|
|
199
|
-
module Enumerable[
|
|
200
|
-
def find: () { (
|
|
199
|
+
module Enumerable[E, R]
|
|
200
|
+
def find: () { (E) -> boolish } -> E?
|
|
201
201
|
end
|
|
202
202
|
```
|
|
203
203
|
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# RBS AST binary serialization
|
|
2
|
+
|
|
3
|
+
This document describes the binary format used to move a parsed RBS AST out of
|
|
4
|
+
the parser and into Ruby objects without going through the Ruby C API. It exists
|
|
5
|
+
so that RBS can run on Ruby implementations that cannot load the C extension
|
|
6
|
+
(notably JRuby): the parser runs inside WebAssembly, serializes the result with
|
|
7
|
+
this format, and the host rebuilds `RBS::AST` objects in pure Ruby.
|
|
8
|
+
|
|
9
|
+
The encoder (`rbs_serialize_node`, `src/serialize.c`) and the schema that drives
|
|
10
|
+
the decoder (`RBS::WASM::SerializationSchema`, `lib/rbs/wasm/serialization_schema.rb`)
|
|
11
|
+
are both generated from `config.yml`, so they always agree. The decoder itself
|
|
12
|
+
is `RBS::WASM::Deserializer`.
|
|
13
|
+
|
|
14
|
+
## Conventions
|
|
15
|
+
|
|
16
|
+
- All multi-byte integers are **little-endian**.
|
|
17
|
+
- `u8`, `u32` are unsigned; `i32` is signed.
|
|
18
|
+
- `str` is a `u32` byte length followed by that many raw bytes (no terminator).
|
|
19
|
+
- A value is reconstructed to mirror exactly what `ast_translation.c` produces,
|
|
20
|
+
including string encodings: string/integer literal nodes are UTF-8, while
|
|
21
|
+
comments, annotations and symbols use the source buffer's encoding.
|
|
22
|
+
|
|
23
|
+
## Nodes
|
|
24
|
+
|
|
25
|
+
Every node begins with a `u8` **tag**:
|
|
26
|
+
|
|
27
|
+
- `0` — a NULL node (`nil` on the Ruby side).
|
|
28
|
+
- `1..N` — a node type, in the order they appear in `SerializationSchema::SCHEMA`.
|
|
29
|
+
- `SYMBOL_TAG` (`N + 1`) — an interned symbol, followed by `str` (the symbol's
|
|
30
|
+
bytes). Decoded with `String#to_sym`.
|
|
31
|
+
|
|
32
|
+
A few node types are encoded specially, matching their bespoke handling in
|
|
33
|
+
`ast_translation.c`:
|
|
34
|
+
|
|
35
|
+
| Node | Payload after tag | Decoded as |
|
|
36
|
+
| --- | --- | --- |
|
|
37
|
+
| `RBS::AST::Bool` | `u8` | `true` / `false` |
|
|
38
|
+
| `RBS::AST::Integer` | `str` | `String#to_i` |
|
|
39
|
+
| `RBS::AST::String` | `str` | the string (UTF-8) |
|
|
40
|
+
| `RBS::Types::Record::FieldType` | node, then `u8` | `[type, required]` |
|
|
41
|
+
| `RBS::Signature` | node-list, then node-list | `[directives, declarations]` |
|
|
42
|
+
| `RBS::Namespace` | node-list, then `u8` | `RBS::Namespace[path, absolute]` |
|
|
43
|
+
| `RBS::TypeName` | node, then node | `RBS::TypeName[namespace, name]` |
|
|
44
|
+
|
|
45
|
+
Every other node is encoded generically:
|
|
46
|
+
|
|
47
|
+
1. If the node exposes a location, its **base location** is written (see below),
|
|
48
|
+
followed by one location range per declared child, in order.
|
|
49
|
+
2. Each field is written in declaration order, encoded by its type (see below).
|
|
50
|
+
|
|
51
|
+
The decoder constructs `Klass.new(location:, **fields)` (omitting `location:`
|
|
52
|
+
for nodes that do not expose one). For `Class`, `Module`, `Interface`,
|
|
53
|
+
`TypeAlias` and `MethodType`, `RBS::AST::TypeParam.resolve_variables` is applied
|
|
54
|
+
to `type_params` first, exactly as the C translation does.
|
|
55
|
+
|
|
56
|
+
## Fields
|
|
57
|
+
|
|
58
|
+
| Field type | Encoding |
|
|
59
|
+
| --- | --- |
|
|
60
|
+
| node (`rbs_node`, `rbs_type_name`, `rbs_ast_comment`, `rbs_ast_symbol`, ...) | a node (recursive; NULL allowed) |
|
|
61
|
+
| `rbs_node_list` | `u32` count, then that many nodes |
|
|
62
|
+
| `rbs_hash` | `u32` count, then count × (key node, value node) |
|
|
63
|
+
| `rbs_string` | `str` (source encoding) |
|
|
64
|
+
| `bool` | `u8` |
|
|
65
|
+
| enum | `u8` index into the enum's values (see `SCHEMA`) |
|
|
66
|
+
| `rbs_location_range` | a location range |
|
|
67
|
+
| `rbs_location_range_list` | `u32` count, then that many location ranges |
|
|
68
|
+
| `rbs_attr_ivar_name` | `u8` tag: `0` → `nil`, `1` → `false`, `2` → `str` → symbol |
|
|
69
|
+
|
|
70
|
+
## Location ranges
|
|
71
|
+
|
|
72
|
+
A location range is a `u8` presence flag:
|
|
73
|
+
|
|
74
|
+
- `0` — null range (`nil`, or a node with no location).
|
|
75
|
+
- `1` — followed by `i32` start and `i32` end **character** positions.
|
|
76
|
+
|
|
77
|
+
The base location and child ranges together let the decoder rebuild an
|
|
78
|
+
`RBS::Location` (with its required/optional children) through the public
|
|
79
|
+
`RBS::Location` API, so the same decoder works whether `RBS::Location` is backed
|
|
80
|
+
by the C extension or a pure-Ruby implementation.
|