diff options
author | Jongwook Choi <wookayin@gmail.com> | 2023-12-10 23:50:54 -0500 |
---|---|---|
committer | Mathias Fußenegger <mfussenegger@users.noreply.github.com> | 2023-12-27 10:48:06 +0100 |
commit | 2f43af6423193eb52e9a6635034f8c79f40f1706 (patch) | |
tree | 350ceddfd682d2f29391e63fed746f3780d7e96b /scripts/gen_lsp.lua | |
parent | 3767468b9615b617e252e9e9498e070087fe570f (diff) | |
download | rneovim-2f43af6423193eb52e9a6635034f8c79f40f1706.tar.gz rneovim-2f43af6423193eb52e9a6635034f8c79f40f1706.tar.bz2 rneovim-2f43af6423193eb52e9a6635034f8c79f40f1706.zip |
refactor(gen_lsp.lua): add typing for the LSP protocol JSON data model
Enhance readability and intellisense by incorporating type annotations.
Types are not very strict and may not encompass th entire LSP Protocol
metamodel; the scope is up to what's relevant for generating type
annotations for LSP (`_meta/protocol.lua`).
Based on the model schema:
https://raw.githubusercontent.com/microsoft/language-server-protocol/gh-pages/_specifications/lsp/3.18/metaModel/metaModel.schema.json
No behavioral changes (and hence no diff on _meta/protocol.lua) should
exist in this commit.
Diffstat (limited to 'scripts/gen_lsp.lua')
-rw-r--r-- | scripts/gen_lsp.lua | 126 |
1 files changed, 118 insertions, 8 deletions
diff --git a/scripts/gen_lsp.lua b/scripts/gen_lsp.lua index 9fbcc1c15e..943e88896b 100644 --- a/scripts/gen_lsp.lua +++ b/scripts/gen_lsp.lua @@ -24,7 +24,17 @@ local function tofile(fname, text) end end ----@param opt gen_lsp._opt +--- The LSP protocol JSON data (it's partial, non-exhaustive). +--- https://raw.githubusercontent.com/microsoft/language-server-protocol/gh-pages/_specifications/lsp/3.18/metaModel/metaModel.schema.json +--- @class vim._gen_lsp.Protocol +--- @field requests vim._gen_lsp.Request[] +--- @field notifications vim._gen_lsp.Notification[] +--- @field structures vim._gen_lsp.Structure[] +--- @field enumerations vim._gen_lsp.Enumeration[] +--- @field typeAliases vim._gen_lsp.TypeAlias[] + +---@param opt vim._gen_lsp.opt +---@return vim._gen_lsp.Protocol local function read_json(opt) local uri = 'https://raw.githubusercontent.com/microsoft/language-server-protocol/gh-pages/_specifications/lsp/' .. opt.version @@ -46,6 +56,7 @@ local function name(s) return s:gsub('^%$', 'dollar'):gsub('/', '_') end +---@param protocol vim._gen_lsp.Protocol local function gen_methods(protocol) local output = { '-- Generated by gen_lsp.lua, keep at end of file.', @@ -56,6 +67,32 @@ local function gen_methods(protocol) } local indent = (' '):rep(2) + --- @class vim._gen_lsp.Request + --- @field deprecated? string + --- @field documentation? string + --- @field messageDirection string + --- @field method string + --- @field params? any + --- @field proposed? boolean + --- @field registrationMethod? string + --- @field registrationOptions? any + --- @field since? string + + --- @class vim._gen_lsp.Notification + --- @field deprecated? string + --- @field documentation? string + --- @field errorData? any + --- @field messageDirection string + --- @field method string + --- @field params? any[] + --- @field partialResult? any + --- @field proposed? boolean + --- @field registrationMethod? string + --- @field registrationOptions? any + --- @field result any + --- @field since? string + + ---@type (vim._gen_lsp.Request|vim._gen_lsp.Notification)[] local all = vim.list_extend(protocol.requests, protocol.notifications) table.sort(all, function(a, b) return name(a.method) < name(b.method) @@ -106,14 +143,15 @@ return protocol vim.cmd.write() end ----@class gen_lsp._opt +---@class vim._gen_lsp.opt ---@field output_file string ---@field version string ---@field methods boolean ----@param opt gen_lsp._opt +---@param opt vim._gen_lsp.opt function M.gen(opt) - local protocol = read_json(opt) --- @type table + --- @type vim._gen_lsp.Protocol + local protocol = read_json(opt) if opt.methods then gen_methods(protocol) @@ -144,6 +182,7 @@ function M.gen(opt) local anonymous_num = 0 + ---@type string[] local anonym_classes = {} local simple_types = { @@ -154,32 +193,65 @@ function M.gen(opt) 'decimal', } + --- @class vim._gen_lsp.Type + --- @field kind string a common field for all Types. + --- @field name? string for ReferenceType, BaseType + --- @field element? any for ArrayType + --- @field items? vim._gen_lsp.Type[] for OrType, AndType + --- @field key? vim._gen_lsp.Type for MapType + --- @field value? string|vim._gen_lsp.Type for StringLiteralType, MapType, StructureLiteralType + + ---@param type vim._gen_lsp.Type + ---@return string local function parse_type(type) + -- ReferenceType | BaseType 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 + + -- ArrayType elseif type.kind == 'array' then return parse_type(type.element) .. '[]' + + -- OrType elseif type.kind == 'or' then local val = '' for _, item in ipairs(type.items) do - val = val .. parse_type(item) .. '|' + val = val .. parse_type(item) .. '|' --[[ @as string ]] end val = val:sub(0, -2) return val + + -- StringLiteralType elseif type.kind == 'stringLiteral' then return '"' .. type.value .. '"' + + -- MapType elseif type.kind == 'map' then - return 'table<' .. parse_type(type.key) .. ', ' .. parse_type(type.value) .. '>' + local key = assert(type.key) + local value = type.value --[[ @as vim._gen_lsp.Type ]] + return 'table<' .. parse_type(key) .. ', ' .. parse_type(value) .. '>' + + -- StructureLiteralType 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 + + --- @class vim._gen_lsp.StructureLiteral translated to anonymous @class. + --- @field deprecated? string + --- @field description? string + --- @field properties vim._gen_lsp.Property[] + --- @field proposed? boolean + --- @field since? string + + ---@type vim._gen_lsp.StructureLiteral + local structural_literal = assert(type.value) --[[ @as vim._gen_lsp.StructureLiteral ]] + for _, field in ipairs(structural_literal.properties) do if field.documentation then field.documentation = field.documentation:gsub('\n', '\n---') anonym[#anonym + 1] = '---' .. field.documentation @@ -195,6 +267,8 @@ function M.gen(opt) anonym_classes[#anonym_classes + 1] = line end return 'anonym' .. anonymous_num + + -- TupleType elseif type.kind == 'tuple' then local tuple = '{ ' for i, value in ipairs(type.items) do @@ -204,10 +278,20 @@ function M.gen(opt) tuple = tuple:sub(0, -3) return tuple .. ' }' end - vim.print(type) + + vim.print('WARNING: Unknown type ', type) return '' end + --- @class vim._gen_lsp.Structure translated to @class + --- @field deprecated? string + --- @field documentation? string + --- @field extends? { kind: string, name: string }[] + --- @field mixins? { kind: string, name: string }[] + --- @field name string + --- @field properties? vim._gen_lsp.Property[] members, translated to @field + --- @field proposed? boolean + --- @field since? string for _, structure in ipairs(protocol.structures) do if structure.documentation then structure.documentation = structure.documentation:gsub('\n', '\n---') @@ -225,6 +309,15 @@ function M.gen(opt) else output[#output + 1] = '---@class lsp.' .. structure.name end + + --- @class vim._gen_lsp.Property translated to @field + --- @field deprecated? string + --- @field documentation? string + --- @field name string + --- @field optional? boolean + --- @field proposed? boolean + --- @field since? string + --- @field type { kind: string, name: string } for _, field in ipairs(structure.properties or {}) do if field.documentation then field.documentation = field.documentation:gsub('\n', '\n---') @@ -239,6 +332,14 @@ function M.gen(opt) output[#output + 1] = '' end + --- @class vim._gen_lsp.Enumeration translated to @enum + --- @field deprecated string? + --- @field documentation string? + --- @field name string? + --- @field proposed boolean? + --- @field since string? + --- @field suportsCustomValues boolean? + --- @field values { name: string, value: string, documentation?: string, since?: string }[] for _, enum in ipairs(protocol.enumerations) do if enum.documentation then enum.documentation = enum.documentation:gsub('\n', '\n---') @@ -256,6 +357,13 @@ function M.gen(opt) output[#output + 1] = '' end + --- @class vim._gen_lsp.TypeAlias translated to @alias + --- @field deprecated? string? + --- @field documentation? string + --- @field name string + --- @field proposed? boolean + --- @field since? string + --- @field type vim._gen_lsp.Type for _, alias in ipairs(protocol.typeAliases) do if alias.documentation then alias.documentation = alias.documentation:gsub('\n', '\n---') @@ -274,6 +382,7 @@ function M.gen(opt) output[#output + 1] = '' end + -- anonymous classes for _, line in ipairs(anonym_classes) do output[#output + 1] = line end @@ -281,6 +390,7 @@ function M.gen(opt) tofile(opt.output_file, table.concat(output, '\n')) end +---@type vim._gen_lsp.opt local opt = { output_file = 'runtime/lua/vim/lsp/_meta/protocol.lua', version = DEFAULT_LSP_VERSION, |