diff options
author | 最萌小汐 <sumneko@hotmail.com> | 2021-03-15 15:54:18 +0800 |
---|---|---|
committer | 最萌小汐 <sumneko@hotmail.com> | 2021-03-15 15:54:18 +0800 |
commit | 4e68872ea96a53f9c7ad5e11c83794b92f477fb4 (patch) | |
tree | e18475aefccae62be35ba93d6a600e036fd0cdab | |
parent | ba041ed17bac8a00a0e83ee289e7a257bf6f3d8b (diff) | |
download | lua-language-server-4e68872ea96a53f9c7ad5e11c83794b92f477fb4.zip |
#close 289
-rw-r--r-- | changelog.md | 1 | ||||
-rw-r--r-- | script/core/guide.lua | 69 | ||||
-rw-r--r-- | script/parser/luadoc.lua | 42 | ||||
-rw-r--r-- | test/references/init.lua | 38 |
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!>() +]] |