diff options
-rw-r--r-- | script/core/hover/arg.lua | 11 | ||||
-rw-r--r-- | script/core/hover/description.lua | 5 | ||||
-rw-r--r-- | script/core/hover/init.lua | 5 | ||||
-rw-r--r-- | script/core/hover/label.lua | 14 | ||||
-rw-r--r-- | script/core/hover/name.lua | 16 | ||||
-rw-r--r-- | script/core/hover/return.lua | 27 | ||||
-rw-r--r-- | script/core/infer.lua | 38 | ||||
-rw-r--r-- | script/vm/getClass.lua | 64 | ||||
-rw-r--r-- | script/vm/getInfer.lua | 104 | ||||
-rw-r--r-- | script/vm/init.lua | 2 | ||||
-rw-r--r-- | test.lua | 2 | ||||
-rw-r--r-- | test/hover/init.lua | 64 |
12 files changed, 107 insertions, 245 deletions
diff --git a/script/core/hover/arg.lua b/script/core/hover/arg.lua index b8c9eba0..122d7dc8 100644 --- a/script/core/hover/arg.lua +++ b/script/core/hover/arg.lua @@ -1,4 +1,5 @@ -local searcher = require 'core.searcher' +local guide = require 'parser.guide' +local infer = require 'core.infer' local vm = require 'vm' local function optionalArg(arg) @@ -21,7 +22,7 @@ local function asFunction(source, oop) methodDef = true end if methodDef then - args[#args+1] = ('self: %s'):format(vm.getInferType(parent.node)) + args[#args+1] = ('self: %s'):format(infer.searchAndViewInfers(parent.node)) end if source.args then for i = 1, #source.args do @@ -29,15 +30,15 @@ local function asFunction(source, oop) if arg.dummy then goto CONTINUE end - local name = arg.name or searcher.getKeyName(arg) + local name = arg.name or guide.getKeyName(arg) if name then args[#args+1] = ('%s%s: %s'):format( name, optionalArg(arg) and '?' or '', - vm.getInferType(arg) + infer.searchAndViewInfers(arg) ) else - args[#args+1] = ('%s'):format(vm.getInferType(arg)) + args[#args+1] = ('%s'):format(infer.searchAndViewInfers(arg)) end ::CONTINUE:: end diff --git a/script/core/hover/description.lua b/script/core/hover/description.lua index 85224c66..891d7cae 100644 --- a/script/core/hover/description.lua +++ b/script/core/hover/description.lua @@ -2,11 +2,12 @@ local vm = require 'vm' local ws = require 'workspace' local furi = require 'file-uri' local files = require 'files' -local searcher = require 'core.searcher' +local searcher = require 'core.searcher' local markdown = require 'provider.markdown' local config = require 'config' local lang = require 'language' local util = require 'utility' +local guide = require 'parser.guide' local function asStringInRequire(source, literal) local rootPath = ws.path or '' @@ -72,7 +73,7 @@ local function asStringView(source, literal) end local function asString(source) - local literal = searcher.getLiteral(source) + local literal = guide.getLiteral(source) if type(literal) ~= 'string' then return nil end diff --git a/script/core/hover/init.lua b/script/core/hover/init.lua index 86c5b992..ded3e9eb 100644 --- a/script/core/hover/init.lua +++ b/script/core/hover/init.lua @@ -1,5 +1,5 @@ local files = require 'files' -local searcher = require 'core.searcher' +local searcher = require 'core.searcher' local vm = require 'vm' local getLabel = require 'core.hover.label' local getDesc = require 'core.hover.description' @@ -7,6 +7,7 @@ local util = require 'utility' local findSource = require 'core.find-source' local lang = require 'language' local markdown = require 'provider.markdown' +local infer = require 'core.infer' local function eachFunctionAndOverload(value, callback) callback(value) @@ -123,7 +124,7 @@ local function getHover(source) if source.type == 'doc.type.name' then return getHoverAsDocName(source) end - local isFunction = vm.hasInferType(source, 'function', 0) + local isFunction = infer.hasType(source, 'function') if isFunction then return getHoverAsFunction(source) else diff --git a/script/core/hover/label.lua b/script/core/hover/label.lua index da07200f..40e697dc 100644 --- a/script/core/hover/label.lua +++ b/script/core/hover/label.lua @@ -2,9 +2,10 @@ 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 infer = require 'core.infer' local vm = require 'vm' local util = require 'utility' -local searcher = require 'core.searcher' +local searcher = require 'core.searcher' local lang = require 'language' local config = require 'config' local files = require 'files' @@ -44,16 +45,15 @@ end local function asValue(source, title) local name = buildName(source) - local infers = vm.getInfers(source, 0) - local type = vm.getInferType(source, 0) - local class = vm.getClass(source, 0) - local literal = vm.getInferLiteral(source, 0) + local type = infer.searchAndViewInfers(source, 0) + local class = nil -- infer.getClass(source, 0) + local literal = infer.searchAndViewLiterals(source, 0) local cont - if not vm.hasInferType(source, 'string', 0) + if not infer.hasType(source, 'string', 0) and not type:find('%[%]$') and not type:find('%w%<') then if #vm.getFields(source, 0) > 0 - or vm.hasInferType(source, 'table', 0) then + or infer.hasType(source, 'table', 0) then cont = buildTable(source) end end diff --git a/script/core/hover/name.lua b/script/core/hover/name.lua index fe0f2ffb..6db6e8ea 100644 --- a/script/core/hover/name.lua +++ b/script/core/hover/name.lua @@ -1,10 +1,12 @@ -local searcher = require 'core.searcher' +local searcher = require 'core.searcher' +local infer = require 'core.infer' +local guide = require 'parser.guide' local vm = require 'vm' local buildName local function asLocal(source) - local name = searcher.getKeyName(source) + local name = guide.getKeyName(source) if not source.attrs then return name end @@ -19,10 +21,10 @@ end local function asField(source, oop) local class if source.node.type ~= 'getglobal' then - class = vm.getClass(source.node, 0) + class = infer.getClass(source) end - local node = class or searcher.getKeyName(source.node) or '?' - local method = searcher.getKeyName(source) + local node = class or guide.getKeyName(source.node) or '?' + local method = guide.getKeyName(source) if oop then return ('%s:%s'):format(node, method) else @@ -34,11 +36,11 @@ local function asTableField(source) if not source.field then return end - return searcher.getKeyName(source.field) + return guide.getKeyName(source.field) end local function asGlobal(source) - return searcher.getKeyName(source) + return guide.getKeyName(source) end local function asDocFunction(source) diff --git a/script/core/hover/return.lua b/script/core/hover/return.lua index 0825e77d..050e25cd 100644 --- a/script/core/hover/return.lua +++ b/script/core/hover/return.lua @@ -1,12 +1,5 @@ -local searcher = require 'core.searcher' -local vm = require 'vm' - -local function mergeTypes(returns) - if type(returns) == 'string' then - return returns - end - return searcher.mergeTypes(returns) -end +local vm = require 'vm' +local infer = require 'core.infer' local function getReturnDualByDoc(source) local docs = source.bindDocs @@ -55,24 +48,20 @@ local function asFunction(source) local returns = {} for i, rtn in ipairs(dual) do local line = {} - local types = {} + local infers = {} if i == 1 then line[#line+1] = ' -> ' else line[#line+1] = ('% 3d. '):format(i) end for n = 1, #rtn do - local values = vm.getInfers(rtn[n]) - for _, value in ipairs(values) do - if value.type then - for tp in value.type:gmatch '[^|]+' do - types[tp] = true - end - end + local values = infer.searchInfers(rtn[n]) + for tp in pairs(values) do + infers[tp] = true end end - if next(types) or rtn[1] then - local tp = mergeTypes(types) or 'any' + if next(infers) or rtn[1] then + local tp = infer.viewInfers(infers) if rtn[1].name then line[#line+1] = ('%s%s: %s'):format( rtn[1].name[1], diff --git a/script/core/infer.lua b/script/core/infer.lua index 770b48f9..17935aa5 100644 --- a/script/core/infer.lua +++ b/script/core/infer.lua @@ -1,6 +1,8 @@ local searcher = require 'core.searcher' local config = require 'config' local noder = require 'core.noder' +local vm = require "vm.vm" +local guide = require "parser.guide" local STRING_OR_TABLE = {'STRING_OR_TABLE'} local BE_RETURN = {'BE_RETURN'} @@ -484,4 +486,40 @@ function m.searchAndViewInfers(source) return view end +function m.searchAndViewLiterals(source) + if not source then + return nil + end + local result = {} + local defs = vm.getDefs(source) + for _, def in ipairs(defs) do + if guide.isLiteral(def) and def[1] ~= nil then + result[#result+1] = ('%q'):format(def[1]) + end + end + table.sort(result) + return table.concat(result, '|') +end + +---搜索并显示推断的class +---@param source parser.guide.object +---@return string? +function m.getClass(source) + if not source then + return nil + end + local infers = {} + local defs = searcher.requestDefinition(source) + for _, def in ipairs(defs) do + if def.type == 'doc.class.name' then + infers[def[1]] = true + end + end + local view = m.viewInfers(infers) + if view == 'any' then + return nil + end + return view +end + return m diff --git a/script/vm/getClass.lua b/script/vm/getClass.lua deleted file mode 100644 index fbd50fc8..00000000 --- a/script/vm/getClass.lua +++ /dev/null @@ -1,64 +0,0 @@ ----@type vm -local vm = require 'vm.vm' -local searcher = require 'core.searcher' - -local function lookUpDocClass(source) - local infers = vm.getInfers(source, 0) - for _, infer in ipairs(infers) do - if infer.source.type == 'doc.class' - or infer.source.type == 'doc.type' then - return searcher.viewInferType(infers) - end - end - return nil -end - -local function getClass(source, classes, depth, deep) - local docClass = lookUpDocClass(source) - if docClass then - classes[docClass] = true - return - end - if depth > 3 then - return - end - local value = searcher.getObjectValue(source) or source - if not deep then - if value and value.type == 'string' then - classes[value[1]] = true - end - else - for _, src in ipairs(vm.getDefFields(value)) do - local key = vm.getKeyName(src) - if not key then - goto CONTINUE - end - local lkey = key:lower() - if lkey == 'type' - or lkey == '__name' - or lkey == 'name' - or lkey == 'class' then - local value = searcher.getObjectValue(src) - if value and value.type == 'string' then - classes[value[1]] = true - end - end - ::CONTINUE:: - end - end - if next(classes) then - return - end - vm.eachMeta(source, function (mt) - getClass(mt, classes, depth + 1, deep) - end) -end - -function vm.getClass(source, deep) - local classes = {} - getClass(source, classes, 1, deep) - if not next(classes) then - return nil - end - return searcher.mergeTypes(classes) -end diff --git a/script/vm/getInfer.lua b/script/vm/getInfer.lua deleted file mode 100644 index be9a66ab..00000000 --- a/script/vm/getInfer.lua +++ /dev/null @@ -1,104 +0,0 @@ ----@type vm -local vm = require 'vm.vm' -local searcher= require 'core.searcher' -local util = require 'utility' -local await = require 'await' -local config = require 'config' - -NIL = setmetatable({'<nil>'}, { __tostring = function () return 'nil' end }) - ---- 是否包含某种类型 -function vm.hasType(source, type, deep) - local defs = vm.getDefs(source, deep) - for i = 1, #defs do - local def = defs[i] - local value = searcher.getObjectValue(def) or def - if value.type == type then - return true - end - end - return false -end - ---- 是否包含某种类型 -function vm.hasInferType(source, type, deep) - local infers = vm.getInfers(source, deep) - for i = 1, #infers do - local infer = infers[i] - if infer.type == type then - return true - end - end - return false -end - -function vm.getInferType(source, deep) - local infers = vm.getInfers(source, deep) - return searcher.viewInferType(infers) -end - -function vm.getInferLiteral(source, deep) - local infers = vm.getInfers(source, deep) - local literals = {} - local mark = {} - for _, infer in ipairs(infers) do - local value = infer.value - if value and not mark[value] then - mark[value] = true - literals[#literals+1] = util.viewLiteral(value) - end - end - if #literals == 0 then - return nil - end - table.sort(literals) - return table.concat(literals, '|') -end - -local function getInfers(source, deep) - local results = {} - local lock = vm.lock('getInfers', source) - if not lock then - return results - end - - deep = config.config.intelliSense.searchDepth + (deep or 0) - - await.delay() - - local clock = os.clock() - local myResults, count = searcher.requestInfer(source, vm.interface, deep) - if DEVELOP and os.clock() - clock > 0.1 then - log.warn('requestInfer', count, os.clock() - clock, searcher.getUri(source), util.dump(source, { deep = 1 })) - end - vm.mergeResults(results, myResults) - - lock() - - return results -end - -local function getInfersBySource(source, deep) - deep = deep or -999 - local cache = vm.getCache('getInfers')[source] - if not cache or cache.deep < deep then - cache = getInfers(source, deep) - cache.deep = deep - vm.getCache('getInfers')[source] = cache - end - return cache -end - ---- 获取对象的值 ---- 会尝试穿透函数调用 -function vm.getInfers(source, deep) - if searcher.isGlobal(source) then - local name = searcher.getKeyName(source) - local cache = vm.getCache('getInfersOfGlobal')[name] - or getInfersBySource(source, deep) - vm.getCache('getInfersOfGlobal')[name] = cache - return cache - else - return getInfersBySource(source, deep) - end -end diff --git a/script/vm/init.lua b/script/vm/init.lua index b9e8e147..586236f3 100644 --- a/script/vm/init.lua +++ b/script/vm/init.lua @@ -2,8 +2,6 @@ local vm = require 'vm.vm' require 'vm.getGlobals' require 'vm.getDocs' require 'vm.getLibrary' -require 'vm.getInfer' -require 'vm.getClass' require 'vm.getMeta' require 'vm.eachField' require 'vm.eachDef' @@ -65,11 +65,11 @@ local function testAll() test 'references' test 'definition' test 'type_inference' + test 'hover' test 'crossfile' test 'diagnostics' test 'highlight' test 'rename' - test 'hover' test 'completion' test 'signature' test 'document_symbol' diff --git a/test/hover/init.lua b/test/hover/init.lua index d0e50036..adfa00bf 100644 --- a/test/hover/init.lua +++ b/test/hover/init.lua @@ -54,39 +54,39 @@ obj:<?init?>(1, '测试') function mt:init(a: any, b: any, c: any) ]] -TEST [[ -local mt = {} -mt.__index = mt -mt.type = 'Class' - -function mt:init(a, b, c) - return -end - -local obj = setmetatable({}, mt) - -obj:<?init?>(1, '测试') -]] -[[ -function Class:init(a: any, b: any, c: any) -]] - -TEST [[ -local mt = {} -mt.__index = mt -mt.__name = 'Class' - -function mt:init(a, b, c) - return -end - -local obj = setmetatable({}, mt) +--TEST [[ +--local mt = {} +--mt.__index = mt +--mt.type = 'Class' +-- +--function mt:init(a, b, c) +-- return +--end +-- +--local obj = setmetatable({}, mt) +-- +--obj:<?init?>(1, '测试') +--]] +--[[ +--function Class:init(a: any, b: any, c: any) +--]] -obj:<?init?>(1, '测试') -]] -[[ -function Class:init(a: any, b: any, c: any) -]] +--TEST [[ +--local mt = {} +--mt.__index = mt +--mt.__name = 'Class' +-- +--function mt:init(a, b, c) +-- return +--end +-- +--local obj = setmetatable({}, mt) +-- +--obj:<?init?>(1, '测试') +--]] +--[[ +--function Class:init(a: any, b: any, c: any) +--]] TEST [[ local mt = {} |