diff options
author | 最萌小汐 <sumneko@hotmail.com> | 2022-04-14 15:04:16 +0800 |
---|---|---|
committer | 最萌小汐 <sumneko@hotmail.com> | 2022-04-14 15:04:16 +0800 |
commit | bae265094084e3b1887b92402de0cf2be14abb5d (patch) | |
tree | 842ee6ba352885a0a4478dfb52922580dc0e2367 /script | |
parent | 73a4780aa866737851040239eee52a013b5401d0 (diff) | |
download | lua-language-server-bae265094084e3b1887b92402de0cf2be14abb5d.zip |
update
Diffstat (limited to 'script')
-rw-r--r-- | script/vm/compiler.lua | 41 | ||||
-rw-r--r-- | script/vm/node.lua | 117 | ||||
-rw-r--r-- | script/vm/sign.lua | 14 |
3 files changed, 117 insertions, 55 deletions
diff --git a/script/vm/compiler.lua b/script/vm/compiler.lua index 8ad26f63..ed8db18a 100644 --- a/script/vm/compiler.lua +++ b/script/vm/compiler.lua @@ -612,7 +612,7 @@ local function compileCallArgNode(arg, call, callNode, fixIndex, myIndex) local myEvent if n.args[eventIndex] then local argNode = vm.compileNode(n.args[eventIndex]) - myEvent = argNode[1] + myEvent = argNode:get(1) end if not myEvent or not eventMap @@ -633,7 +633,7 @@ local function compileCallArgNode(arg, call, callNode, fixIndex, myIndex) end ---@param arg parser.object ----@param call parser.position +---@param call parser.object ---@param index? integer function vm.compileCallArg(arg, call, index) if not index then @@ -738,7 +738,6 @@ local compilerSwitch = util.switch() if not source.value and source.ref and not hasMarkDoc then - vm.pauseCache() for _, ref in ipairs(source.ref) do if ref.type == 'setlocal' and ref.value then if ref.value.type == 'table' then @@ -748,7 +747,6 @@ local compilerSwitch = util.switch() end end end - vm.resumeCache() end -- function x.y(self, ...) --> function x:y(...) if source[1] == 'self' @@ -792,7 +790,7 @@ local compilerSwitch = util.switch() : case 'setlocal' : case 'getlocal' : call(function (source) - vm.setNode(source, vm.compileNode(source.node), true) + vm.setNode(source, vm.compileNode(source.node)) end) : case 'setfield' : case 'setmethod' @@ -1522,26 +1520,6 @@ local function compileByGlobal(uri, source) end end -local pauseCacheCount = 0 -local originCacheKeys = {} -local originCacheValues = {} -function vm.pauseCache() - pauseCacheCount = pauseCacheCount + 1 -end - -function vm.resumeCache() - pauseCacheCount = pauseCacheCount - 1 - if pauseCacheCount == 0 then - for source in pairs(originCacheKeys) do - if originCacheValues[source] then - vm.setNode(source, originCacheValues[source], true) - end - originCacheKeys[source] = nil - originCacheValues[source] = nil - end - end -end - ---@param source vm.object ---@param uri? uri ---@return vm.node @@ -1554,15 +1532,12 @@ function vm.compileNode(source, uri) return cache end - local pauseCache = pauseCacheCount > 0 - if pauseCache and not originCacheKeys[source] then - originCacheKeys[source] = true - originCacheValues[source] = cache - end - - vm.setNode(source, vm.createNode(), true) + local node = vm.createNode() + vm.setNode(source, node, true) compileByGlobal(uri, source) compileByNode(source) - return vm.getNode(source) + node = vm.getNode(source) + + return node end diff --git a/script/vm/node.lua b/script/vm/node.lua index 941f2b09..1486ac47 100644 --- a/script/vm/node.lua +++ b/script/vm/node.lua @@ -8,10 +8,13 @@ vm.nodeCache = {} ---@class vm.node local mt = {} -mt.__index = mt -mt.type = 'vm.node' -mt.optional = nil -mt.lastInfer = nil +mt.__index = mt +mt.type = 'vm.node' +mt.optional = nil +mt.lastInfer = nil +---@type vm.node[] +mt._childs = nil +mt._locked = false ---@param node vm.node | vm.object function mt:merge(node) @@ -19,15 +22,28 @@ function mt:merge(node) return end if node.type == 'vm.node' then - for _, c in ipairs(node) do - if not self[c] then - self[c] = true - self[#self+1] = c - end + if node == self then + return end if node:isOptional() then self.optional = true end + if node._locked then + if not self._childs then + self._childs = {} + end + if not self._childs[node] then + self._childs[#self._childs+1] = node + self._childs[node] = true + end + else + for _, obj in ipairs(node) do + if not self[obj] then + self[obj] = true + self[#self+1] = obj + end + end + end else if not self[node] then self[node] = true @@ -36,16 +52,84 @@ function mt:merge(node) end end ----@return vm.node -function mt:copy() - return vm.createNode(self) +function mt:_each(mark, callback) + if mark[self] then + return + end + mark[self] = true + for i = 1, #self do + callback(self[i]) + end + local childs = self._childs + if not childs then + return + end + for i = 1, #childs do + local child = childs[i] + if not child:isLocked() then + child:_each(mark, callback) + end + end +end + +function mt:_expand() + local childs = self._childs + if not childs then + return + end + self._childs = nil + + local mark = {} + mark[self] = true + + local function insert(obj) + if not self[obj] then + self[obj] = true + self[#self+1] = obj + end + end + + for i = 1, #childs do + local child = childs[i] + if child:isLocked() then + if not self._childs then + self._childs = {} + end + if not self._childs[child] then + self._childs[#self._childs+1] = child + self._childs[child] = true + end + else + child:_each(mark, insert) + end + end end ---@return boolean function mt:isEmpty() + self:_expand() return #self == 0 end +---@param n integer +---@return vm.object? +function mt:get(n) + self:_expand() + return self[n] +end + +function mt:lock() + self._locked = true +end + +function mt:unlock() + self._locked = false +end + +function mt:isLocked() + return self._locked == true +end + function mt:addOptional() if self:isOptional() then return self @@ -57,6 +141,7 @@ function mt:removeOptional() if not self:isOptional() then return self end + self:_expand() for i = #self, 1, -1 do local n = self[i] if n.type == 'nil' @@ -73,6 +158,7 @@ function mt:isOptional() if self.optional ~= nil then return self.optional end + self:_expand() for _, c in ipairs(self) do if c.type == 'nil' or (c.type == 'boolean' and c[1] == false) @@ -87,6 +173,7 @@ end ---@return fun():vm.object function mt:eachObject() + self:_expand() local i = 0 return function () i = i + 1 @@ -106,15 +193,15 @@ function vm.setNode(source, node, cover) return end local me = vm.nodeCache[source] - if not me then + if me then + me:merge(node) + else if node.type == 'vm.node' then vm.nodeCache[source] = node else vm.nodeCache[source] = vm.createNode(node) end - return end - vm.nodeCache[source] = vm.createNode(me, node) end ---@return vm.node? diff --git a/script/vm/sign.lua b/script/vm/sign.lua index ca326965..2d45a5a7 100644 --- a/script/vm/sign.lua +++ b/script/vm/sign.lua @@ -54,21 +54,21 @@ function mt:resolve(uri, args) for _, ufield in ipairs(object.fields) do local ufieldNode = vm.compileNode(ufield.name) local uvalueNode = vm.compileNode(ufield.extends) - if ufieldNode[1].type == 'doc.generic.name' and uvalueNode[1].type == 'doc.generic.name' then + if ufieldNode:get(1).type == 'doc.generic.name' and uvalueNode:get(1).type == 'doc.generic.name' then -- { [number]: number} -> { [K]: V } local tfieldNode = vm.getTableKey(uri, node, 'any') local tvalueNode = vm.getTableValue(uri, node, 'any') - resolve(ufieldNode[1], tfieldNode) - resolve(uvalueNode[1], tvalueNode) + resolve(ufieldNode:get(1), tfieldNode) + resolve(uvalueNode:get(1), tvalueNode) else - if ufieldNode[1].type == 'doc.generic.name' then + if ufieldNode:get(1).type == 'doc.generic.name' then -- { [number]: number}|number[] -> { [K]: number } local tnode = vm.getTableKey(uri, node, uvalueNode) - resolve(ufieldNode[1], tnode) - elseif uvalueNode[1].type == 'doc.generic.name' then + resolve(ufieldNode:get(1), tnode) + elseif uvalueNode:get(1).type == 'doc.generic.name' then -- { [number]: number}|number[] -> { [number]: V } local tnode = vm.getTableValue(uri, node, ufieldNode) - resolve(uvalueNode[1], tnode) + resolve(uvalueNode:get(1), tnode) end end end |