Skip to content

Commit

Permalink
fix: improved emmy lua annotations
Browse files Browse the repository at this point in the history
  • Loading branch information
folke committed May 20, 2021
1 parent 72c4e61 commit 4f5a10f
Show file tree
Hide file tree
Showing 14 changed files with 387 additions and 317 deletions.
154 changes: 102 additions & 52 deletions lua/lua-dev/parser.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,79 +3,129 @@ local M = {}

function M.comment(str, comment_str)
comment_str = comment_str or "--"
return comment_str .. " " .. str:gsub("[\n]", "\n" .. comment_str .. " ")
return comment_str .. " " .. vim.fn.trim(str):gsub("[\n]", "\n" .. comment_str .. " "):gsub("%s+\n", "\n")
end

function M.infer_type(doc, param, param_type)
local type = param_type or "any"
function M.infer_type(param)
local type = param.type or "any"
if type == "" then
type = "any"
end

if param == "fn" then
type = "fun(...)"
elseif param == "args" or param == "list" then
type = "any[]"
elseif param == "dict" then
type = "dictionary"
elseif type == "arrayof(string)" then
if type == "any" then
if param.name == "fn" then
type = "fun(...)"
elseif param.name == "args" or param.name == "list" then
type = "any[]"
elseif param.name == "dict" then
type = "dictionary"
end
end
if type == "arrayof(string)" then
type = "string[]"
elseif type == "arrayof(integer, 2)" then
type = "number[]"
elseif type == "dictionaryof(luaref)" then
type = "table<string, luaref>"
end
return type
end

local ret = ""
if param then
if param == "end" then
param = "_end"
end
ret = ret .. param .. " "
function M.emmy_param(param, is_return)
local type = M.infer_type(param)
local parts = {}
if param.name and param.name ~= "..." then
table.insert(parts, param.name)
end
if type then
ret = ret .. type .. " "
table.insert(parts, type)
end
if param.doc then
table.insert(parts, "#" .. param.doc)
end

if not param.doc and type == "any" then
return ""
end
local ret = table.concat(parts, " ")
if is_return then
return M.comment("@return " .. ret, "---") .. "\n"
elseif param.name == "..." then
return M.comment("@vararg " .. ret, "---") .. "\n"
else
return M.comment("@param " .. ret, "---") .. "\n"
end
return ret .. "#" .. doc
end

function M.emmy(name, fun, prefix)
local ret = ""
if fun.doc and fun.doc[1] then
ret = ret .. (M.comment(fun.doc[1])) .. "\n"
end
local have_err = false
if fun.parameters_doc then
local types = {}
for _, param in pairs(fun.parameters or {}) do
if param[1] then
types[param[2]] = string.lower(param[1])
end
--- @return ApiFunction
function M.process(name, fun, prefix)
--- @class ApiFunction
local ret = {
doc = (fun.doc and fun.doc[1]) and fun.doc[1] or "",
name = name,
fqname = prefix .. "." .. name,
params = {},
["return"] = {},
}

for _, r in pairs(fun["return"]) do
table.insert(ret["return"], { doc = r })
end

local param_docs = {}
for param, doc in pairs(fun.parameters_doc or {}) do
param_docs[param] = doc
end

for i, p in ipairs(fun.parameters or {}) do
local type, pname = unpack(p)
local param = { name = pname }
if type ~= "" then
param.type = type:lower()
end
for param, param_doc in pairs(fun.parameters_doc) do
if param == "err" then
have_err = true
end
if param ~= "self" then
ret = ret .. M.comment("@param " .. M.infer_type(param_doc, param, types[param]), "---") .. "\n"
end
if param_docs[pname] then
param.doc = param_docs[pname]
end
if param.name == "end" then
param.name = "end_"
end
-- only include err param if it's documented
-- most nvim_ functions have an err param at the end, but these should not be included
local skip = i == #fun.parameters and (pname == "err" or pname == "error")
-- skip self params
if param.name == "self" or param.name == "" then
skip = true
end
if not skip then
table.insert(ret.params, param)
end
end
if fun["return"] and fun["return"][1] then
ret = ret .. M.comment("@return " .. M.infer_type(fun["return"][1]), "---") .. "\n"
if name == "on_publish_diagnostics" then
dump({ fun, ret })
end
return ret
end

--- @param fun ApiFunction
function M.emmy(fun)
local ret = ""
if fun.doc ~= "" then
ret = ret .. (M.comment(fun.doc)) .. "\n"
end

