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
|
local guide = require 'parser.guide'
local files = require 'files'
local vm = require 'vm'
local findSource = require 'core.find-source'
local function isValidFunction(source, offset)
-- 必须点在 `function` 这个单词上才能查找函数引用
return offset >= source.start and offset < source.start + #'function'
end
local function sortResults(results)
-- 先按照顺序排序
table.sort(results, function (a, b)
local u1 = guide.getRoot(a).uri
local u2 = guide.getRoot(b).uri
if u1 == u2 then
return a.target.start < b.target.start
else
return u1 < u2
end
end)
-- 如果2个结果处于嵌套状态,则取范围小的那个
local lf, lu
for i = #results, 1, -1 do
local res = results[i].target
local f = res.finish
local uri = guide.getRoot(res).uri
if lf and f > lf and uri == lu then
table.remove(results, i)
else
lu = uri
lf = f
end
end
end
local accept = {
['local'] = true,
['setlocal'] = true,
['getlocal'] = true,
['label'] = true,
['goto'] = true,
['field'] = true,
['method'] = true,
['setindex'] = true,
['getindex'] = true,
['tableindex'] = true,
['setglobal'] = true,
['getglobal'] = true,
['function'] = true,
}
return function (uri, offset)
local ast = files.getAst(uri)
if not ast then
return nil
end
local source = findSource(ast, offset, accept)
if not source then
return nil
end
if source.type == 'function' and not isValidFunction(source, offset) and not TEST then
return nil
end
local results = {}
vm.eachRef(source, function (src)
local root = guide.getRoot(src)
if src.type == 'setfield'
or src.type == 'getfield'
or src.type == 'tablefield' then
src = src.field
elseif src.type == 'setindex'
or src.type == 'getindex'
or src.type == 'tableindex' then
src = src.index
elseif src.type == 'getmethod'
or src.type == 'setmethod' then
src = src.method
end
results[#results+1] = {
target = src,
uri = files.getOriginUri(root.uri),
}
end)
if #results == 0 then
return nil
end
sortResults(results)
return results
end
|