summaryrefslogtreecommitdiff
path: root/server/src/core/hover/function.lua
blob: 8621aee080fac9ed08396409ddd661543bc343ee (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
local function buildValueArgs(func, object, select)
    if not func then
        return '', nil
    end
    local names = {}
    local values = {}
    if func.argValues then
        for i, value in ipairs(func.argValues) do
            values[i] = value:getType()
        end
    end
    if func.args then
        for i, arg in ipairs(func.args) do
            names[#names+1] = arg:getName()
            local param = func:findEmmyParamByName(arg:getName())
            if param then
                values[i] = param:getType()
            end
        end
    end
    local strs = {}
    local start = 1
    if object then
        start = 2
    end
    local max
    if func:getSource() then
        max = #names
    else
        max = math.max(#names, #values)
    end
    for i = start, max do
        if i > start then
            strs[#strs+1] = ', '
        end
        local name = names[i]
        local value = values[i] or 'any'
        if i == select then
            strs[#strs+1] = '@ARG'
        end
        if name then
            strs[#strs+1] = name .. ': ' .. value
        else
            strs[#strs+1] = value
        end
        if i == select then
            strs[#strs+1] = '@ARG'
        end
    end
    if func:hasDots() then
        if max > 0 then
            strs[#strs+1] = ', '
        end
        strs[#strs+1] = '...'
    end
    local text = table.concat(strs)
    local argLabel = {}
    for i = 1, 2 do
        local pos = text:find('@ARG', 1, true)
        if pos then
            if i == 1 then
                argLabel[i] = pos
            else
                argLabel[i] = pos - 1
            end
            text = text:sub(1, pos-1) .. text:sub(pos+4)
        end
    end
    if #argLabel == 0 then
        argLabel = nil
    end
    return text, argLabel
end

local function buildValueReturns(func)
    if not func then
        return '\n  -> any'
    end
    if not func:get 'hasReturn' then
        return ''
    end
    local strs = {}
    if func.returns then
        for i, rtn in ipairs(func.returns) do
            strs[i] = rtn:getType()
        end
    end
    if #strs == 0 then
        strs[1] = 'any'
    end
    return '\n  -> ' .. table.concat(strs, ', ')
end

local function getComment(func)
    if not func then
        return nil
    end
    return func:getComment() or ''
end

return function (name, func, object, select)
    local args, argLabel = buildValueArgs(func, object, select)
    local returns = buildValueReturns(func)
    local comment = getComment(func)
    local headLen = #('function %s('):format(name)
    local title = ('function %s(%s)%s'):format(name, args, returns)
    if argLabel then
        argLabel[1] = argLabel[1] + headLen
        argLabel[2] = argLabel[2] + headLen
    end
    return {
        label = title,
        argLabel = argLabel,
        description = comment,
    }
end