local signature = "function %s.%s(%s) end"
local params = {}
for i, param in ipairs(fun.parameters or {}) do
param = param[2]
if param == "end" then
param = "_end"
end
if have_err or not (i == #fun.parameters and param == "err") then
if param ~= "self" then
table.insert(params, param)
end
end

for _, param in pairs(fun.params) do
table.insert(params, param.name)
ret = ret .. M.emmy_param(param)
end
for _, r in pairs(fun["return"]) do
ret = ret .. M.emmy_param(r, true)
end

ret = ret .. signature:format(prefix, name, table.concat(params, ", "))
local signature = "function %s(%s) end"

ret = ret .. signature:format(fun.fqname, table.concat(params, ", "))
return ret .. "\n\n"
end

Expand Down Expand Up @@ -131,7 +181,7 @@ function M.parse(mpack, prefix, exclude)
]]):format(prefix .. "." .. parts[1], prefix .. "." .. parts[1]), -1)
classes[parts[1]] = true
end
local emmy = M.emmy(name, fun, prefix)
local emmy = M.emmy(M.process(name, fun, prefix))
size = size + #emmy
uv.fs_write(fd, emmy, -1)

Expand Down
79 changes: 39 additions & 40 deletions types/api.1.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
--# selene: allow(unused_variable)
---@diagnostic disable: unused-local

-- Gets a line-range from the buffer.
--- @param buffer buffer #Buffer handle, or 0 for current buffer
--- @param start integer #First line index
--- @param end_ integer #Last line index (exclusive)
--- @param strict_indexing boolean #Whether out-of-bounds should be an
--- error.
--- @return any #Array of lines, or empty array for unloaded buffer.
function vim.api.nvim_buf_get_lines(buffer, start, end_, strict_indexing) end

-- Return a tuple (row,col) representing the position of the
-- named mark.
--- @param buffer buffer #Buffer handle, or 0 for current buffer
Expand All @@ -14,8 +23,8 @@ function vim.api.nvim_buf_get_mark(buffer, name) end
function vim.api.nvim_buf_get_name(buffer) end

-- Returns the byte offset of a line (0-indexed). |api-indexing|
--- @param index integer #Line index
--- @param buffer buffer #Buffer handle, or 0 for current buffer
--- @param index integer #Line index
--- @return any #Integer byte offset, or -1 for unloaded buffer.
function vim.api.nvim_buf_get_offset(buffer, index) end

Expand Down Expand Up @@ -48,7 +57,10 @@ function vim.api.nvim_buf_is_valid(buffer) end
function vim.api.nvim_buf_line_count(buffer) end

-- Creates or updates an extmark.
--- @param buffer buffer #Buffer handle, or 0 for current buffer
--- @param ns_id integer #Namespace id from |nvim_create_namespace()|
--- @param line integer #Line number where to place the mark
--- @param col integer #Column where to place the mark
--- @param opts dictionary #Optional parameters.
--- • id : id of the extmark to edit.
--- • end_line : ending line of the mark, 0-based
Expand All @@ -66,7 +78,7 @@ function vim.api.nvim_buf_line_count(buffer) end
--- text.
--- • "right_align": display right aligned in the
--- window.
---
---
--- • virt_text_win_col : position the virtual text
--- at a fixed window column (starting from the
--- first text column)
Expand All @@ -82,7 +94,7 @@ function vim.api.nvim_buf_line_count(buffer) end
--- • "combine": combine with background text
--- color
--- • "blend": blend with background text color.
---
---
--- • hl_eol : when true, for a multiline highlight
--- covering the EOL of a line, continue the
--- highlight for the rest of the screen line
Expand All @@ -104,24 +116,25 @@ function vim.api.nvim_buf_line_count(buffer) end
--- • priority: a priority value for the highlight
--- group. For example treesitter highlighting
--- uses a value of 100.
--- @param col integer #Column where to place the mark
--- @param line integer #Line number where to place the mark
--- @param buffer buffer #Buffer handle, or 0 for current buffer
--- @return any #Id of the created/updated extmark
function vim.api.nvim_buf_set_extmark(buffer, ns_id, line, col, opts) end

-- Sets a buffer-local |mapping| for the given mode.
--- @param buffer buffer #Buffer handle, or 0 for current buffer
--- @param mode string
--- @param lhs string
--- @param rhs string
--- @param opts dictionary
function vim.api.nvim_buf_set_keymap(buffer, mode, lhs, rhs, opts) end

