Skip to content

Commit a8007df

Browse files
authored
Merge pull request #1597 from CppCXY/master
psi viewer
2 parents e8dd3c3 + 18691bd commit a8007df

File tree

3 files changed

+140
-0
lines changed

3 files changed

+140
-0
lines changed

script/core/view/psi-select.lua

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
local files = require("files")
2+
local guide = require("parser.guide")
3+
local converter = require("proto.converter")
4+
5+
return function(uri, position)
6+
local state = files.getState(uri)
7+
if not state then
8+
return
9+
end
10+
11+
local pos = converter.unpackPosition(uri, position)
12+
return { data = guide.positionToOffset(state, pos) }
13+
end

script/core/view/psi-view.lua

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
local files = require("files")
2+
local guide = require("parser.guide")
3+
local converter = require("proto.converter")
4+
local subString = require 'core.substring'
5+
6+
7+
8+
---@class psi.view.node
9+
---@field name string
10+
---@field attr? psi.view.attr
11+
---@field children? psi.view.node[]
12+
13+
---@class psi.view.attr
14+
---@field range psi.view.range
15+
16+
---@class psi.view.range
17+
---@field start integer
18+
---@field end integer
19+
20+
---@param astNode parser.object
21+
---@param state parser.state
22+
---@return psi.view.node | nil
23+
local function toPsiNode(astNode, state)
24+
if not astNode then
25+
return
26+
end
27+
28+
local startOffset = guide.positionToOffset(state, astNode.start)
29+
local finishOffset = guide.positionToOffset(state, astNode.finish)
30+
local startPosition = converter.packPosition(state.uri, astNode.start)
31+
local finishPosition = converter.packPosition(state.uri, astNode.finish)
32+
return {
33+
name = string.format("%s@[%d:%d .. %d:%d]",
34+
astNode.type,
35+
startPosition.line + 1, startPosition.character + 1,
36+
finishPosition.line + 1, finishPosition.character + 1),
37+
attr = {
38+
range = {
39+
start = startOffset,
40+
["end"] = finishOffset
41+
}
42+
}
43+
}
44+
end
45+
46+
---@param astNode parser.object
47+
---@return psi.view.node | nil
48+
local function collectPsi(astNode, state)
49+
local psiNode = toPsiNode(astNode, state)
50+
51+
if not psiNode then
52+
return
53+
end
54+
55+
guide.eachChild(astNode, function(child)
56+
if psiNode.children == nil then
57+
psiNode.children = {}
58+
end
59+
60+
local psi = collectPsi(child, state)
61+
if psi then
62+
psiNode.children[#psiNode.children+1] = psi
63+
end
64+
end)
65+
66+
if psiNode.children and psiNode.attr then
67+
local range = psiNode.attr.range
68+
if range.start > psiNode.children[1].attr.range.start then
69+
range.start = psiNode.children[1].attr.range.start
70+
end
71+
if range["end"] < psiNode.children[#psiNode.children].attr.range["end"] then
72+
range["end"] = psiNode.children[#psiNode.children].attr.range["end"]
73+
end
74+
end
75+
76+
if not psiNode.children then
77+
local subber = subString(state)
78+
local showText = subber(astNode.start + 1, astNode.finish)
79+
if string.len(showText) > 30 then
80+
showText = showText:sub(0, 30).. " ... "
81+
end
82+
83+
psiNode.name = psiNode.name .. " " .. showText
84+
end
85+
86+
return psiNode
87+
end
88+
89+
return function(uri)
90+
local state = files.getState(uri)
91+
if not state then
92+
return
93+
end
94+
95+
return { data = collectPsi(state.ast, state) }
96+
end

script/provider/provider.lua

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1400,6 +1400,37 @@ m.register '$/api/report' {
14001400
end
14011401
}
14021402

1403+
m.register '$/psi/view' {
1404+
---@async
1405+
function (params)
1406+
local uri = files.getRealUri(params.uri)
1407+
workspace.awaitReady(uri)
1408+
local _ <close> = progress.create(uri, lang.script.WINDOW_PROCESSING_TYPE_FORMATTING, 0.5)
1409+
if not files.exists(uri) then
1410+
return nil
1411+
end
1412+
local core = require 'core.view.psi-view'
1413+
local result = core(uri)
1414+
return result
1415+
end
1416+
}
1417+
1418+
m.register '$/psi/select' {
1419+
---@async
1420+
function(params)
1421+
local uri = files.getRealUri(params.uri)
1422+
workspace.awaitReady(uri)
1423+
local _<close> = progress.create(uri, lang.script.WINDOW_PROCESSING_TYPE_FORMATTING, 0.5)
1424+
if not files.exists(uri) then
1425+
return nil
1426+
end
1427+
local core = require 'core.view.psi-select'
1428+
local result = core(uri, params.position)
1429+
return result
1430+
end
1431+
}
1432+
1433+
14031434
local function refreshStatusBar()
14041435
local valid = config.get(nil, 'Lua.window.statusBar')
14051436
for _, scp in ipairs(workspace.folders) do

0 commit comments

Comments
 (0)