rbs 4.1.0 → 4.1.2
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/.github/dependabot.yml +1 -1
- data/.github/workflows/bundle-update.yml +1 -1
- data/.github/workflows/jruby.yml +1 -6
- data/.github/workflows/release-gems.yml +235 -0
- data/CHANGELOG.md +26 -0
- data/README.md +1 -1
- data/Rakefile +407 -79
- data/config.yml +2 -0
- data/docs/release.md +210 -32
- data/include/rbs/ast.h +4 -4
- data/lib/rbs/version.rb +1 -1
- data/src/ast.c +2 -2
- data/src/parser.c +6 -3
- data/wasm/README.md +33 -0
- metadata +3 -3
- data/.github/workflows/milestone.yml +0 -91
data/docs/release.md
CHANGED
|
@@ -1,69 +1,247 @@
|
|
|
1
1
|
# Releasing RBS
|
|
2
2
|
|
|
3
|
+
A release is a pull request and one workflow run. Everything that leaves the
|
|
4
|
+
repository — the tag, both gems, and the GitHub release — is produced by the
|
|
5
|
+
`Release gems` workflow, so nothing has to be built or pushed from a laptop.
|
|
6
|
+
|
|
3
7
|
Each release ships **two gems**:
|
|
4
8
|
|
|
5
|
-
| Gem | Platform | Parser |
|
|
6
|
-
| --- | --- | --- |
|
|
7
|
-
| `rbs-X.Y.Z.gem` | `ruby` (MRI) | C extension
|
|
8
|
-
| `rbs-X.Y.Z-java.gem` | `java` (JRuby) |
|
|
9
|
+
| Gem | Platform | Parser |
|
|
10
|
+
| --- | --- | --- |
|
|
11
|
+
| `rbs-X.Y.Z.gem` | `ruby` (MRI) | C extension, compiled on install |
|
|
12
|
+
| `rbs-X.Y.Z-java.gem` | `java` (JRuby) | `rbs_parser.wasm`, built by the workflow |
|
|
9
13
|
|
|
10
14
|
The `-java` gem contains no native code — just `rbs_parser.wasm`. The Chicory/ASM
|
|
11
15
|
jars it needs are not shipped in the gem; they are declared as `jar-dependencies`
|
|
12
16
|
requirements and fetched from Maven when the gem is installed. So the gem can be
|
|
13
17
|
built once in any environment and runs on every JRuby.
|
|
14
18
|
|
|
19
|
+
There are three kinds of release, and they differ in what gets written up:
|
|
20
|
+
|
|
21
|
+
| Version | CHANGELOG section | GitHub release |
|
|
22
|
+
| --- | --- | --- |
|
|
23
|
+
| `X.Y.Z` | The whole cycle since the previous release proper, prereleases included | Published |
|
|
24
|
+
| `X.Y.Z.pre.N` | What changed since `X.Y.Z.pre.N-1` | Published, marked as a prerelease |
|
|
25
|
+
| `X.Y.Z.dev.N` | None | None |
|
|
26
|
+
|
|
27
|
+
`.dev.N` releases are cut from the development line for people who need a change
|
|
28
|
+
early, so they are gems and tags and nothing else.
|
|
29
|
+
|
|
15
30
|
## Prerequisites
|
|
16
31
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
-
|
|
20
|
-
|
|
32
|
+
Push rights to the `rbs` gem on RubyGems are **not** needed: the workflow
|
|
33
|
+
authenticates through a trusted publisher registered for this repository and
|
|
34
|
+
`release-gems.yml`. What is needed is write access to the repository, since that
|
|
35
|
+
is what lets you dispatch the workflow.
|
|
21
36
|
|
|
22
37
|
## Steps
|
|
23
38
|
|
|
24
|
-
|
|
39
|
+
The release pull request in step 1 is merged by a person who has reviewed it. Its merge commit is
|
|
40
|
+
what step 2 dispatches, tags, and pushes to RubyGems, and none of that can be taken back — so
|
|
41
|
+
prepare that pull request and stop there, rather than merging it and carrying on to step 2.
|
|
42
|
+
|
|
43
|
+
The bump that starts a new minor is the only other pull request that sets `RBS::VERSION`. It
|
|
44
|
+
publishes nothing and another bump undoes it, so one opened on an explicit request can go through
|
|
45
|
+
on its own.
|
|
25
46
|
|
|
26
|
-
|
|
47
|
+
### 1. Prepare the release
|
|
48
|
+
|
|
49
|
+
Open a pull request that carries everything the release needs:
|
|
50
|
+
|
|
51
|
+
- `lib/rbs/version.rb` — set `RBS::VERSION` to the version being released.
|
|
52
|
+
- `Gemfile.lock` — run `bundle install` after the bump; the lockfile records the version too.
|
|
53
|
+
- `CHANGELOG.md` — add a section for the new version, directly under the `# CHANGELOG` heading.
|
|
54
|
+
Sections are newest first.
|
|
55
|
+
|
|
56
|
+
Label the pull request `skip-changelog`. It carries no change of its own, and without the label it
|
|
57
|
+
shows up in the next release's list — that is why 4.1.0's changelog contains a `Version 4.1.0`
|
|
58
|
+
entry.
|
|
59
|
+
|
|
60
|
+
`rake gem:changelog` lists the pull requests merged since the last release, already formatted:
|
|
27
61
|
|
|
28
62
|
```console
|
|
29
|
-
$ bundle exec rake
|
|
63
|
+
$ bundle exec rake gem:changelog | pbcopy
|
|
30
64
|
```
|
|
31
65
|
|
|
32
|
-
|
|
66
|
+
Where it starts follows `RBS::VERSION`, so bump the version first: a prerelease starts from the
|
|
67
|
+
latest tag, and a release proper skips the prerelease tags and starts from the previous release
|
|
68
|
+
proper. Pass a version to override it (`rake 'gem:changelog[4.1.0]'`). Only the list goes to
|
|
69
|
+
STDOUT, so it pipes cleanly. Pull requests labeled `skip-changelog` are left out and reported on
|
|
70
|
+
STDERR, and pull requests that only touch `rust/` are left out because the crates have their own
|
|
71
|
+
release cycle.
|
|
33
72
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
- runs `release:note`, which opens a GitHub **draft** release (with
|
|
38
|
-
`--prerelease` for `*.pre.*` versions) and prints the remaining manual steps.
|
|
73
|
+
On a release proper, the `X.Y.Z.pre.N` sections above the previous release are replaced by the one
|
|
74
|
+
section being written — their pull requests are in it, and the notes they were published with stay
|
|
75
|
+
on their own GitHub releases.
|
|
39
76
|
|
|
40
|
-
|
|
77
|
+
Sort the list into the sections below. `rake gem:changelog:json` prints the same pull requests with
|
|
78
|
+
the changed files, labels, and body of each, which is what the sorting is based on.
|
|
41
79
|
|
|
42
|
-
|
|
80
|
+
```markdown
|
|
81
|
+
## X.Y.Z (YYYY-MM-DD)
|
|
43
82
|
|
|
44
|
-
|
|
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 .
|
|
83
|
+
### Signature updates
|
|
47
84
|
|
|
48
|
-
|
|
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
|
|
85
|
+
### Language updates
|
|
52
86
|
|
|
53
|
-
|
|
87
|
+
### Library changes
|
|
88
|
+
|
|
89
|
+
#### rbs prototype
|
|
90
|
+
|
|
91
|
+
#### rbs collection
|
|
92
|
+
|
|
93
|
+
### Miscellaneous
|
|
54
94
|
```
|
|
55
95
|
|
|
56
|
-
|
|
96
|
+
The sections always appear in this order; delete the ones that end up empty, which is most of them
|
|
97
|
+
on a small release. Two things scale with the size of the release:
|
|
98
|
+
|
|
99
|
+
- **Summary paragraphs**, above the first section. A patch release usually has none, 4.1.0 has four
|
|
100
|
+
paragraphs, and 4.0.0 has nine.
|
|
101
|
+
- **A list of the types whose signatures changed**, as the first line of `### Signature updates`,
|
|
102
|
+
written as `**Updated classes/modules/methods:**` followed by the names in backticks. Used on
|
|
103
|
+
`X.Y.0` releases only.
|
|
104
|
+
|
|
105
|
+
The date is the day the gem is released, matching the `vX.Y.Z` tag — not the day this pull request
|
|
106
|
+
is opened. Fix it up before step 2 if the pull request sat for a few days.
|
|
107
|
+
|
|
108
|
+
### 2. Run the `Release gems` workflow
|
|
109
|
+
|
|
110
|
+
Once the pull request is merged, dispatch
|
|
111
|
+
[`release-gems.yml`](../.github/workflows/release-gems.yml) from the Actions tab with two inputs:
|
|
112
|
+
|
|
113
|
+
| Input | Value |
|
|
114
|
+
| --- | --- |
|
|
115
|
+
| `commit` | The full 40-character SHA of the merge commit, taken from the merged pull request |
|
|
116
|
+
| `version` | `X.Y.Z`, without the leading `v` |
|
|
117
|
+
|
|
118
|
+
The ref selector picks which copy of the workflow file runs, not what gets released — leave it on
|
|
119
|
+
`master`. Everything is built from `commit`, so the run is unaffected by whatever lands on `master`
|
|
120
|
+
in the meantime, and a patch release cut from a release branch is dispatched the same way as any
|
|
121
|
+
other: the workflow does not care which branch the commit is on.
|
|
122
|
+
|
|
123
|
+
The two inputs say the same thing twice, once as a commit and once as a name, and the run stops
|
|
124
|
+
before anything is built unless they agree with each other and with the repository:
|
|
125
|
+
|
|
126
|
+
- `commit` has to be a full SHA that some branch contains,
|
|
127
|
+
- `version` has to be the `RBS::VERSION` that commit declares,
|
|
128
|
+
- CHANGELOG.md has to start with a section for `version` (skipped for `.dev.N`, which is not
|
|
129
|
+
written up),
|
|
130
|
+
- `vX.Y.Z` must not exist yet.
|
|
131
|
+
|
|
132
|
+
It then:
|
|
133
|
+
|
|
134
|
+
- builds `rbs-X.Y.Z.gem`,
|
|
135
|
+
- compiles `rbs_parser.wasm` and builds `rbs-X.Y.Z-java.gem`,
|
|
136
|
+
- checks both: platforms, the C extension on one and its absence on the other, and that the wasm
|
|
137
|
+
module made it into the `java` gem,
|
|
138
|
+
- installs the `java` gem on JRuby and parses with it, so the WebAssembly runtime is exercised
|
|
139
|
+
before anything is published,
|
|
140
|
+
- uploads both gems as an artifact,
|
|
141
|
+
- tags `commit` as `vX.Y.Z` and pushes the tag,
|
|
142
|
+
- pushes both gems to RubyGems through trusted publishing,
|
|
143
|
+
- publishes the GitHub release with the notes from CHANGELOG.md, skipping this last step for
|
|
144
|
+
`.dev.N` versions.
|
|
145
|
+
|
|
146
|
+
The tag is created once both gems are known to build and run, and before anything is published: a
|
|
147
|
+
tag can be deleted, while a version pushed to RubyGems can only be yanked.
|
|
148
|
+
|
|
149
|
+
Checking the `dry_run` box runs everything up to the artifact and stops — no tag, no gems pushed,
|
|
150
|
+
no release — which is how the build is exercised without releasing. `version` still has to match
|
|
151
|
+
the commit, so a dry run is also how a release is rehearsed before it is cut.
|
|
152
|
+
|
|
153
|
+
## The version on `master`
|
|
154
|
+
|
|
155
|
+
`RBS::VERSION` on `master` is read one of two ways, told apart by how the version ends:
|
|
156
|
+
|
|
157
|
+
| On `master` | Means |
|
|
158
|
+
| --- | --- |
|
|
159
|
+
| `X.Y.0.dev` — a bare `.dev` | `X.Y.0` is being developed |
|
|
160
|
+
| A complete version — `X.Y.Z`, `X.Y.Z.pre.N`, `X.Y.Z.dev.N` | The version *after* the one named is being developed |
|
|
161
|
+
|
|
162
|
+
So `4.1.1` on `master` is not a claim that `master` is 4.1.1. It says 4.1.1 has shipped and what
|
|
163
|
+
comes after it is being worked on. `4.1.2.dev.1` says the same thing about itself: that release is
|
|
164
|
+
out, and the line continues towards 4.1.2.
|
|
165
|
+
|
|
166
|
+
Both become true the moment the release is tagged, so **nothing has to be done to `master` after a
|
|
167
|
+
release**. `4.0.1` was followed by `4.0.2` with no version change in between, and `4.1.2.dev.1` is
|
|
168
|
+
what `master` carries today.
|
|
169
|
+
|
|
170
|
+
The bare `X.Y.0.dev` is the exception because it is the one version that names a target rather than
|
|
171
|
+
a predecessor: a new minor is developed towards `X.Y.0` for a long time, before it is known whether
|
|
172
|
+
the next thing to ship is `X.Y.0.pre.1` or `X.Y.0` itself. Setting it is the only version change
|
|
173
|
+
that has to be made deliberately.
|
|
174
|
+
|
|
175
|
+
`rake gem:changelog` reads `RBS::VERSION` too, to decide where the next changelog starts — but the
|
|
176
|
+
version is set to the one being released before the changelog is generated, so it sees that rather
|
|
177
|
+
than whatever `master` was carrying.
|
|
178
|
+
|
|
179
|
+
## Starting a new minor
|
|
180
|
+
|
|
181
|
+
`master` is the development line of one minor at a time. Moving it from `X.Y` to `X.(Y+1)` is not
|
|
182
|
+
part of any one release — it is the decision that the `X.Y` line is done, taken whenever that
|
|
183
|
+
becomes true — and it is the one moment the version on `master` is changed by hand. Two changes, in
|
|
184
|
+
opposite places:
|
|
185
|
+
|
|
186
|
+
1. **Branch the line being left behind**, from the last `master` commit that belongs to it:
|
|
187
|
+
|
|
188
|
+
```console
|
|
189
|
+
$ git switch --create aaa-X.Y.x <that commit>
|
|
190
|
+
$ git push -u origin aaa-X.Y.x
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Branch from the commit *before* the bump below, so the branch keeps the version its line was
|
|
194
|
+
released under. Patch releases of `X.Y` are cut from here from now on, with their changes
|
|
195
|
+
cherry-picked from `master` — see [Backports](#backports). The `aaa-` prefix carries no meaning
|
|
196
|
+
beyond sorting the release branches to the top of the branch list.
|
|
197
|
+
|
|
198
|
+
2. **Bump `master`** to `X.(Y+1).0.dev`, in a pull request with `Gemfile.lock` regenerated and
|
|
199
|
+
labeled `skip-changelog` like the release pull request itself. `4.1` was started exactly this
|
|
200
|
+
way: `aaa-4.0.x` was branched at the commit before `Start 4.1 development`, which set
|
|
201
|
+
`RBS::VERSION` to `4.1.0.dev`.
|
|
202
|
+
|
|
203
|
+
Two loose ends that are easy to forget:
|
|
204
|
+
|
|
205
|
+
- **The release note of the new line.** `rake gem:gh_release` links every published release to
|
|
206
|
+
`https://github.com/ruby/rbs/wiki/Release-Note-X.Y`, built from the version number without
|
|
207
|
+
checking that the page is there. Nothing has to be written when the line starts — the page comes
|
|
208
|
+
together as the first release proper of the line comes into view — but it does have to exist by
|
|
209
|
+
the time that release is published, or its notes link to an empty page.
|
|
210
|
+
- **Release branches that are done.** A branch is worth keeping only while its line might still
|
|
211
|
+
get a patch. The ones that exist do not cover every line that ever had one — `3.8.1` shipped and
|
|
212
|
+
there is no `aaa-3.8.x` — so this is housekeeping rather than a rule, but starting a new minor is
|
|
213
|
+
the natural moment to look at the bottom of the branch list and delete what has been superseded.
|
|
214
|
+
|
|
215
|
+
## Backports
|
|
216
|
+
|
|
217
|
+
A patch release is cut from a release branch (`aaa-X.Y.x`), and what it carries beyond the previous
|
|
218
|
+
release is cherry-picked from the development line. Cherry-pick with `-x`:
|
|
57
219
|
|
|
58
220
|
```console
|
|
59
|
-
$
|
|
60
|
-
'gem install /pkg/rbs-X.Y.Z-java.gem && ruby -e "require %q{rbs}; puts [RUBY_ENGINE, RBS::VERSION].join(%q{ })"'
|
|
221
|
+
$ git cherry-pick -x <commit>
|
|
61
222
|
```
|
|
62
223
|
|
|
224
|
+
`-x` records the commit the change was copied from, and that recorded line is what `rake
|
|
225
|
+
gem:changelog` follows to reach the pull request the change was written and reviewed in. Without
|
|
226
|
+
it, the only pull request a backported commit is associated with is the one that carried the
|
|
227
|
+
backport, which says nothing about the change and is the same for every commit it brought over —
|
|
228
|
+
that is why the 4.0.3 changelog credits its three entries to the same pull request.
|
|
229
|
+
|
|
63
230
|
## Notes
|
|
64
231
|
|
|
65
232
|
- Prereleases (`X.Y.Z.pre.N`) are only installed with `gem install rbs --pre`;
|
|
66
233
|
a plain `gem install rbs` is unaffected. On JRuby, `gem install rbs [--pre]`
|
|
67
234
|
resolves to the `-java` gem automatically.
|
|
68
|
-
- The
|
|
69
|
-
`
|
|
235
|
+
- The WASI SDK version is pinned in `wasm.yml`, `jruby.yml`, `release-gems.yml`, and
|
|
236
|
+
`Dockerfile.jruby`, each carrying its own copy. Keep them in sync when bumping. The
|
|
237
|
+
Chicory/ASM versions are not duplicated: they are the `jar` requirements in
|
|
238
|
+
`rbs.gemspec`, which is where the workflow, `Dockerfile.jruby` and `gem install` all
|
|
239
|
+
read them from.
|
|
240
|
+
- `rake 'gem:check_release[X.Y.Z]'` and `rake gem:tag` are what the workflow runs to
|
|
241
|
+
check the release and to create the tag. Both work locally, which is the fallback
|
|
242
|
+
if the tag ever has to be created by hand.
|
|
243
|
+
- Those two tasks and `rake gem:gh_release` come from the Rakefile of the commit
|
|
244
|
+
being released, not from the branch the workflow was dispatched from. Releasing
|
|
245
|
+
from a release branch (`aaa-X.Y.x`) therefore needs the release tooling on that
|
|
246
|
+
branch as well; without it the run fails on the missing task, before publishing
|
|
247
|
+
anything.
|
data/include/rbs/ast.h
CHANGED
|
@@ -583,7 +583,7 @@ typedef struct rbs_ast_ruby_annotations_class_alias_annotation {
|
|
|
583
583
|
|
|
584
584
|
rbs_location_range prefix_location;
|
|
585
585
|
rbs_location_range keyword_location;
|
|
586
|
-
struct rbs_type_name *
|
|
586
|
+
struct rbs_type_name *RBS_NULLABLE type_name;
|
|
587
587
|
rbs_location_range type_name_location;
|
|
588
588
|
} rbs_ast_ruby_annotations_class_alias_annotation_t;
|
|
589
589
|
|
|
@@ -631,7 +631,7 @@ typedef struct rbs_ast_ruby_annotations_module_alias_annotation {
|
|
|
631
631
|
|
|
632
632
|
rbs_location_range prefix_location;
|
|
633
633
|
rbs_location_range keyword_location;
|
|
634
|
-
struct rbs_type_name *
|
|
634
|
+
struct rbs_type_name *RBS_NULLABLE type_name;
|
|
635
635
|
rbs_location_range type_name_location;
|
|
636
636
|
} rbs_ast_ruby_annotations_module_alias_annotation_t;
|
|
637
637
|
|
|
@@ -998,12 +998,12 @@ rbs_ast_members_prepend_t *RBS_NONNULL rbs_ast_members_prepend_new(rbs_allocator
|
|
|
998
998
|
rbs_ast_members_private_t *RBS_NONNULL rbs_ast_members_private_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location);
|
|
999
999
|
rbs_ast_members_public_t *RBS_NONNULL rbs_ast_members_public_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location);
|
|
1000
1000
|
rbs_ast_ruby_annotations_block_param_type_annotation_t *RBS_NONNULL rbs_ast_ruby_annotations_block_param_type_annotation_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_location_range prefix_location, rbs_location_range ampersand_location, rbs_location_range name_location, rbs_location_range colon_location, rbs_location_range question_location, rbs_location_range type_location, rbs_node_t *RBS_NONNULL type_, rbs_location_range comment_location);
|
|
1001
|
-
rbs_ast_ruby_annotations_class_alias_annotation_t *RBS_NONNULL rbs_ast_ruby_annotations_class_alias_annotation_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_location_range prefix_location, rbs_location_range keyword_location, rbs_type_name_t *
|
|
1001
|
+
rbs_ast_ruby_annotations_class_alias_annotation_t *RBS_NONNULL rbs_ast_ruby_annotations_class_alias_annotation_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_location_range prefix_location, rbs_location_range keyword_location, rbs_type_name_t *RBS_NULLABLE type_name, rbs_location_range type_name_location);
|
|
1002
1002
|
rbs_ast_ruby_annotations_colon_method_type_annotation_t *RBS_NONNULL rbs_ast_ruby_annotations_colon_method_type_annotation_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_location_range prefix_location, rbs_node_list_t *RBS_NONNULL annotations, rbs_node_t *RBS_NONNULL method_type);
|
|
1003
1003
|
rbs_ast_ruby_annotations_double_splat_param_type_annotation_t *RBS_NONNULL rbs_ast_ruby_annotations_double_splat_param_type_annotation_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_location_range prefix_location, rbs_location_range star2_location, rbs_location_range name_location, rbs_location_range colon_location, rbs_node_t *RBS_NONNULL param_type, rbs_location_range comment_location);
|
|
1004
1004
|
rbs_ast_ruby_annotations_instance_variable_annotation_t *RBS_NONNULL rbs_ast_ruby_annotations_instance_variable_annotation_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_location_range prefix_location, rbs_ast_symbol_t *RBS_NONNULL ivar_name, rbs_location_range ivar_name_location, rbs_location_range colon_location, rbs_node_t *RBS_NONNULL type, rbs_location_range comment_location);
|
|
1005
1005
|
rbs_ast_ruby_annotations_method_types_annotation_t *RBS_NONNULL rbs_ast_ruby_annotations_method_types_annotation_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_location_range prefix_location, rbs_node_list_t *RBS_NONNULL overloads, rbs_location_range_list_t *RBS_NONNULL vertical_bar_locations, rbs_location_range dot3_location);
|
|
1006
|
-
rbs_ast_ruby_annotations_module_alias_annotation_t *RBS_NONNULL rbs_ast_ruby_annotations_module_alias_annotation_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_location_range prefix_location, rbs_location_range keyword_location, rbs_type_name_t *
|
|
1006
|
+
rbs_ast_ruby_annotations_module_alias_annotation_t *RBS_NONNULL rbs_ast_ruby_annotations_module_alias_annotation_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_location_range prefix_location, rbs_location_range keyword_location, rbs_type_name_t *RBS_NULLABLE type_name, rbs_location_range type_name_location);
|
|
1007
1007
|
rbs_ast_ruby_annotations_module_self_annotation_t *RBS_NONNULL rbs_ast_ruby_annotations_module_self_annotation_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_location_range prefix_location, rbs_location_range keyword_location, rbs_location_range colon_location, rbs_type_name_t *RBS_NONNULL name, rbs_node_list_t *RBS_NONNULL args, rbs_location_range open_bracket_location, rbs_location_range close_bracket_location, rbs_location_range_list_t *RBS_NONNULL args_comma_locations, rbs_location_range comment_location);
|
|
1008
1008
|
rbs_ast_ruby_annotations_node_type_assertion_t *RBS_NONNULL rbs_ast_ruby_annotations_node_type_assertion_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_location_range prefix_location, rbs_node_t *RBS_NONNULL type);
|
|
1009
1009
|
rbs_ast_ruby_annotations_param_type_annotation_t *RBS_NONNULL rbs_ast_ruby_annotations_param_type_annotation_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_location_range prefix_location, rbs_location_range name_location, rbs_location_range colon_location, rbs_node_t *RBS_NONNULL param_type, rbs_location_range comment_location);
|
data/lib/rbs/version.rb
CHANGED
data/src/ast.c
CHANGED
|
@@ -913,7 +913,7 @@ rbs_ast_ruby_annotations_block_param_type_annotation_t *RBS_NONNULL rbs_ast_ruby
|
|
|
913
913
|
return instance;
|
|
914
914
|
}
|
|
915
915
|
#line 140 "templates/src/ast.c.erb"
|
|
916
|
-
rbs_ast_ruby_annotations_class_alias_annotation_t *RBS_NONNULL rbs_ast_ruby_annotations_class_alias_annotation_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_location_range prefix_location, rbs_location_range keyword_location, rbs_type_name_t *
|
|
916
|
+
rbs_ast_ruby_annotations_class_alias_annotation_t *RBS_NONNULL rbs_ast_ruby_annotations_class_alias_annotation_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_location_range prefix_location, rbs_location_range keyword_location, rbs_type_name_t *RBS_NULLABLE type_name, rbs_location_range type_name_location) {
|
|
917
917
|
rbs_ast_ruby_annotations_class_alias_annotation_t *instance = rbs_allocator_alloc(allocator, rbs_ast_ruby_annotations_class_alias_annotation_t);
|
|
918
918
|
|
|
919
919
|
*instance = (rbs_ast_ruby_annotations_class_alias_annotation_t) {
|
|
@@ -1001,7 +1001,7 @@ rbs_ast_ruby_annotations_method_types_annotation_t *RBS_NONNULL rbs_ast_ruby_ann
|
|
|
1001
1001
|
return instance;
|
|
1002
1002
|
}
|
|
1003
1003
|
#line 140 "templates/src/ast.c.erb"
|
|
1004
|
-
rbs_ast_ruby_annotations_module_alias_annotation_t *RBS_NONNULL rbs_ast_ruby_annotations_module_alias_annotation_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_location_range prefix_location, rbs_location_range keyword_location, rbs_type_name_t *
|
|
1004
|
+
rbs_ast_ruby_annotations_module_alias_annotation_t *RBS_NONNULL rbs_ast_ruby_annotations_module_alias_annotation_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_location_range prefix_location, rbs_location_range keyword_location, rbs_type_name_t *RBS_NULLABLE type_name, rbs_location_range type_name_location) {
|
|
1005
1005
|
rbs_ast_ruby_annotations_module_alias_annotation_t *instance = rbs_allocator_alloc(allocator, rbs_ast_ruby_annotations_module_alias_annotation_t);
|
|
1006
1006
|
|
|
1007
1007
|
*instance = (rbs_ast_ruby_annotations_module_alias_annotation_t) {
|
data/src/parser.c
CHANGED
|
@@ -405,18 +405,21 @@ NODISCARD
|
|
|
405
405
|
static bool parse_keyword_key(rbs_parser_t *parser, rbs_ast_symbol_t **key) {
|
|
406
406
|
rbs_parser_advance(parser);
|
|
407
407
|
|
|
408
|
-
|
|
408
|
+
rbs_range_t symbol_range = parser->current_token.range;
|
|
409
409
|
|
|
410
410
|
if (parser->next_token.type == pQUESTION) {
|
|
411
|
+
// The `?` is part of the key, so it is part of the location too.
|
|
412
|
+
symbol_range.end = parser->next_token.range.end;
|
|
413
|
+
|
|
411
414
|
*key = rbs_ast_symbol_new(
|
|
412
415
|
ALLOCATOR(),
|
|
413
|
-
symbol_range,
|
|
416
|
+
RBS_RANGE_LEX2AST(symbol_range),
|
|
414
417
|
&parser->constant_pool,
|
|
415
418
|
intern_token_start_end(parser, parser->current_token, parser->next_token)
|
|
416
419
|
);
|
|
417
420
|
rbs_parser_advance(parser);
|
|
418
421
|
} else {
|
|
419
|
-
*key = rbs_ast_symbol_new(ALLOCATOR(), symbol_range, &parser->constant_pool, INTERN_TOKEN(parser, parser->current_token));
|
|
422
|
+
*key = rbs_ast_symbol_new(ALLOCATOR(), RBS_RANGE_LEX2AST(symbol_range), &parser->constant_pool, INTERN_TOKEN(parser, parser->current_token));
|
|
420
423
|
}
|
|
421
424
|
|
|
422
425
|
return true;
|
data/wasm/README.md
CHANGED
|
@@ -27,6 +27,39 @@ $ rake wasm:install_jars # download the Chicory/ASM jars into ~/.m2 (run on JRub
|
|
|
27
27
|
|
|
28
28
|
The compiled `rbs_parser.wasm` is a build artifact and is not checked in.
|
|
29
29
|
|
|
30
|
+
The WASI SDK is needed for the *build*, not for running the result — the host clang already
|
|
31
|
+
knows the `wasm32` target, but there is no wasm32 libc on a normal machine, so it picks up the
|
|
32
|
+
host headers and fails on the first `#include`. That is what the SDK supplies, along with the
|
|
33
|
+
builtins the link step needs.
|
|
34
|
+
|
|
35
|
+
## Running the suite on JRuby
|
|
36
|
+
|
|
37
|
+
[`Dockerfile.jruby`](../Dockerfile.jruby) builds an image that has everything this needs, so no
|
|
38
|
+
JRuby, JDK or WASI SDK has to be installed to work on the JRuby side:
|
|
39
|
+
|
|
40
|
+
```console
|
|
41
|
+
$ docker build -f Dockerfile.jruby -t rbs-jruby .
|
|
42
|
+
$ docker run --rm rbs-jruby # run the test suite
|
|
43
|
+
$ docker run --rm -e RBS_PLATFORM=java rbs-jruby \
|
|
44
|
+
gem build rbs.gemspec # build the -java gem
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Two things in it are not obvious:
|
|
48
|
+
|
|
49
|
+
- `build-essential` is for prism, which builds `libprism.so` and loads it through FFI on JRuby
|
|
50
|
+
rather than as an MRI C extension. It needs `cc` and `make`.
|
|
51
|
+
- Bundler is skipped. The development `Gemfile` pulls in CRuby-only C extensions (bigdecimal,
|
|
52
|
+
stackprof, …) that cannot build on JRuby, so the few gems the suite needs are installed
|
|
53
|
+
directly, in the same set as [`jruby.yml`](../.github/workflows/jruby.yml).
|
|
54
|
+
|
|
55
|
+
The image compiles `rbs_parser.wasm` itself, which is why it carries the WASI SDK. That is not
|
|
56
|
+
the only arrangement: the build needs the SDK but not JRuby, and running the suite needs JRuby
|
|
57
|
+
but not the SDK, so `jruby.yml` splits them instead — it compiles the module on CRuby and then
|
|
58
|
+
switches engines to test against the result.
|
|
59
|
+
|
|
60
|
+
`rake wasm:install_jars` is the step that has to be on JRuby either way: it resolves the `jar`
|
|
61
|
+
requirements from `rbs.gemspec` through the JVM.
|
|
62
|
+
|
|
30
63
|
## Exported functions
|
|
31
64
|
|
|
32
65
|
The module is built as a "reactor": it has no `main`, and the host calls
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rbs
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 4.1.
|
|
4
|
+
version: 4.1.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Soutaro Matsumoto
|
|
@@ -70,7 +70,7 @@ files:
|
|
|
70
70
|
- ".github/workflows/comments.yml"
|
|
71
71
|
- ".github/workflows/dependabot.yml"
|
|
72
72
|
- ".github/workflows/jruby.yml"
|
|
73
|
-
- ".github/workflows/
|
|
73
|
+
- ".github/workflows/release-gems.yml"
|
|
74
74
|
- ".github/workflows/ruby.yml"
|
|
75
75
|
- ".github/workflows/rust.yml"
|
|
76
76
|
- ".github/workflows/truffleruby.yml"
|
|
@@ -649,7 +649,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
649
649
|
- !ruby/object:Gem::Version
|
|
650
650
|
version: '0'
|
|
651
651
|
requirements: []
|
|
652
|
-
rubygems_version: 4.0.
|
|
652
|
+
rubygems_version: 4.0.17
|
|
653
653
|
specification_version: 4
|
|
654
654
|
summary: Type signature for Ruby.
|
|
655
655
|
test_files: []
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
name: Check milestone
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
pull_request:
|
|
5
|
-
types: [opened, edited, labeled, unlabeled, milestoned, demilestoned, synchronize]
|
|
6
|
-
merge_group: {}
|
|
7
|
-
|
|
8
|
-
permissions:
|
|
9
|
-
contents: read
|
|
10
|
-
|
|
11
|
-
jobs:
|
|
12
|
-
check:
|
|
13
|
-
runs-on: ubuntu-latest
|
|
14
|
-
|
|
15
|
-
steps:
|
|
16
|
-
# The milestone is a property of the pull request, so there is nothing to
|
|
17
|
-
# check once it enters the merge queue. This job still has to run there
|
|
18
|
-
# because `check` is a required status check -- it just reports success
|
|
19
|
-
# without doing anything.
|
|
20
|
-
- uses: actions/checkout@v7
|
|
21
|
-
if: github.event_name == 'pull_request'
|
|
22
|
-
|
|
23
|
-
- name: Extract RBS::Version
|
|
24
|
-
id: version
|
|
25
|
-
if: github.event_name == 'pull_request'
|
|
26
|
-
run: |
|
|
27
|
-
# Extract version string from lib/rbs/version.rb
|
|
28
|
-
version=$(ruby -e 'load "lib/rbs/version.rb"; print RBS::VERSION')
|
|
29
|
-
echo "version=$version" >> "$GITHUB_OUTPUT"
|
|
30
|
-
|
|
31
|
-
# Parse major.minor.patch
|
|
32
|
-
IFS='.' read -r major minor patch _rest <<< "$version"
|
|
33
|
-
echo "major=$major" >> "$GITHUB_OUTPUT"
|
|
34
|
-
echo "minor=$minor" >> "$GITHUB_OUTPUT"
|
|
35
|
-
echo "patch=$patch" >> "$GITHUB_OUTPUT"
|
|
36
|
-
|
|
37
|
-
echo "RBS::VERSION = $version (major=$major, minor=$minor, patch=$patch)"
|
|
38
|
-
|
|
39
|
-
- name: Check milestone
|
|
40
|
-
if: github.event_name == 'pull_request'
|
|
41
|
-
uses: actions/github-script@v9
|
|
42
|
-
with:
|
|
43
|
-
script: |
|
|
44
|
-
const pr = context.payload.pull_request;
|
|
45
|
-
const milestone = pr.milestone;
|
|
46
|
-
const labels = pr.labels.map(l => l.name);
|
|
47
|
-
|
|
48
|
-
const version = '${{ steps.version.outputs.version }}';
|
|
49
|
-
const major = '${{ steps.version.outputs.major }}';
|
|
50
|
-
const minor = '${{ steps.version.outputs.minor }}';
|
|
51
|
-
const patch = parseInt('${{ steps.version.outputs.patch }}', 10);
|
|
52
|
-
|
|
53
|
-
if (!milestone) {
|
|
54
|
-
if (labels.includes('no-milestone')) {
|
|
55
|
-
core.info('No milestone set, but no-milestone label is present — OK');
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
core.setFailed(
|
|
59
|
-
'No milestone set. Add a milestone or add the "no-milestone" label.'
|
|
60
|
-
);
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
if (labels.includes('no-milestone')) {
|
|
65
|
-
core.setFailed(
|
|
66
|
-
'Milestone is set but "no-milestone" label is present. Remove the label or the milestone.'
|
|
67
|
-
);
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
const milestoneName = milestone.title;
|
|
72
|
-
core.info(`Milestone: "${milestoneName}", RBS::VERSION: ${version}`);
|
|
73
|
-
|
|
74
|
-
// Expected milestone based on version:
|
|
75
|
-
// patch == 0 → "RBS major.minor" (e.g. "RBS 4.0")
|
|
76
|
-
// patch >= 1 → "RBS major.minor.x" (e.g. "RBS 4.0.x")
|
|
77
|
-
let expectedMilestone;
|
|
78
|
-
if (patch === 0) {
|
|
79
|
-
expectedMilestone = `RBS ${major}.${minor}`;
|
|
80
|
-
} else {
|
|
81
|
-
expectedMilestone = `RBS ${major}.${minor}.x`;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
if (milestoneName !== expectedMilestone) {
|
|
85
|
-
core.setFailed(
|
|
86
|
-
`Milestone "${milestoneName}" does not match RBS::VERSION ${version}. ` +
|
|
87
|
-
`Expected milestone: "${expectedMilestone}"`
|
|
88
|
-
);
|
|
89
|
-
} else {
|
|
90
|
-
core.info(`Milestone "${milestoneName}" matches RBS::VERSION ${version}`);
|
|
91
|
-
}
|