diff options
author | Josh Rahm <joshuarahm@gmail.com> | 2024-11-19 22:57:13 +0000 |
---|---|---|
committer | Josh Rahm <joshuarahm@gmail.com> | 2024-11-19 22:57:13 +0000 |
commit | 9be89f131f87608f224f0ee06d199fcd09d32176 (patch) | |
tree | 11022dcfa9e08cb4ac5581b16734196128688d48 /scripts/gen_eval_files.lua | |
parent | ff7ed8f586589d620a806c3758fac4a47a8e7e15 (diff) | |
parent | 88085c2e80a7e3ac29aabb6b5420377eed99b8b6 (diff) | |
download | rneovim-9be89f131f87608f224f0ee06d199fcd09d32176.tar.gz rneovim-9be89f131f87608f224f0ee06d199fcd09d32176.tar.bz2 rneovim-9be89f131f87608f224f0ee06d199fcd09d32176.zip |
Merge remote-tracking branch 'upstream/master' into mix_20240309
Diffstat (limited to 'scripts/gen_eval_files.lua')
-rwxr-xr-x | scripts/gen_eval_files.lua | 166 |
1 files changed, 109 insertions, 57 deletions
diff --git a/scripts/gen_eval_files.lua b/scripts/gen_eval_files.lua index f1bba5c0a2..b9ea4e73f0 100755 --- a/scripts/gen_eval_files.lua +++ b/scripts/gen_eval_files.lua @@ -2,11 +2,15 @@ -- Generator for various vimdoc and Lua type files +local util = require('scripts.util') +local fmt = string.format + local DEP_API_METADATA = 'build/funcs_metadata.mpack' +local TEXT_WIDTH = 78 --- @class vim.api.metadata --- @field name string ---- @field parameters {[1]:string,[2]:string}[] +--- @field parameters [string,string][] --- @field return_type string --- @field deprecated_since integer --- @field eval boolean @@ -20,7 +24,7 @@ local DEP_API_METADATA = 'build/funcs_metadata.mpack' local LUA_API_RETURN_OVERRIDES = { nvim_buf_get_command = 'table<string,vim.api.keyset.command_info>', - nvim_buf_get_extmark_by_id = 'vim.api.keyset.get_extmark_item', + nvim_buf_get_extmark_by_id = 'vim.api.keyset.get_extmark_item_by_id', nvim_buf_get_extmarks = 'vim.api.keyset.get_extmark_item[]', nvim_buf_get_keymap = 'vim.api.keyset.keymap[]', nvim_get_autocmds = 'vim.api.keyset.get_autocmds.ret[]', @@ -29,11 +33,11 @@ local LUA_API_RETURN_OVERRIDES = { nvim_get_keymap = 'vim.api.keyset.keymap[]', nvim_get_mark = 'vim.api.keyset.get_mark', - -- Can also return table<string,vim.api.keyset.hl_info>, however we need to + -- Can also return table<string,vim.api.keyset.get_hl_info>, however we need to -- pick one to get some benefit. -- REVISIT lewrus01 (26/01/24): we can maybe add - -- @overload fun(ns: integer, {}): table<string,vim.api.keyset.hl_info> - nvim_get_hl = 'vim.api.keyset.hl_info', + -- @overload fun(ns: integer, {}): table<string,vim.api.keyset.get_hl_info> + nvim_get_hl = 'vim.api.keyset.get_hl_info', nvim_get_mode = 'vim.api.keyset.get_mode', nvim_get_namespaces = 'table<string,integer>', @@ -112,7 +116,7 @@ local API_TYPES = { String = 'string', Array = 'any[]', LuaRef = 'function', - Dictionary = 'table<string,any>', + Dict = 'table<string,any>', Float = 'number', HLGroupID = 'number|string', void = '', @@ -140,7 +144,7 @@ local function api_type(t) return 'vim.api.keyset.' .. d end - local d0 = t:match('^DictionaryOf%((.*)%)') + local d0 = t:match('^DictOf%((.*)%)') if d0 then return 'table<string,' .. api_type(d0) .. '>' end @@ -149,7 +153,7 @@ local function api_type(t) end --- @param f string ---- @param params {[1]:string,[2]:string}[]|true +--- @param params [string,string][]|true --- @return string local function render_fun_sig(f, params) local param_str --- @type string @@ -158,7 +162,7 @@ local function render_fun_sig(f, params) else param_str = table.concat( vim.tbl_map( - --- @param v {[1]:string,[2]:string} + --- @param v [string,string] --- @return string function(v) return v[1] @@ -170,16 +174,16 @@ local function render_fun_sig(f, params) end if LUA_KEYWORDS[f] then - return string.format("vim.fn['%s'] = function(%s) end", f, param_str) + return fmt("vim.fn['%s'] = function(%s) end", f, param_str) else - return string.format('function vim.fn.%s(%s) end', f, param_str) + return fmt('function vim.fn.%s(%s) end', f, param_str) end end --- Uniquify names --- Fix any names that are lua keywords ---- @param params {[1]:string,[2]:string,[3]:string}[] ---- @return {[1]:string,[2]:string,[3]:string}[] +--- @param params [string,string,string][] +--- @return [string,string,string][] local function process_params(params) local seen = {} --- @type table<string,true> local sfx = 1 @@ -199,14 +203,6 @@ local function process_params(params) return params end ---- @class vim.gen_vim_doc_fun ---- @field signature string ---- @field doc string[] ---- @field parameters_doc table<string,string> ---- @field return string[] ---- @field seealso string[] ---- @field annotations string[] - --- @return table<string, vim.EvalFn> local function get_api_meta() local ret = {} --- @type table<string, vim.EvalFn> @@ -245,7 +241,17 @@ local function get_api_meta() for _, fun in pairs(functions) do local deprecated = fun.deprecated_since ~= nil - local params = {} --- @type {[1]:string,[2]:string}[] + local notes = {} --- @type string[] + for _, note in ipairs(fun.notes or {}) do + notes[#notes + 1] = note.desc + end + + local sees = {} --- @type string[] + for _, see in ipairs(fun.see or {}) do + sees[#sees + 1] = see.desc + end + + local params = {} --- @type [string,string][] for _, p in ipairs(fun.params) do params[#params + 1] = { p.name, @@ -258,13 +264,15 @@ local function get_api_meta() signature = 'NA', name = fun.name, params = params, + notes = notes, + see = sees, returns = api_type(fun.returns[1].type), deprecated = deprecated, } if not deprecated then r.desc = fun.desc - r.return_desc = fun.returns[1].desc + r.returns_desc = fun.returns[1].desc end ret[fun.name] = r @@ -278,8 +286,19 @@ end --- Ensure code blocks have one empty line before the start fence and after the closing fence. --- --- @param x string +--- @param special string? +--- | 'see-api-meta' Normalize `@see` for API meta docstrings. --- @return string -local function norm_text(x) +local function norm_text(x, special) + if special == 'see-api-meta' then + -- Try to guess a symbol that actually works in @see. + -- "nvim_xx()" => "vim.api.nvim_xx" + x = x:gsub([=[%|?(nvim_[^.()| ]+)%(?%)?%|?]=], 'vim.api.%1') + -- TODO: Remove backticks when LuaLS resolves: https://github.com/LuaLS/lua-language-server/issues/2889 + -- "|foo|" => "`:help foo`" + x = x:gsub([=[|([^ ]+)|]=], '`:help %1`') + end + return ( x:gsub('|([^ ]+)|', '`%1`') :gsub('\n*>lua', '\n\n```lua') @@ -291,14 +310,13 @@ local function norm_text(x) ) end +--- Generates LuaLS docstring for an API function. --- @param _f string --- @param fun vim.EvalFn --- @param write fun(line: string) local function render_api_meta(_f, fun, write) write('') - local text_utils = require('scripts.text_utils') - if vim.startswith(fun.name, 'nvim__') then write('--- @private') end @@ -309,10 +327,18 @@ local function render_api_meta(_f, fun, write) local desc = fun.desc if desc then - desc = text_utils.md_to_vimdoc(desc, 0, 0, 74) - for _, l in ipairs(split(norm_text(desc))) do - write('--- ' .. l) - end + write(util.prefix_lines('--- ', norm_text(desc))) + end + + -- LuaLS doesn't support @note. Render @note items as a markdown list. + if fun.notes and #fun.notes > 0 then + write('--- Note:') + write(util.prefix_lines('--- ', table.concat(fun.notes, '\n'))) + write('---') + end + + for _, see in ipairs(fun.see or {}) do + write(util.prefix_lines('--- @see ', norm_text(see, 'see-api-meta'))) end local param_names = {} --- @type string[] @@ -322,8 +348,6 @@ local function render_api_meta(_f, fun, write) local pdesc = p[3] if pdesc then local s = '--- @param ' .. p[1] .. ' ' .. p[2] .. ' ' - local indent = #('@param ' .. p[1] .. ' ') - pdesc = text_utils.md_to_vimdoc(pdesc, #s, indent, 74, true) local pdesc_a = split(vim.trim(norm_text(pdesc))) write(s .. pdesc_a[1]) for i = 2, #pdesc_a do @@ -336,15 +360,15 @@ local function render_api_meta(_f, fun, write) write('--- @param ' .. p[1] .. ' ' .. p[2]) end end + if fun.returns ~= '' then - local ret_desc = fun.returns_desc and ' : ' .. fun.returns_desc or '' - ret_desc = text_utils.md_to_vimdoc(ret_desc, 0, 0, 74) + local ret_desc = fun.returns_desc and ' # ' .. fun.returns_desc or '' local ret = LUA_API_RETURN_OVERRIDES[fun.name] or fun.returns - write('--- @return ' .. ret .. ret_desc) + write(util.prefix_lines('--- ', '@return ' .. ret .. ret_desc)) end local param_str = table.concat(param_names, ', ') - write(string.format('function vim.api.%s(%s) end', fun.name, param_str)) + write(fmt('function vim.api.%s(%s) end', fun.name, param_str)) end --- @return table<string, vim.EvalFn> @@ -372,10 +396,14 @@ local function get_api_keysets_meta() return ret end +--- Generates LuaLS docstring for an API keyset. --- @param _f string --- @param fun vim.EvalFn --- @param write fun(line: string) local function render_api_keyset_meta(_f, fun, write) + if string.sub(fun.name, 1, 1) == '_' then + return -- not exported + end write('') write('--- @class vim.api.keyset.' .. fun.name) for _, p in ipairs(fun.params) do @@ -388,6 +416,7 @@ local function get_eval_meta() return require('src/nvim/eval').funcs end +--- Generates LuaLS docstring for a Vimscript "eval" function. --- @param f string --- @param fun vim.EvalFn --- @param write fun(line: string) @@ -397,7 +426,6 @@ local function render_eval_meta(f, fun, write) end local funname = fun.name or f - local params = process_params(fun.params) write('') @@ -421,25 +449,28 @@ local function render_eval_meta(f, fun, write) for i, param in ipairs(params) do local pname, ptype = param[1], param[2] local optional = (pname ~= '...' and i > req_args) and '?' or '' - write(string.format('--- @param %s%s %s', pname, optional, ptype)) + write(fmt('--- @param %s%s %s', pname, optional, ptype)) end if fun.returns ~= false then - write('--- @return ' .. (fun.returns or 'any')) + local ret_desc = fun.returns_desc and ' # ' .. fun.returns_desc or '' + write('--- @return ' .. (fun.returns or 'any') .. ret_desc) end write(render_fun_sig(funname, params)) end +--- Generates vimdoc heading for a Vimscript "eval" function signature. --- @param name string +--- @param name_tag boolean --- @param fun vim.EvalFn --- @param write fun(line: string) -local function render_sig_and_tag(name, fun, write) +local function render_sig_and_tag(name, name_tag, fun, write) if not fun.signature then return end - local tags = { '*' .. name .. '()*' } + local tags = name_tag and { '*' .. name .. '()*' } or {} if fun.tags then for _, t in ipairs(fun.tags) do @@ -447,6 +478,11 @@ local function render_sig_and_tag(name, fun, write) end end + if #tags == 0 then + write(fun.signature) + return + end + local tag = table.concat(tags, ' ') local siglen = #fun.signature local conceal_offset = 2 * (#tags - 1) @@ -456,32 +492,28 @@ local function render_sig_and_tag(name, fun, write) write(string.rep(' ', tag_pad_len) .. tag) write(fun.signature) else - write(string.format('%s%s%s', fun.signature, string.rep(' ', tag_pad_len - siglen), tag)) + write(fmt('%s%s%s', fun.signature, string.rep(' ', tag_pad_len - siglen), tag)) end end +--- Generates vimdoc for a Vimscript "eval" function. --- @param f string --- @param fun vim.EvalFn --- @param write fun(line: string) local function render_eval_doc(f, fun, write) - if fun.deprecated then - return - end - - if not fun.signature then + if fun.deprecated or not fun.signature then return end - if f:find('__%d+$') then - write(fun.signature) - else - render_sig_and_tag(fun.name or f, fun, write) - end + render_sig_and_tag(fun.name or f, not f:find('__%d+$'), fun, write) if not fun.desc then return end + local params = process_params(fun.params) + local req_args = type(fun.args) == 'table' and fun.args[1] or fun.args or 0 + local desc_l = split(vim.trim(fun.desc)) for _, l in ipairs(desc_l) do l = l:gsub('^ ', '') @@ -497,6 +529,26 @@ local function render_eval_doc(f, fun, write) if #desc_l > 0 and not desc_l[#desc_l]:match('^<?$') then write('') end + + if #params > 0 then + write(util.md_to_vimdoc('Parameters: ~', 16, 16, TEXT_WIDTH)) + for i, param in ipairs(params) do + local pname, ptype = param[1], param[2] + local optional = (pname ~= '...' and i > req_args) and '?' or '' + local s = fmt('- %-14s (`%s%s`)', fmt('{%s}', pname), ptype, optional) + write(util.md_to_vimdoc(s, 16, 18, TEXT_WIDTH)) + end + write('') + end + + if fun.returns ~= false then + write(util.md_to_vimdoc('Return: ~', 16, 16, TEXT_WIDTH)) + local ret = ('(`%s`)'):format((fun.returns or 'any')) + ret = ret .. (fun.returns_desc and ' ' .. fun.returns_desc or '') + ret = util.md_to_vimdoc(ret, 18, 18, TEXT_WIDTH) + write(ret) + write('') + end end --- @param d vim.option_defaults @@ -734,9 +786,9 @@ local function render_option_doc(_f, opt, write) local name_str --- @type string if opt.abbreviation then - name_str = string.format("'%s' '%s'", opt.full_name, opt.abbreviation) + name_str = fmt("'%s' '%s'", opt.full_name, opt.abbreviation) else - name_str = string.format("'%s'", opt.full_name) + name_str = fmt("'%s'", opt.full_name) end local otype = opt.type == 'boolean' and 'boolean' or opt.type @@ -744,13 +796,13 @@ local function render_option_doc(_f, opt, write) local v = render_option_default(opt.defaults, true) local pad = string.rep('\t', math.max(1, math.ceil((24 - #name_str) / 8))) if opt.defaults.doc then - local deflen = #string.format('%s%s%s (', name_str, pad, otype) + local deflen = #fmt('%s%s%s (', name_str, pad, otype) --- @type string v = v:gsub('\n', '\n' .. string.rep(' ', deflen - 2)) end - write(string.format('%s%s%s\t(default %s)', name_str, pad, otype, v)) + write(fmt('%s%s%s\t(default %s)', name_str, pad, otype, v)) else - write(string.format('%s\t%s', name_str, otype)) + write(fmt('%s\t%s', name_str, otype)) end write('\t\t\t' .. scope_to_doc(opt.scope) .. scope_more_doc(opt)) |