-
-
Notifications
You must be signed in to change notification settings - Fork 430
Feature: Narrow overload candidates by preceding argument types #3430
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -66,15 +66,41 @@ local function getReceiverGenericMap(uri, source) | |
| return nil | ||
| end | ||
|
|
||
| ---@param uri uri | ||
| ---@param funcNode vm.node | ||
| ---@param callArgs parser.object[] | ||
| ---@param i integer | ||
| ---@param classGenericMap table<string, vm.node>? | ||
| ---@return vm.node? | ||
| local function getDefNode(funcNode, i, classGenericMap) | ||
| local defNode = vm.createNode() | ||
| ---@return parser.object[] | ||
| local function getCheckableFunctions(uri, funcNode, callArgs, i) | ||
| local funcs = {} | ||
| for src in funcNode:eachObject() do | ||
| if src.type == 'function' | ||
| or src.type == 'doc.type.function' then | ||
| funcs[#funcs+1] = src | ||
| end | ||
| end | ||
| if #funcs > 1 then | ||
| local matched = {} | ||
| for _, src in ipairs(funcs) do | ||
| if vm.isPriorArgsMatched(uri, src, callArgs, i) then | ||
| matched[#matched+1] = src | ||
| end | ||
| end | ||
| if #matched > 0 then | ||
| funcs = matched | ||
| end | ||
| end | ||
| return funcs | ||
| end | ||
|
|
||
| ---@param funcs parser.object[] | ||
| ---@param i integer | ||
| ---@param classGenericMap table<string, vm.node>? | ||
| ---@return vm.node? | ||
| local function getDefNode(funcs, i, classGenericMap) | ||
| local defNode = vm.createNode() | ||
| for _, src in ipairs(funcs) do | ||
| if src.args then | ||
| local param = src.args and src.args[i] | ||
| if param then | ||
| local paramNode = vm.compileNode(param) | ||
|
|
@@ -108,14 +134,13 @@ local function getDefNode(funcNode, i, classGenericMap) | |
| return defNode | ||
| end | ||
|
|
||
| ---@param funcNode vm.node | ||
| ---@param funcs parser.object[] | ||
| ---@param i integer | ||
| ---@return vm.node | ||
| local function getRawDefNode(funcNode, i) | ||
| local function getRawDefNode(funcs, i) | ||
| local defNode = vm.createNode() | ||
| for f in funcNode:eachObject() do | ||
| if f.type == 'function' | ||
| or f.type == 'doc.type.function' then | ||
| for _, f in ipairs(funcs) do | ||
| if f.args then | ||
| local param = f.args and f.args[i] | ||
| if param then | ||
| defNode:merge(vm.compileNode(param)) | ||
|
|
@@ -146,7 +171,8 @@ return function (uri, callback) | |
| if not refNode then | ||
| goto CONTINUE | ||
| end | ||
| local defNode = getDefNode(funcNode, i, classGenericMap) | ||
| local funcs = getCheckableFunctions(uri, funcNode, source.args, i) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| local defNode = getDefNode(funcs, i, classGenericMap) | ||
| if not defNode then | ||
| goto CONTINUE | ||
| end | ||
|
|
@@ -159,7 +185,7 @@ return function (uri, callback) | |
| end | ||
| local errs = {} | ||
| if not vm.canCastType(uri, defNode, refNode, errs) then | ||
| local rawDefNode = getRawDefNode(funcNode, i) | ||
| local rawDefNode = getRawDefNode(funcs, i) | ||
| assert(errs) | ||
| callback { | ||
| start = arg.start, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1208,23 +1208,41 @@ local function compileCallArgNode(arg, call, callNode, fixIndex, myIndex) | |
| end | ||
| end | ||
|
|
||
| local docFuncs = {} | ||
| for n in callNode:eachObject() do | ||
| if n.type == 'function' then | ||
| ---@cast n parser.object | ||
| dealFunction(n) | ||
| elseif n.type == 'doc.type.function' then | ||
| ---@cast n parser.object | ||
| dealDocFunc(n) | ||
| docFuncs[#docFuncs+1] = n | ||
| elseif n.type == 'global' and n.cate == 'type' then | ||
| ---@cast n vm.global | ||
| local overloads = vm.getOverloadsByTypeName(n.name, guide.getUri(arg)) | ||
| if overloads then | ||
| for _, func in ipairs(overloads) do | ||
| dealDocFunc(func) | ||
| docFuncs[#docFuncs+1] = func | ||
| end | ||
| end | ||
| end | ||
| end | ||
|
|
||
| if #docFuncs > 1 and call.args then | ||
| local uri = guide.getUri(arg) | ||
| local matched = {} | ||
| for _, n in ipairs(docFuncs) do | ||
| if vm.isPriorArgsMatched(uri, n, call.args, myIndex, fixIndex) then | ||
| matched[#matched+1] = n | ||
| end | ||
| end | ||
| if #matched > 0 then | ||
| docFuncs = matched | ||
| end | ||
| end | ||
|
Comment on lines
+1230
to
+1241
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Pass |
||
|
|
||
| for _, n in ipairs(docFuncs) do | ||
| dealDocFunc(n) | ||
| end | ||
| end | ||
|
|
||
| ---@param arg parser.object | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -353,6 +353,44 @@ local function isAllParamMatched(uri, args, params) | |
| return true | ||
| end | ||
|
|
||
| ---@param param parser.object | ||
| ---@return boolean | ||
| local function isVarargParam(param) | ||
| return param.type == '...' | ||
| or (param.name and param.name[1] == '...') | ||
| end | ||
|
|
||
| ---@param uri uri | ||
| ---@param func parser.object -- `function` or `doc.type.function` | ||
| ---@param callArgs parser.object[] | ||
| ---@param myIndex integer | ||
| ---@param fixIndex? integer | ||
| ---@return boolean | ||
| function vm.isPriorArgsMatched(uri, func, callArgs, myIndex, fixIndex) | ||
| fixIndex = fixIndex or 0 | ||
| local params = func.args | ||
| if not params then | ||
| return true | ||
| end | ||
| for i = 1, myIndex - 1 do | ||
| local callArg = callArgs[i + fixIndex] | ||
| local param = params[i] | ||
| if not callArg or not param then | ||
| break | ||
| end | ||
| if callArg.type ~= '...' | ||
| and param.type ~= 'self' | ||
| and not isVarargParam(param) then | ||
| local defNode = vm.compileNode(param) | ||
| local refNode = vm.compileNode(callArg) | ||
| if not vm.canCastType(uri, defNode, refNode) then | ||
| return false | ||
| end | ||
| end | ||
| end | ||
| return true | ||
| end | ||
|
Comment on lines
+363
to
+392
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is a misalignment bug when matching prior arguments for method calls (using In Lua, a method definition like When checking prior arguments for We can fix this by passing the |
||
|
|
||
| ---@param uri uri | ||
| ---@param args parser.object[] | ||
| ---@param func parser.object | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update
getCheckableFunctionsto accept thecallAST node (source) instead ofcallArgsto support the parameter alignment fix invm.isPriorArgsMatched.