summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2021-03-15 15:54:18 +0800
committer最萌小汐 <sumneko@hotmail.com>2021-03-15 15:54:18 +0800
commit4e68872ea96a53f9c7ad5e11c83794b92f477fb4 (patch)
treee18475aefccae62be35ba93d6a600e036fd0cdab
parentba041ed17bac8a00a0e83ee289e7a257bf6f3d8b (diff)
downloadlua-language-server-4e68872ea96a53f9c7ad5e11c83794b92f477fb4.zip
#close 289
-rw-r--r--changelog.md1
-rw-r--r--script/core/guide.lua69
-rw-r--r--script/parser/luadoc.lua42
-rw-r--r--test/references/init.lua38
4 files changed, 150 insertions, 0 deletions
diff --git a/changelog.md b/changelog.md
index 63352989..2feb8102 100644
--- a/changelog.md
+++ b/changelog.md
@@ -3,6 +3,7 @@
## 1.19.0
* `NEW` VSCode: new setting `Lua.misc.parameters`
* `NEW` quick fix: disable diagnostic in line/file
+* `CHG` intelli-scense: search from generic param to return
* `CHG` improve performance
* `CHG` text-document-synchronization: refactored
* `FIX` missed syntax error `function m['x']() end`
diff --git a/script/core/guide.lua b/script/core/guide.lua
index c05d5fb0..7ef69380 100644
--- a/script/core/guide.lua
+++ b/script/core/guide.lua
@@ -1399,6 +1399,10 @@ function m.getCallAndArgIndex(callarg)
end
end
local call = callargs.parent
+ local node = call.node
+ if node.type == 'getmethod' then
+ index = index + 1
+ end
return call, index
end
@@ -2584,6 +2588,69 @@ function m.checkSameSimpleAsKeyOrValueInForParis(status, ref, start, pushQueue)
end
end
+---
+---@param func core.guide.object
+---@param argIndex integer
+---@return integer?
+local function findGenericFromArgIndexToReturnIndex(func, argIndex)
+ if not func.bindDocs then
+ return nil
+ end
+ local paramType
+ for _, doc in ipairs(func.bindDocs) do
+ if doc.type == 'doc.param' then
+ if doc.extends.paramIndex == argIndex then
+ paramType = doc.extends
+ break
+ end
+ end
+ end
+ if not paramType then
+ return nil
+ end
+ for _, typeUnit in ipairs(paramType.types) do
+ if typeUnit.typeGeneric then
+ local generic = typeUnit.typeGeneric[typeUnit[1]]
+ if generic then
+ for _, typeName in ipairs(generic) do
+ local docType = typeName.parent
+ if docType.returnIndex then
+ return docType.returnIndex
+ end
+ end
+ end
+ end
+ end
+ return nil
+end
+
+function m.checkSameSimpleAsCallArg(status, ref, start, pushQueue)
+ local call, index = m.getCallAndArgIndex(ref)
+ if not call then
+ return
+ end
+ local newStatus = m.status(status)
+ m.searchRefs(newStatus, call.node, 'def')
+ for _, func in ipairs(newStatus.results) do
+ local rindex = findGenericFromArgIndexToReturnIndex(func, index)
+ if rindex then
+ if rindex == 1 then
+ if call.parent.type == 'select' then
+ pushQueue(call.parent.parent, start, true)
+ end
+ else
+ if call.extParent then
+ for _, slt in ipairs(call.extParent) do
+ if slt.index == rindex then
+ pushQueue(slt.parent, start, true)
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
local function hasTypeName(doc, name)
if doc.type == 'doc.type' then
for _, tunit in ipairs(doc.types) do
@@ -2858,6 +2925,8 @@ function m.checkSameSimple(status, simple, ref, start, force, mode, pushQueue)
m.checkSameSimpleAsSetValue(status, ref, i, pushQueue)
-- 检查形如 for k,v in pairs()/ipairs() do end 的情况
m.checkSameSimpleAsKeyOrValueInForParis(status, ref, i, pushQueue)
+ -- 检查自己是函数参数的情况(泛型) local x = call(V)
+ m.checkSameSimpleAsCallArg(status, ref, i, pushQueue)
end
end
if i == #simple then
diff --git a/script/parser/luadoc.lua b/script/parser/luadoc.lua
index dad32378..1b48719d 100644
--- a/script/parser/luadoc.lua
+++ b/script/parser/luadoc.lua
@@ -1103,6 +1103,47 @@ local function bindDocsBetween(sources, binded, bindSources, start, finish)
end
end
+local function bindParamAndReturnIndex(binded)
+ local func
+ for _, source in ipairs(binded[1].bindSources) do
+ if source.type == 'function' then
+ func = source
+ break
+ end
+ end
+ if not func then
+ return
+ end
+ if not func.args then
+ return
+ end
+ local paramIndex = 0
+ local parent = func.parent
+ if parent.type == 'setmethod' then
+ paramIndex = paramIndex + 1
+ end
+ local paramMap = {}
+ for _, param in ipairs(func.args) do
+ paramIndex = paramIndex + 1
+ if param[1] then
+ paramMap[param[1]] = paramIndex
+ end
+ end
+ local returnIndex = 0
+ for _, doc in ipairs(binded) do
+ if doc.type == 'doc.param' then
+ if doc.extends then
+ doc.extends.paramIndex = paramMap[doc.param[1]]
+ end
+ elseif doc.type == 'doc.return' then
+ for _, rtn in ipairs(doc.returns) do
+ returnIndex = returnIndex + 1
+ rtn.returnIndex = returnIndex
+ end
+ end
+ end
+end
+
local function bindDoc(sources, lns, binded)
if not binded then
return
@@ -1124,6 +1165,7 @@ local function bindDoc(sources, lns, binded)
if #bindSources == 0 then
bindDocsBetween(sources, binded, bindSources, nstart, nfinish)
end
+ bindParamAndReturnIndex(binded)
end
local function bindDocs(state)
diff --git a/test/references/init.lua b/test/references/init.lua
index 08dc30da..8494e12b 100644
--- a/test/references/init.lua
+++ b/test/references/init.lua
@@ -348,3 +348,41 @@ local function f() end
local a, b = f()
return a.x, b.<!x!>
]]
+
+TEST [[
+---@class Dog
+local Dog = {}
+function Dog:<?eat?>()
+end
+
+---@generic T
+---@param type1 T
+---@return T
+function foobar(type1)
+ return {}
+end
+
+local v1 = foobar(Dog)
+v1:<!eat!>()
+]]
+
+TEST [[
+---@class Dog
+local Dog = {}
+function Dog:<?eat?>()
+end
+
+---@class Master
+local Master = {}
+
+---@generic T
+---@param type1 string
+---@param type2 T
+---@return T
+function Master:foobar(type1, type2)
+ return {}
+end
+
+local v1 = Master:foobar("", Dog)
+v1.<!eat!>()
+]]