mirror of
https://github.com/neovim/neovim.git
synced 2026-05-24 05:40:08 +00:00
build(docs): sort/lint class fields and keysets
Problem: Fields (key names) in classes, keysets, and quasi-keysets are ordered randomly, which adds friction when reading docs. Solution: - Sort class fields and keysets when generating docs. - Add a lint check for quasi-keysets (keysets defined as unstructured markdown lists within a docstring).
This commit is contained in:
@@ -328,6 +328,7 @@ local function get_api_keysets_meta()
|
||||
lint.lint_names('src/nvim/api/keysets_defs.h', nil, keysets)
|
||||
|
||||
for _, k in ipairs(keysets) do
|
||||
util.sort_by_key(k.keys)
|
||||
local params = {}
|
||||
for _, key in ipairs(k.keys) do
|
||||
local pty = k.types[key] or 'any'
|
||||
|
||||
@@ -610,6 +610,8 @@ local function inline_type(obj, classes)
|
||||
end
|
||||
end
|
||||
|
||||
util.sort_by_key(cls.fields, 'name')
|
||||
|
||||
local desc_append = {}
|
||||
for _, f in ipairs(cls.fields) do
|
||||
if not f.access then
|
||||
@@ -715,6 +717,8 @@ local function render_class(class, classes, hidden_fields, cfg)
|
||||
end, fields)
|
||||
end
|
||||
|
||||
util.sort_by_key(fields, 'name')
|
||||
|
||||
local fields_txt = render_fields_or_params(fields, nil, classes, cfg)
|
||||
if not fields_txt:match('^%s*$') then
|
||||
table.insert(ret, '\n Fields: ~\n')
|
||||
@@ -1145,6 +1149,7 @@ local function gen_target(cfg)
|
||||
|
||||
if not f:find('ui_events%.in%.h$') then -- TODO(justinmk): also lint UI events.
|
||||
lint.lint_names(f, funs, nil, classes)
|
||||
lint.lint_quasi_keysets(f, funs)
|
||||
end
|
||||
|
||||
local mod_cls_nm = find_module_class(classes, 'M')
|
||||
|
||||
@@ -226,4 +226,46 @@ function M.lint_names(source, api_funs, keysets, classes)
|
||||
end
|
||||
end
|
||||
|
||||
--- Checks that markdown list items (`- name :` or `- {name}`) in parameter/field
|
||||
--- descriptions are in sorted order.
|
||||
---
|
||||
--- This is for "quasi-keysets" defined as markdown lists in docstrings. Ideally they would be
|
||||
--- defined as a luals `@class` or a API keyset, but sometimes that isn't possible.
|
||||
---
|
||||
--- @param source string Source filename.
|
||||
--- @param funs {name:string, params:{name:string, desc?:string}[]}[]
|
||||
function M.lint_quasi_keysets(source, funs)
|
||||
local errors = {} --- @type string[]
|
||||
|
||||
for _, fun in ipairs(funs) do
|
||||
for _, p in ipairs(fun.params or {}) do
|
||||
if p.desc then
|
||||
local prev = nil --- @type string?
|
||||
for name in p.desc:gmatch('\n%- ([%w_]+)') do
|
||||
-- Sort underscore-prefixed keys (e.g. "_cmdline_offset") at the end.
|
||||
local prev_key = prev and prev:gsub('^_', '~') or nil
|
||||
local name_key = name:gsub('^_', '~')
|
||||
if prev_key and name_key < prev_key then
|
||||
errors[#errors + 1] = fmt(
|
||||
'%s: %s(): param "%s": key "%s" should come before "%s" (sort alphabetically)',
|
||||
source,
|
||||
fun.name,
|
||||
p.name,
|
||||
name,
|
||||
prev
|
||||
)
|
||||
end
|
||||
prev = name
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if #errors > 0 then
|
||||
error(
|
||||
'lint_quasi_keysets(): unsorted keys in doc comments:\n ' .. table.concat(errors, '\n ')
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
return M
|
||||
|
||||
@@ -404,4 +404,17 @@ function M.md_to_vimdoc(text, start_indent, indent, text_width, is_list)
|
||||
return s
|
||||
end
|
||||
|
||||
--- Sorts a list in-place, with underscore-prefixed names last (e.g. "_cmdline_offset").
|
||||
--- If `key` is given, sorts by `item[key]`; otherwise sorts by value.
|
||||
---
|
||||
--- @param t any[]
|
||||
--- @param key? string
|
||||
function M.sort_by_key(t, key)
|
||||
table.sort(t, function(a, b)
|
||||
local a_val = key and a[key] or a
|
||||
local b_val = key and b[key] or b
|
||||
return a_val:gsub('^_', '~') < b_val:gsub('^_', '~')
|
||||
end)
|
||||
end
|
||||
|
||||
return M
|
||||
|
||||
Reference in New Issue
Block a user