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
|
local files = require 'files'
local guide = require 'parser.guide'
local vm = require 'vm'
local define = require 'proto.define'
local lang = require 'language'
local await = require 'await'
local client = require 'client'
local function isToBeClosed(source)
if not source.attrs then
return false
end
for _, attr in ipairs(source.attrs) do
if attr[1] == 'close' then
return true
end
end
return false
end
---@param source parser.object
local function isValidFunction(source)
if not source then
return false
end
if source.type == 'main' then
return false
end
local parent = source.parent
if not parent then
return false
end
if parent.type ~= 'local'
and parent.type ~= 'setlocal' then
return false
end
if isToBeClosed(parent) then
return false
end
return true
end
local function collect(ast, white, roots, links)
guide.eachSourceType(ast, 'function', function (src)
if not isValidFunction(src) then
return
end
local loc = src.parent
if loc.type == 'setlocal' then
loc = loc.node
end
for _, ref in ipairs(loc.ref or {}) do
if ref.type == 'getlocal' then
local func = guide.getParentFunction(ref)
if not isValidFunction(func) or roots[func] then
roots[src] = true
return
end
if not links[func] then
links[func] = {}
end
links[func][#links[func]+1] = src
end
end
white[src] = true
end)
return white, roots, links
end
local function turnBlack(source, black, white, links)
if black[source] then
return
end
black[source] = true
white[source] = nil
for _, link in ipairs(links[source] or {}) do
turnBlack(link, black, white, links)
end
end
---@async
return function (uri, callback)
local state = files.getState(uri)
if not state then
return
end
if vm.isMetaFile(uri) then
return
end
local black = {}
local white = {}
local roots = {}
local links = {}
-- collect
collect(state.ast, white, roots, links)
-- turn black
for source in pairs(roots) do
turnBlack(source, black, white, links)
end
for source in pairs(white) do
if client.isVSCode() then
callback {
start = source.start,
finish = source.finish,
tags = { define.DiagnosticTag.Unnecessary },
message = lang.script.DIAG_UNUSED_FUNCTION,
}
else
callback {
start = source.keyword[1],
finish = source.keyword[2],
tags = { define.DiagnosticTag.Unnecessary },
message = lang.script.DIAG_UNUSED_FUNCTION,
}
end
end
end
|