summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2022-04-01 02:46:36 +0800
committer最萌小汐 <sumneko@hotmail.com>2022-04-01 02:46:36 +0800
commitd8e7c0b4b388c5ca125d17554814be68444ce1aa (patch)
tree0259c411ad5c861520069ec11304ea86b24a8d45
parentbf6538f45636c4f3bceba6e3f4bbdaef3d21a071 (diff)
downloadlua-language-server-d8e7c0b4b388c5ca125d17554814be68444ce1aa.zip
update
-rw-r--r--script/core/completion/completion.lua2
-rw-r--r--script/core/hover/label.lua2
-rw-r--r--script/core/hover/name.lua2
-rw-r--r--script/core/hover/table.lua93
-rw-r--r--script/vm/infer.lua54
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