diff options
author | 最萌小汐 <sumneko@hotmail.com> | 2022-11-08 00:01:12 +0800 |
---|---|---|
committer | 最萌小汐 <sumneko@hotmail.com> | 2022-11-08 00:01:12 +0800 |
commit | 00dd1ed171beda2e892a2460d6e7eff321c775e8 (patch) | |
tree | 95a17424f070cc6d0ee7d458011519c82039a378 /script | |
parent | 34d32a478bcd066baf49ccf36f5f26a132cbfab8 (diff) | |
download | lua-language-server-00dd1ed171beda2e892a2460d6e7eff321c775e8.zip |
support enums with runtime values
resolved #1411
Diffstat (limited to 'script')
-rw-r--r-- | script/core/completion/completion.lua | 34 | ||||
-rw-r--r-- | script/vm/global.lua | 23 | ||||
-rw-r--r-- | script/vm/type.lua | 44 |
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 |