diff --git a/changelog.md b/changelog.md index f030ebda6..14c5bbe5f 100644 --- a/changelog.md +++ b/changelog.md @@ -2,6 +2,7 @@ ## Unreleased +* `FIX` Improve type narrow with **literal alias type** during completion and signature help * `NEW` Setting: `Lua.type.inferTableSize`: A Small Table array can be infered ## 3.12.0 diff --git a/script/core/signature.lua b/script/core/signature.lua index c52dcff31..27f555a71 100644 --- a/script/core/signature.lua +++ b/script/core/signature.lua @@ -114,7 +114,13 @@ local function isEventNotMatch(call, src) end local eventLiteral = event.extends.types[1] and guide.getLiteral(event.extends.types[1]) if eventLiteral == nil then - return false + -- extra checking when function param is not pure literal + -- eg: it maybe an alias type with literal values + local eventMap = vm.getLiterals(event.extends.types[1]) + if not eventMap then + return false + end + return not eventMap[literal] end return eventLiteral ~= literal end diff --git a/script/vm/compiler.lua b/script/vm/compiler.lua index 8701e8d7b..a3053f589 100644 --- a/script/vm/compiler.lua +++ b/script/vm/compiler.lua @@ -962,6 +962,26 @@ local function compileCallArgNode(arg, call, callNode, fixIndex, myIndex) local function dealDocFunc(n) local myEvent if n.args[eventIndex] then + if eventMap and myIndex > eventIndex then + -- if call param has literal types, then also check if function def param has literal types + -- 1. has no literal values => not enough info, thus allowed by default + -- 2. has literal values and >= 1 matches call param's literal types => allowed + -- 3. has literal values but none matches call param's literal types => filtered + local myEventMap = vm.getLiterals(n.args[eventIndex]) + if myEventMap then + local found = false + for k in pairs(eventMap) do + if myEventMap[k] then + -- there is a matching literal + found = true + break + end + end + if not found then + return + end + end + end local argNode = vm.compileNode(n.args[eventIndex]) myEvent = argNode:get(1) end diff --git a/test/completion/common.lua b/test/completion/common.lua index 30350642a..7f576e0bf 100644 --- a/test/completion/common.lua +++ b/test/completion/common.lua @@ -3138,6 +3138,44 @@ emit.on(emit, 'won', ) } } +TEST [[ +--- @alias event.AAA "AAA" +--- @alias event.BBB "BBB" + +--- @class Emit +--- @field on fun(self: Emit, eventName: string, cb: function) +--- @field on fun(self: Emit, eventName: event.AAA, cb: fun(i: integer)) +--- @field on fun(self: Emit, eventName: event.BBB, cb: fun(s: string)) +local emit = {} + +emit:on('AAA', ) +]] +{ + [1] = { + label = 'fun(i: integer)', + kind = define.CompletionItemKind.Function, + } +} + +TEST [[ +--- @alias event.AAA "AAA" +--- @alias event.BBB "BBB" + +--- @class Emit +--- @field on fun(self: Emit, eventName: string, cb: function) +--- @field on fun(self: Emit, eventName: event.AAA, cb: fun(i: integer)) +--- @field on fun(self: Emit, eventName: event.BBB, cb: fun(s: string)) +local emit = {} + +emit:on('BBB', ) +]] +{ + [1] = { + label = 'fun(s: string)', + kind = define.CompletionItemKind.Function, + } +} + TEST [[ local function f() local inferCache diff --git a/test/signature/init.lua b/test/signature/init.lua index bd4d40cd4..010c15314 100644 --- a/test/signature/init.lua +++ b/test/signature/init.lua @@ -373,6 +373,40 @@ t:event("onTimer", ) '(method) (ev: "onTimer", )', } +TEST [[ +---@alias event.onChat "onChat" +---@alias event.onTimer "onTimer" + +---@class A +---@field event fun(self: self, ev: event.onChat, c: string) +---@field event fun(self: self, ev: event.onTimer, t: integer) + +---@type A +local t + +t:event("onChat", ) +]] +{ +'(method) (ev: "onChat", )', +} + +TEST [[ +---@alias event.onChat "onChat" +---@alias event.onTimer "onTimer" + +---@class A +---@field event fun(self: self, ev: event.onChat, c: string) +---@field event fun(self: self, ev: event.onTimer, t: integer) + +---@type A +local t + +t:event("onTimer", ) +]] +{ +'(method) (ev: "onTimer", )', +} + local config = require 'config' config.set(nil, "Lua.type.inferParamType", true)