-- Sets (replaces) a line-range in the buffer.
--- @param replacement string[] #Array of lines to use as replacement
--- @param buffer buffer #Buffer handle, or 0 for current buffer
--- @param _end integer #Last line index (exclusive)
--- @param start integer #First line index
--- @param end_ integer #Last line index (exclusive)
--- @param strict_indexing boolean #Whether out-of-bounds should be an
--- error.
--- @param start integer #First line index
function vim.api.nvim_buf_set_lines(buffer, start, _end, strict_indexing, replacement) end
--- @param replacement string[] #Array of lines to use as replacement
function vim.api.nvim_buf_set_lines(buffer, start, end_, strict_indexing, replacement) end

-- Sets the full file name for a buffer
--- @param buffer buffer #Buffer handle, or 0 for current buffer
Expand All @@ -130,37 +143,36 @@ function vim.api.nvim_buf_set_name(buffer, name) end

-- Sets a buffer option value. Passing 'nil' as value deletes the
-- option (only works if there's a global fallback)
--- @param name string #Option name
--- @param buffer buffer #Buffer handle, or 0 for current buffer
--- @param name string #Option name
--- @param value object #Option value
function vim.api.nvim_buf_set_option(buffer, name, value) end

-- Sets (replaces) a range in the buffer
--- @param replacement string[] #Array of lines to use as replacement
--- @param end_row integer #Last line index
--- @param buffer buffer #Buffer handle, or 0 for current buffer
--- @param start_column any #Last column
--- @param end_column any #Last column
--- @param start_row integer #First line index
--- @param start_col integer
--- @param end_row integer #Last line index
--- @param end_col integer
--- @param replacement string[] #Array of lines to use as replacement
function vim.api.nvim_buf_set_text(buffer, start_row, start_col, end_row, end_col, replacement) end

-- Sets a buffer-scoped (b:) variable
--- @param name string #Variable name
--- @param buffer buffer #Buffer handle, or 0 for current buffer
--- @param name string #Variable name
--- @param value object #Variable value
function vim.api.nvim_buf_set_var(buffer, name, value) end

-- Set the virtual text (annotation) for a buffer line.
--- @param ns_id any #Namespace to use or 0 to create a namespace, or
--- -1 for a ungrouped annotation
--- @param opts dictionary #Optional parameters. Currently not used.
--- @param buffer buffer #Buffer handle, or 0 for current buffer
--- @param src_id integer
--- @param line integer #Line to annotate with virtual text
--- (zero-indexed)
--- @param chunks array #A list of [text, hl_group] arrays, each
--- representing a text chunk with specified
--- highlight. `hl_group` element can be omitted for
--- no highlight.
--- @param line integer #Line to annotate with virtual text
--- (zero-indexed)
--- @param buffer buffer #Buffer handle, or 0 for current buffer
--- @param opts dictionary #Optional parameters. Currently not used.
--- @return any #The ns_id that was used
function vim.api.nvim_buf_set_virtual_text(buffer, src_id, line, chunks, opts) end

Expand All @@ -178,16 +190,16 @@ function vim.api.nvim_buf_set_virtual_text(buffer, src_id, line, chunks, opts) e
function vim.api.nvim_call_atomic(calls) end

-- Calls a VimL |Dictionary-function| with the given arguments.
--- @param dict dictionary #Dictionary, or String evaluating to a VimL |self|
--- @param dict object #Dictionary, or String evaluating to a VimL |self|
--- dict
--- @param args any[] #Function arguments packed in an Array
--- @param fn fun(...) #Name of the function defined on the VimL dict
--- @param fn string #Name of the function defined on the VimL dict
--- @param args array #Function arguments packed in an Array
--- @return any #Result of the function call
function vim.api.nvim_call_dict_function(dict, fn, args) end

-- Calls a VimL function with the given arguments.
--- @param args any[] #Function arguments packed in an Array
--- @param fn fun(...) #Function to call
--- @param fn string #Function to call
--- @param args array #Function arguments packed in an Array
--- @return any #Result of the function call
function vim.api.nvim_call_function(fn, args) end

Expand All @@ -204,16 +216,3 @@ function vim.api.nvim_chan_send(chan, data) end
--- @param command string #Ex-command string
function vim.api.nvim_command(command) end

-- Creates a new, empty, unnamed buffer.
--- @param scratch boolean #Creates a "throwaway" |scratch-buffer| for
--- temporary work (always 'nomodified'). Also sets
--- 'nomodeline' on the buffer.
--- @param listed boolean #Sets 'buflisted'
--- @return any #Buffer handle, or 0 on error
function vim.api.nvim_create_buf(listed, scratch) end

-- Creates a new namespace, or gets an existing one.
--- @param name string #Namespace name or empty string
--- @return any #Namespace id
function vim.api.nvim_create_namespace(name) end

Loading

0 comments on commit 4f5a10f

Please sign in to comment.