summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Newton <kddnewton@gmail.com>2026-01-28 21:23:15 -0500
committergit <svn-admin@ruby-lang.org>2026-01-29 02:35:38 +0000
commitfa09afb15c9cf901d84e2963b86c4c7a7d0e104e (patch)
treeb8446fdceae0f231520b5100e7c2a86d2e9b25d4
parent0c30897d0bf579ee7be08fc828932e1bac1196aa (diff)
[ruby/prism] Support `version: "nearest"`.
This clamps to supported versions based on the current Ruby version. https://github.com/ruby/prism/commit/eb63748e8b
-rw-r--r--lib/prism/ffi.rb24
-rw-r--r--prism/extension.c27
-rw-r--r--prism/options.h8
3 files changed, 49 insertions, 10 deletions
diff --git a/lib/prism/ffi.rb b/lib/prism/ffi.rb
index d4c9d60c9a..57d878a33f 100644
--- a/lib/prism/ffi.rb
+++ b/lib/prism/ffi.rb
@@ -423,10 +423,26 @@ module Prism
# Return the value that should be dumped for the version option.
def dump_options_version(version)
- current = version == "current"
+ checking =
+ case version
+ when "current"
+ RUBY_VERSION
+ when "latest"
+ nil
+ when "nearest"
+ if RUBY_VERSION <= "3.3"
+ "3.3"
+ elsif RUBY_VERSION >= "4.1"
+ "4.1"
+ else
+ RUBY_VERSION
+ end
+ else
+ version
+ end
- case current ? RUBY_VERSION : version
- when nil, "latest"
+ case checking
+ when nil
0 # Handled in pm_parser_init
when /\A3\.3(\.\d+)?\z/
1
@@ -437,7 +453,7 @@ module Prism
when /\A4\.1(\.\d+)?\z/
4
else
- if current
+ if version == "current"
raise CurrentVersionError, RUBY_VERSION
else
raise ArgumentError, "invalid version: #{version}"
diff --git a/prism/extension.c b/prism/extension.c
index 400546a4ce..cde10bf360 100644
--- a/prism/extension.c
+++ b/prism/extension.c
@@ -201,9 +201,24 @@ build_options_i(VALUE key, VALUE value, VALUE argument) {
const char *version = check_string(value);
if (RSTRING_LEN(value) == 7 && strncmp(version, "current", 7) == 0) {
- const char *current_version = RSTRING_PTR(rb_const_get(rb_cObject, rb_intern("RUBY_VERSION")));
- if (!pm_options_version_set(options, current_version, 3)) {
- rb_exc_raise(rb_exc_new_cstr(rb_cPrismCurrentVersionError, current_version));
+ const char *ruby_version = RSTRING_PTR(rb_const_get(rb_cObject, rb_intern("RUBY_VERSION")));
+ if (!pm_options_version_set(options, ruby_version, 3)) {
+ rb_exc_raise(rb_exc_new_cstr(rb_cPrismCurrentVersionError, ruby_version));
+ }
+ } else if (RSTRING_LEN(value) == 7 && strncmp(version, "nearest", 7) == 0) {
+ const char *ruby_version = RSTRING_PTR(rb_const_get(rb_cObject, rb_intern("RUBY_VERSION")));
+ const char *nearest_version;
+
+ if (ruby_version[0] < '3' || (ruby_version[0] == '3' && ruby_version[2] < '3')) {
+ nearest_version = "3.3";
+ } else if (ruby_version[0] > '4' || (ruby_version[0] == '4' && ruby_version[2] > '1')) {
+ nearest_version = "4.1";
+ } else {
+ nearest_version = ruby_version;
+ }
+
+ if (!pm_options_version_set(options, nearest_version, 3)) {
+ rb_raise(rb_eArgError, "invalid nearest version: %s", nearest_version);
}
} else if (!pm_options_version_set(options, version, RSTRING_LEN(value))) {
rb_raise(rb_eArgError, "invalid version: %" PRIsVALUE, value);
@@ -894,8 +909,10 @@ parse_input(pm_string_t *input, const pm_options_t *options) {
* version of Ruby syntax (which you can trigger with `nil` or
* `"latest"`). You may also restrict the syntax to a specific version of
* Ruby, e.g., with `"3.3.0"`. To parse with the same syntax version that
- * the current Ruby is running use `version: "current"`. Raises
- * ArgumentError if the version is not currently supported by Prism.
+ * the current Ruby is running use `version: "current"`. To parse with the
+ * nearest version to the current Ruby that is running, use
+ * `version: "nearest"`. Raises ArgumentError if the version is not
+ * currently supported by Prism.
*/
static VALUE
parse(int argc, VALUE *argv, VALUE self) {
diff --git a/prism/options.h b/prism/options.h
index c00c7bf755..9a19a2aead 100644
--- a/prism/options.h
+++ b/prism/options.h
@@ -82,7 +82,10 @@ typedef void (*pm_options_shebang_callback_t)(struct pm_options *options, const
* parse in the same way as a specific version of CRuby would have.
*/
typedef enum {
- /** If an explicit version is not provided, the current version of prism will be used. */
+ /**
+ * If an explicit version is not provided, the current version of prism will
+ * be used.
+ */
PM_OPTIONS_VERSION_UNSET = 0,
/** 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);
* | ----- | ------------------------- |
* | `0` | use the latest version of prism |
* | `1` | use the version of prism that is vendored in CRuby 3.3.0 |
+ * | `2` | use the version of prism that is vendored in CRuby 3.4.0 |
+ * | `3` | use the version of prism that is vendored in CRuby 4.0.0 |
+ * | `4` | use the version of prism that is vendored in CRuby 4.1.0 |
*
* Each scope is laid out as follows:
*