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

How to implement automatic derivation of function parameter types

Open fesily opened this issue 1 year ago • 4 comments

local function t(a)
  a? --unkown
end
t({A=1})

This feature is not available in the current language server. I would like to add it as a feature and have no clue where to start changing it. The primary target is a function that is called only once

fesily avatar Jan 15 '24 06:01 fesily

script/vm/compiler.lua compileLocal

    if source.parent.type == 'funcargs' and not hasMarkDoc and not hasMarkParam then
        local func = source.parent.parent
        -- local call ---@type fun(f: fun(x: number));call(function (x) end) --> x -> number
        local funcNode = vm.compileNode(func)
        local hasDocArg
        for n in funcNode:eachObject() do
            if n.type == 'doc.type.function' then
                for index, arg in ipairs(n.args) do
                    if func.args[index] == source then
                        local argNode = vm.compileNode(arg)
                        for an in argNode:eachObject() do
                            if an.type ~= 'doc.generic.name' then
                                vm.setNode(source, an)
                            end
                        end
                        hasDocArg = true
                    end
                end
            end
        end
        if not hasDocArg then
            local refs = vm.getRefs(source.parent.parent)
            local findCall
            if refs then
                for i, ref in ipairs(refs) do
                    if ref.parent.type == 'call' then
                        findCall = ref.parent
                        break
                    end
                end
            end
            if findCall then
                local index
                for i, arg in ipairs(source.parent) do
                    if arg == source then
                        index = i
                        break
                    end
                end
                if index then
                    hasDocArg = true
                    local callerArg = findCall.args[index]
                    vm.setNode(source, vm.compileNode(callerArg))
                end
            end
        end
        if not hasDocArg then
            vm.setNode(source, vm.declareGlobal('type', 'any'))
        end
    end

It's worked

fesily avatar Jan 15 '24 09:01 fesily

vm.getRefs may very slow

sumneko avatar Jan 16 '24 02:01 sumneko

It is indeed slow, so one should limit the search in which way. I think first just find the first valid function call.

fesily avatar Jan 16 '24 02:01 fesily

Limiting types to local variables,maybe better

fesily avatar Jan 16 '24 03:01 fesily