diff options
author | 最萌小汐 <sumneko@hotmail.com> | 2019-11-04 11:00:30 +0800 |
---|---|---|
committer | 最萌小汐 <sumneko@hotmail.com> | 2019-11-04 11:00:30 +0800 |
commit | da08423453d5b2e0c60fbee50b86ce1a7e03ba82 (patch) | |
tree | 21e2d138e09c275b9371ed996e9a680d97d3e889 /server-beta/src/doctor.lua | |
parent | a9af7f7bc869466da14ef2c4b7fb07ed589f7a09 (diff) | |
download | lua-language-server-da08423453d5b2e0c60fbee50b86ce1a7e03ba82.zip |
支持 uri
Diffstat (limited to 'server-beta/src/doctor.lua')
-rw-r--r-- | server-beta/src/doctor.lua | 210 |
1 files changed, 127 insertions, 83 deletions
diff --git a/server-beta/src/doctor.lua b/server-beta/src/doctor.lua index 48c3ebbe..08ec69cf 100644 --- a/server-beta/src/doctor.lua +++ b/server-beta/src/doctor.lua @@ -1,10 +1,8 @@ -local ac = ac local type = type local next = next local ipairs = ipairs local rawget = rawget local pcall = pcall -local collectgarbage = collectgarbage local getregistry = debug.getregistry local getmetatable = debug.getmetatable local getupvalue = debug.getupvalue @@ -16,101 +14,102 @@ local mathType = math.type local tableConcat = table.concat local _G = _G local registry = getregistry() +local tableSort = table.sort _ENV = nil local m = {} ---- 内存快照 ----@return table -function m.snapshot() - local mark = {} - local find +local function getTostring(obj) + local mt = getmetatable(obj) + if not mt then + return nil + end + local toString = rawget(mt, '__tostring') + if not toString then + return nil + end + local suc, str = pcall(toString, obj) + if not suc then + return nil + end + if type(str) ~= 'string' then + return nil + end + return str +end - local function getTostring(obj) - local mt = getmetatable(obj) - if not mt then - return nil +local function formatName(obj) + local tp = type(obj) + if tp == 'nil' then + return 'nil:nil' + elseif tp == 'boolean' then + if obj == true then + return 'boolean:true' + else + return 'boolean:false' end - local toString = rawget(mt, '__tostring') - if not toString then - return nil + elseif tp == 'number' then + if mathType(obj) == 'integer' then + return ('number:%d'):format(obj) + else + -- 如果浮点数可以完全表示为整数,那么就转换为整数 + local str = ('%.10f'):format(obj):gsub('%.?[0]+$', '') + if str:find('.', 1, true) then + -- 如果浮点数不能表示为整数,那么再加上它的精确表示法 + str = ('%s(%q)'):format(str, obj) + end + return 'number:' .. str end - local suc, str = pcall(toString, obj) - if not suc then - return nil + elseif tp == 'string' then + local str = ('%q'):format(obj) + if #str > 100 then + local new = ('%s...(len=%d)'):format(str:sub(1, 100), #str) + if #new < #str then + str = new + end end - if type(str) ~= 'string' then - return nil + return 'string:' .. str + elseif tp == 'function' then + local info = getinfo(obj, 'S') + if info.what == 'c' then + return ('function:%p(C)'):format(obj) + elseif info.what == 'main' then + return ('function:%p(main)'):format(obj) + else + return ('function:%p(%s:%d-%d)'):format(obj, info.source, info.linedefined, info.lastlinedefined) end - return str - end - - local function formatName(obj) - local tp = type(obj) - if tp == 'nil' then - return 'nil:nil' - elseif tp == 'boolean' then - if obj == true then - return 'boolean:true' - else - return 'boolean:false' - end - elseif tp == 'number' then - if mathType(obj) == 'integer' then - return ('number:%d'):format(obj) - else - -- 如果浮点数可以完全表示为整数,那么就转换为整数 - local str = ('%.10f'):format(obj):gsub('%.?[0]+$', '') - if str:find('.', 1, true) then - -- 如果浮点数不能表示为整数,那么再加上它的精确表示法 - str = ('%s(%q)'):format(str, obj) - end - return 'number:' .. str - end - elseif tp == 'string' then - local str = ('%q'):format(obj) - if #str > 100 then - local new = ('%s...(len=%d)'):format(str:sub(1, 100), #str) - if #new < #str then - str = new - end - end - return 'string:' .. str - elseif tp == 'function' then - local info = getinfo(obj, 'S') - if info.what == 'c' then - return ('function:%p(C)'):format(obj) - elseif info.what == 'main' then - return ('function:%p(main)'):format(obj) - else - return ('function:%p(%s:%d-%d)'):format(obj, info.source, info.linedefined, info.lastlinedefined) - end - elseif tp == 'table' then - local id = getTostring(obj) - if not id then - if obj == _G then - id = '_G' - elseif obj == registry then - id = 'registry' - end - end - if id then - return ('table:%p(%s)'):format(obj, id) - else - return ('table:%p'):format(obj) - end - elseif tp == 'userdata' then - local id = getTostring(obj) - if id then - return ('userdata:%p(%s)'):format(obj, id) - else - return ('userdata:%p'):format(obj) + elseif tp == 'table' then + local id = getTostring(obj) + if not id then + if obj == _G then + id = '_G' + elseif obj == registry then + id = 'registry' end + end + if id then + return ('table:%p(%s)'):format(obj, id) else - return ('%s:%p'):format(tp, obj) + return ('table:%p'):format(obj) end + elseif tp == 'userdata' then + local id = getTostring(obj) + if id then + return ('userdata:%p(%s)'):format(obj, id) + else + return ('userdata:%p'):format(obj) + end + else + return ('%s:%p'):format(tp, obj) end +end + +--- 内存快照 +---@return table +function m.snapshot() + local mark = {} + local find local function findTable(t, result) result = result or {} @@ -333,4 +332,49 @@ function m.catch(...) return result end +--- 生成一个报告 +---@return string +function m.report() + local snapshot = m.snapshot() + local cache = {} + local mark = {} + + local function scan(t) + local obj = t.info.object + local tp = type(obj) + if tp == 'table' + or tp == 'userdata' + or tp == 'function' + or tp == 'string' + or tp == 'thread' then + local point = ('%p'):format(obj) + if not cache[point] then + cache[point] = { + point = point, + count = 0, + name = formatName(obj), + } + end + cache[point].count = cache[point].count + 1 + end + if not mark[t.info] then + mark[t.info] = true + for _, child in ipairs(t.info) do + scan(child) + end + end + end + + scan(snapshot) + + local list = {} + for _, info in next, cache do + list[#list+1] = info + end + tableSort(list, function (a, b) + return a.name < b.name + end) + return list +end + return m |