diff options
author | max397574 <81827001+max397574@users.noreply.github.com> | 2023-06-07 13:32:39 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-06-07 12:32:39 +0100 |
commit | 5f4895200a49d92e636dea9c5474ab5b0882384d (patch) | |
tree | f75996e9ce0b0de69ed86753ed27117b9744c164 /scripts/lsp_types.lua | |
parent | a217675a67233ca2032cd668e919858d2aed92e7 (diff) | |
download | rneovim-5f4895200a49d92e636dea9c5474ab5b0882384d.tar.gz rneovim-5f4895200a49d92e636dea9c5474ab5b0882384d.tar.bz2 rneovim-5f4895200a49d92e636dea9c5474ab5b0882384d.zip |
feat(scripts): add lsp_types.lua (#23750)
Diffstat (limited to 'scripts/lsp_types.lua')
-rw-r--r-- | scripts/lsp_types.lua | 207 |
1 files changed, 207 insertions, 0 deletions
diff --git a/scripts/lsp_types.lua b/scripts/lsp_types.lua new file mode 100644 index 0000000000..8f3ed811d6 --- /dev/null +++ b/scripts/lsp_types.lua @@ -0,0 +1,207 @@ +--[[ +Generates lua-ls annotations for lsp +USAGE: +nvim -l scripts/lsp_types.lua gen --runtime/lua/vim/lsp/types/protocol.lua +--]] + +local M = {} + +local function tofile(fname, text) + local f = io.open(fname, 'w') + if not f then + error(('failed to write: %s'):format(f)) + else + f:write(text) + f:close() + end +end + +function M.gen(opt) + if vim.loop.fs_stat('./lsp.json') then + vim.fn.delete('./lsp.json') + end + vim.fn.system({ + 'curl', + 'https://raw.githubusercontent.com/microsoft/lsprotocol/main/generator/lsp.json', + '-o', + './lsp.json', + }) + local protocol = vim.fn.json_decode(vim.fn.readfile('./lsp.json')) + vim.fn.delete('./lsp.json') + local output_file = opt[1] + protocol = protocol or {} + local output = { + '--[[', + 'This file is autogenerated from scripts/lsp_types.lua', + 'Regenerate:', + [=[nvim -l scripts/lsp_types.lua gen --runtime/lua/vim/lsp/types/protocol.lua]=], + '--]]', + '', + '---@alias lsp.null nil', + '---@alias uinteger integer', + '---@alias lsp.decimal number', + '---@alias lsp.DocumentUri string', + '---@alias lsp.URI string', + '---@alias lsp.LSPObject table<string, lsp.LSPAny>', + '---@alias lsp.LSPArray lsp.LSPAny[]', + '---@alias lsp.LSPAny lsp.LSPObject|lsp.LSPArray|string|number|boolean|nil', + '', + } + + local anonymous_num = 0 + + local anonym_classes = {} + + local simple_types = { + 'string', + 'boolean', + 'integer', + 'uinteger', + 'decimal', + } + + local function parse_type(type) + if type.kind == 'reference' or type.kind == 'base' then + if vim.tbl_contains(simple_types, type.name) then + return type.name + end + return 'lsp.' .. type.name + elseif type.kind == 'array' then + return parse_type(type.element) .. '[]' + elseif type.kind == 'or' then + local val = '' + for _, item in ipairs(type.items) do + val = val .. parse_type(item) .. '|' + end + val = val:sub(0, -2) + return val + elseif type.kind == 'stringLiteral' then + return '"' .. type.value .. '"' + elseif type.kind == 'map' then + return 'table<' .. parse_type(type.key) .. ', ' .. parse_type(type.value) .. '>' + elseif type.kind == 'literal' then + -- can I use ---@param disabled? {reason: string} + -- use | to continue the inline class to be able to add docs + -- https://github.com/LuaLS/lua-language-server/issues/2128 + anonymous_num = anonymous_num + 1 + local anonym = { '---@class anonym' .. anonymous_num } + for _, field in ipairs(type.value.properties) do + if field.documentation then + field.documentation = field.documentation:gsub('\n', '\n---') + anonym[#anonym + 1] = '---' .. field.documentation + end + anonym[#anonym + 1] = '---@field ' + .. field.name + .. (field.optional and '?' or '') + .. ' ' + .. parse_type(field.type) + end + anonym[#anonym + 1] = '' + for _, line in ipairs(anonym) do + anonym_classes[#anonym_classes + 1] = line + end + return 'anonym' .. anonymous_num + elseif type.kind == 'tuple' then + local tuple = '{ ' + for i, value in ipairs(type.items) do + tuple = tuple .. '[' .. i .. ']: ' .. parse_type(value) .. ', ' + end + -- remove , at the end + tuple = tuple:sub(0, -3) + return tuple .. ' }' + end + vim.print(type) + return '' + end + + for _, structure in ipairs(protocol.structures) do + if structure.documentation then + structure.documentation = structure.documentation:gsub('\n', '\n---') + output[#output + 1] = '---' .. structure.documentation + end + if structure.extends then + local class_string = '---@class lsp.' + .. structure.name + .. ': ' + .. parse_type(structure.extends[1]) + for _, mixin in ipairs(structure.mixins or {}) do + class_string = class_string .. ', ' .. parse_type(mixin) + end + output[#output + 1] = class_string + else + output[#output + 1] = '---@class lsp.' .. structure.name + end + for _, field in ipairs(structure.properties or {}) do + if field.documentation then + field.documentation = field.documentation:gsub('\n', '\n---') + output[#output + 1] = '---' .. field.documentation + end + output[#output + 1] = '---@field ' + .. field.name + .. (field.optional and '?' or '') + .. ' ' + .. parse_type(field.type) + end + output[#output + 1] = '' + end + + for _, enum in ipairs(protocol.enumerations) do + if enum.documentation then + enum.documentation = enum.documentation:gsub('\n', '\n---') + output[#output + 1] = '---' .. enum.documentation + end + local enum_type = '---@alias lsp.' .. enum.name + for _, value in ipairs(enum.values) do + enum_type = enum_type + .. '\n---| ' + .. (type(value.value) == 'string' and '"' .. value.value .. '"' or value.value) + .. ' # ' + .. value.name + end + output[#output + 1] = enum_type + output[#output + 1] = '' + end + + for _, alias in ipairs(protocol.typeAliases) do + if alias.documentation then + alias.documentation = alias.documentation:gsub('\n', '\n---') + output[#output + 1] = '---' .. alias.documentation + end + if alias.type.kind == 'or' then + local alias_type = '---@alias lsp.' .. alias.name .. ' ' + for _, item in ipairs(alias.type.items) do + alias_type = alias_type .. parse_type(item) .. '|' + end + alias_type = alias_type:sub(0, -2) + output[#output + 1] = alias_type + else + output[#output + 1] = '---@alias lsp.' .. alias.name .. ' ' .. parse_type(alias.type) + end + output[#output + 1] = '' + end + + for _, line in ipairs(anonym_classes) do + output[#output + 1] = line + end + + tofile(output_file, table.concat(output, '\n')) +end + +local opt = {} + +local index = 1 +for _, a in ipairs(arg) do + if vim.startswith(a, '--') then + local name = a:sub(3) + opt[index] = name + index = index + 1 + end +end + +for _, a in ipairs(arg) do + if M[a] then + M[a](opt) + end +end + +return M |