summaryrefslogtreecommitdiff
path: root/script
diff options
context:
space:
mode:
Diffstat (limited to 'script')
-rw-r--r--script/core/diagnostics/undefined-field.lua7
-rw-r--r--script/vm/compiler.lua43
-rw-r--r--script/vm/node.lua9
3 files changed, 42 insertions, 17 deletions
diff --git a/script/core/diagnostics/undefined-field.lua b/script/core/diagnostics/undefined-field.lua
index fac9607d..025c217a 100644
--- a/script/core/diagnostics/undefined-field.lua
+++ b/script/core/diagnostics/undefined-field.lua
@@ -3,6 +3,7 @@ local vm = require 'vm'
local lang = require 'language'
local guide = require 'parser.guide'
local await = require 'await'
+local infer = require 'vm.infer'
local skipCheckClass = {
['unknown'] = true,
@@ -33,11 +34,9 @@ return function (uri, callback)
end
local node = src.node
if node then
- local defs = vm.getDefs(node)
local ok
- for _, def in ipairs(defs) do
- if def.type == 'doc.class'
- and not skipCheckClass[def.class[1]] then
+ for view in infer.getInfer(node):eachView() do
+ if not skipCheckClass[view] then
ok = true
break
end
diff --git a/script/vm/compiler.lua b/script/vm/compiler.lua
index 43c7be1e..a87f2eba 100644
--- a/script/vm/compiler.lua
+++ b/script/vm/compiler.lua
@@ -443,6 +443,9 @@ function m.compileByParentNode(source, key, pushResult)
end
local function selectNode(source, list, index)
+ if not list then
+ return nil
+ end
local exp
if list[index] then
exp = list[index]
@@ -644,17 +647,6 @@ local compilerSwitch = util.switch()
if source.bindDocs then
hasMarkDoc = bindDocs(source)
end
- if source.ref and not hasMarkDoc then
- for _, ref in ipairs(source.ref) do
- if ref.type == 'setlocal' then
- if ref.value and ref.value.type == 'table' then
- nodeMgr.setNode(source, ref.value)
- else
- nodeMgr.setNode(source, m.compileNode(ref.value))
- end
- end
- end
- end
local hasMarkParam
if source.dummy and not hasMarkDoc then
hasMarkParam = true
@@ -669,6 +661,19 @@ local compilerSwitch = util.switch()
end
end
end
+ if not source.value
+ and source.ref
+ and not hasMarkDoc then
+ for _, ref in ipairs(source.ref) do
+ if ref.type == 'setlocal' then
+ if ref.value and ref.value.type == 'table' then
+ nodeMgr.setNode(source, ref.value)
+ else
+ nodeMgr.setNode(source, m.compileNode(ref.value))
+ end
+ end
+ end
+ end
-- function x.y(self, ...) --> function x:y(...)
if source[1] == 'self'
and not hasMarkDoc
@@ -707,11 +712,25 @@ local compilerSwitch = util.switch()
if source.parent.type == 'loop' then
nodeMgr.setNode(source, globalMgr.getGlobal('type', 'integer'))
end
+
+ -- avoid self reference
+ -- `local x; x = x`
+ -- the third `x` is unknown here
+ -- x[1] -> value of x[2] -> x[3] -> x[1](locked!)
+ if source.ref then
+ local myNode = nodeMgr.getNode(source)
+ for _, ref in ipairs(source.ref) do
+ if ref.type == 'setlocal'
+ or ref.type == 'getlocal' then
+ nodeMgr.setNode(ref, myNode, true)
+ end
+ end
+ end
end)
: case 'setlocal'
: case 'getlocal'
: call(function (source)
- nodeMgr.setNode(source, m.compileNode(source.node))
+ nodeMgr.setNode(source, m.compileNode(source.node), true)
end)
: case 'setfield'
: case 'setmethod'
diff --git a/script/vm/node.lua b/script/vm/node.lua
index d51c2318..409841fc 100644
--- a/script/vm/node.lua
+++ b/script/vm/node.lua
@@ -23,7 +23,14 @@ function m.mergeNode(a, b)
return union(a, b)
end
-function m.setNode(source, node)
+---@param source parser.object
+---@param node vm.node
+---@param cover? boolean
+function m.setNode(source, node, cover)
+ if cover then
+ m.nodeCache[source] = node
+ return
+ end
if not node then
return
end