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
(cherry picked from commit ea0af59854)
This commit is contained in:
Lewis Russell
2026-06-26 10:50:17 +01:00
committed by github-actions[bot]
parent fa365cedad
commit ea07b60fb1
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] local container = ptype[1]
if container == 'Union' then if container == 'Union' then
return 'Object' 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' return 'Array'
elseif container == 'DictOf' or container == 'DictAs' then elseif container == 'DictOf' or container == 'DictAs' then
return 'Dict' return 'Dict'

View File

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