lua-language-server icon indicating copy to clipboard operation
lua-language-server copied to clipboard

generic param no hint

Open sundream opened this issue 1 year ago • 2 comments

How are you using the lua-language-server?

Visual Studio Code Extension (sumneko.lua)

Which OS are you using?

Windows

What is the issue affecting?

Completion

Expected Behaviour

---删除物品
---@class pb.S2C_DelItem
---@field itemId integer 物品id

---发送协议到客户端
---@generic T
---@param cmd pb.`T` 命令名
---@param args T
---@return T
function sendToClient(cmd, args)
    return nil
end

local ret = sendToClient("S2C_DelItem",{
    itemId = 1,                 -- 无法推断出args为pb.S2C_DelItem类型,输入itemId无字段类型提示
})

ret.itemId                       -- 返回值能推断出为pb.S2C_DelItem类型,输入itemId有字段类型提示

47d177bc16d5104b26100d38e2e7a69 4373b0763922e91aab1d34326241dd1

Actual Behaviour

能正确推断出泛型参数类型并有代码提示

Reproduction steps

如上代码

Additional Notes

No response

Log File

No response

sundream avatar Aug 15 '24 07:08 sundream

泛型参数已经匹配了 pb.T 所以不会继续匹配第二个参数了, 泛型函数不能你这样用

CppCXY avatar Aug 15 '24 07:08 CppCXY

在我的使用經驗中,泛型参數在 ---@param 階段下只能用來 捕獲 (capture) param type,而不能 強制 (enforce) param type。跟這個 discussion 的提問有點類似: https://github.com/LuaLS/lua-language-server/discussions/2669

該 discussion 內提出的建議是修改 syntax 中間用1個 factory function => 按 cmd 來返回1個 接受對應 type 的 closure 當然這個涉及修改 syntax,你或者會認為不合適 😇

---删除物品
---@class pb.S2C_DelItem
---@field itemId integer 物品id

---发送协议到客户端
---@generic T
---@param cmd pb.`T` 命令名
---@return fun(args: T): T
local function sendToClientWrapper(cmd)
    return nil -- 要返回 closure,可以參考下 discussion 內是怎樣寫
end

local ret = sendToClientWrapper("S2C_DelItem") {
    --< 可以觸發字段 auto complete
}

如果要不改 syntax,那感覺只能用 @overload 方式來處理了 這個你得用法方式來 auto gen 1個 meta definition file 較好 類似這裡提到的: https://github.com/LuaLS/lua-language-server/discussions/2723#discussioncomment-9842624

在你的 use case 大概會是這樣

---删除物品
---@class pb.S2C_DelItem
---@field itemId integer 物品id

---增加物品
---@class pb.S2C_AddItem
---@field itemId integer 物品id
---@field count integer  物品數量

---@enum (key) Cmds
local Cmds = {
    S2C_DelItem = 1,
    S2C_AddItem = 2,
}

---发送协议到客户端
---@generic T: table
---@param cmd Cmds
---@param args T
---@return T
---@overload fun(cmd: "S2C_DelItem", args: pb.S2C_DelItem): pb.S2C_DelItem
---@overload fun(cmd: "S2C_AddItem", args: pb.S2C_AddItem): pb.S2C_AddItem
local function sendToClient(cmd, args)
    return nil
end

local ret = sendToClient("S2C_DelItem", {
    -- auto complete 會提示 itemId
})

local ret2 = sendToClient("S2C_AddItem", {
    -- auto complete 會提示 itemId, count
})

(但是 luals 的 @overload 機制好像是有點小 bug,不確定會否在什麼時候不能正確地 type narrow 的 🙈 )

tomlau10 avatar Aug 15 '24 12:08 tomlau10