diff options
Diffstat (limited to 'script')
-rw-r--r-- | script/core/diagnostics/undefined-field.lua | 7 | ||||
-rw-r--r-- | script/vm/compiler.lua | 43 | ||||
-rw-r--r-- | script/vm/node.lua | 9 |
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 |