summaryrefslogtreecommitdiff
path: root/script/core/linker.lua
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2021-04-14 20:13:00 +0800
committer最萌小汐 <sumneko@hotmail.com>2021-04-14 20:13:00 +0800
commitede808fe32a66ac828762818bf43d18fc343c159 (patch)
treea4cc8808fff798ea3bfd7103fb56bfb1d74f9c9c /script/core/linker.lua
parentbabe8e194576b0cd2ede04d98417a5f0e2a23647 (diff)
downloadlua-language-server-ede808fe32a66ac828762818bf43d18fc343c159.zip
stash
Diffstat (limited to 'script/core/linker.lua')
-rw-r--r--script/core/linker.lua100
1 files changed, 95 insertions, 5 deletions
diff --git a/script/core/linker.lua b/script/core/linker.lua
index d7f53fa4..6002b22c 100644
--- a/script/core/linker.lua
+++ b/script/core/linker.lua
@@ -1,4 +1,5 @@
local util = require 'utility'
+local guide = require 'parser.guide'
local function getKey(source)
if source.type == 'local' then
@@ -33,6 +34,15 @@ local function checkGlobal(source)
return nil
end
+local function checkLocal(source)
+ if source.type == 'local'
+ or source.type == 'setlocal'
+ or source.type == 'getlocal' then
+ return true
+ end
+ return nil
+end
+
local function checkTableField(source)
if source.type == 'table' then
return true
@@ -56,35 +66,61 @@ local function checkFunctionReturn(source)
return nil
end
+local IDList = {}
local function getID(source)
if source.type == 'field'
or source.type == 'method' then
source = source.parent
end
local current = source
- local idList = {}
+ local index = 0
while true do
local id, node = getKey(current)
if not id then
break
end
- idList[#idList+1] = id
+ index = index + 1
+ IDList[index] = id
source = current
if not node then
break
end
current = node
end
- util.revertTable(idList)
- local id = table.concat(idList, '|')
+ for i = index + 1, #IDList do
+ IDList[i] = nil
+ end
+ util.revertTable(IDList)
+ local id = table.concat(IDList, '|')
return id, current
end
+---@class link
+---@field id string
+-- 语法树单元
+---@field source parser.guide.object
+-- 是否是局部变量
+---@field loc boolean
+-- 是否是全局变量
+---@field global boolean
+-- 是否是字面量表中的字段
+---@field tfield boolean
+-- 返回值,文件返回值总是0,函数返回值为第几个返回值
+---@field freturn integer
+
---创建source的链接信息
+---@param source parser.guide.object
+---@return link
local function createLink(source)
local id, node = getID(source)
+ if not id then
+ return nil
+ end
return {
- id = id,
+ id = id,
+ source = source,
+ -- 局部变量
+ loc = checkLocal(node),
-- 全局变量
global = checkGlobal(node),
-- 字面量表中的字段
@@ -94,9 +130,31 @@ local function createLink(source)
}
end
+local function insertLinker(linkers, tp, link)
+ local list = linkers[tp]
+ local id = link.id
+ if not list[id] then
+ list[id] = {}
+ end
+ list[id][#list[id]+1] = link
+ link._linker = list[id]
+end
+
local m = {}
+---根据语法树单元获取关联的link列表
+---@param source parser.guide.object
+---@return link[]?
+function m.getLinkersBySource(source)
+ if not source._link then
+ source._link = createLink(source)
+ end
+ return source._link and source._link._linker
+end
+
---获取source的链接信息
+---@param source parser.guide.object
+---@return link
function m.getLink(source)
if not source._link then
source._link = createLink(source)
@@ -104,4 +162,36 @@ function m.getLink(source)
return source._link
end
+---编译整个文件的link
+---@param source parser.guide.object
+---@return table
+function m.compileLinks(source)
+ local root = guide.getRoot(source)
+ if root._linkers then
+ return root._linkers
+ end
+ local linkers = {
+ loc = {},
+ global = {},
+ tfield = {},
+ }
+ guide.eachSource(root, function (src)
+ local link = m.getLink(src)
+ if not link then
+ return
+ end
+ if link.global then
+ insertLinker(linkers, 'global', link)
+ end
+ if link.loc then
+ insertLinker(linkers, 'loc', link)
+ end
+ if link.tfield then
+ insertLinker(linkers, 'tfield', link)
+ end
+ end)
+ root._linkers = linkers
+ return linkers
+end
+
return m