summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--changelog.md3
-rw-r--r--script/vm/compiler.lua29
-rw-r--r--script/vm/type.lua80
-rw-r--r--test/hover/init.lua2
-rw-r--r--test/type_inference/init.lua12
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]
+]]