diff options
author | 最萌小汐 <sumneko@hotmail.com> | 2019-11-22 23:26:32 +0800 |
---|---|---|
committer | 最萌小汐 <sumneko@hotmail.com> | 2019-11-22 23:26:32 +0800 |
commit | d0ff66c9abe9d6abbca12fd811e0c3cb69c1033a (patch) | |
tree | bb34518d70b85de7656dbdbe958dfa221a3ff3b3 /server/src/core/hover | |
parent | 0a2c2ad15e1ec359171fb0dd4c72e57c5b66e9ba (diff) | |
download | lua-language-server-d0ff66c9abe9d6abbca12fd811e0c3cb69c1033a.zip |
整理一下目录结构
Diffstat (limited to 'server/src/core/hover')
-rw-r--r-- | server/src/core/hover/emmy_function.lua | 143 | ||||
-rw-r--r-- | server/src/core/hover/function.lua | 243 | ||||
-rw-r--r-- | server/src/core/hover/hover.lua | 326 | ||||
-rw-r--r-- | server/src/core/hover/init.lua | 1 | ||||
-rw-r--r-- | server/src/core/hover/lib_function.lua | 222 | ||||
-rw-r--r-- | server/src/core/hover/name.lua | 38 |
6 files changed, 0 insertions, 973 deletions
diff --git a/server/src/core/hover/emmy_function.lua b/server/src/core/hover/emmy_function.lua deleted file mode 100644 index 7c87954e..00000000 --- a/server/src/core/hover/emmy_function.lua +++ /dev/null @@ -1,143 +0,0 @@ ----@param emmy EmmyFunctionType -local function buildEmmyArgs(emmy, object, select) - local start - if object then - start = 2 - else - start = 1 - end - local strs = {} - local args = {} - local i = 0 - emmy:eachParam(function (name, typeObj) - i = i + 1 - if i < start then - return - end - if i > start then - strs[#strs+1] = ', ' - end - if i == select then - strs[#strs+1] = '@ARG' - end - strs[#strs+1] = name .. ': ' .. typeObj:getType() - args[#args+1] = strs[#strs] - 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, args -end - -local function buildEmmyReturns(emmy) - local rtns = {} - local i = 0 - emmy:eachReturn(function (rtn) - i = i + 1 - if i > 1 then - rtns[#rtns+1] = ('\n% 3d. '):format(i) - end - rtns[#rtns+1] = rtn:getType() - end) - if #rtns == 0 then - return '\n -> ' .. 'any' - else - return '\n -> ' .. table.concat(rtns) - end -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 = {} - local raw = {} - 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 - raw[name] = {} - 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 - raw[name][#raw[name]+1] = strs[#strs] - if enum.description then - strs[#strs+1] = ' -- ' .. enum.description - end - end - end - return table.concat(strs), raw -end - -return function (name, emmy, object, select) - local argStr, argLabel, args = buildEmmyArgs(emmy, object, select) - local returns = buildEmmyReturns(emmy) - local enum, rawEnum = buildEnum(emmy) - local tip = emmy.description - return { - label = ('function %s(%s)%s'):format(name, argStr, returns), - name = name, - argStr = argStr, - returns = returns, - description = tip, - enum = enum, - rawEnum = rawEnum, - argLabel = argLabel, - args = args, - } -end diff --git a/server/src/core/hover/function.lua b/server/src/core/hover/function.lua deleted file mode 100644 index 3865f602..00000000 --- a/server/src/core/hover/function.lua +++ /dev/null @@ -1,243 +0,0 @@ -local emmyFunction = require 'core.hover.emmy_function' - -local function buildValueArgs(func, object, select) - if not func then - return '', nil - end - local names = {} - local values = {} - local options = {} - if func.argValues then - for i, value in ipairs(func.argValues) do - values[i] = value:getType() - end - end - if func.args then - for i, arg in ipairs(func.args) do - names[#names+1] = arg:getName() - local param = func:findEmmyParamByName(arg:getName()) - if param then - values[i] = param:getType() - options[i] = param:getOption() - end - end - end - local strs = {} - local start = 1 - if object then - start = 2 - end - local max - if func:getSource() then - max = #names - else - max = math.max(#names, #values) - end - local args = {} - for i = start, max do - local name = names[i] - local value = values[i] or 'any' - local option = options[i] - if option and option.optional then - if i > start then - strs[#strs+1] = ' [' - else - strs[#strs+1] = '[' - end - end - if i > start then - strs[#strs+1] = ', ' - end - - if i == select then - strs[#strs+1] = '@ARG' - end - if name then - strs[#strs+1] = name .. ': ' .. value - else - strs[#strs+1] = value - end - args[#args+1] = strs[#strs] - if i == select then - strs[#strs+1] = '@ARG' - end - - if option and option.optional == 'self' then - strs[#strs+1] = ']' - end - end - if func:hasDots() then - if max > 0 then - strs[#strs+1] = ', ' - end - strs[#strs+1] = '...' - end - - if options then - for _, option in pairs(options) do - if option.optional == 'after' then - strs[#strs+1] = ']' - end - 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, args -end - -local function buildValueReturns(func) - if not func then - return '\n -> any' - end - if not func:get 'hasReturn' then - return '' - end - local strs = {} - local emmys = {} - local n = 0 - func:eachEmmyReturn(function (emmy) - n = n + 1 - emmys[n] = emmy - end) - if func.returns then - for i, rtn in ipairs(func.returns) do - local emmy = emmys[i] - local option = emmy and emmy.option - if option and option.optional then - if i > 1 then - strs[#strs+1] = ' [' - else - strs[#strs+1] = '[' - end - end - if i > 1 then - strs[#strs+1] = ('\n% 3d. '):format(i) - end - if emmy and emmy.name then - strs[#strs+1] = ('%s: '):format(emmy.name) - elseif option and option.name then - strs[#strs+1] = ('%s: '):format(option.name) - end - strs[#strs+1] = rtn:getType() - if option and option.optional == 'self' then - strs[#strs+1] = ']' - end - end - for i = 1, #func.returns do - local emmy = emmys[i] - if emmy and emmy.option and emmy.option.optional == 'after' then - strs[#strs+1] = ']' - end - end - end - if #strs == 0 then - strs[1] = 'any' - end - return '\n -> ' .. table.concat(strs) -end - ----@param func emmyFunction -local function buildEnum(func) - if not func then - return nil - end - local params = func:getEmmyParams() - if not params then - return nil - end - local strs = {} - local raw = {} - for _, param in ipairs(params) do - local first = true - local name = param:getName() - raw[name] = {} - param:eachEnum(function (enum) - if first then - first = false - strs[#strs+1] = ('\n%s: %s'):format(param:getName(), param:getType()) - end - if enum.default then - strs[#strs+1] = ('\n |>%s'):format(enum[1]) - else - strs[#strs+1] = ('\n | %s'):format(enum[1]) - end - if enum.comment then - strs[#strs+1] = ' -- ' .. enum.comment - end - raw[name][#raw[name]+1] = enum[1] - end) - end - if #strs == 0 then - return nil - end - return table.concat(strs), raw -end - -local function getComment(func) - if not func then - return nil - end - local comments = {} - local params = func:getEmmyParams() - if params then - for _, param in ipairs(params) do - local option = param:getOption() - if option and option.comment then - comments[#comments+1] = ('+ `%s`*(%s)*: %s'):format(param:getName(), param:getType(), option.comment) - end - end - end - comments[#comments+1] = func:getComment() - if #comments == 0 then - return nil - end - return table.concat(comments, '\n\n') -end - -local function getOverLoads(name, func, object, select) - local overloads = func and func:getEmmyOverLoads() - if not overloads then - return nil - end - local list = {} - for _, ol in ipairs(overloads) do - local hover = emmyFunction(name, ol, object, select) - list[#list+1] = hover.label - end - return table.concat(list, '\n') -end - -return function (name, func, object, select) - local argStr, argLabel, args = buildValueArgs(func, object, select) - local returns = buildValueReturns(func) - local enum, rawEnum = buildEnum(func) - local comment = getComment(func) - local overloads = getOverLoads(name, func, object, select) - return { - label = ('function %s(%s)%s'):format(name, argStr, returns), - name = name, - argStr = argStr, - returns = returns, - description = comment, - enum = enum, - rawEnum = rawEnum, - argLabel = argLabel, - overloads = overloads, - args = args, - } -end diff --git a/server/src/core/hover/hover.lua b/server/src/core/hover/hover.lua deleted file mode 100644 index 2ee5cf46..00000000 --- a/server/src/core/hover/hover.lua +++ /dev/null @@ -1,326 +0,0 @@ -local findLib = require 'core.find_lib' -local getFunctionHover = require 'core.hover.function' -local getFunctionHoverAsLib = require 'core.hover.lib_function' -local getFunctionHoverAsEmmy = require 'core.hover.emmy_function' -local buildValueName = require 'core.hover.name' - -local OriginTypes = { - ['any'] = true, - ['nil'] = true, - ['integer'] = true, - ['number'] = true, - ['boolean'] = true, - ['string'] = true, - ['thread'] = true, - ['userdata'] = true, - ['table'] = true, - ['function'] = true, -} - -local function longString(str) - for i = 0, 10 do - local finish = ']' .. ('='):rep(i) .. ']' - if not str:find(finish, 1, true) then - return ('[%s[\n%s%s'):format(('='):rep(i), str, finish) - end - end - return ('%q'):format(str) -end - -local function formatString(str) - if #str > 1000 then - str = str:sub(1000) - end - if str:find('[\r\n]') then - str = str:gsub('[\000-\008\011-\012\014-\031\127]', '') - return longString(str) - else - str = str:gsub('[\000-\008\011-\012\014-\031\127]', function (char) - return ('\\%03d'):format(char:byte()) - end) - local single = str:find("'", 1, true) - local double = str:find('"', 1, true) - if single and double then - return longString(str) - elseif double then - return ("'%s'"):format(str) - else - return ('"%s"'):format(str) - end - end -end - -local function formatLiteral(v) - if math.type(v) == 'float' then - return ('%.10f'):format(v):gsub('[0]*$', ''):gsub('%.$', '.0') - elseif type(v) == 'string' then - return formatString(v) - else - return ('%q'):format(v) - end -end - -local function findClass(value) - -- 检查是否有emmy - local emmy = value:getEmmy() - if emmy then - return emmy:getType() - end - -- 检查对象元表 - local metaValue = value:getMetaTable() - if not metaValue then - return nil - end - -- 检查元表中的 __name - local metaName = metaValue:rawGet('__name') - if metaName and type(metaName:getLiteral()) == 'string' then - return metaName:getLiteral() - end - -- 检查元表的 __index - local indexValue = metaValue:rawGet('__index') - if not indexValue then - return nil - end - -- 查找index方法中的以下字段: type name class - -- 允许多重继承 - return indexValue:eachChild(function (k, v) - -- 键值类型必须均为字符串 - if type(k) ~= 'string' then - return - end - if type(v:getLiteral()) ~= 'string' then - return - end - local lKey = k:lower() - if lKey == 'type' - or lKey == 'name' - or lKey == 'class' - then - -- 必须只有过一次赋值 - local hasSet = false - local ok = v:eachInfo(function (info) - if info.type == 'set' then - if hasSet then - return false - else - hasSet = true - end - end - end) - if ok == false then - return false - end - return v:getLiteral() - end - end) -end - -local function formatKey(key) - local kType = type(key) - if kType == 'table' then - key = ('[*%s]'):format(key:getType()) - elseif math.type(key) == 'integer' then - key = ('[%03d]'):format(key) - elseif kType == 'string' then - if key:find '^%d' or key:find '[^%w_]' then - key = ('[%s]'):format(formatString(key)) - end - elseif key == '' then - key = '[*any]' - else - key = ('[%s]'):format(key) - end - return key -end - -local function unpackTable(value) - local lines = {} - value:eachChild(function (key, child) - key = formatKey(key) - - local vType = type(child:getLiteral()) - if vType == 'boolean' - or vType == 'integer' - or vType == 'number' - or vType == 'string' - then - lines[#lines+1] = ('%s: %s = %s'):format(key, child:getType(), formatLiteral(child:getLiteral())) - else - lines[#lines+1] = ('%s: %s'):format(key, child:getType()) - end - end) - local emmy = value:getEmmy() - if emmy then - if emmy.type == 'emmy.arrayType' then - lines[#lines+1] = ('[*integer]: %s'):format(emmy:getName()) - elseif emmy.type == 'emmy.tableType' then - lines[#lines+1] = ('[*%s]: %s'):format(emmy:getKeyType():getType(), emmy:getValueType():getType()) - end - end - if #lines == 0 then - return '{}' - end - - -- 整理一下表 - local cleaned = {} - local used = {} - for _, line in ipairs(lines) do - if used[line] then - goto CONTINUE - end - used[line] = true - if line == '[*any]: any' then - goto CONTINUE - end - cleaned[#cleaned+1] = ' ' .. line .. ',' - :: CONTINUE :: - end - - table.sort(cleaned) - table.insert(cleaned, 1, '{') - cleaned[#cleaned+1] = '}' - return table.concat(cleaned, '\r\n') -end - -local function getValueHover(source, name, value, lib) - local valueType = value:getType() - local class = findClass(value) - - if class then - valueType = class - lib = nil - end - - if not OriginTypes[valueType] then - valueType = '*' .. valueType - end - - local tips = {} - local literal - if lib then - literal = lib.code or (lib.value and formatLiteral(lib.value)) - tips[#tips+1] = lib.description - else - literal = value:getLiteral() and formatLiteral(value:getLiteral()) - end - - tips[#tips+1] = value:getComment() - - local tp - if source:bindLocal() then - tp = 'local' - local loc = source:bindLocal() - if loc.tags then - local mark = {} - local tagBufs = {} - for _, tag in ipairs(loc.tags) do - local tagName = tag[1] - if not mark[tagName] then - mark[tagName] = true - tagBufs[#tagBufs+1] = ('<%s>'):format(tagName) - end - end - name = name .. ' ' .. table.concat(tagBufs, ' ') - end - tips[#tips+1] = loc:getComment() - elseif source:get 'global' then - tp = 'global' - elseif source:get 'simple' then - local simple = source:get 'simple' - if simple[1]:get 'global' then - tp = 'global' - else - tp = 'field' - end - else - tp = 'field' - end - - local text - if valueType == 'table' then - text = ('%s %s: %s'):format(tp, name, unpackTable(value)) - else - if literal == nil then - if class and not OriginTypes[class] then - text = ('%s %s: %s %s'):format(tp, name, valueType, unpackTable(value)) - else - text = ('%s %s: %s'):format(tp, name, valueType) - end - else - text = ('%s %s: %s = %s'):format(tp, name, valueType, literal) - end - end - - local tip - if #tips > 0 then - tip = table.concat(tips, '\n\n-------------\n\n') - end - return { - label = text, - description = tip, - } -end - -local function hoverAsValue(source, lsp, select) - local lib, fullkey = findLib(source) - ---@type value - local value = source:findValue() - local name = fullkey or buildValueName(source) - - local hover - if value:getType() == 'function' then - local object = source:get 'object' - if lib then - hover = getFunctionHoverAsLib(name, lib, object, select) - else - local emmy = value:getEmmy() - if emmy and emmy.type == 'emmy.functionType' then - hover = getFunctionHoverAsEmmy(name, emmy, object, select) - else - local func = value:getFunction() - hover = getFunctionHover(name, func, object, select) - end - end - else - hover = getValueHover(source, name, value, lib) - end - - if not hover then - return nil - end - hover.name = name - return hover -end - -local function hoverAsTargetUri(source, lsp) - local uri = source:get 'target uri' - if not lsp or not lsp.workspace then - return nil - end - local path = lsp.workspace:relativePathByUri(uri) - if not path then - return nil - end - return { - description = ('[%s](%s)'):format(path:string(), uri), - } -end - -return function (source, lsp, select) - if not source then - return nil - end - if source:get 'target uri' then - return hoverAsTargetUri(source, lsp) - end - if source.type == 'name' and source:bindValue() then - return hoverAsValue(source, lsp, select) - end - if source.type == 'simple' then - source = source[#source] - if source.type == 'name' and source:bindValue() then - return hoverAsValue(source, lsp, select) - end - end - return nil -end diff --git a/server/src/core/hover/init.lua b/server/src/core/hover/init.lua deleted file mode 100644 index be5b5632..00000000 --- a/server/src/core/hover/init.lua +++ /dev/null @@ -1 +0,0 @@ -return require 'core.hover.hover' diff --git a/server/src/core/hover/lib_function.lua b/server/src/core/hover/lib_function.lua deleted file mode 100644 index 06087312..00000000 --- a/server/src/core/hover/lib_function.lua +++ /dev/null @@ -1,222 +0,0 @@ -local lang = require 'language' -local config = require 'config' -local function buildLibArgs(lib, object, select) - if not lib.args then - return '' - end - local start - if object then - start = 2 - else - start = 1 - end - local strs = {} - local args = {} - for i = start, #lib.args do - local arg = lib.args[i] - if arg.optional then - if i > start then - strs[#strs+1] = ' [' - else - strs[#strs+1] = '[' - end - end - if i > start then - strs[#strs+1] = ', ' - end - - local argStr = {} - if i == select then - argStr[#argStr+1] = '@ARG' - end - local name = '' - if arg.name then - name = ('%s: '):format(arg.name) - end - if type(arg.type) == 'table' then - name = name .. table.concat(arg.type, '/') - else - name = name .. (arg.type or 'any') - end - argStr[#argStr+1] = name - args[#args+1] = name - if arg.default then - argStr[#argStr+1] = ('(%q)'):format(arg.default) - end - if i == select then - argStr[#argStr+1] = '@ARG' - end - - for _, str in ipairs(argStr) do - strs[#strs+1] = str - end - if arg.optional == 'self' then - strs[#strs+1] = ']' - end - end - for _, arg in ipairs(lib.args) do - if arg.optional == 'after' then - strs[#strs+1] = ']' - 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, args -end - -local function buildLibReturns(lib) - if not lib.returns then - return '' - end - local strs = {} - for i, rtn in ipairs(lib.returns) do - if rtn.optional then - if i > 1 then - strs[#strs+1] = ' [' - else - strs[#strs+1] = '[' - end - end - if i > 1 then - strs[#strs+1] = ('\n% 3d. '):format(i) - end - if rtn.name then - strs[#strs+1] = ('%s: '):format(rtn.name) - end - if type(rtn.type) == 'table' then - strs[#strs+1] = table.concat(rtn.type, '/') - else - strs[#strs+1] = rtn.type or 'any' - end - if rtn.default then - strs[#strs+1] = ('(%q)'):format(rtn.default) - end - if rtn.optional == 'self' then - strs[#strs+1] = ']' - end - end - for _, rtn in ipairs(lib.returns) do - if rtn.optional == 'after' then - strs[#strs+1] = ']' - end - end - return '\n -> ' .. table.concat(strs) -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 = {} - local raw = {} - 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') - raw[name] = {} - 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] = tostring(enum.enum) - end - raw[name][#raw[name]+1] = strs[#strs] - if enum.description then - strs[#strs+1] = ' -- ' .. enum.description - end - end - end - return table.concat(strs), raw -end - -local function buildDoc(lib) - local doc = lib.doc - if not doc then - return - end - if lib.web then - return lang.script(lib.web, doc) - end - local version = config.config.runtime.version - if version == 'Lua 5.1' then - return lang.script('HOVER_DOCUMENT_LUA51', doc) - elseif version == 'Lua 5.2' then - return lang.script('HOVER_DOCUMENT_LUA52', doc) - elseif version == 'Lua 5.3' then - return lang.script('HOVER_DOCUMENT_LUA53', doc) - elseif version == 'Lua 5.4' then - return lang.script('HOVER_DOCUMENT_LUA54', doc) - elseif version == 'LuaJIT' then - return lang.script('HOVER_DOCUMENT_LUAJIT', doc) - end -end - -return function (name, lib, object, select) - local argStr, argLabel, args = buildLibArgs(lib, object, select) - local returns = buildLibReturns(lib) - local enum, rawEnum = buildEnum(lib) - local tip = lib.description - local doc = buildDoc(lib) - return { - label = ('function %s(%s)%s'):format(name, argStr, returns), - name = name, - argStr = argStr, - returns = returns, - description = tip, - enum = enum, - rawEnum = rawEnum, - argLabel = argLabel, - doc = doc, - args = args, - } -end diff --git a/server/src/core/hover/name.lua b/server/src/core/hover/name.lua deleted file mode 100644 index 763083b9..00000000 --- a/server/src/core/hover/name.lua +++ /dev/null @@ -1,38 +0,0 @@ -local getName = require 'core.name' - -return function (source) - if not source then - return '' - end - local value = source:bindValue() - if not value then - return '' - end - local func = value:getFunction() - local declarat - if func and func:getSource() then - declarat = func:getSource().name - else - declarat = source - end - if not declarat then - -- 如果声明者没有给名字,则找一个合适的名字 - local names = {} - value:eachInfo(function (info, src) - if info.type == 'local' or info.type == 'set' or info.type == 'return' then - if src.type == 'name' and src.uri == value.uri then - names[#names+1] = src - end - end - end) - if #names == 0 then - return '' - end - table.sort(names, function (a, b) - return a.id < b.id - end) - return names[1][1] or '' - end - - return getName(declarat, source) -end |