diff options
| author | Earlopain <14981592+Earlopain@users.noreply.github.com> | 2026-02-04 14:31:32 +0100 |
|---|---|---|
| committer | git <svn-admin@ruby-lang.org> | 2026-02-04 14:58:08 +0000 |
| commit | 673c37d76ac2767b13a1ab7ba74b0ea8cda17c81 (patch) | |
| tree | 7447e58dbe4772161e957b1646f38d0366fb47be | |
| parent | 1258992bdff8818d3ce868e98ccc3496069d996d (diff) | |
[ruby/prism] Rewrite "version: nearest" to require no maintenance
Currently I see myself not updating this when a new version is added.
Instead, rewrite it to just work with new versions:
* Try to set the version
* If that doesn't succeed, check if it is lower
* If it isn't lower, it must be higher
We can then use `PM_OPTIONS_VERSION_LATEST` which doesn't need to change.
Also added a very basic test.
https://github.com/ruby/prism/commit/443e9b9959
| -rw-r--r-- | lib/prism/ffi.rb | 43 | ||||
| -rw-r--r-- | prism/extension.c | 20 | ||||
| -rw-r--r-- | test/prism/api/parse_test.rb | 4 |
3 files changed, 31 insertions, 36 deletions
diff --git a/lib/prism/ffi.rb b/lib/prism/ffi.rb index 57d878a33f..618324ded6 100644 --- a/lib/prism/ffi.rb +++ b/lib/prism/ffi.rb @@ -423,27 +423,28 @@ module Prism # Return the value that should be dumped for the version option. def dump_options_version(version) - 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 + case version + when "current" + version_string_to_number(RUBY_VERSION) || raise(CurrentVersionError, RUBY_VERSION) + when "latest", nil + 0 # Handled in pm_parser_init + when "nearest" + dump = version_string_to_number(RUBY_VERSION) + return dump if dump + if RUBY_VERSION < "3.3" + version_string_to_number("3.3") else - version + 0 # Handled in pm_parser_init end + else + version_string_to_number(version) || raise(ArgumentError, "invalid version: #{version}") + end + end - case checking - when nil - 0 # Handled in pm_parser_init + # Converts a version string like "4.0.0" or "4.0" into a number. + # Returns nil if the version is unknown. + def version_string_to_number(version) + case version when /\A3\.3(\.\d+)?\z/ 1 when /\A3\.4(\.\d+)?\z/ @@ -452,12 +453,6 @@ module Prism 3 when /\A4\.1(\.\d+)?\z/ 4 - else - if version == "current" - raise CurrentVersionError, RUBY_VERSION - else - raise ArgumentError, "invalid version: #{version}" - end end end diff --git a/prism/extension.c b/prism/extension.c index 363144970c..fe3cd6a8f3 100644 --- a/prism/extension.c +++ b/prism/extension.c @@ -205,18 +205,14 @@ build_options_i(VALUE key, VALUE value, VALUE argument) { rb_exc_raise(rb_exc_new_cstr(rb_cPrismCurrentVersionError, ruby_version)); } } else if (RSTRING_LEN(value) == 7 && strncmp(version, "nearest", 7) == 0) { - 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); + if (!pm_options_version_set(options, ruby_version, 3)) { + // Prism doesn't know this specific version. Is it lower? + if (ruby_version[0] < '3' || (ruby_version[0] == '3' && ruby_version[2] < '3')) { + options->version == PM_OPTIONS_VERSION_CRUBY_3_3; + } else { + // Must be higher. + options->version == PM_OPTIONS_VERSION_LATEST; + } } } else if (!pm_options_version_set(options, version, RSTRING_LEN(value))) { rb_raise(rb_eArgError, "invalid version: %" PRIsVALUE, value); diff --git a/test/prism/api/parse_test.rb b/test/prism/api/parse_test.rb index bbf28201ff..c9a47c1a61 100644 --- a/test/prism/api/parse_test.rb +++ b/test/prism/api/parse_test.rb @@ -154,6 +154,10 @@ module Prism end end + def test_nearest + assert Prism.parse_success?("1 + 1", version: "nearest") + end + def test_scopes assert_kind_of Prism::CallNode, Prism.parse_statement("foo") assert_kind_of Prism::LocalVariableReadNode, Prism.parse_statement("foo", scopes: [[:foo]]) |
