fix(api): preserve ArrayOf metadata #40429

ArrayOf metadata existed before the LuaCATS type documentation refactor and is
useful to typed clients consuming api_info().

Keep Tuple metadata normalized to Array, since tuple element types can be mixed,
but preserve ArrayOf(...) for exported API metadata.

Fixes #38734

AI-assisted: Codex
This commit is contained in:
Lewis Russell
2026-06-26 10:50:17 +01:00
committed by GitHub
parent b9b1992d9d
commit ea0af59854
2 changed files with 21 additions and 5 deletions

View File

@@ -24,7 +24,16 @@ local function real_type(type, exported)
local container = ptype[1]
if container == 'Union' then
return 'Object'
elseif container == 'Tuple' or container == 'ArrayOf' then
elseif container == 'Tuple' then
return 'Array'
elseif container == 'ArrayOf' then
if exported then
local elem = real_type(ptype[2], true)
if ptype[3] then
return ('ArrayOf(%s, %s)'):format(elem, ptype[3])
end
return ('ArrayOf(%s)'):format(elem)
end
return 'Array'
elseif container == 'DictOf' or container == 'DictAs' then
return 'Dict'

View File

@@ -59,15 +59,15 @@ describe('api metadata', function()
--- Remove or patch metadata that is not essential to backwards-compatibility.
--- @param f gen_api_dispatch.Function.Exported
local function normalize_func_metadata(f)
-- Dictionary was renamed to Dict. That doesn't break back-compat because clients don't actually
-- use the `return_type` field (evidence: "ArrayOf(…)" didn't break clients).
-- Dictionary was renamed to Dict. That doesn't break back-compat because it names the
-- same RPC map type.
f.return_type = f.return_type:gsub('Dictionary', 'Dict')
f.return_type = f.return_type:gsub('^ArrayOf%(.*', 'Array')
f.deprecated_since = nil
for idx, _ in ipairs(f.parameters) do
-- Dictionary was renamed to Dict. Doesn't break back-compat because clients don't actually
-- use the `parameters` field of API metadata (evidence: "ArrayOf(…)" didn't break clients).
-- Dictionary was renamed to Dict. That doesn't break back-compat because it names the
-- same RPC map type.
f.parameters[idx][1] = f.parameters[idx][1]:gsub('Dictionary', 'Dict')
f.parameters[idx][1] = f.parameters[idx][1]:gsub('ArrayOf%(.*', 'Array')
@@ -151,6 +151,13 @@ describe('api metadata', function()
n.check_close()
end)
it('preserves ArrayOf type metadata', function()
local funcs = name_table(api_info.functions)
eq('ArrayOf(String)', funcs.nvim_list_runtime_paths.return_type)
eq('ArrayOf(Integer, 2)', funcs.nvim_buf_get_mark.return_type)
eq('ArrayOf(String)', funcs.nvim_buf_set_lines.parameters[5][1])
end)
it('functions are compatible with old metadata or have new level', function()
local funcs_new = name_table(api_info.functions)
local funcs_compat = {}