summaryrefslogtreecommitdiff
path: root/script
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2021-05-11 17:39:54 +0800
committer最萌小汐 <sumneko@hotmail.com>2021-05-11 17:39:54 +0800
commit7c70c6c2efbba20c3f2526dc01d3f8791fa97ca4 (patch)
treee188ee6e8ab1e2005fa153ebde83c8fcefd50f91 /script
parent3518ac420c14ff936019aed45c82056404999c30 (diff)
downloadlua-language-server-7c70c6c2efbba20c3f2526dc01d3f8791fa97ca4.zip
stash
Diffstat (limited to 'script')
-rw-r--r--script/core/generic.lua93
-rw-r--r--script/core/linker.lua32
-rw-r--r--script/core/searcher.lua127
3 files changed, 129 insertions, 123 deletions
diff --git a/script/core/generic.lua b/script/core/generic.lua
index 19c445cd..8c05d0df 100644
--- a/script/core/generic.lua
+++ b/script/core/generic.lua
@@ -1,7 +1,9 @@
+local linker = require "core.linker"
---@class generic.value
---@field type string
---@field closure generic.closure
---@field proto parser.guide.object
+---@field parent parser.guide.object
---@class generic.closure
---@field type string
@@ -12,12 +14,15 @@
local m = {}
+---@param closure generic.closure
+---@param proto parser.guide.object
local function instantValue(closure, proto)
---@type generic.value
local value = {
type = 'generic.value',
closure = closure,
proto = proto,
+ parent = proto.parent,
}
return value
end
@@ -25,12 +30,15 @@ end
---递归实例化对象
---@param obj parser.guide.object
---@return generic.value
-local function createValue(closure, obj)
+local function createValue(closure, obj, callback, road)
+ if callback then
+ road = road or {}
+ end
if obj.type == 'doc.type' then
local types = {}
local hasGeneric
for i, tp in ipairs(obj.types) do
- local genericValue = createValue(tp)
+ local genericValue = createValue(closure, tp, callback, road)
if genericValue then
hasGeneric = true
types[i] = genericValue
@@ -38,13 +46,59 @@ local function createValue(closure, obj)
types[i] = tp
end
end
- if hasGeneric then
- local value = instantValue(closure, obj)
- value.types = types
- return value
- else
+ if not hasGeneric then
return nil
end
+ local value = instantValue(closure, obj)
+ value.types = types
+ linker.compileLink(value)
+ return value
+ end
+ if obj.type == 'doc.type.name' then
+ if not obj.typeGeneric then
+ return nil
+ end
+ local key = obj[1]
+ local value = instantValue(closure, obj)
+ if callback then
+ callback(road, key)
+ end
+ linker.compileLink(value)
+ return value
+ end
+end
+
+-- 为所有的 param 与 return 创建副本
+---@param closure generic.closure
+local function buildValues(closure)
+ local protoFunction = closure.proto
+ local upvalues = closure.upvalues
+ local params = closure.call.args
+ if protoFunction.type == 'function' then
+ for _, doc in ipairs(protoFunction.bindDocs) do
+ if doc.type == 'doc.param' then
+ local extends = doc.extends
+ local index = extends.paramIndex
+ closure.params[index] = createValue(closure, extends, function (road, key)
+ local paramID = linker.getID(params[index])
+ if not paramID then
+ return
+ end
+ if not upvalues[key] then
+ upvalues[key] = {}
+ end
+ -- TODO
+ upvalues[key][#upvalues[key]+1] = paramID
+ end)
+ elseif doc.type == 'doc.return' then
+ for _, rtn in ipairs(doc.returns) do
+ closure.returns[rtn.returnIndex] = createValue(closure, rtn)
+ end
+ end
+ end
+ end
+ if protoFunction.type == 'doc.function' then
+
end
end
@@ -56,34 +110,21 @@ function m.createClosure(protoFunction, call, parentClosure)
---@type generic.closure
local closure = {
type = 'generic.closure',
- parent = parentClosure,
+ parent = protoFunction.parent,
proto = protoFunction,
call = call,
upvalues = parentClosure and parentClosure.upvalues or {},
params = {},
returns = {},
}
+ buildValues(closure)
- -- 立刻解决所有的泛型
- -- 对每个参数进行核对,存入泛型表
- -- 为所有的 param 与 return 创建副本
- -- 如果return中有function,也要递归创建闭包
- if protoFunction.type == 'function' then
- for _, doc in ipairs(protoFunction.bindDocs) do
- if doc.type == 'doc.param' then
- local extends = doc.extends
- closure.params[extends.paramIndex] = createValue(closure, extends)
- elseif doc.type == 'doc.return' then
- for _, rtn in ipairs(doc.returns) do
- closure.returns[rtn.returnIndex] = createValue(closure, rtn)
- end
- end
- end
- end
- if protoFunction.type == 'doc.function' then
-
+ if #closure.returns == 0 then
+ return nil
end
+ linker.compileLink(closure)
+
return closure
end
diff --git a/script/core/linker.lua b/script/core/linker.lua
index 5ca11087..fd7f886e 100644
--- a/script/core/linker.lua
+++ b/script/core/linker.lua
@@ -569,11 +569,41 @@ function m.compileLink(source)
end
end
if doc.type == 'doc.generic' then
- source._isGeneric = true
+ source.isGeneric = true
end
end
end
end
+ if source.type == 'generic.closure' then
+ for i, rtn in ipairs(source.returns) do
+ local closureID = ('%s%s%s'):format(
+ id,
+ RETURN_INDEX_CHAR,
+ i
+ )
+ local returnID = getID(rtn)
+ pushForward(closureID, returnID)
+ pushBackward(returnID, closureID)
+ end
+ end
+ if source.type == 'generic.value' then
+ local proto = source.proto
+ local closure = source.closure
+ local upvalues = closure.upvalues
+ if proto.type == 'doc.type.name' then
+ local key = proto[1]
+ for _, paramID in ipairs(upvalues[key]) do
+ pushForward(id, paramID)
+ pushBackward(paramID, id)
+ end
+ end
+ if proto.type == 'doc.type' then
+ for _, tp in ipairs(source.types) do
+ pushForward(id, getID(tp))
+ pushBackward(getID(tp), id)
+ end
+ end
+ end
end
---根据ID来获取所有的link
diff --git a/script/core/searcher.lua b/script/core/searcher.lua
index db581e9c..4150759b 100644
--- a/script/core/searcher.lua
+++ b/script/core/searcher.lua
@@ -1,6 +1,7 @@
-local linker = require 'core.linker'
-local guide = require 'parser.guide'
-local files = require 'files'
+local linker = require 'core.linker'
+local guide = require 'parser.guide'
+local files = require 'files'
+local generic = require 'core.generic'
local function checkFunctionReturn(source)
if source.parent
@@ -240,113 +241,48 @@ function m.searchRefsByID(status, uri, expect, mode)
search(parentID, linker.SPLIT_CHAR .. linker.RETURN_INDEX_CHAR .. returnIndex)
end
- local function findCallParam(key, index)
- for i = #idStack, 1, -1 do
- local id = idStack[i]
- local link = linker.getLinkByID(root, id)
- if not link then
- goto CONTINUE
- end
- local call = link.call
- if not call then
- goto CONTINUE
- end
- local args = call.args
- if not args then
- goto CONTINUE
- end
- do return args[index] end
- ::CONTINUE::
+ local function isCallID(field)
+ if not field then
+ return false
end
+ if field:sub(1, 1) == linker.SPLIT_CHAR
+ and field:sub(2, 2) == linker.RETURN_INDEX_CHAR then
+ return true
+ end
+ return false
end
- local function getGenericID(typeUnit, index)
- local key = typeUnit[1]
- local generics = typeUnit.typeGeneric[key]
- local callParam = findCallParam(key, index)
- if not callParam then
- return nil
- end
- if typeUnit.literal then
- if callParam.type == 'string' then
- return generics, ('dn:%s'):format(callParam[1] or '')
+ local function findLastCall()
+ for i = #idStack, 1, -1 do
+ local id = idStack[i]
+ local link = linker.getLinkByID(root, id)
+ if link.call then
+ return link.call
end
- else
- return generics, linker.getID(callParam)
end
return nil
end
- local function genericStashParam(docType, index)
- if #idStack == 0 then
+ local function checkGeneric(source, field)
+ if not source.isGeneric then
return
end
- for _, typeUnit in ipairs(docType.types) do
- if typeUnit.typeGeneric then
- local generics, id = getGenericID(typeUnit, index)
- if id then
- genericStashMap[generics] = id
- end
- end
- -- 支持 V[]
- if typeUnit.type == 'doc.type.array' then
- if typeUnit.node.typeGeneric then
- local generics, id = getGenericID(typeUnit.node, index)
- if id then
- genericStashMap[generics] = id .. linker.SPLIT_CHAR
- end
- end
- end
- -- 支持 table<number, V>
- if typeUnit.type == 'doc.type.table' then
- if typeUnit.value then
- for _, typeUnit2 in ipairs(typeUnit.value.types) do
- if typeUnit2.typeGeneric then
- local generics, id = getGenericID(typeUnit2, index)
- if id then
- genericStashMap[generics] = id .. linker.SPLIT_CHAR
- end
- end
- end
- end
- end
- end
- end
-
- -- TODO 这里的实现是有问题的,在多次穿透泛型时可能出错,不过错就错吧,让用户自己写注解
- local function genericStash(source)
- if source.type ~= 'function'
- and source.type ~= 'doc.type.function' then
+ if not isCallID(field) then
return
end
- if source.type == 'function' then
- if not source.docParamMap then
- return
- end
- for index, param in ipairs(source.args) do
- local docParam = param.docParam
- if docParam then
- genericStashParam(docParam.extends, index)
- end
- end
- end
- if source.type == 'doc.type.function' then
- for index, param in ipairs(source.args) do
- genericStashParam(param.extends, index)
- end
+ local call = findLastCall()
+ if not call then
+ return
end
- end
-
- local function genericResolve(source, field)
- if not source.typeGeneric then
+ if not call.args or #call.args == 0 then
return
end
- local key = source[1]
- local generics = source.typeGeneric[key]
- local paramID = genericStashMap[generics]
- if paramID then
- searchID(paramID, field)
+ local closure = generic.createClosure(source, call)
+ if not closure then
+ return
end
+ local id = linker.getID(closure)
+ searchID(id, field)
end
local stepCount = 0
@@ -375,8 +311,7 @@ function m.searchRefsByID(status, uri, expect, mode)
end
if link.sources then
- genericStash(link.sources[1])
- genericResolve(link.sources[1], field)
+ checkGeneric(link.sources[1], field)
end
idStack[#idStack] = nil