Skip to content

Commit

Permalink
fix: improve function type narrow by checking params' literal identical
Browse files Browse the repository at this point in the history
  • Loading branch information
tomlau10 committed Aug 24, 2024
1 parent ba8f90e commit 09ba965
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 11 deletions.
1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## Unreleased
<!-- Add all new changes here. They will be moved under a version at release -->
* `FIX` Improve type narrow by checking exact match on literal type params

## 3.10.5
`2024-8-19`
Expand Down
55 changes: 44 additions & 11 deletions script/vm/function.lua
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,31 @@ local function isAllParamMatched(uri, args, params)
return true
end

---@param uri uri
---@param args parser.object[]
---@param func parser.object
---@return integer
local function calcFunctionMatchScore(uri, args, func)
if vm.isVarargFunctionWithOverloads(func)
or not isAllParamMatched(uri, args, func.args)
then
return -1
end
local matchScore = 0
for i = 1, math.min(#args, #func.args) do
local arg, param = args[i], func.args[i]
-- if param's literals map contains arg's literal, this is the most narrowed exact match
local argLiteral = guide.getLiteral(arg)
if argLiteral ~= nil then
local defLiterals = vm.getLiterals(param)
if defLiterals and defLiterals[argLiteral] then
matchScore = matchScore + 1
end
end
end
return matchScore
end

---@param func parser.object
---@param args? parser.object[]
---@return parser.object[]?
Expand All @@ -365,21 +390,29 @@ function vm.getExactMatchedFunctions(func, args)
return funcs
end
local uri = guide.getUri(func)
local needRemove
local matchScores = {}
for i, n in ipairs(funcs) do
if vm.isVarargFunctionWithOverloads(n)
or not isAllParamMatched(uri, args, n.args) then
if not needRemove then
needRemove = {}
end
needRemove[#needRemove+1] = i
end
matchScores[i] = calcFunctionMatchScore(uri, args, n)
end

local maxMatchScore = math.max(table.unpack(matchScores))
if maxMatchScore == -1 then
-- all should be removed
return nil
end
if not needRemove then

local minMatchScore = math.min(table.unpack(matchScores))
if minMatchScore == maxMatchScore then
-- all should be kept
return funcs
end
if #needRemove == #funcs then
return nil

-- remove functions that have matchScore < maxMatchScore
local needRemove = {}
for i, matchScore in ipairs(matchScores) do
if matchScore < maxMatchScore then
needRemove[#needRemove + 1] = i
end
end
util.tableMultiRemove(funcs, needRemove)
return funcs
Expand Down

0 comments on commit 09ba965

Please sign in to comment.