diff options
author | 最萌小汐 <sumneko@hotmail.com> | 2022-04-01 02:46:36 +0800 |
---|---|---|
committer | 最萌小汐 <sumneko@hotmail.com> | 2022-04-01 02:46:36 +0800 |
commit | d8e7c0b4b388c5ca125d17554814be68444ce1aa (patch) | |
tree | 0259c411ad5c861520069ec11304ea86b24a8d45 | |
parent | bf6538f45636c4f3bceba6e3f4bbdaef3d21a071 (diff) | |
download | lua-language-server-d8e7c0b4b388c5ca125d17554814be68444ce1aa.zip |
update
-rw-r--r-- | script/core/completion/completion.lua | 2 | ||||
-rw-r--r-- | script/core/hover/label.lua | 2 | ||||
-rw-r--r-- | script/core/hover/name.lua | 2 | ||||
-rw-r--r-- | script/core/hover/table.lua | 93 | ||||
-rw-r--r-- | script/vm/infer.lua | 54 |
5 files changed, 79 insertions, 74 deletions
diff --git a/script/core/completion/completion.lua b/script/core/completion/completion.lua index 133b262d..6a979af9 100644 --- a/script/core/completion/completion.lua +++ b/script/core/completion/completion.lua @@ -168,7 +168,7 @@ local function buildDetail(source) return end local types = infer.getInfer(source):view() - local literals = infer.viewLiterals(source) + local literals = infer.getInfer(source):viewLiterals() if literals then return types .. ' = ' .. literals else diff --git a/script/core/hover/label.lua b/script/core/hover/label.lua index 150f0f24..30a3e833 100644 --- a/script/core/hover/label.lua +++ b/script/core/hover/label.lua @@ -44,7 +44,7 @@ end local function asValue(source, title) local name = buildName(source, false) or '' local type = infer.getInfer(source):view() - local literal = infer.viewLiterals(source) + local literal = infer.getInfer(source):viewLiterals() local cont if not infer.getInfer(source):hasType 'string' and not type:find('%[%]$') then diff --git a/script/core/hover/name.lua b/script/core/hover/name.lua index 3b1a45c2..905c5ec7 100644 --- a/script/core/hover/name.lua +++ b/script/core/hover/name.lua @@ -19,7 +19,7 @@ end local function asField(source, oop) local class if source.node.type ~= 'getglobal' then - class = infer.viewClass(source.node) + class = infer.getInfer(source.node):viewClass() end local node = class or buildName(source.node, false) diff --git a/script/core/hover/table.lua b/script/core/hover/table.lua index e8c9b95d..b83f3dcb 100644 --- a/script/core/hover/table.lua +++ b/script/core/hover/table.lua @@ -16,23 +16,23 @@ local function formatKey(key) return ('[%s]'):format(key) end -local function buildAsHash(keys, inferMap, literalMap, optMap, reachMax) +local function buildAsHash(keys, typeMap, literalMap, optMap, reachMax) local lines = {} lines[#lines+1] = '{' for _, key in ipairs(keys) do - local inferView = inferMap[key] + local typeView = typeMap[key] local literalView = literalMap[key] if literalView then lines[#lines+1] = (' %s%s: %s = %s,'):format( formatKey(key), optMap[key] and '?' or '', - inferView, + typeView, literalView) else lines[#lines+1] = (' %s%s: %s,'):format( formatKey(key), optMap[key] and '?' or '', - inferView + typeView ) end end @@ -43,27 +43,27 @@ local function buildAsHash(keys, inferMap, literalMap, optMap, reachMax) return table.concat(lines, '\n') end -local function buildAsConst(keys, inferMap, literalMap, optMap, reachMax) +local function buildAsConst(keys, typeMap, literalMap, optMap, reachMax) table.sort(keys, function (a, b) return tonumber(literalMap[a]) < tonumber(literalMap[b]) end) local lines = {} lines[#lines+1] = '{' for _, key in ipairs(keys) do - local inferView = inferMap[key] + local typeView = typeMap[key] local literalView = literalMap[key] if literalView then lines[#lines+1] = (' %s%s: %s = %s,'):format( formatKey(key), optMap[key] and '?' or '', - inferView, + typeView, literalView ) else lines[#lines+1] = (' %s%s: %s,'):format( formatKey(key), optMap[key] and '?' or '', - inferView + typeView ) end end @@ -82,11 +82,11 @@ local typeSorter = { local function getKeyMap(fields) local keys = {} - local mark = {} + local map = {} for _, field in ipairs(fields) do local key = vm.getKeyName(field) - if key and not mark[key] then - mark[key] = true + if key and not map[key] then + map[key] = true keys[#keys+1] = key end end @@ -107,68 +107,87 @@ local function getKeyMap(fields) return tsa < tsb end end) - return keys + return keys, map end ----@async -local function getFieldMap(fields, keys) - local fieldMap = {} - for _, key in ipairs(keys) do - fieldMap[key] = { - infer = nil, - literal = nil, - opt = false, - } - end +local function getOptMap(fields, keyMap) + local optMap = {} for _, field in ipairs(fields) do if field.type == 'doc.field.name' then if field.parent.optional then local key = vm.getKeyName(field) - fieldMap[key].opt = true + if keyMap[key] then + optMap[key] = true + end end end if field.type == 'doc.type.field' then if field.optional then local key = vm.getKeyName(field) - fieldMap[key].opt = true + if keyMap[key] then + optMap[key] = true + end end end end - return fieldMap + return optMap +end + +---@async +local function getInferMap(fields, keyMap) + ---@type table<string, vm.infer> + local inferMap = {} + for _, field in ipairs(fields) do + local key = vm.getKeyName(field) + if not keyMap[key] then + goto CONTINUE + end + await.delay() + local ifr = infer.getInfer(field) + if inferMap[key] then + inferMap[key]:merge(ifr) + else + inferMap[key] = ifr + end + ::CONTINUE:: + end + return inferMap end ---@async return function (source) - local maxFields = config.get(guide.getUri(source), 'Lua.hover.previewFields') + local uri = guide.getUri(source) + local maxFields = config.get(uri, 'Lua.hover.previewFields') if maxFields <= 0 then return 'table' end - local fields = vm.getFields(source) - local keys = getKeyMap(fields) - local fieldMap = getFieldMap(fields, keys) - + local fields = vm.getFields(source) + local keys, map = getKeyMap(fields) if #keys == 0 then return '{}' end - local inferMap = {} - local literalMap = {} - local reachMax = #keys - maxFields if #keys > maxFields then for i = maxFields + 1, #keys do + map[keys[i]] = nil keys[i] = nil end end + local optMap = getOptMap(fields, map) + local inferMap = getInferMap(fields, map) + + local typeMap = {} + local literalMap = {} local isConsts = true for i = 1, #keys do await.delay() local key = keys[i] - inferMap[key] = infer.viewType(source, key) - literalMap[key] = infer.viewLiterals(source, key) + typeMap[key] = inferMap[key]:view('unknown', uri) + literalMap[key] = inferMap[key]:viewLiterals() if not tonumber(literalMap[key]) then isConsts = false end @@ -177,9 +196,9 @@ return function (source) local result if isConsts then - result = buildAsConst(keys, inferMap, literalMap, optMap, reachMax) + result = buildAsConst(keys, typeMap, literalMap, optMap, reachMax) else - result = buildAsHash(keys, inferMap, literalMap, optMap, reachMax) + result = buildAsHash(keys, typeMap, literalMap, optMap, reachMax) end --if timeUp then diff --git a/script/vm/infer.lua b/script/vm/infer.lua index 6a435e97..cb84571b 100644 --- a/script/vm/infer.lua +++ b/script/vm/infer.lua @@ -22,7 +22,7 @@ mt.isParam = false mt.isLocal = false mt.hasDocFunction = false -local nullInfer = setmetatable({}, mt) +m.NULL = setmetatable({}, mt) local inferSorted = { ['boolean'] = - 100, @@ -135,7 +135,7 @@ local viewNodeSwitch = util.switch() function m.getInfer(source) local node = compiler.compileNode(source) if not node then - return nullInfer + return m.NULL end if node.type == 'union' and node.lastInfer then return node.lastInfer @@ -213,8 +213,9 @@ function mt:_computeViews() end ---@param default? string +---@param uri? uri ---@return string -function mt:view(default) +function mt:view(default, uri) self:_computeViews() if self.views['any'] then @@ -244,7 +245,7 @@ function mt:view(default) end) local max = #array - local limit = config.get(self.uri, 'Lua.hover.enumsLimit') + local limit = config.get(uri or self.uri, 'Lua.hover.enumsLimit') if max > limit then local view = string.format('%s...(+%d)' @@ -265,43 +266,30 @@ function mt:view(default) end ---@param other vm.infer ----@param uri? uri ---@return vm.infer -function mt:merge(other, uri) - local infer = setmetatable({ - node = union(self.node, other.node), - uri = uri or self.uri, - views = {}, - }, mt) - - for view in pairs(self.views) do - infer.views[view] = true +function mt:merge(other) + if self == m.NULL then + return other end - for view in pairs(other.views) do - infer.views[view] = true + if other == m.NULL then + return self end - infer.hasClass = self.hasClass or other.hasClass - infer.hasDocFunction = self.hasDocFunction or other.hasDocFunction - infer.hasNumber = self.hasNumber or other.hasNumber - infer.hasTable = self.hasTable or other.hasTable - infer.isLocal = self.isLocal or other.isLocal - infer.isParam = self.isParam or other.isParam - - infer:_trim() + local infer = setmetatable({ + node = union(self.node, other.node), + uri = self.uri, + }, mt) return infer end ----@param source parser.object ---@return string? -function m.viewLiterals(source) - local node = compiler.compileNode(source) - if not node then +function mt:viewLiterals() + if not self.node then return nil end local literals = {} - for n in nodeMgr.eachNode(node) do + for n in nodeMgr.eachNode(self.node) do if n.type == 'string' or n.type == 'number' or n.type == 'integer' then @@ -315,15 +303,13 @@ function m.viewLiterals(source) return table.concat(literals, '|') end ----@param source parser.object ---@return string? -function m.viewClass(source) - local node = compiler.compileNode(source) - if not node then +function mt:viewClass() + if not self.node then return nil end local class = {} - for n in nodeMgr.eachNode(node) do + for n in nodeMgr.eachNode(self.node) do if n.type == 'global' and n.cate == 'type' then class[#class+1] = n.name end |