diff options
Diffstat (limited to 'scripts/lsp_types.lua')
-rw-r--r-- | scripts/lsp_types.lua | 133 |
1 files changed, 115 insertions, 18 deletions
diff --git a/scripts/lsp_types.lua b/scripts/lsp_types.lua index 4a089bd76d..61ee6ad309 100644 --- a/scripts/lsp_types.lua +++ b/scripts/lsp_types.lua @@ -2,8 +2,9 @@ Generates lua-ls annotations for lsp USAGE: nvim -l scripts/lsp_types.lua gen # this will overwrite runtime/lua/vim/lsp/types/protocol.lua -nvim -l scripts/lsp_types.lua gen --build/new_lsp_types.lua -nvim -l scripts/lsp_types.lua gen --out runtime/lua/vim/lsp/types/protocol.lua --ref 2023.0.0a2 # specify a git reference from microsoft/lsprotocol +nvim -l scripts/lsp_types.lua gen --version 3.1x --build/new_lsp_types.lua +nvim -l scripts/lsp_types.lua gen --version 3.1x --out runtime/lua/vim/lsp/types/protocol.lua +nvim -l scripts/lsp_types.lua gen --version 3.1x --methods --]] local M = {} @@ -18,24 +19,117 @@ local function tofile(fname, text) end end -function M.gen(opt) - if vim.uv.fs_stat('./lsp.json') then - vim.fn.delete('./lsp.json') +local function sort_by_method(tbl) + local single, client, textD, workspace, others = {}, {}, {}, {}, {} + for _, item in ipairs(tbl) do + local parts = vim.split(item.method, '/', { trimempty = true }) + if #parts == 1 then + single[#single + 1] = item + elseif parts[1] == 'textDocument' then + textD[#textD + 1] = item + elseif parts[1] == 'client' then + client[#client + 1] = item + elseif parts[1] == 'workspace' then + workspace[#workspace + 1] = item + else + others[#others + 1] = item + end + end + + local res = {} + for _, item in ipairs({ single, client, textD, workspace, others }) do + res = vim.list_extend(res, item) end - vim.fn.system({ - 'curl', - 'https://raw.githubusercontent.com/microsoft/lsprotocol/' .. opt.ref .. '/generator/lsp.json', - '-o', - './lsp.json', + return res +end + +local function read_json(opt) + local uri = 'https://raw.githubusercontent.com/microsoft/language-server-protocol/gh-pages/_specifications/lsp/' + .. opt.version + .. '/metaModel/metaModel.json' + + local res = vim.system({ 'curl', uri, '-o', '-' }):wait() + + if res.code ~= 0 then + io.write(res.stderr) + return + end + return vim.json.decode(res.stdout) +end + +local function gen_methods(protocol) + local output = { + '-- Generated by lsp_types.lua, keep at end of file.', + '--- LSP method names.', + '---', + '---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#metaModel', + 'protocol.Methods = {', + } + local indent = (' '):rep(2) + + for _, item in ipairs(sort_by_method(protocol.requests)) do + if item.method then + local name = item.method:gsub('/', '_', 3) + if item.documentation then + local document = vim.split(item.documentation, '\n?\n', { trimempty = true }) + for _, docstring in ipairs(document) do + output[#output + 1] = indent .. '--- ' .. docstring + end + end + output[#output + 1] = indent .. name .. " = '" .. item.method .. "'," + end + end + output[#output + 1] = '}' + output = vim.list_extend( + output, + vim.split( + [[ +local function freeze(t) + return setmetatable({}, { + __index = t, + __newindex = function() + error('cannot modify immutable table') + end, }) - local protocol = vim.fn.json_decode(vim.fn.readfile('./lsp.json')) - vim.fn.delete('./lsp.json') - protocol = protocol or {} +end +protocol.Methods = freeze(protocol.Methods) + +return protocol +]], + '\n', + { trimempty = true } + ) + ) + + local fname = './runtime/lua/vim/lsp/protocol.lua' + local bufnr = vim.fn.bufadd(fname) + vim.fn.bufload(bufnr) + vim.api.nvim_set_current_buf(bufnr) + local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false) + local index = vim.iter(ipairs(lines)):find(function(key, item) + return vim.startswith(item, '-- Generated by') and key or nil + end) + index = index and index - 1 or vim.api.nvim_buf_line_count(bufnr) - 1 + vim.api.nvim_buf_set_lines(bufnr, index, -1, true, output) + vim.cmd.write() +end + +function M.gen(opt) + local protocol = read_json(opt) + if not protocol then + os.exit(1) + return + end + + if opt.methods then + gen_methods(protocol) + end + 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]=], + [=[nvim -l scripts/lsp_types.lua gen --version 3.1x --runtime/lua/vim/lsp/types/protocol.lua]=], '--]]', '', '---@alias lsp.null nil', @@ -190,14 +284,17 @@ end local opt = { output_file = 'runtime/lua/vim/lsp/types/protocol.lua', - ref = 'main', + version = nil, + methods = nil, } for i = 1, #_G.arg do if _G.arg[i] == '--out' then - opt.output_file = _G.arg[i+1] - elseif _G.arg[i] == '--ref' then - opt.ref = _G.arg[i+1] + opt.output_file = _G.arg[i + 1] + elseif _G.arg[i] == '--version' then + opt.version = _G.arg[i + 1] + elseif _G.arg[i] == '--methods' then + opt.methods = true elseif vim.startswith(_G.arg[i], '--') then opt.output_file = _G.arg[i]:sub(3) end |