rbs 4.1.3-java → 4.2.0.pre.1-java
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/.gitattributes +1 -0
- data/.github/workflows/bundle-update.yml +2 -2
- data/.github/workflows/c-check.yml +2 -2
- data/.github/workflows/changelog.yml +121 -0
- data/.github/workflows/comments.yml +2 -2
- data/.github/workflows/dependabot.yml +1 -1
- data/.github/workflows/jruby.yml +3 -3
- data/.github/workflows/release-gems.yml +6 -7
- data/.github/workflows/ruby.yml +6 -6
- data/.github/workflows/rust.yml +12 -12
- data/.github/workflows/truffleruby.yml +2 -2
- data/.github/workflows/typecheck.yml +2 -2
- data/.github/workflows/wasm.yml +3 -3
- data/.github/workflows/windows.yml +2 -2
- data/CHANGELOG.md +27 -0
- data/Rakefile +50 -21
- data/config.yml +5 -0
- data/docs/CONTRIBUTING.md +1 -1
- data/docs/release.md +57 -1
- data/docs/stdlib.md +8 -0
- data/docs/syntax.md +12 -0
- data/ext/rbs_extension/ast_translation.c +15 -0
- data/ext/rbs_extension/class_constants.c +2 -0
- data/ext/rbs_extension/class_constants.h +1 -0
- data/ext/rbs_extension/main.c +55 -19
- data/include/rbs/ast.h +21 -13
- data/include/rbs/defines.h +2 -2
- data/include/rbs/lexer.h +13 -12
- data/include/rbs/parser.h +37 -3
- data/lib/rbs/ast/declarations.rb +1 -1
- data/lib/rbs/ast/type_param.rb +1 -1
- data/lib/rbs/definition_builder/ancestor_builder.rb +8 -5
- data/lib/rbs/definition_builder/method_builder.rb +4 -4
- data/lib/rbs/definition_builder.rb +5 -2
- data/lib/rbs/environment/class_entry.rb +12 -0
- data/lib/rbs/environment/module_entry.rb +26 -1
- data/lib/rbs/parser_aux.rb +2 -2
- data/lib/rbs/types.rb +44 -2
- data/lib/rbs/version.rb +1 -1
- data/lib/rbs/wasm/parser.rb +62 -25
- data/lib/rbs/wasm/rbs_parser.wasm +0 -0
- data/lib/rbs/wasm/runtime.rb +19 -4
- data/lib/rbs/wasm/serialization_schema.rb +3 -2
- data/schema/function.json +12 -1
- data/sig/environment/class_entry.rbs +6 -0
- data/sig/environment/module_entry.rbs +15 -0
- data/sig/parser.rbs +4 -4
- data/sig/types.rbs +11 -1
- data/src/ast.c +17 -1
- data/src/lexer.c +1562 -1560
- data/src/lexer.re +50 -18
- data/src/lexstate.c +2 -1
- data/src/parser.c +130 -70
- data/src/serialize.c +20 -13
- data/src/util/rbs_encoding.c +195 -49
- data/wasm/README.md +20 -4
- data/wasm/rbs_wasm.c +93 -37
- metadata +3 -1
data/docs/release.md
CHANGED
|
@@ -77,6 +77,10 @@ on their own GitHub releases.
|
|
|
77
77
|
Sort the list into the sections below. `rake gem:changelog:json` prints the same pull requests with
|
|
78
78
|
the changed files, labels, and body of each, which is what the sorting is based on.
|
|
79
79
|
|
|
80
|
+
Both tasks reach GitHub through `gh`, which a Claude Code on the web session cannot do. See
|
|
81
|
+
[Assembling the changelog without `gh`](#assembling-the-changelog-without-gh), which runs them on a
|
|
82
|
+
runner instead.
|
|
83
|
+
|
|
80
84
|
```markdown
|
|
81
85
|
## X.Y.Z (YYYY-MM-DD)
|
|
82
86
|
|
|
@@ -97,7 +101,8 @@ The sections always appear in this order; delete the ones that end up empty, whi
|
|
|
97
101
|
on a small release. Two things scale with the size of the release:
|
|
98
102
|
|
|
99
103
|
- **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.
|
|
104
|
+
paragraphs, and 4.0.0 has nine. A prerelease has none whatever its size: the cycle it belongs to
|
|
105
|
+
is summarized once, on the release proper that folds it in.
|
|
101
106
|
- **A list of the types whose signatures changed**, as the first line of `### Signature updates`,
|
|
102
107
|
written as `**Updated classes/modules/methods:**` followed by the names in backticks. Used on
|
|
103
108
|
`X.Y.0` releases only.
|
|
@@ -195,6 +200,11 @@ opposite places:
|
|
|
195
200
|
cherry-picked from `master` — see [Backports](#backports). The `aaa-` prefix carries no meaning
|
|
196
201
|
beyond sorting the release branches to the top of the branch list.
|
|
197
202
|
|
|
203
|
+
The branch carries its own release tooling, since that is read from the ref rather than from
|
|
204
|
+
`master`: the `gem:` tasks, and `changelog.yml` for the changelog. Branching from `master`
|
|
205
|
+
brings both along; what needs watching is a later change to either, which reaches this line
|
|
206
|
+
only if it is cherry-picked here too.
|
|
207
|
+
|
|
198
208
|
2. **Bump `master`** to `X.(Y+1).0.dev`, in a pull request with `Gemfile.lock` regenerated and
|
|
199
209
|
labeled `skip-changelog` like the release pull request itself. `4.1` was started exactly this
|
|
200
210
|
way: `aaa-4.0.x` was branched at the commit before `Start 4.1 development`, which set
|
|
@@ -227,6 +237,52 @@ it, the only pull request a backported commit is associated with is the one that
|
|
|
227
237
|
backport, which says nothing about the change and is the same for every commit it brought over —
|
|
228
238
|
that is why the 4.0.3 changelog credits its three entries to the same pull request.
|
|
229
239
|
|
|
240
|
+
The entry names that pull request and adds the one that carried the backport:
|
|
241
|
+
|
|
242
|
+
```markdown
|
|
243
|
+
* {title} ([#{original}](https://github.com/ruby/rbs/pull/{original}), Backported in [#{backport}](https://github.com/ruby/rbs/pull/{backport}))
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
`gem:changelog` prints this form on its own, from the same `-x` trailer: the origin it resolves is
|
|
247
|
+
the first link, and the pull request of the cherry-pick in front of it is the second. On the
|
|
248
|
+
development line nothing is a cherry-pick, so entries there keep the plain single link.
|
|
249
|
+
|
|
250
|
+
The second link is what keeps the entry from reading as a mistake. The original pull request is
|
|
251
|
+
against `master`, so it is listed again when the development line ships — and with nothing to tell
|
|
252
|
+
the two apart, the same link under two version headings looks like a change written into the wrong
|
|
253
|
+
section. #1923 is the pair to look at: plain under 3.6.0.pre.1, annotated under 3.5.2, which
|
|
254
|
+
backported it.
|
|
255
|
+
|
|
256
|
+
## Assembling the changelog without `gh`
|
|
257
|
+
|
|
258
|
+
`gem:changelog` and `gem:changelog:json` reach GitHub through `gh`, so they cannot run from a
|
|
259
|
+
Claude Code on the web session. `api.github.com` refuses anything the shell does there, and the
|
|
260
|
+
refusal is keyed on the session rather than on the client, so installing `gh` does not help:
|
|
261
|
+
|
|
262
|
+
```console
|
|
263
|
+
$ curl -s -o /dev/null -w '%{http_code}' https://api.github.com/repos/ruby/rbs
|
|
264
|
+
403
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
Nothing else about the release is affected. `gem:check_release` and `gem:tag` read git and the
|
|
268
|
+
working tree, `gem:gh_release` runs on a runner, and git itself reaches github.com normally —
|
|
269
|
+
clone, fetch and push all work.
|
|
270
|
+
|
|
271
|
+
So the task is run where it does work. Dispatch
|
|
272
|
+
[`changelog.yml`](../.github/workflows/changelog.yml), which runs it on a runner, and read the list
|
|
273
|
+
from the run summary, the log, or the `changelog` artifact.
|
|
274
|
+
|
|
275
|
+
| Input | Value |
|
|
276
|
+
| --- | --- |
|
|
277
|
+
| The ref selector | The branch the changelog is for: `aaa-X.Y.x` for a patch release, `master` otherwise |
|
|
278
|
+
| `version` | Where the changelog starts, when that should not follow `RBS::VERSION`. It names the release before the one being written, so `4.1.2` produces the 4.1.3 changelog |
|
|
279
|
+
| `format` | `list` for the template, `json` for the pull request details the sections are sorted from |
|
|
280
|
+
|
|
281
|
+
The ref is not incidental the way it is for `release-gems.yml`: it picks the history being
|
|
282
|
+
described *and* the copy of the task that describes it. So a release branch needs `changelog.yml`
|
|
283
|
+
on it, the same way it needs the release tasks — dispatching on a ref without the file fails with
|
|
284
|
+
`Workflow does not have 'workflow_dispatch' trigger`, since the trigger is read from the ref.
|
|
285
|
+
|
|
230
286
|
## Notes
|
|
231
287
|
|
|
232
288
|
- Prereleases (`X.Y.Z.pre.N`) are only installed with `gem install rbs --pre`;
|
data/docs/stdlib.md
CHANGED
|
@@ -15,6 +15,14 @@ $ bundle exec rake 'generate:stdlib_test[String]'
|
|
|
15
15
|
Created: test/stdlib/String_test.rb
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
+
Core signatures are loaded by default. To generate a test for a class defined in standard library signatures,
|
|
19
|
+
pass the paths containing those signatures and their dependencies after the class name.
|
|
20
|
+
|
|
21
|
+
```console
|
|
22
|
+
$ bundle exec rake 'generate:stdlib_test[CSV::Row,stdlib/csv/0,stdlib/forwardable/0]'
|
|
23
|
+
Created: test/stdlib/CSV_Row_test.rb
|
|
24
|
+
```
|
|
25
|
+
|
|
18
26
|
It generates `test/stdlib/[class_name]_test.rb`.
|
|
19
27
|
The test scripts would look like the following:
|
|
20
28
|
|
data/docs/syntax.md
CHANGED
|
@@ -48,6 +48,18 @@ _proc_ ::= `^` _parameters?_ _self-type-binding?_ _block?_ `->` _type_
|
|
|
48
48
|
| `^` `(` `?` `)` `->` _type_ # Proc type with untyped parameter
|
|
49
49
|
```
|
|
50
50
|
|
|
51
|
+
`\w` above, and everywhere else in this document, is `[a-zA-Z0-9_]` together
|
|
52
|
+
with every character outside ASCII -- the same set Ruby takes into an
|
|
53
|
+
identifier. So `ServicioÚltimaVez` is a class name and `nombre_único` is an
|
|
54
|
+
alias name.
|
|
55
|
+
|
|
56
|
+
The leading character is the exception. RBS reads it to tell a class name from
|
|
57
|
+
an interface name from an alias name, so where it makes that distinction it has
|
|
58
|
+
to be ASCII: `class 日本語` is a class in Ruby but not a name RBS can write.
|
|
59
|
+
Nowhere else is restricted -- a method name, a variable name, an instance
|
|
60
|
+
variable name and a class variable name may all open with any character Ruby
|
|
61
|
+
accepts.
|
|
62
|
+
|
|
51
63
|
### Class instance type
|
|
52
64
|
|
|
53
65
|
Class instance type denotes _an instance of a class_.
|
|
@@ -1636,6 +1636,7 @@ VALUE rbs_struct_to_ruby_value(rbs_translation_context_t ctx, rbs_node_t *instan
|
|
|
1636
1636
|
VALUE arg_required_keywords = rbs_hash_to_ruby_hash(ctx, node->required_keywords);
|
|
1637
1637
|
VALUE arg_optional_keywords = rbs_hash_to_ruby_hash(ctx, node->optional_keywords);
|
|
1638
1638
|
VALUE arg_rest_keywords = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->rest_keywords); // rbs_node
|
|
1639
|
+
VALUE arg_forwarding = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->forwarding); // rbs_node
|
|
1639
1640
|
VALUE arg_return_type = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->return_type); // rbs_node
|
|
1640
1641
|
|
|
1641
1642
|
// Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
|
|
@@ -1649,9 +1650,23 @@ VALUE rbs_struct_to_ruby_value(rbs_translation_context_t ctx, rbs_node_t *instan
|
|
|
1649
1650
|
rb_hash_aset(h, ID2SYM(rb_intern("required_keywords")), arg_required_keywords);
|
|
1650
1651
|
rb_hash_aset(h, ID2SYM(rb_intern("optional_keywords")), arg_optional_keywords);
|
|
1651
1652
|
rb_hash_aset(h, ID2SYM(rb_intern("rest_keywords")), arg_rest_keywords);
|
|
1653
|
+
rb_hash_aset(h, ID2SYM(rb_intern("forwarding")), arg_forwarding);
|
|
1652
1654
|
rb_hash_aset(h, ID2SYM(rb_intern("return_type")), arg_return_type);
|
|
1653
1655
|
return CLASS_NEW_INSTANCE(RBS_Types_Function, 1, &h);
|
|
1654
1656
|
}
|
|
1657
|
+
case RBS_TYPES_FUNCTION_FORWARDING_PARAM: {
|
|
1658
|
+
rbs_types_function_forwarding_param_t *node = (rbs_types_function_forwarding_param_t *) instance;
|
|
1659
|
+
|
|
1660
|
+
// Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
|
|
1661
|
+
VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
|
|
1662
|
+
|
|
1663
|
+
// Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
|
|
1664
|
+
// Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
|
|
1665
|
+
VALUE h = ctx.reusable_kwargs_hash;
|
|
1666
|
+
rb_hash_clear(h);
|
|
1667
|
+
rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
|
|
1668
|
+
return CLASS_NEW_INSTANCE(RBS_Types_Function_ForwardingParam, 1, &h);
|
|
1669
|
+
}
|
|
1655
1670
|
case RBS_TYPES_FUNCTION_PARAM: {
|
|
1656
1671
|
rbs_types_function_param_t *node = (rbs_types_function_param_t *) instance;
|
|
1657
1672
|
|
|
@@ -79,6 +79,7 @@ VALUE RBS_Types_Block;
|
|
|
79
79
|
VALUE RBS_Types_ClassInstance;
|
|
80
80
|
VALUE RBS_Types_ClassSingleton;
|
|
81
81
|
VALUE RBS_Types_Function;
|
|
82
|
+
VALUE RBS_Types_Function_ForwardingParam;
|
|
82
83
|
VALUE RBS_Types_Function_Param;
|
|
83
84
|
VALUE RBS_Types_Interface;
|
|
84
85
|
VALUE RBS_Types_Intersection;
|
|
@@ -173,6 +174,7 @@ void rbs__init_constants(void) {
|
|
|
173
174
|
IMPORT_CONSTANT(RBS_Types_ClassInstance, RBS_Types, "ClassInstance");
|
|
174
175
|
IMPORT_CONSTANT(RBS_Types_ClassSingleton, RBS_Types, "ClassSingleton");
|
|
175
176
|
IMPORT_CONSTANT(RBS_Types_Function, RBS_Types, "Function");
|
|
177
|
+
IMPORT_CONSTANT(RBS_Types_Function_ForwardingParam, RBS_Types_Function, "ForwardingParam");
|
|
176
178
|
IMPORT_CONSTANT(RBS_Types_Function_Param, RBS_Types_Function, "Param");
|
|
177
179
|
IMPORT_CONSTANT(RBS_Types_Interface, RBS_Types, "Interface");
|
|
178
180
|
IMPORT_CONSTANT(RBS_Types_Intersection, RBS_Types, "Intersection");
|
|
@@ -87,6 +87,7 @@ extern VALUE RBS_Types_Block;
|
|
|
87
87
|
extern VALUE RBS_Types_ClassInstance;
|
|
88
88
|
extern VALUE RBS_Types_ClassSingleton;
|
|
89
89
|
extern VALUE RBS_Types_Function;
|
|
90
|
+
extern VALUE RBS_Types_Function_ForwardingParam;
|
|
90
91
|
extern VALUE RBS_Types_Function_Param;
|
|
91
92
|
extern VALUE RBS_Types_Interface;
|
|
92
93
|
extern VALUE RBS_Types_Intersection;
|
data/ext/rbs_extension/main.c
CHANGED
|
@@ -146,44 +146,80 @@ static VALUE parse_type_try(VALUE a) {
|
|
|
146
146
|
return rbs_struct_to_ruby_value(ctx, type);
|
|
147
147
|
}
|
|
148
148
|
|
|
149
|
-
|
|
149
|
+
/**
|
|
150
|
+
* `end_pos` may point past the end of the buffer: clamping with a large
|
|
151
|
+
* number instead of measuring the buffer is ordinary, and the lexer stops at
|
|
152
|
+
* the end on its own.
|
|
153
|
+
* */
|
|
154
|
+
static void validate_position_range(VALUE string, int start_pos, int end_pos) {
|
|
150
155
|
if (start_pos < 0 || end_pos < 0) {
|
|
151
156
|
rb_raise(rb_eArgError, "negative position range: %d...%d", start_pos, end_pos);
|
|
152
157
|
}
|
|
153
158
|
if (start_pos > end_pos) {
|
|
154
159
|
rb_raise(rb_eArgError, "invalid position range: %d...%d", start_pos, end_pos);
|
|
155
160
|
}
|
|
161
|
+
|
|
162
|
+
long size = RSTRING_LEN(string);
|
|
163
|
+
if ((long) start_pos > size) {
|
|
164
|
+
rb_raise(rb_eArgError, "position range starts past the end of the buffer: %d...%d, buffer is %ld bytes", start_pos, end_pos, size);
|
|
165
|
+
}
|
|
156
166
|
}
|
|
157
167
|
|
|
158
168
|
static rbs_lexer_t *alloc_lexer_from_buffer(rbs_allocator_t *allocator, VALUE string, rb_encoding *encoding, int start_pos, int end_pos) {
|
|
159
|
-
validate_position_range(start_pos, end_pos);
|
|
169
|
+
validate_position_range(string, start_pos, end_pos);
|
|
160
170
|
|
|
161
171
|
const char *encoding_name = rb_enc_name(encoding);
|
|
162
172
|
|
|
163
|
-
|
|
173
|
+
rbs_lexer_t *lexer = rbs_lexer_new(
|
|
164
174
|
allocator,
|
|
165
175
|
rbs_string_from_ruby_string(string),
|
|
166
176
|
rbs_encoding_find((const uint8_t *) encoding_name, (const uint8_t *) (encoding_name + strlen(encoding_name))),
|
|
167
177
|
start_pos,
|
|
168
178
|
end_pos
|
|
169
179
|
);
|
|
180
|
+
|
|
181
|
+
if (lexer == NULL) {
|
|
182
|
+
rb_raise(rb_eArgError, "position range starts inside a character: %d...%d", start_pos, end_pos);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return lexer;
|
|
170
186
|
}
|
|
171
187
|
|
|
172
|
-
|
|
173
|
-
|
|
188
|
+
// Build the parser options from the arguments the `_parse_*` entry points
|
|
189
|
+
// receive. The optional syntax these enable is not part of the public
|
|
190
|
+
// `RBS::Parser` API, so only the private entry points pass them through.
|
|
191
|
+
static rbs_parser_options_t parser_options(VALUE enable_forwarding_params) {
|
|
192
|
+
return (rbs_parser_options_t) {
|
|
193
|
+
.enable_forwarding_params = RB_TEST(enable_forwarding_params),
|
|
194
|
+
};
|
|
195
|
+
}
|
|
174
196
|
|
|
197
|
+
static rbs_parser_t *alloc_parser_from_buffer_with_options(VALUE buffer, int start_pos, int end_pos, rbs_parser_options_t options) {
|
|
175
198
|
VALUE string = rb_funcall(buffer, rb_intern("content"), 0);
|
|
176
199
|
StringValue(string);
|
|
177
200
|
|
|
201
|
+
validate_position_range(string, start_pos, end_pos);
|
|
202
|
+
|
|
178
203
|
rb_encoding *encoding = rb_enc_get(string);
|
|
179
204
|
const char *encoding_name = rb_enc_name(encoding);
|
|
180
205
|
|
|
181
|
-
|
|
206
|
+
rbs_parser_t *parser = rbs_parser_new_with_options(
|
|
182
207
|
rbs_string_from_ruby_string(string),
|
|
183
208
|
rbs_encoding_find((const uint8_t *) encoding_name, (const uint8_t *) (encoding_name + strlen(encoding_name))),
|
|
184
209
|
start_pos,
|
|
185
|
-
end_pos
|
|
210
|
+
end_pos,
|
|
211
|
+
options
|
|
186
212
|
);
|
|
213
|
+
|
|
214
|
+
if (parser == NULL) {
|
|
215
|
+
rb_raise(rb_eArgError, "position range starts inside a character: %d...%d", start_pos, end_pos);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
return parser;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
static rbs_parser_t *alloc_parser_from_buffer(VALUE buffer, int start_pos, int end_pos) {
|
|
222
|
+
return alloc_parser_from_buffer_with_options(buffer, start_pos, end_pos, (rbs_parser_options_t) { 0 });
|
|
187
223
|
}
|
|
188
224
|
|
|
189
225
|
static VALUE rbsparser_parse_type(VALUE self, VALUE buffer, VALUE start_pos, VALUE end_pos, VALUE variables, VALUE require_eof, VALUE void_allowed, VALUE self_allowed, VALUE classish_allowed) {
|
|
@@ -232,12 +268,12 @@ static VALUE parse_method_type_try(VALUE a) {
|
|
|
232
268
|
return rbs_struct_to_ruby_value(ctx, (rbs_node_t *) method_type);
|
|
233
269
|
}
|
|
234
270
|
|
|
235
|
-
static VALUE rbsparser_parse_method_type(VALUE self, VALUE buffer, VALUE start_pos, VALUE end_pos, VALUE variables, VALUE require_eof) {
|
|
271
|
+
static VALUE rbsparser_parse_method_type(VALUE self, VALUE buffer, VALUE start_pos, VALUE end_pos, VALUE variables, VALUE require_eof, VALUE enable_forwarding_params) {
|
|
236
272
|
VALUE string = rb_funcall(buffer, rb_intern("content"), 0);
|
|
237
273
|
StringValue(string);
|
|
238
274
|
rb_encoding *encoding = rb_enc_get(string);
|
|
239
275
|
|
|
240
|
-
rbs_parser_t *parser =
|
|
276
|
+
rbs_parser_t *parser = alloc_parser_from_buffer_with_options(buffer, FIX2INT(start_pos), FIX2INT(end_pos), parser_options(enable_forwarding_params));
|
|
241
277
|
declare_type_variables(parser, variables, buffer);
|
|
242
278
|
struct parse_method_type_arg arg = {
|
|
243
279
|
.buffer = buffer,
|
|
@@ -271,12 +307,12 @@ static VALUE parse_signature_try(VALUE a) {
|
|
|
271
307
|
return rbs_struct_to_ruby_value(ctx, (rbs_node_t *) signature);
|
|
272
308
|
}
|
|
273
309
|
|
|
274
|
-
static VALUE rbsparser_parse_signature(VALUE self, VALUE buffer, VALUE start_pos, VALUE end_pos) {
|
|
310
|
+
static VALUE rbsparser_parse_signature(VALUE self, VALUE buffer, VALUE start_pos, VALUE end_pos, VALUE enable_forwarding_params) {
|
|
275
311
|
VALUE string = rb_funcall(buffer, rb_intern("content"), 0);
|
|
276
312
|
StringValue(string);
|
|
277
313
|
rb_encoding *encoding = rb_enc_get(string);
|
|
278
314
|
|
|
279
|
-
rbs_parser_t *parser =
|
|
315
|
+
rbs_parser_t *parser = alloc_parser_from_buffer_with_options(buffer, FIX2INT(start_pos), FIX2INT(end_pos), parser_options(enable_forwarding_params));
|
|
280
316
|
struct parse_signature_arg arg = {
|
|
281
317
|
.buffer = buffer,
|
|
282
318
|
.encoding = encoding,
|
|
@@ -364,12 +400,12 @@ static VALUE parse_method_type_to_bytes_try(VALUE a) {
|
|
|
364
400
|
return serialized_node_to_string(parser, (rbs_node_t *) method_type);
|
|
365
401
|
}
|
|
366
402
|
|
|
367
|
-
static VALUE rbsparser_parse_method_type_to_bytes(VALUE self, VALUE buffer, VALUE start_pos, VALUE end_pos, VALUE variables, VALUE require_eof) {
|
|
403
|
+
static VALUE rbsparser_parse_method_type_to_bytes(VALUE self, VALUE buffer, VALUE start_pos, VALUE end_pos, VALUE variables, VALUE require_eof, VALUE enable_forwarding_params) {
|
|
368
404
|
VALUE string = rb_funcall(buffer, rb_intern("content"), 0);
|
|
369
405
|
StringValue(string);
|
|
370
406
|
rb_encoding *encoding = rb_enc_get(string);
|
|
371
407
|
|
|
372
|
-
rbs_parser_t *parser =
|
|
408
|
+
rbs_parser_t *parser = alloc_parser_from_buffer_with_options(buffer, FIX2INT(start_pos), FIX2INT(end_pos), parser_options(enable_forwarding_params));
|
|
373
409
|
declare_type_variables(parser, variables, buffer);
|
|
374
410
|
struct parse_method_type_arg arg = {
|
|
375
411
|
.buffer = buffer,
|
|
@@ -397,12 +433,12 @@ static VALUE parse_signature_to_bytes_try(VALUE a) {
|
|
|
397
433
|
return serialized_node_to_string(parser, (rbs_node_t *) signature);
|
|
398
434
|
}
|
|
399
435
|
|
|
400
|
-
static VALUE rbsparser_parse_signature_to_bytes(VALUE self, VALUE buffer, VALUE start_pos, VALUE end_pos) {
|
|
436
|
+
static VALUE rbsparser_parse_signature_to_bytes(VALUE self, VALUE buffer, VALUE start_pos, VALUE end_pos, VALUE enable_forwarding_params) {
|
|
401
437
|
VALUE string = rb_funcall(buffer, rb_intern("content"), 0);
|
|
402
438
|
StringValue(string);
|
|
403
439
|
rb_encoding *encoding = rb_enc_get(string);
|
|
404
440
|
|
|
405
|
-
rbs_parser_t *parser =
|
|
441
|
+
rbs_parser_t *parser = alloc_parser_from_buffer_with_options(buffer, FIX2INT(start_pos), FIX2INT(end_pos), parser_options(enable_forwarding_params));
|
|
406
442
|
struct parse_signature_arg arg = {
|
|
407
443
|
.buffer = buffer,
|
|
408
444
|
.encoding = encoding,
|
|
@@ -587,11 +623,11 @@ void rbs__init_parser(void) {
|
|
|
587
623
|
rb_gc_register_mark_object(EMPTY_HASH);
|
|
588
624
|
|
|
589
625
|
rb_define_singleton_method(RBS_Parser, "_parse_type", rbsparser_parse_type, 8);
|
|
590
|
-
rb_define_singleton_method(RBS_Parser, "_parse_method_type", rbsparser_parse_method_type,
|
|
591
|
-
rb_define_singleton_method(RBS_Parser, "_parse_signature", rbsparser_parse_signature,
|
|
626
|
+
rb_define_singleton_method(RBS_Parser, "_parse_method_type", rbsparser_parse_method_type, 6);
|
|
627
|
+
rb_define_singleton_method(RBS_Parser, "_parse_signature", rbsparser_parse_signature, 4);
|
|
592
628
|
rb_define_singleton_method(RBS_Parser, "_parse_type_to_bytes", rbsparser_parse_type_to_bytes, 8);
|
|
593
|
-
rb_define_singleton_method(RBS_Parser, "_parse_method_type_to_bytes", rbsparser_parse_method_type_to_bytes,
|
|
594
|
-
rb_define_singleton_method(RBS_Parser, "_parse_signature_to_bytes", rbsparser_parse_signature_to_bytes,
|
|
629
|
+
rb_define_singleton_method(RBS_Parser, "_parse_method_type_to_bytes", rbsparser_parse_method_type_to_bytes, 6);
|
|
630
|
+
rb_define_singleton_method(RBS_Parser, "_parse_signature_to_bytes", rbsparser_parse_signature_to_bytes, 4);
|
|
595
631
|
rb_define_singleton_method(RBS_Parser, "_parse_type_params", rbsparser_parse_type_params, 4);
|
|
596
632
|
rb_define_singleton_method(RBS_Parser, "_parse_inline_leading_annotation", rbsparser_parse_inline_leading_annotation, 4);
|
|
597
633
|
rb_define_singleton_method(RBS_Parser, "_parse_inline_trailing_annotation", rbsparser_parse_inline_trailing_annotation, 4);
|
data/include/rbs/ast.h
CHANGED
|
@@ -125,18 +125,19 @@ enum rbs_node_type {
|
|
|
125
125
|
RBS_TYPES_CLASS_INSTANCE = 63,
|
|
126
126
|
RBS_TYPES_CLASS_SINGLETON = 64,
|
|
127
127
|
RBS_TYPES_FUNCTION = 65,
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
128
|
+
RBS_TYPES_FUNCTION_FORWARDING_PARAM = 66,
|
|
129
|
+
RBS_TYPES_FUNCTION_PARAM = 67,
|
|
130
|
+
RBS_TYPES_INTERFACE = 68,
|
|
131
|
+
RBS_TYPES_INTERSECTION = 69,
|
|
132
|
+
RBS_TYPES_LITERAL = 70,
|
|
133
|
+
RBS_TYPES_OPTIONAL = 71,
|
|
134
|
+
RBS_TYPES_PROC = 72,
|
|
135
|
+
RBS_TYPES_RECORD = 73,
|
|
136
|
+
RBS_TYPES_RECORD_FIELD_TYPE = 74,
|
|
137
|
+
RBS_TYPES_TUPLE = 75,
|
|
138
|
+
RBS_TYPES_UNION = 76,
|
|
139
|
+
RBS_TYPES_UNTYPED_FUNCTION = 77,
|
|
140
|
+
RBS_TYPES_VARIABLE = 78,
|
|
140
141
|
RBS_AST_SYMBOL,
|
|
141
142
|
};
|
|
142
143
|
|
|
@@ -854,9 +855,15 @@ typedef struct rbs_types_function {
|
|
|
854
855
|
struct rbs_hash *RBS_NONNULL required_keywords;
|
|
855
856
|
struct rbs_hash *RBS_NONNULL optional_keywords;
|
|
856
857
|
struct rbs_node *RBS_NULLABLE rest_keywords;
|
|
858
|
+
struct rbs_node *RBS_NULLABLE forwarding;
|
|
857
859
|
struct rbs_node *RBS_NONNULL return_type;
|
|
858
860
|
} rbs_types_function_t;
|
|
859
861
|
|
|
862
|
+
typedef struct rbs_types_function_forwarding_param {
|
|
863
|
+
rbs_node_t base;
|
|
864
|
+
|
|
865
|
+
} rbs_types_function_forwarding_param_t;
|
|
866
|
+
|
|
860
867
|
typedef struct rbs_types_function_param {
|
|
861
868
|
rbs_node_t base;
|
|
862
869
|
|
|
@@ -1030,7 +1037,8 @@ rbs_types_bases_void_t *RBS_NONNULL rbs_types_bases_void_new(rbs_allocator_t *RB
|
|
|
1030
1037
|
rbs_types_block_t *RBS_NONNULL rbs_types_block_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_node_t *RBS_NONNULL type, bool required, rbs_node_t *RBS_NULLABLE self_type);
|
|
1031
1038
|
rbs_types_class_instance_t *RBS_NONNULL rbs_types_class_instance_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_type_name_t *RBS_NONNULL name, rbs_node_list_t *RBS_NONNULL args, rbs_location_range name_range);
|
|
1032
1039
|
rbs_types_class_singleton_t *RBS_NONNULL rbs_types_class_singleton_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_type_name_t *RBS_NONNULL name, rbs_node_list_t *RBS_NONNULL args, rbs_location_range name_range);
|
|
1033
|
-
rbs_types_function_t *RBS_NONNULL rbs_types_function_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_node_list_t *RBS_NONNULL required_positionals, rbs_node_list_t *RBS_NONNULL optional_positionals, rbs_node_t *RBS_NULLABLE rest_positionals, rbs_node_list_t *RBS_NONNULL trailing_positionals, rbs_hash_t *RBS_NONNULL required_keywords, rbs_hash_t *RBS_NONNULL optional_keywords, rbs_node_t *RBS_NULLABLE rest_keywords, rbs_node_t *RBS_NONNULL return_type);
|
|
1040
|
+
rbs_types_function_t *RBS_NONNULL rbs_types_function_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_node_list_t *RBS_NONNULL required_positionals, rbs_node_list_t *RBS_NONNULL optional_positionals, rbs_node_t *RBS_NULLABLE rest_positionals, rbs_node_list_t *RBS_NONNULL trailing_positionals, rbs_hash_t *RBS_NONNULL required_keywords, rbs_hash_t *RBS_NONNULL optional_keywords, rbs_node_t *RBS_NULLABLE rest_keywords, rbs_node_t *RBS_NULLABLE forwarding, rbs_node_t *RBS_NONNULL return_type);
|
|
1041
|
+
rbs_types_function_forwarding_param_t *RBS_NONNULL rbs_types_function_forwarding_param_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location);
|
|
1034
1042
|
rbs_types_function_param_t *RBS_NONNULL rbs_types_function_param_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_node_t *RBS_NONNULL type, rbs_ast_symbol_t *RBS_NULLABLE name);
|
|
1035
1043
|
rbs_types_interface_t *RBS_NONNULL rbs_types_interface_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_type_name_t *RBS_NONNULL name, rbs_node_list_t *RBS_NONNULL args, rbs_location_range name_range);
|
|
1036
1044
|
rbs_types_intersection_t *RBS_NONNULL rbs_types_intersection_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_node_list_t *RBS_NONNULL types);
|
data/include/rbs/defines.h
CHANGED
|
@@ -69,9 +69,9 @@
|
|
|
69
69
|
**********************************************************************************************************************/
|
|
70
70
|
|
|
71
71
|
#if defined(_MSC_VER)
|
|
72
|
-
#define
|
|
72
|
+
#define RBS_NODISCARD _Check_return_
|
|
73
73
|
#else
|
|
74
|
-
#define
|
|
74
|
+
#define RBS_NODISCARD __attribute__((warn_unused_result))
|
|
75
75
|
#endif
|
|
76
76
|
|
|
77
77
|
/**
|
data/include/rbs/lexer.h
CHANGED
|
@@ -72,18 +72,19 @@ enum RBSTokenType {
|
|
|
72
72
|
kRETURN, /* return */
|
|
73
73
|
kMODULESELF, /* module-self */
|
|
74
74
|
|
|
75
|
-
tLIDENT,
|
|
76
|
-
tUIDENT,
|
|
77
|
-
tULIDENT,
|
|
78
|
-
tULLIDENT,
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
75
|
+
tLIDENT, /* Identifiers starting with lower case */
|
|
76
|
+
tUIDENT, /* Identifiers starting with upper case */
|
|
77
|
+
tULIDENT, /* Identifiers starting with `_` followed by upper case */
|
|
78
|
+
tULLIDENT, /* Identifiers starting with `_` followed by lower case */
|
|
79
|
+
tNONASCIIIDENT, /* Identifiers starting with a character outside ASCII */
|
|
80
|
+
tGIDENT, /* Identifiers starting with `$` */
|
|
81
|
+
tAIDENT, /* Identifiers starting with `@` */
|
|
82
|
+
tA2IDENT, /* Identifiers starting with `@@` */
|
|
83
|
+
tBANGIDENT, /* Identifiers ending with `!` */
|
|
84
|
+
tEQIDENT, /* Identifiers ending with `=` */
|
|
85
|
+
tQIDENT, /* Quoted identifier */
|
|
86
|
+
pAREF_OPR, /* [] */
|
|
87
|
+
tOPERATOR, /* Operator identifier */
|
|
87
88
|
|
|
88
89
|
tCOMMENT, /* Comment */
|
|
89
90
|
tLINECOMMENT, /* Comment of all line */
|
data/include/rbs/parser.h
CHANGED
|
@@ -40,6 +40,21 @@ typedef struct rbs_error_t {
|
|
|
40
40
|
bool syntax_error;
|
|
41
41
|
} rbs_error_t;
|
|
42
42
|
|
|
43
|
+
/**
|
|
44
|
+
* Options that control which syntax the parser accepts.
|
|
45
|
+
*
|
|
46
|
+
* Zero-initializing the struct gives the default configuration, where
|
|
47
|
+
* every optional syntax is disabled.
|
|
48
|
+
* */
|
|
49
|
+
typedef struct {
|
|
50
|
+
/**
|
|
51
|
+
* Accept `(...)` forwarding parameters in method types.
|
|
52
|
+
*
|
|
53
|
+
* The syntax is experimental and disabled by default.
|
|
54
|
+
* */
|
|
55
|
+
bool enable_forwarding_params;
|
|
56
|
+
} rbs_parser_options_t;
|
|
57
|
+
|
|
43
58
|
/**
|
|
44
59
|
* An RBS parser is a LL(3) parser.
|
|
45
60
|
* */
|
|
@@ -57,6 +72,8 @@ typedef struct {
|
|
|
57
72
|
rbs_constant_pool_t constant_pool;
|
|
58
73
|
rbs_allocator_t *allocator;
|
|
59
74
|
rbs_error_t *error;
|
|
75
|
+
|
|
76
|
+
rbs_parser_options_t options;
|
|
60
77
|
} rbs_parser_t;
|
|
61
78
|
|
|
62
79
|
/**
|
|
@@ -80,7 +97,7 @@ void rbs_parser_push_typevar_table(rbs_parser_t *parser, bool reset);
|
|
|
80
97
|
/**
|
|
81
98
|
* Insert new type variable into the latest table.
|
|
82
99
|
* */
|
|
83
|
-
|
|
100
|
+
RBS_NODISCARD bool rbs_parser_insert_typevar(rbs_parser_t *parser, rbs_constant_id_t id);
|
|
84
101
|
|
|
85
102
|
/**
|
|
86
103
|
* Allocate new rbs_lexer_t object.
|
|
@@ -89,8 +106,13 @@ NODISCARD bool rbs_parser_insert_typevar(rbs_parser_t *parser, rbs_constant_id_t
|
|
|
89
106
|
* VALUE string = rb_funcall(buffer, rb_intern("content"), 0);
|
|
90
107
|
* rbs_lexer_new(string, 0, 31) // New rbs_lexer_t with buffer content
|
|
91
108
|
* ```
|
|
109
|
+
*
|
|
110
|
+
* Returns `NULL` when `start_pos` is not the first byte of a character in
|
|
111
|
+
* `string` -- inside one, or past the end of the buffer. The lexer reaches
|
|
112
|
+
* `start_pos` a character at a time, so nowhere else is a position it can
|
|
113
|
+
* start from.
|
|
92
114
|
* */
|
|
93
|
-
rbs_lexer_t *rbs_lexer_new(rbs_allocator_t *, rbs_string_t string, const rbs_encoding_t *encoding, int start_pos, int end_pos);
|
|
115
|
+
RBS_NODISCARD rbs_lexer_t *rbs_lexer_new(rbs_allocator_t *, rbs_string_t string, const rbs_encoding_t *encoding, int start_pos, int end_pos);
|
|
94
116
|
|
|
95
117
|
/**
|
|
96
118
|
* Allocate new rbs_parser_t object.
|
|
@@ -98,8 +120,20 @@ rbs_lexer_t *rbs_lexer_new(rbs_allocator_t *, rbs_string_t string, const rbs_enc
|
|
|
98
120
|
* ```
|
|
99
121
|
* rbs_parser_new(buffer, string, encoding, 0, 1);
|
|
100
122
|
* ```
|
|
123
|
+
*
|
|
124
|
+
* Returns `NULL` for a `start_pos` that `rbs_lexer_new` rejects.
|
|
125
|
+
* */
|
|
126
|
+
RBS_NODISCARD rbs_parser_t *rbs_parser_new(rbs_string_t string, const rbs_encoding_t *encoding, int start_pos, int end_pos);
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Allocate new rbs_parser_t object with the given options.
|
|
130
|
+
*
|
|
131
|
+
* `rbs_parser_new` is equivalent to passing a zero-initialized
|
|
132
|
+
* `rbs_parser_options_t`, which disables every optional syntax.
|
|
133
|
+
*
|
|
134
|
+
* Returns `NULL` for a `start_pos` that `rbs_lexer_new` rejects.
|
|
101
135
|
* */
|
|
102
|
-
rbs_parser_t *
|
|
136
|
+
RBS_NODISCARD rbs_parser_t *rbs_parser_new_with_options(rbs_string_t string, const rbs_encoding_t *encoding, int start_pos, int end_pos, rbs_parser_options_t options);
|
|
103
137
|
void rbs_parser_free(rbs_parser_t *parser);
|
|
104
138
|
|
|
105
139
|
/**
|
data/lib/rbs/ast/declarations.rb
CHANGED
data/lib/rbs/ast/type_param.rb
CHANGED
|
@@ -114,7 +114,7 @@ module RBS
|
|
|
114
114
|
def self.rename(params, new_names:)
|
|
115
115
|
raise unless params.size == new_names.size
|
|
116
116
|
|
|
117
|
-
subst = Substitution.build(
|
|
117
|
+
subst = Substitution.build(params.map(&:name), Types::Variable.build(new_names))
|
|
118
118
|
|
|
119
119
|
params.map.with_index do |param, index|
|
|
120
120
|
new_name = new_names[index]
|
|
@@ -179,7 +179,13 @@ module RBS
|
|
|
179
179
|
|
|
180
180
|
super_types = with_super_classes.map do |decl|
|
|
181
181
|
super_class = decl.super_class or raise
|
|
182
|
-
|
|
182
|
+
args = super_class.args
|
|
183
|
+
|
|
184
|
+
if align_params = entry.align_params(decl)
|
|
185
|
+
args = args.map {|type| type.sub(align_params) }
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
Types::ClassInstance.new(name: super_class.name, args: args, location: nil)
|
|
183
189
|
end
|
|
184
190
|
|
|
185
191
|
super_types.uniq!
|
|
@@ -473,10 +479,7 @@ module RBS
|
|
|
473
479
|
|
|
474
480
|
def mixin_ancestors(entry, type_name, included_modules:, included_interfaces:, extended_modules:, prepended_modules:, extended_interfaces:)
|
|
475
481
|
entry.each_decl do |decl|
|
|
476
|
-
align_params =
|
|
477
|
-
decl.type_params.each.map(&:name),
|
|
478
|
-
entry.type_params.map {|param| Types::Variable.new(name: param.name, location: param.location) }
|
|
479
|
-
)
|
|
482
|
+
align_params = entry.align_params(decl)
|
|
480
483
|
|
|
481
484
|
mixin_ancestors0(decl,
|
|
482
485
|
type_name,
|
|
@@ -104,7 +104,7 @@ module RBS
|
|
|
104
104
|
type = Types::ClassInstance.new(name: type_name, args: args, location: nil)
|
|
105
105
|
Methods.new(type: type).tap do |methods|
|
|
106
106
|
entry.each_decl do |decl|
|
|
107
|
-
subst =
|
|
107
|
+
subst = entry.align_params(decl)
|
|
108
108
|
case decl
|
|
109
109
|
when AST::Declarations::Base
|
|
110
110
|
each_rbs_member_with_accessibility(decl.members) do |member, accessibility|
|
|
@@ -115,14 +115,14 @@ module RBS
|
|
|
115
115
|
build_method(
|
|
116
116
|
methods,
|
|
117
117
|
type,
|
|
118
|
-
member: member.update(overloads: member.overloads.map {|overload| overload.sub(subst) }),
|
|
118
|
+
member: subst ? member.update(overloads: member.overloads.map {|overload| overload.sub(subst) }) : member,
|
|
119
119
|
accessibility: member.visibility || accessibility
|
|
120
120
|
)
|
|
121
121
|
when :singleton_instance
|
|
122
122
|
build_method(
|
|
123
123
|
methods,
|
|
124
124
|
type,
|
|
125
|
-
member: member.update(overloads: member.overloads.map {|overload| overload.sub(subst) }),
|
|
125
|
+
member: subst ? member.update(overloads: member.overloads.map {|overload| overload.sub(subst) }) : member,
|
|
126
126
|
accessibility: :private
|
|
127
127
|
)
|
|
128
128
|
end
|
|
@@ -130,7 +130,7 @@ module RBS
|
|
|
130
130
|
if member.kind == :instance
|
|
131
131
|
build_attribute(methods,
|
|
132
132
|
type,
|
|
133
|
-
member: member.update(type: member.type.sub(subst)),
|
|
133
|
+
member: subst ? member.update(type: member.type.sub(subst)) : member,
|
|
134
134
|
accessibility: member.visibility || accessibility)
|
|
135
135
|
end
|
|
136
136
|
when AST::Members::Alias
|
|
@@ -124,10 +124,13 @@ module RBS
|
|
|
124
124
|
end
|
|
125
125
|
|
|
126
126
|
entry = env.class_decls[type_name] or raise "Unknown name for build_instance: #{type_name}"
|
|
127
|
-
args = entry.type_params.map {|param| Types::Variable.new(name: param.name, location: param.location) }
|
|
128
127
|
|
|
129
128
|
entry.each_decl do |decl|
|
|
130
|
-
|
|
129
|
+
if align_params = entry.align_params(decl)
|
|
130
|
+
subst_ = subst + align_params
|
|
131
|
+
else
|
|
132
|
+
subst_ = subst
|
|
133
|
+
end
|
|
131
134
|
|
|
132
135
|
decl.members.each do |member|
|
|
133
136
|
case member
|
|
@@ -64,6 +64,18 @@ module RBS
|
|
|
64
64
|
end
|
|
65
65
|
end
|
|
66
66
|
end
|
|
67
|
+
|
|
68
|
+
def align_params(decl)
|
|
69
|
+
entry_params = type_params
|
|
70
|
+
decl_param_names = decl.type_params.map(&:name)
|
|
71
|
+
|
|
72
|
+
return nil if decl_param_names == entry_params.map(&:name)
|
|
73
|
+
|
|
74
|
+
Substitution.build(
|
|
75
|
+
decl_param_names,
|
|
76
|
+
entry_params.map {|param| Types::Variable.new(name: param.name, location: param.location) }
|
|
77
|
+
)
|
|
78
|
+
end
|
|
67
79
|
end
|
|
68
80
|
end
|
|
69
81
|
end
|