commit 092962b07c5753e9d602f5597ad1753b19854561
parent 6a728382f90a70fd31f72e493f7fb6814631a48f
Author: Phạm Bình An <111893501+brianhuster@users.noreply.github.com>
Date: Fri, 11 Apr 2025 17:15:18 +0700
fix(vim.version): vim.VersionRange:has(<prerelease>) (#33324)
Problem:
`vim.version.range('>=0.10'):has('0.12.0-dev')` returns false, which is
wrong per semver.
Solution:
`vim.VersionRange:has()` shouldn't have special handling for prereleases
(Why would we need it when `__eq`, `__lt`, `__le` already handle
prereleases?).
Closes #33316
Diffstat:
3 files changed, 16 insertions(+), 8 deletions(-)
diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt
@@ -179,6 +179,7 @@ These existing features changed their behavior.
• 'spellfile' location defaults to `stdpath("data").."/spell/"` instead of the
first writable directoy in 'runtimepath'.
+• |vim.version.range()| doesn't exclude `to` if it is equal to `from`.
==============================================================================
REMOVED FEATURES *news-removed*
diff --git a/runtime/lua/vim/version.lua b/runtime/lua/vim/version.lua
@@ -238,8 +238,8 @@ function VersionRange:has(version)
version = setmetatable(vim.deepcopy(version, true), Version)
end
if version then
- if version.prerelease ~= self.from.prerelease then
- return false
+ if self.from == self.to then
+ return version == self.from
end
return version >= self.from and (self.to == nil or version < self.to)
end
@@ -310,9 +310,7 @@ function M.range(spec) -- Adapted from https://github.com/folke/lazy.nvim
local from = semver --- @type vim.Version?
local to = vim.deepcopy(semver, true) --- @type vim.Version?
---@diagnostic disable: need-check-nil
- if mods == '' or mods == '=' then
- to.patch = to.patch + 1
- elseif mods == '<' then
+ if mods == '<' then
from = M._version({})
elseif mods == '<=' then
from = M._version({})
diff --git a/test/functional/lua/version_spec.lua b/test/functional/lua/version_spec.lua
@@ -55,9 +55,9 @@ describe('version', function()
describe('range', function()
local tests = {
- ['1.2.3'] = { from = { 1, 2, 3 }, to = { 1, 2, 4 } },
+ ['1.2.3'] = { from = { 1, 2, 3 }, to = { 1, 2, 3 } },
['1.2'] = { from = { 1, 2, 0 }, to = { 1, 3, 0 } },
- ['=1.2.3'] = { from = { 1, 2, 3 }, to = { 1, 2, 4 } },
+ ['=1.2.3'] = { from = { 1, 2, 3 }, to = { 1, 2, 3 } },
['>1.2.3'] = { from = { 1, 2, 4 } },
['>=1.2.3'] = { from = { 1, 2, 3 } },
['<1.2.3'] = { from = { 0, 0, 0 }, to = { 1, 2, 3 } },
@@ -100,17 +100,25 @@ describe('version', function()
end)
it('[to] not in range ' .. input .. ' to:' .. tostring(range.to), function()
- if range.to then
+ if range.to and range.to ~= range.from then
assert(not (range.to < range.to))
assert(not range:has(range.to))
end
end)
+
+ it('[to] in range ' .. input .. ' to:' .. tostring(range.to), function()
+ if range.to and range.to == range.from then
+ assert(range:has(range.to))
+ end
+ end)
end
it('handles prerelease', function()
assert(not vim.version.range('1.2.3'):has('1.2.3-alpha'))
assert(vim.version.range('1.2.3-alpha'):has('1.2.3-alpha'))
assert(not vim.version.range('1.2.3-alpha'):has('1.2.3-beta'))
+ assert(vim.version.range('>0.10'):has('0.12.0-dev'))
+ assert(not vim.version.range('>=0.12'):has('0.12.0-dev'))
end)
it('returns nil with empty version', function()
@@ -138,6 +146,7 @@ describe('version', function()
{ v1 = '1.0.0-2.0', v2 = '1.0.0-2', want = 1 },
{ v1 = '1.0.0-2.0', v2 = '1.0.0-2.0', want = 0 },
{ v1 = '1.0.0-alpha', v2 = '1.0.0-alpha', want = 0 },
+ -- Per semver spec, prereleases have alphabetical ordering.
{ v1 = '1.0.0-alpha', v2 = '1.0.0-beta', want = -1 },
{ v1 = '1.0.0-beta', v2 = '1.0.0-alpha', want = 1 },
{ v1 = '1.0.0-alpha', v2 = '1.0.0-alpha.1', want = -1 },