diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua index 52a21587f4..fd49f63558 100644 --- a/runtime/lua/vim/_editor.lua +++ b/runtime/lua/vim/_editor.lua @@ -1033,21 +1033,44 @@ end --- ---@return string|nil # Deprecated message, or nil if no message was shown. function vim.deprecate(name, alternative, version, plugin, backtrace) + vim.validate { + name = { name, 'string' }, + alternative = { alternative, 'string', true }, + version = { version, 'string', true }, + plugin = { plugin, 'string', true }, + } + plugin = plugin or 'Nvim' + -- Only issue warning if feature is hard-deprecated as specified by MAINTAIN.md. - if plugin == nil then - local current_version = vim.version() - local deprecated_version = assert(vim.version.parse(version)) - local soft_deprecated_version = - { deprecated_version.major, deprecated_version.minor - 1, deprecated_version.patch } - local deprecate = vim.version.lt(current_version, soft_deprecated_version) - if deprecate then + -- e.g., when planned to be removed in version = '0.12' (soft-deprecated since 0.10-dev), + -- show warnings since 0.11, including 0.11-dev (hard_deprecated_since = 0.11-dev). + if plugin == 'Nvim' then + local current_version = vim.version() ---@type Version + local removal_version = assert(vim.version.parse(version)) + local is_hard_deprecated ---@type boolean + + if removal_version.minor > 0 then + local hard_deprecated_since = assert(vim.version._version({ + major = removal_version.major, + minor = removal_version.minor - 1, + patch = 0, + prerelease = 'dev', -- Show deprecation warnings in devel (nightly) version as well + })) + is_hard_deprecated = (current_version >= hard_deprecated_since) + else + -- Assume there will be no next minor version before bumping up the major version; + -- therefore we can always show a warning. + assert(removal_version.minor == 0, vim.inspect(removal_version)) + is_hard_deprecated = true + end + + if not is_hard_deprecated then return end end local msg = ('%s is deprecated'):format(name) - plugin = plugin or 'Nvim' - msg = alternative and ('%s, use %s instead.'):format(msg, alternative) or msg + msg = alternative and ('%s, use %s instead.'):format(msg, alternative) or (msg .. '.') msg = ('%s%s\nThis feature will be removed in %s version %s'):format( msg, (plugin == 'Nvim' and ' :help deprecated' or ''), diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua index 98968f3695..6e05728b0c 100644 --- a/test/functional/lua/vim_spec.lua +++ b/test/functional/lua/vim_spec.lua @@ -128,33 +128,93 @@ describe('lua stdlib', function() eq(1, fn.luaeval('vim.stricmp("\\0C\\0", "\\0B\\0")')) end) - it('vim.deprecate', function() + local function test_vim_deprecate(current_version) -- vim.deprecate(name, alternative, version, plugin, backtrace) - eq( - dedent [[ - foo.bar() is deprecated, use zub.wooo{ok=yay} instead. :help deprecated - This feature will be removed in Nvim version 0.10]], - exec_lua('return vim.deprecate(...)', 'foo.bar()', 'zub.wooo{ok=yay}', '0.10') - ) - -- Same message, skipped. - eq(vim.NIL, exec_lua('return vim.deprecate(...)', 'foo.bar()', 'zub.wooo{ok=yay}', '0.10')) - -- Don't show error if not hard deprecated - eq(vim.NIL, exec_lua('return vim.deprecate(...)', 'foo.bar()', 'nil', '5000.0.0')) - -- When `plugin` is specified, don't show ":help deprecated". #22235 - eq( - dedent [[ - foo.bar() is deprecated, use zub.wooo{ok=yay} instead. - This feature will be removed in my-plugin.nvim version 0.3.0]], - exec_lua( - 'return vim.deprecate(...)', - 'foo.bar()', - 'zub.wooo{ok=yay}', - '0.3.0', - 'my-plugin.nvim', - false - ) - ) - end) + -- See MAINTAIN.md for the soft/hard deprecation policy + + describe(('vim.deprecate [current_version = %s]'):format(current_version), function() + before_each(function() + -- mock vim.version() behavior, should be pinned for consistent testing + exec_lua( + [[ + local current_version_mock = vim.version.parse(...) + getmetatable(vim.version).__call = function() + return current_version_mock + end + ]], + current_version + ) + end) + + it('when plugin = nil', function() + eq( + dedent [[ + foo.bar() is deprecated, use zub.wooo{ok=yay} instead. :help deprecated + This feature will be removed in Nvim version 0.10]], + exec_lua('return vim.deprecate(...)', 'foo.bar()', 'zub.wooo{ok=yay}', '0.10') + ) + -- Same message, skipped. + eq(vim.NIL, exec_lua('return vim.deprecate(...)', 'foo.bar()', 'zub.wooo{ok=yay}', '0.10')) + + -- Don't show error if not hard-deprecated (only soft-deprecated) + eq( + vim.NIL, + exec_lua('return vim.deprecate(...)', 'foo.baz()', 'foo.better_baz()', '0.12.0') + ) + + -- Show error if hard-deprecated + eq( + dedent [[ + foo.hard_dep() is deprecated, use vim.new_api() instead. :help deprecated + This feature will be removed in Nvim version 0.11]], + exec_lua('return vim.deprecate(...)', 'foo.hard_dep()', 'vim.new_api()', '0.11') + ) + + -- To be deleted in the next major version (1.0) + eq( + dedent [[ + foo.baz() is deprecated. :help deprecated + This feature will be removed in Nvim version 1.0]], + exec_lua [[ return vim.deprecate('foo.baz()', nil, '1.0') ]] + ) + end) + + it('when plugin is specified', function() + -- When `plugin` is specified, don't show ":help deprecated". #22235 + eq( + dedent [[ + foo.bar() is deprecated, use zub.wooo{ok=yay} instead. + This feature will be removed in my-plugin.nvim version 0.3.0]], + exec_lua( + 'return vim.deprecate(...)', + 'foo.bar()', + 'zub.wooo{ok=yay}', + '0.3.0', + 'my-plugin.nvim', + false + ) + ) + + -- plugins: no soft deprecation period + eq( + dedent [[ + foo.bar() is deprecated, use zub.wooo{ok=yay} instead. + This feature will be removed in my-plugin.nvim version 0.11.0]], + exec_lua( + 'return vim.deprecate(...)', + 'foo.bar()', + 'zub.wooo{ok=yay}', + '0.11.0', + 'my-plugin.nvim', + false + ) + ) + end) + end) + end + + test_vim_deprecate('0.10') + test_vim_deprecate('0.10-dev+g0000000') it('vim.startswith', function() eq(true, fn.luaeval('vim.startswith("123", "1")'))