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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
|
local hoverFunction = require 'core.hover_function'
local hoverName = require 'core.hover_name'
local hover = require 'core.hover'
local SymbolKind = {
File = 1,
Module = 2,
Namespace = 3,
Package = 4,
Class = 5,
Method = 6,
Property = 7,
Field = 8,
Constructor = 9,
Enum = 10,
Interface = 11,
Function = 12,
Variable = 13,
Constant = 14,
String = 15,
Number = 16,
Boolean = 17,
Array = 18,
Object = 19,
Key = 20,
Null = 21,
EnumMember = 22,
Struct = 23,
Event = 24,
Operator = 25,
TypeParameter = 26,
}
local function buildFunction(vm, func)
local source = func.source
local declarat = func.declarat
local name
local var
if declarat then
if declarat.type == 'function' then
var = vm.results.sources[declarat.name]
else
var = vm.results.sources[declarat]
end
end
if var then
name = hoverName(var, declarat)
else
name = ''
end
local hvr = hoverFunction(name, func, declarat and declarat.object)
if not hvr then
return nil
end
local selectionRange
local range
local kind = SymbolKind.Function
if var then
range = { math.min(source.start, declarat.start), source.finish }
selectionRange = { declarat.start, declarat.finish }
if var.parent and var.parent.value and not var.parent.value.ENV then
kind = SymbolKind.Field
end
else
range = { source.start, source.finish }
selectionRange = { source.start, source.start }
end
return {
name = name,
-- 前端不支持多行
detail = hvr.label:gsub('[\r\n]', ''),
kind = kind,
range = range,
selectionRange = selectionRange,
}
end
local function isLocalTable(var)
if not var.value or var.value.type ~= 'table' then
return false
end
if var.value.source.start == 0 then
return false
end
if var.source == var.value.declarat then
return true
end
return false
end
local function buildVar(vm, var)
if var.source.start == 0 then
return nil
end
if var.value and var.value.type == 'function' and var.value.uri == vm.uri then
return nil
end
if var.hide then
return nil
end
local key = var.key
if key == '_' then
return nil
end
if type(key) ~= 'string' then
key = ('[%s]'):format(key)
end
local range
if isLocalTable(var) then
range = { var.source.start, var.value.source.finish }
else
range = { var.source.start, var.source.finish }
end
local hvr = hover(var, var.source)
if not hvr then
return nil
end
local kind
if var.source.isIndex then
kind = SymbolKind.Class
else
kind = SymbolKind.Variable
end
return {
name = key,
-- 前端不支持多行
detail = hvr.label:gsub('[\r\n]', ''),
kind = kind,
range = range,
selectionRange = { var.source.start, var.source.finish },
}
end
local function packChild(symbols, finish, kind)
local t
while true do
local symbol = symbols[#symbols]
if not symbol then
break
end
if symbol.range[1] > finish then
break
end
symbols[#symbols] = nil
symbol.children = packChild(symbols, symbol.range[2], symbol.kind)
if symbol.kind == SymbolKind.Class and kind == SymbolKind.Function then
else
if not t then
t = {}
end
t[#t+1] = symbol
end
end
return t
end
local function packSymbols(symbols)
-- 按照start位置反向排序
table.sort(symbols, function (a, b)
return a.range[1] > b.range[1]
end)
-- 处理嵌套
return packChild(symbols, math.maxinteger, SymbolKind.Function)
end
return function (vm)
local symbols = {}
for _, func in ipairs(vm.results.funcs) do
symbols[#symbols+1] = buildFunction(vm, func)
end
for _, loc in ipairs(vm.results.locals) do
symbols[#symbols+1] = buildVar(vm, loc)
end
for _, index in ipairs(vm.results.indexs) do
symbols[#symbols+1] = buildVar(vm, index)
end
local packedSymbols = packSymbols(symbols)
return packedSymbols
end
|