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
117
118
119
120
121
122
123
124
125
|
local getFunctionHover = require 'core.hover.function'
local getFunctionHoverAsLib = require 'core.hover.lib_function'
local getFunctionHoverAsEmmy = require 'core.hover.emmy_function'
local findLib = require 'core.find_lib'
local buildValueName = require 'core.hover.name'
local findSource = require 'core.find_source'
local function findCall(vm, pos)
local results = {}
vm:eachSource(function (src)
if src.type == 'call'
and src.start <= pos
and src.finish >= pos
then
results[#results+1] = src
end
end)
if #results == 0 then
return nil
end
-- 可能处于 'func1(func2(' 的嵌套中,将最近的call放到最前面
table.sort(results, function (a, b)
return a.start > b.start
end)
return results
end
local function getSelect(args, pos)
if not args then
return 1
end
for i, arg in ipairs(args) do
if arg.start <= pos and arg.finish >= pos - 1 then
return i
end
end
return #args + 1
end
local function getFunctionSource(call)
local simple = call:get 'simple'
for i, source in ipairs(simple) do
if source == call then
return simple[i-1]
end
end
return nil
end
local function hovers(call, pos)
local args = call:bindCall()
if not args then
return nil
end
local value = call:findCallFunction()
if not value then
return nil
end
local select = getSelect(args, pos)
local source = getFunctionSource(call)
local object = source:get 'object'
local lib, fullkey = findLib(source)
local name = fullkey or buildValueName(source)
local hovers = {}
if lib then
hovers[#hovers+1] = getFunctionHoverAsLib(name, lib, object, select)
else
local emmy = value:getEmmy()
if emmy and emmy.type == 'emmy.functionType' then
hovers[#hovers+1] = getFunctionHoverAsEmmy(name, emmy, object, select)
else
---@type emmyFunction
local func = value:getFunction()
hovers[#hovers+1] = getFunctionHover(name, func, object, select)
local overLoads = func and func:getEmmyOverLoads()
if overLoads then
for _, ol in ipairs(overLoads) do
hovers[#hovers+1] = getFunctionHoverAsEmmy(name, ol, object, select)
end
end
end
end
if #hovers == 0 then
return nil
end
return hovers
end
local function isInFunctionOrTable(call, pos)
local args = call:bindCall()
if not args then
return false
end
local select = getSelect(args, pos)
local arg = args[select]
if not arg then
return false
end
if arg.type == 'function' or arg.type == 'table' then
return true
end
return false
end
return function (vm, pos)
local source = findSource(vm, pos) or findSource(vm, pos-1)
if not source or source.type == 'string' then
return
end
local calls = findCall(vm, pos)
if not calls or #calls == 0 then
return nil
end
local nearCall = calls[1]
if isInFunctionOrTable(nearCall, pos) then
return nil
end
local hovers = hovers(nearCall, pos)
return hovers
end
|