summaryrefslogtreecommitdiff
path: root/script/vm/ref.lua
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2022-03-25 23:17:39 +0800
committer最萌小汐 <sumneko@hotmail.com>2022-03-25 23:17:39 +0800
commit438df4d04ad4bd978226868e85723b28a7765be4 (patch)
tree2b7d97d14794bd4f061313f5fb0dc302bc1068a5 /script/vm/ref.lua
parentc5ac7aa810c1f39c3c09de02b7d43be88e87b1f4 (diff)
downloadlua-language-server-438df4d04ad4bd978226868e85723b28a7765be4.zip
cleanup
Diffstat (limited to 'script/vm/ref.lua')
-rw-r--r--script/vm/ref.lua248
1 files changed, 248 insertions, 0 deletions
diff --git a/script/vm/ref.lua b/script/vm/ref.lua
new file mode 100644
index 00000000..2574a098
--- /dev/null
+++ b/script/vm/ref.lua
@@ -0,0 +1,248 @@
+---@class vm
+local vm = require 'vm.vm'
+local util = require 'utility'
+local compiler = require 'vm.compiler'
+local guide = require 'parser.guide'
+local localID = require 'vm.local-id'
+local globalMgr = require 'vm.global-manager'
+local nodeMgr = require 'vm.node'
+
+local simpleMap
+
+local function searchGetLocal(source, node, pushResult)
+ local key = guide.getKeyName(source)
+ for _, ref in ipairs(node.node.ref) do
+ if ref.type == 'getlocal'
+ and guide.getKeyName(ref.next) == key then
+ pushResult(ref.next)
+ end
+ end
+end
+
+simpleMap = util.switch()
+ : case 'local'
+ : call(function (source, pushResult)
+ pushResult(source)
+ if source.ref then
+ for _, ref in ipairs(source.ref) do
+ if ref.type == 'setlocal'
+ or ref.type == 'getlocal' then
+ pushResult(ref)
+ end
+ end
+ end
+
+ if source.dummy then
+ for _, res in ipairs(vm.getDefs(source.method.node)) do
+ pushResult(res)
+ end
+ end
+ end)
+ : case 'getlocal'
+ : case 'setlocal'
+ : call(function (source, pushResult)
+ simpleMap['local'](source.node, pushResult)
+ end)
+ : case 'field'
+ : call(function (source, pushResult)
+ local parent = source.parent
+ simpleMap[parent.type](parent, pushResult)
+ end)
+ : case 'setfield'
+ : case 'getfield'
+ : call(function (source, pushResult)
+ local node = source.node
+ if node.type == 'getlocal' then
+ searchGetLocal(source, node, pushResult)
+ return
+ end
+ end)
+ : case 'getindex'
+ : case 'setindex'
+ : call(function (source, pushResult)
+ local node = source.node
+ if node.type == 'getlocal' then
+ searchGetLocal(source, node, pushResult)
+ end
+ end)
+ : case 'goto'
+ : call(function (source, pushResult)
+ if source.node then
+ pushResult(source.node)
+ end
+ end)
+ : getMap()
+
+local searchFieldMap = util.switch()
+ : case 'table'
+ : call(function (node, key, pushResult)
+ for _, field in ipairs(node) do
+ if field.type == 'tablefield'
+ or field.type == 'tableindex' then
+ if guide.getKeyName(field) == key then
+ pushResult(field)
+ end
+ end
+ end
+ end)
+ : case 'global'
+ ---@param node vm.node
+ ---@param key string
+ : call(function (node, key, pushResult)
+ if node.cate == 'variable' then
+ local newGlobal = globalMgr.getGlobal('variable', node.name, key)
+ if newGlobal then
+ for _, set in ipairs(newGlobal:getSets()) do
+ pushResult(set)
+ end
+ end
+ end
+ if node.cate == 'type' then
+ compiler.getClassFields(node, key, pushResult)
+ end
+ end)
+ : case 'local'
+ : call(function (node, key, pushResult)
+ local sources = localID.getSources(node, key)
+ if sources then
+ for _, src in ipairs(sources) do
+ if guide.isSet(src) then
+ pushResult(src)
+ end
+ end
+ end
+ end)
+ : case 'doc.type.table'
+ : call(function (node, key, pushResult)
+ for _, field in ipairs(node.fields) do
+ local fieldKey = field.name
+ if fieldKey.type == 'doc.field.name' then
+ if fieldKey[1] == key then
+ pushResult(field)
+ end
+ end
+ end
+ end)
+ : getMap()
+
+local searchByParentNode
+local nodeMap = util.switch()
+ : case 'field'
+ : case 'method'
+ : call(function (source, pushResult)
+ searchByParentNode(source.parent, pushResult)
+ end)
+ : case 'getfield'
+ : case 'setfield'
+ : case 'getmethod'
+ : case 'setmethod'
+ : case 'getindex'
+ : case 'setindex'
+ : call(function (source, pushResult)
+ local parentNode = compiler.compileNode(source.node)
+ if not parentNode then
+ return
+ end
+ local key = guide.getKeyName(source)
+ for pn in nodeMgr.eachNode(parentNode) do
+ if searchFieldMap[pn.type] then
+ searchFieldMap[pn.type](pn, key, pushResult)
+ end
+ end
+ end)
+ : case 'doc.see.field'
+ : call(function (source, pushResult)
+ local parentNode = compiler.compileNode(source.parent.name)
+ if not parentNode then
+ return
+ end
+ for pn in nodeMgr.eachNode(parentNode) do
+ if searchFieldMap[pn.type] then
+ searchFieldMap[pn.type](pn, source[1], pushResult)
+ end
+ end
+ end)
+ : getMap()
+
+---@param source parser.object
+---@param pushResult fun(src: parser.object)
+local function searchBySimple(source, pushResult)
+ local simple = simpleMap[source.type]
+ if simple then
+ simple(source, pushResult)
+ end
+end
+
+---@param source parser.object
+---@param pushResult fun(src: parser.object)
+local function searchByLocalID(source, pushResult)
+ local idSources = localID.getSources(source)
+ if not idSources then
+ return
+ end
+ for _, src in ipairs(idSources) do
+ if guide.isSet(src) then
+ pushResult(src)
+ end
+ end
+end
+
+---@param source parser.object
+---@param pushResult fun(src: parser.object)
+function searchByParentNode(source, pushResult)
+ local node = nodeMap[source.type]
+ if node then
+ node(source, pushResult)
+ end
+end
+
+local function searchByNode(source, pushResult)
+ local node = compiler.compileNode(source)
+ if not node then
+ return
+ end
+ for n in nodeMgr.eachNode(node) do
+ if n.type == 'global' and n.cate == 'type' then
+ for _, set in ipairs(n:getSets()) do
+ pushResult(set)
+ end
+ else
+ pushResult(n)
+ end
+ end
+end
+
+function vm.getRefs(source)
+ local results = {}
+ local mark = {}
+
+ local hasLocal
+ local function pushResult(src)
+ if src.type == 'local' and not src.dummy then
+ if hasLocal then
+ return
+ end
+ hasLocal = true
+ end
+ if not mark[src] then
+ mark[src] = true
+ if src.type == 'global' then
+ for _, set in ipairs(src:getSets()) do
+ pushResult(set)
+ end
+ return
+ end
+ if guide.isSet(src)
+ or guide.isLiteral(src) then
+ results[#results+1] = src
+ end
+ end
+ end
+
+ searchBySimple(source, pushResult)
+ searchByLocalID(source, pushResult)
+ searchByParentNode(source, pushResult)
+ searchByNode(source, pushResult)
+
+ return results
+end