Skip to content

Commit fa0fe1c

Browse files
committed
document-symbol supports block
1 parent cfda344 commit fa0fe1c

File tree

5 files changed

+181
-39
lines changed

5 files changed

+181
-39
lines changed

.luarc.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@
4141
],
4242
"checkThirdParty": false
4343
},
44+
"typeFormat": {
45+
"config": {
46+
"format_line": "false"
47+
}
48+
},
4449
"type": {
4550
"castNumberToInteger": false
4651
}

changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# changelog
22

33
## 3.5.4
4+
* `CHG` `document-symbol`: redesigned to better support for `Sticky Scroll` feature of VSCode
45
* `FIX` `diagnostics.workspaceDelay` can not prevent first workspace diagnostic
56
* `FIX` [#1476](https://github.com/sumneko/lua-language-server/issues/1476)
67

script/core/document-symbol.lua

Lines changed: 77 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -3,38 +3,31 @@ local files = require 'files'
33
local guide = require 'parser.guide'
44
local define = require 'proto.define'
55
local util = require 'utility'
6-
local vm = require 'vm'
6+
local subber = require 'core.substring'
77

8-
local function buildName(source, text)
9-
local uri = guide.getUri(source)
10-
local state = files.getState(uri)
11-
local startOffset = guide.positionToOffset(state, source.start)
8+
local function buildName(source, sub)
129
if source.type == 'setmethod'
1310
or source.type == 'getmethod' then
1411
if source.method then
15-
local finishOffset = guide.positionToOffset(state, source.method.finish)
16-
return text:sub(startOffset + 1, finishOffset)
12+
return sub(source.start + 1, source.method.finish)
1713
end
1814
end
1915
if source.type == 'setfield'
2016
or source.type == 'tablefield'
2117
or source.type == 'getfield' then
2218
if source.field then
23-
local finishOffset = guide.positionToOffset(state, source.field.finish)
24-
return text:sub(startOffset + 1, finishOffset)
19+
return sub(source.start + 1, source.field.finish)
2520
end
2621
end
2722
if source.type == 'tableindex' then
2823
if source.index then
29-
local finishOffset = guide.positionToOffset(state, source.finish)
30-
return text:sub(startOffset + 1, finishOffset)
24+
return sub(source.start + 1, source.finish)
3125
end
3226
end
3327
if source.type == 'tableexp' then
3428
return ('[%d]'):format(source.tindex)
3529
end
36-
local finishOffset = guide.positionToOffset(state, source.finish)
37-
return text:sub(startOffset + 1, finishOffset)
30+
return sub(source.start + 1, source.finish)
3831
end
3932

4033
local function buildFunctionParams(func)
@@ -56,8 +49,7 @@ local function buildFunctionParams(func)
5649
return table.concat(params, ', ')
5750
end
5851

59-
local function buildTable(tbl)
60-
local uri = guide.getUri(tbl)
52+
local function buildTable(tbl, sub)
6153
local buf = {}
6254
for i = 1, 5 do
6355
local field = tbl[i]
@@ -69,9 +61,7 @@ local function buildTable(tbl)
6961
buf[#buf+1] = ('%s'):format(field.field[1])
7062
elseif field.type == 'tableindex'
7163
and field.index then
72-
local view = vm.getInfer(field.index):viewLiterals()
73-
or vm.getInfer(field.index):view(uri)
74-
buf[#buf+1] = ('[%s]'):format(view)
64+
buf[#buf+1] = ('[%s]'):format(sub(field.index.start + 1, field.index.finish))
7565
elseif field.type == 'tableexp' then
7666
buf[#buf+1] = ('[%s]'):format(field.tindex)
7767
end
@@ -82,25 +72,23 @@ local function buildTable(tbl)
8272
return table.concat(buf, ', ')
8373
end
8474

85-
local function buildArray(tbl)
86-
local uri = guide.getUri(tbl)
75+
local function buildArray(tbl, sub)
8776
local buf = {}
8877
for i = 1, 5 do
8978
local field = tbl[i]
9079
if not field then
9180
break
9281
end
93-
buf[#buf+1] = vm.getInfer(field):viewLiterals()
94-
or vm.getInfer(field):view(uri)
82+
buf[#buf+1] = sub(field.start + 1, field.finish)
9583
end
9684
if #tbl > 5 then
9785
buf[#buf+1] = ('...(+%d)'):format(#tbl - 5)
9886
end
9987
return table.concat(buf, ', ')
10088
end
10189

102-
local function buildValue(source, text, used, symbols)
103-
local name = buildName(source, text)
90+
local function buildValue(source, sub, used, symbols)
91+
local name = buildName(source, sub)
10492
local range, sRange, valueRange, kind
10593
local details = {}
10694
if source.type == 'local' then
@@ -175,12 +163,12 @@ local function buildValue(source, text, used, symbols)
175163
-- Array
176164
kind = define.SymbolKind.Array
177165
details[#details+1] = '['
178-
details[#details+1] = buildArray(source.value)
166+
details[#details+1] = buildArray(source.value, sub)
179167
details[#details+1] = ']'
180168
else
181169
-- Object
182170
details[#details+1] = '{'
183-
details[#details+1] = buildTable(source.value)
171+
details[#details+1] = buildTable(source.value, sub)
184172
details[#details+1] = '}'
185173
end
186174
end
@@ -211,7 +199,7 @@ local function buildValue(source, text, used, symbols)
211199
}
212200
end
213201

214-
local function buildAnonymousFunction(source, text, used, symbols)
202+
local function buildAnonymousFunction(source, sub, used, symbols)
215203
if used[source] then
216204
return
217205
end
@@ -223,7 +211,7 @@ local function buildAnonymousFunction(source, text, used, symbols)
223211
elseif parent.type == 'callargs' then
224212
local call = parent.parent
225213
local node = call.node
226-
head = buildName(node, text) .. ' -> '
214+
head = buildName(node, sub) .. ' -> '
227215
end
228216
symbols[#symbols+1] = {
229217
name = '',
@@ -235,7 +223,54 @@ local function buildAnonymousFunction(source, text, used, symbols)
235223
}
236224
end
237225

238-
local function buildSource(source, text, used, symbols)
226+
local function buildBlock(source, sub, used, symbols)
227+
if used[source] then
228+
return
229+
end
230+
used[source] = true
231+
if source.type == 'if' then
232+
for _, block in ipairs(source) do
233+
symbols[#symbols+1] = {
234+
name = block.type:gsub('block$', ''),
235+
detail = sub(block.start + 1, block.keyword[4] or block.keyword[2]),
236+
kind = define.SymbolKind.Package,
237+
range = { block.start, block.finish },
238+
valueRange = { block.start, block.finish },
239+
selectionRange = { block.keyword[1], block.keyword[2] },
240+
}
241+
end
242+
elseif source.type == 'while' then
243+
symbols[#symbols+1] = {
244+
name = 'while',
245+
detail = sub(source.start + 1, source.keyword[4] or source.keyword[2]),
246+
kind = define.SymbolKind.Package,
247+
range = { source.start, source.finish },
248+
valueRange = { source.start, source.finish },
249+
selectionRange = { source.keyword[1], source.keyword[2] },
250+
}
251+
elseif source.type == 'repeat' then
252+
symbols[#symbols+1] = {
253+
name = 'repeat',
254+
detail = source.filter and sub(source.keyword[3] + 1, source.filter.finish) or '',
255+
kind = define.SymbolKind.Package,
256+
range = { source.start, source.finish },
257+
valueRange = { source.start, source.finish },
258+
selectionRange = { source.keyword[1], source.keyword[2] },
259+
}
260+
elseif source.type == 'loop'
261+
or source.type == 'in' then
262+
symbols[#symbols+1] = {
263+
name = 'for',
264+
detail = sub(source.start, source.keyword[4] or source.keyword[2]),
265+
kind = define.SymbolKind.Package,
266+
range = { source.start, source.finish },
267+
valueRange = { source.start, source.finish },
268+
selectionRange = { source.keyword[1], source.keyword[2] },
269+
}
270+
end
271+
end
272+
273+
local function buildSource(source, sub, used, symbols)
239274
if source.type == 'local'
240275
or source.type == 'setlocal'
241276
or source.type == 'setglobal'
@@ -244,26 +279,32 @@ local function buildSource(source, text, used, symbols)
244279
or source.type == 'tablefield'
245280
or source.type == 'tableexp'
246281
or source.type == 'tableindex' then
247-
buildValue(source, text, used, symbols)
282+
buildValue(source, sub, used, symbols)
248283
elseif source.type == 'function' then
249-
buildAnonymousFunction(source, text, used, symbols)
284+
buildAnonymousFunction(source, sub, used, symbols)
285+
elseif source.type == 'if'
286+
or source.type == 'while'
287+
or source.type == 'in'
288+
or source.type == 'loop'
289+
or source.type == 'repeat' then
290+
buildBlock(source, sub, used, symbols)
250291
end
251292
end
252293

253294
---@async
254295
local function makeSymbol(uri)
255-
local ast = files.getState(uri)
256-
local text = files.getText(uri)
257-
if not ast or not text then
296+
local state = files.getState(uri)
297+
if not state then
258298
return nil
259299
end
260300

301+
local sub = subber(state)
261302
local symbols = {}
262303
local used = {}
263304
local i = 0
264305
---@async
265-
guide.eachSource(ast.ast, function (source)
266-
buildSource(source, text, used, symbols)
306+
guide.eachSource(state.ast, function (source)
307+
buildSource(source, sub, used, symbols)
267308
i = i + 1
268309
if i % 1000 == 0 then
269310
await.delay()

script/parser/compile.lua

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3191,7 +3191,7 @@ local function parseIfBlock(parent)
31913191
pushChunk(ifblock)
31923192
parseActions()
31933193
popChunk()
3194-
ifblock.finish = lastRightPosition()
3194+
ifblock.finish = getPosition(Tokens[Index], 'left')
31953195
if ifblock.locals then
31963196
LocalCount = LocalCount - #ifblock.locals
31973197
end
@@ -3250,7 +3250,7 @@ local function parseElseIfBlock(parent)
32503250
pushChunk(elseifblock)
32513251
parseActions()
32523252
popChunk()
3253-
elseifblock.finish = lastRightPosition()
3253+
elseifblock.finish = getPosition(Tokens[Index], 'left')
32543254
if elseifblock.locals then
32553255
LocalCount = LocalCount - #elseifblock.locals
32563256
end
@@ -3275,7 +3275,7 @@ local function parseElseBlock(parent)
32753275
pushChunk(elseblock)
32763276
parseActions()
32773277
popChunk()
3278-
elseblock.finish = lastRightPosition()
3278+
elseblock.finish = getPosition(Tokens[Index], 'left')
32793279
if elseblock.locals then
32803280
LocalCount = LocalCount - #elseblock.locals
32813281
end

test/document_symbol/init.lua

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -743,3 +743,98 @@ local t = { 1, 2, [5] = 3, [true] = 4, x = 5 }
743743
children = EXISTS
744744
}
745745
}
746+
747+
TEST [[
748+
if 1 then
749+
750+
elseif 2 then
751+
752+
elseif 3 then
753+
754+
else
755+
756+
end
757+
]]
758+
{
759+
{
760+
name = 'if',
761+
detail = 'if 1 then',
762+
kind = define.SymbolKind.Package,
763+
range = {0, 20000},
764+
selectionRange = {0, 2},
765+
valueRange = {0, 20000},
766+
},
767+
{
768+
name = 'elseif',
769+
detail = 'elseif 2 then',
770+
kind = define.SymbolKind.Package,
771+
range = {20000, 40000},
772+
selectionRange = {20000, 20006},
773+
valueRange = {20000, 40000},
774+
},
775+
{
776+
name = 'elseif',
777+
detail = 'elseif 3 then',
778+
kind = define.SymbolKind.Package,
779+
range = {40000, 60000},
780+
selectionRange = {40000, 40006},
781+
valueRange = {40000, 60000},
782+
},
783+
{
784+
name = 'else',
785+
detail = 'else',
786+
kind = define.SymbolKind.Package,
787+
range = {60000, 80000},
788+
selectionRange = {60000, 60004},
789+
valueRange = {60000, 80000},
790+
},
791+
}
792+
793+
TEST [[
794+
while true do
795+
796+
end
797+
]]
798+
{
799+
{
800+
name = 'while',
801+
detail = 'while true do',
802+
kind = define.SymbolKind.Package,
803+
range = {0, 20003},
804+
selectionRange = {0, 5},
805+
valueRange = {0, 20003},
806+
},
807+
}
808+
809+
TEST [[
810+
repeat
811+
812+
until true
813+
]]
814+
{
815+
{
816+
name = 'repeat',
817+
detail = 'until true',
818+
kind = define.SymbolKind.Package,
819+
range = {0, 20010},
820+
selectionRange = {0, 6},
821+
valueRange = {0, 20010},
822+
},
823+
}
824+
825+
TEST [[
826+
for i = 1, 10 do
827+
828+
end
829+
]]
830+
{
831+
{
832+
name = 'for',
833+
detail = 'for i = 1, 10 do',
834+
kind = define.SymbolKind.Package,
835+
range = {0, 20003},
836+
selectionRange = {0, 3},
837+
valueRange = {0, 20003},
838+
children = EXISTS,
839+
},
840+
}

0 commit comments

Comments
 (0)