diff options
Diffstat (limited to 'script/core/hover/label.lua')
-rw-r--r-- | script/core/hover/label.lua | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/script/core/hover/label.lua b/script/core/hover/label.lua new file mode 100644 index 00000000..d785bc27 --- /dev/null +++ b/script/core/hover/label.lua @@ -0,0 +1,211 @@ +local buildName = require 'core.hover.name' +local buildArg = require 'core.hover.arg' +local buildReturn = require 'core.hover.return' +local buildTable = require 'core.hover.table' +local vm = require 'vm' +local util = require 'utility' +local guide = require 'parser.guide' +local lang = require 'language' +local config = require 'config' +local files = require 'files' + +local function asFunction(source, oop) + local name = buildName(source, oop) + local arg = buildArg(source, oop) + local rtn = buildReturn(source) + local lines = {} + lines[1] = ('function %s(%s)'):format(name, arg) + lines[2] = rtn + return table.concat(lines, '\n') +end + +local function asDocFunction(source) + local name = buildName(source) + local arg = buildArg(source) + local rtn = buildReturn(source) + local lines = {} + lines[1] = ('function %s(%s)'):format(name, arg) + lines[2] = rtn + return table.concat(lines, '\n') +end + +local function asDocTypeName(source) + for _, doc in ipairs(vm.getDocTypes(source[1])) do + if doc.type == 'doc.class.name' then + return 'class ' .. source[1] + end + if doc.type == 'doc.alias.name' then + local extends = doc.parent.extends + return lang.script('HOVER_EXTENDS', vm.getInferType(extends)) + end + end +end + +local function asValue(source, title) + local name = buildName(source) + local infers = vm.getInfers(source, 'deep') + local type = vm.getInferType(source, 'deep') + local class = vm.getClass(source, 'deep') + local literal = vm.getInferLiteral(source, 'deep') + local cont + if type ~= 'string' and not type:find('%[%]$') then + if #vm.getFields(source, 'deep') > 0 + or vm.hasInferType(source, 'table', 'deep') then + cont = buildTable(source) + end + end + local pack = {} + pack[#pack+1] = title + pack[#pack+1] = name .. ':' + if cont and type == 'table' then + type = nil + end + if class then + pack[#pack+1] = class + else + pack[#pack+1] = type + end + if literal then + pack[#pack+1] = '=' + pack[#pack+1] = literal + end + if cont then + pack[#pack+1] = cont + end + return table.concat(pack, ' ') +end + +local function asLocal(source) + return asValue(source, 'local') +end + +local function asGlobal(source) + return asValue(source, 'global') +end + +local function isGlobalField(source) + if source.type == 'field' + or source.type == 'method' then + source = source.parent + end + if source.type == 'setfield' + or source.type == 'getfield' + or source.type == 'setmethod' + or source.type == 'getmethod' then + local node = source.node + if node.type == 'setglobal' + or node.type == 'getglobal' then + return true + end + return isGlobalField(node) + elseif source.type == 'tablefield' then + local parent = source.parent + if parent.type == 'setglobal' + or parent.type == 'getglobal' then + return true + end + return isGlobalField(parent) + else + return false + end +end + +local function asField(source) + if isGlobalField(source) then + return asGlobal(source) + end + return asValue(source, 'field') +end + +local function asDocField(source) + local name = source.field[1] + local class + for _, doc in ipairs(source.bindGroup) do + if doc.type == 'doc.class' then + class = doc + break + end + end + if not class then + return ('field ?.%s: %s'):format( + name, + vm.getInferType(source.extends) + ) + end + return ('field %s.%s: %s'):format( + class.class[1], + name, + vm.getInferType(source.extends) + ) +end + +local function asString(source) + local str = source[1] + if type(str) ~= 'string' then + return '' + end + local len = #str + local charLen = util.utf8Len(str, 1, -1) + if len == charLen then + return lang.script('HOVER_STRING_BYTES', len) + else + return lang.script('HOVER_STRING_CHARACTERS', len, charLen) + end +end + +local function formatNumber(n) + local str = ('%.10f'):format(n) + str = str:gsub('%.?0*$', '') + return str +end + +local function asNumber(source) + if not config.config.hover.viewNumber then + return nil + end + local num = source[1] + if type(num) ~= 'number' then + return nil + end + local uri = guide.getUri(source) + local text = files.getText(uri) + if not text then + return nil + end + local raw = text:sub(source.start, source.finish) + if not raw or not raw:find '[^%-%d%.]' then + return nil + end + return formatNumber(num) +end + +return function (source, oop) + if source.type == 'function' then + return asFunction(source, oop) + elseif source.type == 'local' + or source.type == 'getlocal' + or source.type == 'setlocal' then + return asLocal(source) + elseif source.type == 'setglobal' + or source.type == 'getglobal' then + return asGlobal(source) + elseif source.type == 'getfield' + or source.type == 'setfield' + or source.type == 'getmethod' + or source.type == 'setmethod' + or source.type == 'tablefield' + or source.type == 'field' + or source.type == 'method' then + return asField(source) + elseif source.type == 'string' then + return asString(source) + elseif source.type == 'number' then + return asNumber(source) + elseif source.type == 'doc.type.function' then + return asDocFunction(source) + elseif source.type == 'doc.type.name' then + return asDocTypeName(source) + elseif source.type == 'doc.field' then + return asDocField(source) + end +end |