Skip to content

Commit e8c6b49

Browse files
authored
Merge pull request #3886 from ruby/nearest
Support `version: "nearest"`.
2 parents dd27399 + eb63748 commit e8c6b49

3 files changed

Lines changed: 49 additions & 10 deletions

File tree

ext/prism/extension.c

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -201,9 +201,24 @@ build_options_i(VALUE key, VALUE value, VALUE argument) {
201201
const char *version = check_string(value);
202202

203203
if (RSTRING_LEN(value) == 7 && strncmp(version, "current", 7) == 0) {
204-
const char *current_version = RSTRING_PTR(rb_const_get(rb_cObject, rb_intern("RUBY_VERSION")));
205-
if (!pm_options_version_set(options, current_version, 3)) {
206-
rb_exc_raise(rb_exc_new_cstr(rb_cPrismCurrentVersionError, current_version));
204+
const char *ruby_version = RSTRING_PTR(rb_const_get(rb_cObject, rb_intern("RUBY_VERSION")));
205+
if (!pm_options_version_set(options, ruby_version, 3)) {
206+
rb_exc_raise(rb_exc_new_cstr(rb_cPrismCurrentVersionError, ruby_version));
207+
}
208+
} else if (RSTRING_LEN(value) == 7 && strncmp(version, "nearest", 7) == 0) {
209+
const char *ruby_version = RSTRING_PTR(rb_const_get(rb_cObject, rb_intern("RUBY_VERSION")));
210+
const char *nearest_version;
211+
212+
if (ruby_version[0] < '3' || (ruby_version[0] == '3' && ruby_version[2] < '3')) {
213+
nearest_version = "3.3";
214+
} else if (ruby_version[0] > '4' || (ruby_version[0] == '4' && ruby_version[2] > '1')) {
215+
nearest_version = "4.1";
216+
} else {
217+
nearest_version = ruby_version;
218+
}
219+
220+
if (!pm_options_version_set(options, nearest_version, 3)) {
221+
rb_raise(rb_eArgError, "invalid nearest version: %s", nearest_version);
207222
}
208223
} else if (!pm_options_version_set(options, version, RSTRING_LEN(value))) {
209224
rb_raise(rb_eArgError, "invalid version: %" PRIsVALUE, value);
@@ -894,8 +909,10 @@ parse_input(pm_string_t *input, const pm_options_t *options) {
894909
* version of Ruby syntax (which you can trigger with `nil` or
895910
* `"latest"`). You may also restrict the syntax to a specific version of
896911
* Ruby, e.g., with `"3.3.0"`. To parse with the same syntax version that
897-
* the current Ruby is running use `version: "current"`. Raises
898-
* ArgumentError if the version is not currently supported by Prism.
912+
* the current Ruby is running use `version: "current"`. To parse with the
913+
* nearest version to the current Ruby that is running, use
914+
* `version: "nearest"`. Raises ArgumentError if the version is not
915+
* currently supported by Prism.
899916
*/
900917
static VALUE
901918
parse(int argc, VALUE *argv, VALUE self) {

include/prism/options.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,10 @@ typedef void (*pm_options_shebang_callback_t)(struct pm_options *options, const
8282
* parse in the same way as a specific version of CRuby would have.
8383
*/
8484
typedef enum {
85-
/** If an explicit version is not provided, the current version of prism will be used. */
85+
/**
86+
* If an explicit version is not provided, the current version of prism will
87+
* be used.
88+
*/
8689
PM_OPTIONS_VERSION_UNSET = 0,
8790

8891
/** The vendored version of prism in CRuby 3.3.x. */
@@ -452,6 +455,9 @@ PRISM_EXPORTED_FUNCTION void pm_options_free(pm_options_t *options);
452455
* | ----- | ------------------------- |
453456
* | `0` | use the latest version of prism |
454457
* | `1` | use the version of prism that is vendored in CRuby 3.3.0 |
458+
* | `2` | use the version of prism that is vendored in CRuby 3.4.0 |
459+
* | `3` | use the version of prism that is vendored in CRuby 4.0.0 |
460+
* | `4` | use the version of prism that is vendored in CRuby 4.1.0 |
455461
*
456462
* Each scope is laid out as follows:
457463
*

lib/prism/ffi.rb

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -423,10 +423,26 @@ def dump_options_command_line(options)
423423

424424
# Return the value that should be dumped for the version option.
425425
def dump_options_version(version)
426-
current = version == "current"
426+
checking =
427+
case version
428+
when "current"
429+
RUBY_VERSION
430+
when "latest"
431+
nil
432+
when "nearest"
433+
if RUBY_VERSION <= "3.3"
434+
"3.3"
435+
elsif RUBY_VERSION >= "4.1"
436+
"4.1"
437+
else
438+
RUBY_VERSION
439+
end
440+
else
441+
version
442+
end
427443

428-
case current ? RUBY_VERSION : version
429-
when nil, "latest"
444+
case checking
445+
when nil
430446
0 # Handled in pm_parser_init
431447
when /\A3\.3(\.\d+)?\z/
432448
1
@@ -437,7 +453,7 @@ def dump_options_version(version)
437453
when /\A4\.1(\.\d+)?\z/
438454
4
439455
else
440-
if current
456+
if version == "current"
441457
raise CurrentVersionError, RUBY_VERSION
442458
else
443459
raise ArgumentError, "invalid version: #{version}"

0 commit comments

Comments
 (0)