summaryrefslogtreecommitdiff
path: root/script
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2022-11-08 00:01:12 +0800
committer最萌小汐 <sumneko@hotmail.com>2022-11-08 00:01:12 +0800
commit00dd1ed171beda2e892a2460d6e7eff321c775e8 (patch)
tree95a17424f070cc6d0ee7d458011519c82039a378 /script
parent34d32a478bcd066baf49ccf36f5f26a132cbfab8 (diff)
downloadlua-language-server-00dd1ed171beda2e892a2460d6e7eff321c775e8.zip
support enums with runtime values
resolved #1411
Diffstat (limited to 'script')
-rw-r--r--script/core/completion/completion.lua34
-rw-r--r--script/vm/global.lua23
-rw-r--r--script/vm/type.lua44
3 files changed, 54 insertions, 47 deletions
diff --git a/script/core/completion/completion.lua b/script/core/completion/completion.lua
index 39b54209..f87b55a6 100644
--- a/script/core/completion/completion.lua
+++ b/script/core/completion/completion.lua
@@ -1181,11 +1181,25 @@ local function insertDocEnum(state, pos, doc, enums)
if not key then
goto CONTINUE
end
- if field.value.type == 'integer'
- or field.value.type == 'string' then
- if parentName then
- enums[#enums+1] = {
- label = parentName .. '.' .. key,
+ if parentName then
+ enums[#enums+1] = {
+ label = parentName .. '.' .. key,
+ kind = define.CompletionItemKind.EnumMember,
+ id = stack(field, function (newField) ---@async
+ return {
+ detail = buildDetail(newField),
+ description = buildDesc(newField),
+ }
+ end),
+ }
+ end
+ for nd in vm.compileNode(field.value):eachObject() do
+ if nd.type == 'boolean'
+ or nd.type == 'number'
+ or nd.type == 'integer'
+ or nd.type == 'string' then
+ valueEnums[#valueEnums+1] = {
+ label = util.viewLiteral(nd[1]),
kind = define.CompletionItemKind.EnumMember,
id = stack(field, function (newField) ---@async
return {
@@ -1195,16 +1209,6 @@ local function insertDocEnum(state, pos, doc, enums)
end),
}
end
- valueEnums[#valueEnums+1] = {
- label = util.viewLiteral(field.value[1]),
- kind = define.CompletionItemKind.EnumMember,
- id = stack(field, function (newField) ---@async
- return {
- detail = buildDetail(newField),
- description = buildDesc(newField),
- }
- end),
- }
end
::CONTINUE::
end
diff --git a/script/vm/global.lua b/script/vm/global.lua
index 027b096a..6db3a58c 100644
--- a/script/vm/global.lua
+++ b/script/vm/global.lua
@@ -164,11 +164,9 @@ local function createGlobal(name, cate)
}, mt)
end
----@alias parser.enum string|integer
-
---@class parser.object
---@field package _globalNode vm.global|false
----@field package _enums? parser.enum[]
+---@field package _enums? parser.object[]
---@type table<string, vm.global>
local allGlobals = {}
@@ -378,22 +376,7 @@ local compilerGlobalSwitch = util.switch()
for _, field in ipairs(tbl) do
if field.type == 'tablefield'
or field.type == 'tableindex' then
- if not field.value then
- goto CONTINUE
- end
- local key = guide.getKeyName(field)
- if not key then
- goto CONTINUE
- end
- if field.value.type == 'integer'
- or field.value.type == 'string' then
- source._enums[#source._enums+1] = field.value[1]
- end
- if field.value.type == 'binary'
- or field.value.type == 'unary' then
- source._enums[#source._enums+1] = vm.getNumber(field.value)
- end
- ::CONTINUE::
+ source._enums[#source._enums+1] = field
end
end
end)
@@ -546,7 +529,7 @@ function vm.getGlobalNode(source)
end
---@param source parser.object
----@return parser.enum[]?
+---@return parser.object[]?
function vm.getEnums(source)
return source._enums
end
diff --git a/script/vm/type.lua b/script/vm/type.lua
index 47bc1e4f..feaaca9e 100644
--- a/script/vm/type.lua
+++ b/script/vm/type.lua
@@ -53,22 +53,43 @@ local function checkEnum(parentName, child, uri)
if not parentClass then
return nil
end
- for _, set in ipairs(parentClass:getSets(uri)) do
- if set.type == 'doc.enum' then
- if not vm.getEnums(set) then
- return false
+ local hasEnum
+ if child.type == 'global' then
+ ---@cast child vm.global
+ for _, set in ipairs(parentClass:getSets(uri)) do
+ if set.type == 'doc.enum' then
+ hasEnum = true
+ local enums = vm.getEnums(set)
+ if enums then
+ for _, enum in ipairs(enums) do
+ if vm.isSubType(uri, child, vm.compileNode(enum)) then
+ return true
+ end
+ end
+ end
end
- if child.type ~= 'string'
- and child.type ~= 'doc.type.string'
- and child.type ~= 'integer'
- and child.type ~= 'number'
- and child.type ~= 'doc.type.integer' then
- return false
+ end
+ else
+ ---@cast child -vm.global
+ for _, set in ipairs(parentClass:getSets(uri)) do
+ if set.type == 'doc.enum' then
+ hasEnum = true
+ local myLiteral = vm.getInfer(child):viewLiterals()
+ local enums = vm.getEnums(set)
+ if enums then
+ for _, enum in ipairs(enums) do
+ if myLiteral == vm.getInfer(enum):viewLiterals() then
+ return true
+ end
+ end
+ end
end
- return util.arrayHas(vm.getEnums(set), child[1])
end
end
+ if hasEnum then
+ return false
+ end
return nil
end
@@ -269,7 +290,6 @@ function vm.isSubType(uri, child, parent, mark)
return isEnum
end
- -- TODO: check duck
if parentName == 'table' and not guide.isBasicType(childName) then
return true
end