diff options
author | sumneko <sumneko@hotmail.com> | 2019-05-05 20:06:08 +0800 |
---|---|---|
committer | sumneko <sumneko@hotmail.com> | 2019-05-05 20:06:08 +0800 |
commit | 6b95bb52f39082e9df605a954cb6a16d75b9611c (patch) | |
tree | c425335076a50e90f28f3c42ab825fb6c042c13b /server/src/core/hover/emmy_function.lua | |
parent | e00842cf43b6d2e2ff3900db32d3aa4e18a8f800 (diff) | |
download | lua-language-server-6b95bb52f39082e9df605a954cb6a16d75b9611c.zip |
emmyFunctionçš„hover
Diffstat (limited to 'server/src/core/hover/emmy_function.lua')
-rw-r--r-- | server/src/core/hover/emmy_function.lua | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/server/src/core/hover/emmy_function.lua b/server/src/core/hover/emmy_function.lua new file mode 100644 index 00000000..6306957f --- /dev/null +++ b/server/src/core/hover/emmy_function.lua @@ -0,0 +1,123 @@ +---@param emmy EmmyFunctionType +local function buildEmmyArgs(emmy, object, select) + local start + if object then + start = 2 + else + start = 1 + end + local strs = {} + local i = 0 + emmy:eachParam(function (name, typeObj) + i = i + 1 + if i > start then + strs[#strs+1] = ', ' + end + if i == select then + strs[#strs+1] = '@ARG' + end + strs[#strs+1] = name .. ': ' .. typeObj:getType() + if i == select then + strs[#strs+1] = '@ARG' + end + end) + local text = table.concat(strs) + local argLabel = {} + for i = 1, 2 do + local pos = text:find('@ARG', 1, true) + if pos then + if i == 1 then + argLabel[i] = pos + else + argLabel[i] = pos - 1 + end + text = text:sub(1, pos-1) .. text:sub(pos+4) + end + end + if #argLabel == 0 then + argLabel = nil + end + return text, argLabel +end + +local function buildEmmyReturns(emmy) + return '\n -> ' .. emmy:getReturn():getType() +end + +local function buildEnum(lib) + if not lib.enums then + return '' + end + local container = table.container() + for _, enum in ipairs(lib.enums) do + if not enum.name or (not enum.enum and not enum.code) then + goto NEXT_ENUM + end + if not container[enum.name] then + container[enum.name] = {} + if lib.args then + for _, arg in ipairs(lib.args) do + if arg.name == enum.name then + container[enum.name].type = arg.type + break + end + end + end + if lib.returns then + for _, rtn in ipairs(lib.returns) do + if rtn.name == enum.name then + container[enum.name].type = rtn.type + break + end + end + end + end + table.insert(container[enum.name], enum) + ::NEXT_ENUM:: + end + local strs = {} + for name, enums in pairs(container) do + local tp + if type(enums.type) == 'table' then + tp = table.concat(enums.type, '/') + else + tp = enums.type + end + strs[#strs+1] = ('\n%s: %s'):format(name, tp or 'any') + for _, enum in ipairs(enums) do + if enum.default then + strs[#strs+1] = '\n -> ' + else + strs[#strs+1] = '\n | ' + end + if enum.code then + strs[#strs+1] = tostring(enum.code) + else + strs[#strs+1] = ('%q'):format(enum.enum) + end + if enum.description then + strs[#strs+1] = ' -- ' .. enum.description + end + end + end + return table.concat(strs) +end + +return function (name, emmy, object, select) + local args, argLabel = buildEmmyArgs(emmy, object, select) + local returns = buildEmmyReturns(emmy) + local enum = buildEnum(emmy) + local tip = emmy.description + local headLen = #('function %s('):format(name) + local title = ('function %s(%s)%s'):format(name, args, returns) + if argLabel then + argLabel[1] = argLabel[1] + headLen + argLabel[2] = argLabel[2] + headLen + end + return { + label = title, + description = tip, + enum = enum, + argLabel = argLabel, + } +end |