@@ -200,22 +200,101 @@ function M.parse_requirements(str)
200200 return requirements
201201end
202202
203- -- TODO: port https://github.com/dtolnay/semver/blob/master/src%2Fimpls.rs#L51-L107
204203--- @param version ? string
205204--- @param req ? string
206205--- @return integer
207206function M .compare_pre (version , req )
208- if version and req then
209- if version < req then
207+ -- Handle identical strings (optimization)
208+ if version == req then
209+ return 0
210+ end
211+
212+ -- Handle empty prerelease cases
213+ local version_empty = not version or version == " "
214+ local req_empty = not req or req == " "
215+
216+ if version_empty and req_empty then
217+ return 0
218+ elseif version_empty then
219+ -- A real release compares greater than prerelease
220+ return 1
221+ elseif req_empty then
222+ -- Prerelease compares less than the real release
223+ return - 1
224+ end
225+
226+ --- @param str string
227+ --- @return boolean
228+ local function is_numeric (str )
229+ return str :match (" ^%d+$" ) ~= nil
230+ end
231+
232+ --- @param a string
233+ --- @param b string
234+ --- @return integer
235+ local function compare_numeric_strings (a , b )
236+ -- First compare by length (shorter number is smaller)
237+ local len_cmp = # a - # b
238+ if len_cmp ~= 0 then
239+ return len_cmp
240+ end
241+ -- If same length, compare lexically
242+ if a < b then
210243 return - 1
211- elseif version == req then
244+ elseif a > b then
245+ return 1
246+ else
212247 return 0
213- elseif version > req then
248+ end
249+ end
250+
251+ local version_parts = version and vim .split (version , " %." ) or {}
252+ local req_parts = req and vim .split (req , " %." ) or {}
253+
254+ local max_len = math.max (# version_parts , # req_parts )
255+
256+ for i = 1 , max_len do
257+ local version_part = version_parts [i ]
258+ local req_part = req_parts [i ]
259+
260+ -- If one side has no more parts, the longer one is greater
261+ if not version_part then
262+ return - 1
263+ elseif not req_part then
214264 return 1
215265 end
266+
267+ local version_numeric = is_numeric (version_part )
268+ local req_numeric = is_numeric (req_part )
269+
270+ --- @type integer
271+ local cmp
272+ if version_numeric and req_numeric then
273+ -- Both numeric: compare numerically
274+ cmp = compare_numeric_strings (version_part , req_part )
275+ elseif version_numeric and not req_numeric then
276+ -- Numeric has lower precedence than non-numeric
277+ cmp = - 1
278+ elseif not version_numeric and req_numeric then
279+ -- Non-numeric has higher precedence than numeric
280+ cmp = 1
281+ else
282+ -- Both non-numeric: compare lexically
283+ if version_part < req_part then
284+ cmp = - 1
285+ elseif version_part > req_part then
286+ cmp = 1
287+ else
288+ cmp = 0
289+ end
290+ end
291+
292+ if cmp ~= 0 then
293+ return cmp
294+ end
216295 end
217296
218- return ( req and 1 or 0 ) - ( version and 1 or 0 )
297+ return 0
219298end
220299
221300-- TODO: port https://github.com/dtolnay/semver/blob/master/src/impls.rs#L109-L153
0 commit comments