docs(api): document types using LuaCATS types

- Render Lua types in api.txt.

- Added `DictAs(name)` API type which acts the same as `Dict` (no parens)
  when generating the dispatchers, but acts the same as `Dict(name)`
  when generating docs.

- Added `Tuple(...)` API type which is the treated the as `Array` for
  generating the dispatchers, but is used to document richer types.

- Added `Enum(...)` API type to better document enums

- Improve typing of some API functions.

- Improve c_grammar to properly parse API types and replace string pattern
  logic in the parsers.

- Removed all the hardcoded type overrides in gen_eval_files.lua
This commit is contained in:
Lewis Russell
2025-06-16 11:45:44 +01:00
committed by Lewis Russell
parent 3eaa6c5a66
commit 76de3e2d07
21 changed files with 929 additions and 783 deletions

View File

@@ -90,7 +90,8 @@ static int64_t next_autocmd_id = 1;
/// - once: (boolean) whether the autocommand is only run once.
/// - pattern: (string) the autocommand pattern.
/// If the autocommand is buffer local |autocmd-buffer-local|:
Array nvim_get_autocmds(Dict(get_autocmds) *opts, Arena *arena, Error *err)
ArrayOf(DictAs(get_autocmds__ret)) nvim_get_autocmds(Dict(get_autocmds) *opts, Arena *arena,
Error *err)
FUNC_API_SINCE(9)
{
ArrayBuilder autocmd_list = KV_INITIAL_VALUE;

View File

@@ -856,7 +856,8 @@ Integer nvim_buf_get_changedtick(Buffer buffer, Error *err)
/// @param[out] err Error details, if any
/// @returns Array of |maparg()|-like dictionaries describing mappings.
/// The "buffer" key holds the associated buffer id.
ArrayOf(Dict) nvim_buf_get_keymap(Buffer buffer, String mode, Arena *arena, Error *err)
ArrayOf(DictAs(get_keymap)) nvim_buf_get_keymap(Buffer buffer, String mode, Arena *arena,
Error *err)
FUNC_API_SINCE(3)
{
buf_T *buf = find_buffer_by_handle(buffer, err);

View File

@@ -927,6 +927,8 @@ static void build_cmdline_str(char **cmdlinep, exarg_T *eap, CmdParseInfo *cmdin
}
}
// uncrustify:off
/// Creates a global |user-commands| command.
///
/// For Lua usage see |lua-guide-commands-create|.
@@ -968,13 +970,18 @@ static void build_cmdline_str(char **cmdlinep, exarg_T *eap, CmdParseInfo *cmdin
/// - force: (boolean, default true) Override any previous definition.
/// - preview: (function) Preview callback for 'inccommand' |:command-preview|
/// @param[out] err Error details, if any.
void nvim_create_user_command(uint64_t channel_id, String name, Object command,
Dict(user_command) *opts, Error *err)
void nvim_create_user_command(uint64_t channel_id,
String name,
Union(String, LuaRefOf((DictAs(create_user_command__command_args) args))) command,
Dict(user_command) *opts,
Error *err)
FUNC_API_SINCE(9)
{
create_user_command(channel_id, name, command, opts, 0, err);
}
// uncrustify:on
/// Delete a user-defined command.
///
/// @param name Name of the command to delete.
@@ -1045,8 +1052,8 @@ void nvim_buf_del_user_command(Buffer buffer, String name, Error *err)
api_set_error(err, kErrorTypeException, "Invalid command (not found): %s", name.data);
}
void create_user_command(uint64_t channel_id, String name, Object command, Dict(user_command) *opts,
int flags, Error *err)
void create_user_command(uint64_t channel_id, String name, Union(String, LuaRef) command,
Dict(user_command) *opts, int flags, Error *err)
{
uint32_t argt = 0;
int64_t def = -1;
@@ -1260,7 +1267,7 @@ err:
/// @param[out] err Error details, if any.
///
/// @returns Map of maps describing commands.
Dict nvim_get_commands(Dict(get_commands) *opts, Arena *arena, Error *err)
DictOf(DictAs(command_info)) nvim_get_commands(Dict(get_commands) *opts, Arena *arena, Error *err)
FUNC_API_SINCE(4)
{
return nvim_buf_get_commands(-1, opts, arena, err);
@@ -1273,7 +1280,8 @@ Dict nvim_get_commands(Dict(get_commands) *opts, Arena *arena, Error *err)
/// @param[out] err Error details, if any.
///
/// @returns Map of maps describing commands.
Dict nvim_buf_get_commands(Buffer buffer, Dict(get_commands) *opts, Arena *arena, Error *err)
DictAs(command_info) nvim_buf_get_commands(Buffer buffer, Dict(get_commands) *opts, Arena *arena,
Error *err)
FUNC_API_SINCE(4)
{
bool global = (buffer == -1);

View File

@@ -603,7 +603,7 @@ static int64_t convert_index(int64_t index)
/// @param name Option name
/// @param[out] err Error details, if any
/// @return Option Information
Dict nvim_get_option_info(String name, Arena *arena, Error *err)
DictAs(get_option_info) nvim_get_option_info(String name, Arena *arena, Error *err)
FUNC_API_SINCE(7)
FUNC_API_DEPRECATED_SINCE(11)
{

View File

@@ -75,7 +75,7 @@ Integer nvim_create_namespace(String name)
/// Gets existing, non-anonymous |namespace|s.
///
/// @return dict that maps from names to namespace ids.
Dict nvim_get_namespaces(Arena *arena)
DictOf(Integer) nvim_get_namespaces(Arena *arena)
FUNC_API_SINCE(5)
{
Dict retval = arena_dict(arena, map_size(&namespace_ids));
@@ -201,9 +201,9 @@ static Array extmark_to_array(MTPair extmark, bool id, bool add_dict, bool hl_na
/// @param[out] err Error details, if any
/// @return 0-indexed (row, col) tuple or empty list () if extmark id was
/// absent
ArrayOf(Integer) nvim_buf_get_extmark_by_id(Buffer buffer, Integer ns_id,
Integer id, Dict(get_extmark) *opts,
Arena *arena, Error *err)
Tuple(Integer, Integer, *DictAs(extmark_details))
nvim_buf_get_extmark_by_id(Buffer buffer, Integer ns_id, Integer id, Dict(get_extmark) * opts,
Arena *arena, Error *err)
FUNC_API_SINCE(7)
{
Array rv = ARRAY_DICT_INIT;
@@ -287,8 +287,10 @@ ArrayOf(Integer) nvim_buf_get_extmark_by_id(Buffer buffer, Integer ns_id,
/// - type: Filter marks by type: "highlight", "sign", "virt_text" and "virt_lines"
/// @param[out] err Error details, if any
/// @return List of `[extmark_id, row, col]` tuples in "traversal order".
Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object end,
Dict(get_extmarks) *opts, Arena *arena, Error *err)
ArrayOf(DictAs(get_extmark_item)) nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start,
Object end,
Dict(get_extmarks) *opts, Arena *arena,
Error *err)
FUNC_API_SINCE(7)
{
Array rv = ARRAY_DICT_INIT;

View File

@@ -116,9 +116,9 @@ typedef struct {
Float col;
Integer width;
Integer height;
String anchor;
String relative;
String split;
Enum("NW", "NE", "SW", "SE") anchor;
Enum("cursor", "editor", "laststatus", "mouse", "tabline", "win") relative;
Enum("left", "right", "above", "below") split;
Window win;
ArrayOf(Integer) bufpos;
Boolean external;
@@ -126,12 +126,12 @@ typedef struct {
Boolean mouse;
Boolean vertical;
Integer zindex;
Object border;
Union(ArrayOf(String), Enum("none", "single", "double", "rounded", "solid", "shadow")) border;
Object title;
String title_pos;
Enum("center", "left", "right") title_pos;
Object footer;
String footer_pos;
String style;
Enum("center", "left", "right") footer_pos;
Enum("minimal") style;
Boolean noautocmd;
Boolean fixed;
Boolean hide;
@@ -244,7 +244,7 @@ typedef struct {
typedef struct {
OptionalKeys is_set__create_autocmd_;
Buffer buffer;
Object callback;
Union(String, LuaRefOf((DictAs(create_autocmd__callback_args) args), *Boolean)) callback;
String command;
String desc;
Union(Integer, String) group;
@@ -279,15 +279,15 @@ typedef struct {
typedef struct {
OptionalKeys is_set__cmd_;
String cmd;
Array range;
ArrayOf(Integer) range;
Integer count;
String reg;
Boolean bang;
ArrayOf(String) args;
Dict magic;
Dict mods;
Union(Integer, String) nargs;
String addr;
DictAs(cmd__magic) magic;
DictAs(cmd__mods) mods;
Union(Integer, Enum("?", "+", "*")) nargs;
Enum("line", "arg", "buf", "load", "win", "tab", "qf", "none", "?") addr;
String nextcmd;
} Dict(cmd);

View File

@@ -308,7 +308,8 @@ Dict nvim_get_all_options_info(Arena *arena, Error *err)
/// Implies {scope} is "local".
/// @param[out] err Error details, if any
/// @return Option Information
Dict nvim_get_option_info2(String name, Dict(option) *opts, Arena *arena, Error *err)
DictAs(get_option_info) nvim_get_option_info2(String name, Dict(option) *opts, Arena *arena,
Error *err)
FUNC_API_SINCE(11)
{
OptIndex opt_idx = 0;

View File

@@ -18,11 +18,14 @@
#ifdef INCLUDE_GENERATED_DECLARATIONS
# define ArrayOf(...) Array
# define DictOf(...) Dict
# define DictAs(name) Dict
# define Dict(name) KeyDict_##name
# define Enum(...) String
# define DictHash(name) KeyDict_##name##_get_field
# define DictKey(name)
# define LuaRefOf(...) LuaRef
# define Union(...) Object
# define Tuple(...) Array
# include "api/private/defs.h.inline.generated.h"
#endif

View File

@@ -115,7 +115,7 @@ Integer nvim_get_hl_id_by_name(String name)
/// @param[out] err Error details, if any.
/// @return Highlight groups as a map from group name to a highlight definition map as in |nvim_set_hl()|,
/// or only a single highlight definition map if requested by name or id.
Dict nvim_get_hl(Integer ns_id, Dict(get_highlight) *opts, Arena *arena, Error *err)
DictAs(get_hl_info) nvim_get_hl(Integer ns_id, Dict(get_highlight) *opts, Arena *arena, Error *err)
FUNC_API_SINCE(11)
{
return ns_get_hl_defs((NS)ns_id, opts, arena, err);
@@ -607,7 +607,8 @@ String nvim__get_lib_dir(void)
/// @param all whether to return all matches or only the first
/// @param opts is_lua: only search Lua subdirs
/// @return list of absolute paths to the found files
ArrayOf(String) nvim__get_runtime(Array pat, Boolean all, Dict(runtime) *opts, Arena *arena,
ArrayOf(String) nvim__get_runtime(ArrayOf(String) pat, Boolean all, Dict(runtime) *opts,
Arena *arena,
Error *err)
FUNC_API_SINCE(8)
FUNC_API_FAST
@@ -761,7 +762,8 @@ void nvim_set_vvar(String name, Object value, Error *err)
/// - kind: Set the |ui-messages| kind with which this message will be emitted.
/// - verbose: Message is controlled by the 'verbose' option. Nvim invoked with `-V3log`
/// will write the message to the "log" file instead of standard output.
void nvim_echo(Array chunks, Boolean history, Dict(echo_opts) *opts, Error *err)
void nvim_echo(ArrayOf(Tuple(String, HLGroupID)) chunks, Boolean history, Dict(echo_opts) *opts,
Error *err)
FUNC_API_SINCE(7)
{
HlMessage hl_msg = parse_hl_msg(chunks, opts->err, err);
@@ -1320,10 +1322,10 @@ Integer nvim_get_color_by_name(String name)
/// (e.g. 65535).
///
/// @return Map of color names and RGB values.
Dict nvim_get_color_map(Arena *arena)
DictOf(Integer) nvim_get_color_map(Arena *arena)
FUNC_API_SINCE(1)
{
Dict colors = arena_dict(arena, ARRAY_SIZE(color_name_table));
DictOf(Integer) colors = arena_dict(arena, ARRAY_SIZE(color_name_table));
for (int i = 0; color_name_table[i].name != NULL; i++) {
PUT_C(colors, color_name_table[i].name, INTEGER_OBJ(color_name_table[i].color));
@@ -1406,7 +1408,7 @@ Object nvim_load_context(Dict dict, Error *err)
/// "blocking" is true if Nvim is waiting for input.
///
/// @returns Dict { "mode": String, "blocking": Boolean }
Dict nvim_get_mode(Arena *arena)
DictAs(get_mode) nvim_get_mode(Arena *arena)
FUNC_API_SINCE(2) FUNC_API_FAST
{
Dict rv = arena_dict(arena, 2);
@@ -1425,7 +1427,7 @@ Dict nvim_get_mode(Arena *arena)
/// @param mode Mode short-name ("n", "i", "v", ...)
/// @returns Array of |maparg()|-like dictionaries describing mappings.
/// The "buffer" key is always zero.
ArrayOf(Dict) nvim_get_keymap(String mode, Arena *arena)
ArrayOf(DictAs(get_keymap)) nvim_get_keymap(String mode, Arena *arena)
FUNC_API_SINCE(3)
{
return keymap_array(mode, NULL, arena);
@@ -1487,7 +1489,7 @@ void nvim_del_keymap(uint64_t channel_id, String mode, String lhs, Error *err)
/// 1 is the |api-metadata| map (Dict).
///
/// @returns 2-tuple `[{channel-id}, {api-metadata}]`
Array nvim_get_api_info(uint64_t channel_id, Arena *arena)
ArrayOf(Object, 2) nvim_get_api_info(uint64_t channel_id, Arena *arena)
FUNC_API_SINCE(1) FUNC_API_FAST FUNC_API_REMOTE_ONLY
{
Array rv = arena_array(arena, 2);
@@ -1624,7 +1626,7 @@ Dict nvim_get_chan_info(uint64_t channel_id, Integer chan, Arena *arena, Error *
///
/// @returns Array of Dictionaries, each describing a channel with
/// the format specified at |nvim_get_chan_info()|.
Array nvim_list_chans(Arena *arena)
ArrayOf(Dict) nvim_list_chans(Arena *arena)
FUNC_API_SINCE(4)
{
return channel_all_info(arena);
@@ -1715,7 +1717,7 @@ Dict nvim__stats(Arena *arena)
/// - "rgb" true if the UI uses RGB colors (false implies |cterm-colors|)
/// - "ext_..." Requested UI extensions, see |ui-option|
/// - "chan" |channel-id| of remote UI
Array nvim_list_uis(Arena *arena)
ArrayOf(Dict) nvim_list_uis(Arena *arena)
FUNC_API_SINCE(4)
{
return ui_array(arena);
@@ -1916,7 +1918,8 @@ Boolean nvim_del_mark(String name, Error *err)
/// not set.
/// @see |nvim_buf_set_mark()|
/// @see |nvim_del_mark()|
Array nvim_get_mark(String name, Dict(empty) *opts, Arena *arena, Error *err)
Tuple(Integer, Integer, Buffer, String) nvim_get_mark(String name, Dict(empty) *opts, Arena *arena,
Error *err)
FUNC_API_SINCE(8)
{
Array rv = ARRAY_DICT_INIT;
@@ -2001,7 +2004,8 @@ Array nvim_get_mark(String name, Dict(empty) *opts, Arena *arena, Error *err)
/// - start: (number) Byte index (0-based) of first character that uses the highlight.
/// - group: (string) Deprecated. Use `groups` instead.
/// - groups: (array) Names of stacked highlight groups (highest priority last).
Dict nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Arena *arena, Error *err)
DictAs(eval_statusline_ret) nvim_eval_statusline(String str, Dict(eval_statusline) *opts,
Arena *arena, Error *err)
FUNC_API_SINCE(8) FUNC_API_FAST
{
Dict result = ARRAY_DICT_INIT;
@@ -2188,7 +2192,7 @@ void nvim_error_event(uint64_t channel_id, Integer lvl, String data)
/// @return Dict containing these keys:
/// - winid: (number) floating window id
/// - bufnr: (number) buffer id in floating window
Dict nvim__complete_set(Integer index, Dict(complete_set) *opts, Arena *arena, Error *err)
DictOf(Float) nvim__complete_set(Integer index, Dict(complete_set) *opts, Arena *arena, Error *err)
{
Dict rv = arena_dict(arena, 2);
if ((get_cot_flags() & kOptCotFlagPopup) == 0) {

View File

@@ -500,7 +500,8 @@ void nvim_win_set_hl_ns(Window window, Integer ns_id, Error *err)
/// height is reached. 0 if "end_row" is a closed fold.
///
/// @see |virtcol()| for text width.
Dict nvim_win_text_height(Window window, Dict(win_text_height) *opts, Arena *arena, Error *err)
DictAs(win_text_height_ret) nvim_win_text_height(Window window, Dict(win_text_height) *opts,
Arena *arena, Error *err)
FUNC_API_SINCE(12)
{
Dict rv = arena_dict(arena, 2);