Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ---@class SignatureParserState
- ---@field valid boolean
- ---@field params string[]
- ---@field returnType string
- ---@return SignatureParserState
- local function getState()
- return {
- valid = false,
- params = {},
- returnType = "nil",
- }
- end
- local function split(text, sep)
- sep = sep or ":"
- local fields = {}
- local pattern = string.format("([^%s]+)", sep)
- ---@diagnostic disable-next-line: no-unknown
- local _ = text:gsub(pattern, function(c)
- table.insert(fields, c)
- end)
- return fields
- end
- ---@param str string
- ---@return string
- local function trim(str)
- return str:match("^%s*(.-)%s*$")
- end
- ---@param input string
- ---@return diff[]
- local function injectFunctionDefinitions(input)
- local diffs = {}
- local cursor = 0
- local state = getState()
- local lastClass = "global"
- local lastParentClass = "global"
- ---@type integer[]?
- local override
- for line in string.gmatch(input .. "\n", "(.-)\n") do
- local commentStart = line:find("---")
- if commentStart and #line:sub(1, commentStart - 1):gsub(" ", ""):gsub("\t", "") == 0 then
- local trimmedLine = line:sub(commentStart)
- if trimmedLine:sub(1, 9) == "---@param" then
- state.valid = true
- local param = trimmedLine:sub(11)
- ---@type string, string
- local name, typeStr
- if param:find("{") or param:find("<") or param:find(":") then
- name = param:match("^([^%s]*)")
- typeStr = "any"
- else
- name, typeStr = param:match("^([^%s]*)%s*([^%s]*)%s*(.*)")
- end
- table.insert(state.params, {
- name or ("arg" .. #state.params),
- typeStr or "any",
- })
- elseif trimmedLine:sub(1, 10) == "---@return" then
- state.valid = true
- local f = split(trimmedLine, " ")
- state.returnType = f[2] or "nil"
- elseif trimmedLine:sub(1, 9) == "---@class" then
- local c = split(trimmedLine:sub(11):gsub("%(exact%) ", ""), ":")
- lastClass = trim(c[1] or "global")
- lastParentClass = trim(c[2] or "global")
- elseif trimmedLine:sub(1) == "---@override" then
- override = { cursor + commentStart, cursor + #line }
- elseif trimmedLine:sub(1, 3) == "---" then
- state.valid = true
- end
- elseif line:find("function") and line:find(":") then
- local method = line:sub(
- (line:find(":") or 0) + 1,
- (line:find("%(") or 0) - 1
- )
- if override then
- if lastParentClass ~= "global" then
- local text = "---@type def." .. lastParentClass .. "." .. method
- local textSee = "---@see " .. lastParentClass .. "." .. method
- table.insert(diffs, {
- start = override[1],
- finish = override[2],
- text = textSee .. "\n" .. text,
- })
- override = nil
- end
- elseif state.valid and lastClass ~= "global" then
- local parts = {}
- for _, var in ipairs(state.params) do
- table.insert(parts, var[1] .. " : " .. var[2])
- end
- local text = "---@alias def." ..
- lastClass .. "." .. method .. " " ..
- "fun(self: " .. lastClass .. ", " .. table.concat(parts, ", ") .. ") : " .. state.returnType
- table.insert(diffs, {
- start = cursor,
- finish = cursor - 1,
- text = "\n" .. text,
- })
- end
- elseif state.valid then
- state = getState()
- end
- ---@type integer
- cursor = cursor + #line + 1
- end
- return diffs
- end
- ---@class diff
- ---@field start integer # The number of bytes at the beginning of the replacement
- ---@field finish integer # The number of bytes at the end of the replacement
- ---@field text string # What to replace
- ---@param uri string # The uri of file
- ---@param text string # The content of file
- ---@return nil|diff[]
- function OnSetText(uri, text)
- return injectFunctionDefinitions(text)
- end
Advertisement
Add Comment
Please, Sign In to add comment