diff options
-rw-r--r-- | changelog.md | 3 | ||||
-rw-r--r-- | script/vm/compiler.lua | 29 | ||||
-rw-r--r-- | script/vm/type.lua | 80 | ||||
-rw-r--r-- | test/hover/init.lua | 2 | ||||
-rw-r--r-- | test/type_inference/init.lua | 12 |
5 files changed, 62 insertions, 64 deletions
diff --git a/changelog.md b/changelog.md index 14772199..6f33e42a 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,8 @@ # changelog +## 3.0.2 +* `FIX` `table<string, boolean>[string] -> boolean` + ## 3.0.1 `2022-4-11` * `FIX` [#1033](https://github.com/sumneko/lua-language-server/issues/1033) diff --git a/script/vm/compiler.lua b/script/vm/compiler.lua index 19a41540..12c2c24c 100644 --- a/script/vm/compiler.lua +++ b/script/vm/compiler.lua @@ -9,6 +9,8 @@ local union = require 'vm.union' local genericMgr = require 'vm.generic' local rpath = require 'workspace.require-path' local files = require 'files' +---@class vm +local vm = require 'vm.vm' ---@class parser.object ---@field _compiledNodes boolean @@ -20,28 +22,20 @@ local m = {} local searchFieldSwitch = util.switch() : case 'table' : call(function (suri, node, key, pushResult) - local tp - if type(key) == 'table' - and key.type == 'global' - and key.cate == 'type' then - tp = key.name - end local hasFiled = false for _, field in ipairs(node) do if field.type == 'tablefield' or field.type == 'tableindex' then local fieldKey = guide.getKeyName(field) if key == nil - or key == fieldKey - or (tp == 'integer' and math.tointeger(fieldKey)) then + or key == fieldKey then hasFiled = true pushResult(field) end end if field.type == 'tableexp' then if key == nil - or key == field.tindex - or tp == 'integer' then + or key == field.tindex then hasFiled = true pushResult(field) end @@ -772,9 +766,6 @@ local compilerSwitch = util.switch() : call(function (source) compileByLocalID(source) local key = guide.getKeyName(source) - if key == nil and source.index then - key = m.compileNode(source.index) - end if key == nil then return end @@ -797,9 +788,15 @@ local compilerSwitch = util.switch() if key == nil then return end - m.compileByParentNode(source.node, key, function (src) - nodeMgr.setNode(source, m.compileNode(src)) - end) + if type(key) == 'table' then + local uri = guide.getUri(source) + local value = vm.getTableValue(uri, m.compileNode(source.node), key) + nodeMgr.setNode(source, value) + else + m.compileByParentNode(source.node, key, function (src) + nodeMgr.setNode(source, m.compileNode(src)) + end) + end end) : case 'setglobal' : call(function (source) diff --git a/script/vm/type.lua b/script/vm/type.lua index 0f6c8238..82c0e3f4 100644 --- a/script/vm/type.lua +++ b/script/vm/type.lua @@ -21,50 +21,34 @@ function vm.isSubType(uri, child, parent, mark) return false end - if parent.type == 'global' and parent.cate == 'type' and parent.name == 'any' then - return true - end - - if child.type == 'doc.type' then - for _, typeUnit in ipairs(child.types) do - if not vm.isSubType(uri, typeUnit, parent) then - return false - end + mark = mark or {} + for childNode in nodeMgr.eachNode(child) do + if childNode.type ~= 'global' + or childNode.cate ~= 'type' then + goto CONTINUE_CHILD end - return true - end - - if child.type == 'doc.type.name' then - child = globalMgr.getGlobal('type', child[1]) - end - - if child.type == 'global' and child.cate == 'type' then - if parent.type == 'doc.type' then - for _, typeUnit in ipairs(parent.types) do - if vm.isSubType(uri, child, typeUnit) then - return true - end - end - end - - if parent.type == 'doc.type.name' then - parent = globalMgr.getGlobal('type', parent[1]) + if mark[childNode.name] then + return false end - - if parent.type == 'global' and parent.cate == 'type' then - if parent.name == child.name then + mark[childNode.name] = true + for parentNode in nodeMgr.eachNode(parent) do + if parentNode.type ~= 'global' + or parentNode.cate ~= 'type' then + goto CONTINUE_PARENT + end + if parentNode.name == 'any' or childNode.name == 'any' then return true end - mark = mark or {} - if mark[child.name] then - return false + + if parentNode.name == childNode.name then + return true end - mark[child.name] = true - for _, set in ipairs(child:getSets(uri)) do + + for _, set in ipairs(childNode:getSets(uri)) do if set.type == 'doc.class' and set.extends then for _, ext in ipairs(set.extends) do if ext.type == 'doc.extends.name' - and vm.isSubType(uri, globalMgr.getGlobal('type', ext[1]), parent, mark) then + and vm.isSubType(uri, ext[1], parentNode, mark) then return true end end @@ -72,13 +56,15 @@ function vm.isSubType(uri, child, parent, mark) if set.type == 'doc.alias' and set.extends then for _, ext in ipairs(set.extends.types) do if ext.type == 'doc.type.name' - and vm.isSubType(uri, globalMgr.getGlobal('type', ext[1]), parent, mark) then + and vm.isSubType(uri, ext[1], parentNode, mark) then return true end end end end + ::CONTINUE_PARENT:: end + ::CONTINUE_CHILD:: end return false @@ -92,15 +78,13 @@ function vm.getTableValue(uri, tnode, knode) for tn in nodeMgr.eachNode(tnode) do if tn.type == 'doc.type.table' then for _, field in ipairs(tn.fields) do - if vm.isSubType(uri, field.name, knode) then + if vm.isSubType(uri, compiler.compileNode(field.name), knode) then result = nodeMgr.mergeNode(result, compiler.compileNode(field.extends)) end end end if tn.type == 'doc.type.array' then - if vm.isSubType(uri, globalMgr.getGlobal('type', 'integer'), knode) then - result = nodeMgr.mergeNode(result, compiler.compileNode(tn.node)) - end + result = nodeMgr.mergeNode(result, compiler.compileNode(tn.node)) end if tn.type == 'table' then for _, field in ipairs(tn) do @@ -108,10 +92,14 @@ function vm.getTableValue(uri, tnode, knode) result = nodeMgr.mergeNode(result, compiler.compileNode(field.value)) end if field.type == 'tablefield' then - result = nodeMgr.mergeNode(result, compiler.compileNode(field.value)) + if vm.isSubType(uri, knode, 'string') then + result = nodeMgr.mergeNode(result, compiler.compileNode(field.value)) + end end if field.type == 'tableexp' then - result = nodeMgr.mergeNode(result, compiler.compileNode(field.value)) + if vm.isSubType(uri, knode, 'integer') and field.tindex == 1 then + result = nodeMgr.mergeNode(result, compiler.compileNode(field.value)) + end end end end @@ -127,15 +115,13 @@ function vm.getTableKey(uri, tnode, vnode) for tn in nodeMgr.eachNode(tnode) do if tn.type == 'doc.type.table' then for _, field in ipairs(tn.fields) do - if vm.isSubType(uri, field.extends, vnode) then + if vm.isSubType(uri, compiler.compileNode(field.extends), vnode) then result = nodeMgr.mergeNode(result, compiler.compileNode(field.name)) end end end if tn.type == 'doc.type.array' then - if vm.isSubType(uri, tn.node, vnode) then - result = nodeMgr.mergeNode(result, globalMgr.getGlobal('type', 'integer')) - end + result = nodeMgr.mergeNode(result, globalMgr.getGlobal('type', 'integer')) end if tn.type == 'table' then for _, field in ipairs(tn) do diff --git a/test/hover/init.lua b/test/hover/init.lua index d4160dfa..199df06d 100644 --- a/test/hover/init.lua +++ b/test/hover/init.lua @@ -1576,7 +1576,7 @@ local x: unknown ]] TEST [[ ----@type any +---@type unknown local <?t?> t.a = 1 ]] diff --git a/test/type_inference/init.lua b/test/type_inference/init.lua index d199f79b..fd6e464f 100644 --- a/test/type_inference/init.lua +++ b/test/type_inference/init.lua @@ -1439,3 +1439,15 @@ TEST '(string|integer)[]' [[ ---@type (string|integer)[] local <?x?> ]] + +TEST 'boolean' [[ +---@type table<string, boolean> +local t + +---@alias uri string + +---@type string +local uri + +local <?v?> = t[uri] +]] |