From ea0af5985488fe969365355ad4499fe30799394d Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Fri, 26 Jun 2026 10:50:17 +0100 Subject: [PATCH] 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 --- src/gen/gen_api_dispatch.lua | 11 ++++++++++- test/functional/api/version_spec.lua | 15 +++++++++++---- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/gen/gen_api_dispatch.lua b/src/gen/gen_api_dispatch.lua index e8bf7ea8f7..d7b4dde1b2 100644 --- a/src/gen/gen_api_dispatch.lua +++ b/src/gen/gen_api_dispatch.lua @@ -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' diff --git a/test/functional/api/version_spec.lua b/test/functional/api/version_spec.lua index e9770575ce..7bff668323 100644 --- a/test/functional/api/version_spec.lua +++ b/test/functional/api/version_spec.lua @@ -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 = {}