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
This commit is contained in:
Phạm Bình An
2025-04-11 17:15:18 +07:00
committed by brianhuster
parent ae05e0399b
commit 7286e514f2
2 changed files with 15 additions and 8 deletions

View File

@ -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({})

View File

@ -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 },