diff options
author | 最萌小汐 <sumneko@hotmail.com> | 2022-09-30 23:27:06 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-09-30 23:27:06 +0800 |
commit | a8007df95719639d8f7f03d3192d03b372a1d5c6 (patch) | |
tree | 9971529811a2f31791bad0981b19647fde4b3cff | |
parent | e8dd3c3c674790771438173606a027f06a90c9ed (diff) | |
parent | 18691bdfea49c829115437e7d029aa15bddd3d58 (diff) | |
download | lua-language-server-a8007df95719639d8f7f03d3192d03b372a1d5c6.zip |
Merge pull request #1597 from CppCXY/master
psi viewer
-rw-r--r-- | script/core/view/psi-select.lua | 13 | ||||
-rw-r--r-- | script/core/view/psi-view.lua | 96 | ||||
-rw-r--r-- | script/provider/provider.lua | 31 |
3 files changed, 140 insertions, 0 deletions
diff --git a/script/core/view/psi-select.lua b/script/core/view/psi-select.lua new file mode 100644 index 00000000..b6733aa5 --- /dev/null +++ b/script/core/view/psi-select.lua @@ -0,0 +1,13 @@ +local files = require("files") +local guide = require("parser.guide") +local converter = require("proto.converter") + +return function(uri, position) + local state = files.getState(uri) + if not state then + return + end + + local pos = converter.unpackPosition(uri, position) + return { data = guide.positionToOffset(state, pos) } +end diff --git a/script/core/view/psi-view.lua b/script/core/view/psi-view.lua new file mode 100644 index 00000000..86089dd4 --- /dev/null +++ b/script/core/view/psi-view.lua @@ -0,0 +1,96 @@ +local files = require("files") +local guide = require("parser.guide") +local converter = require("proto.converter") +local subString = require 'core.substring' + + + +---@class psi.view.node +---@field name string +---@field attr? psi.view.attr +---@field children? psi.view.node[] + +---@class psi.view.attr +---@field range psi.view.range + +---@class psi.view.range +---@field start integer +---@field end integer + +---@param astNode parser.object +---@param state parser.state +---@return psi.view.node | nil +local function toPsiNode(astNode, state) + if not astNode then + return + end + + local startOffset = guide.positionToOffset(state, astNode.start) + local finishOffset = guide.positionToOffset(state, astNode.finish) + local startPosition = converter.packPosition(state.uri, astNode.start) + local finishPosition = converter.packPosition(state.uri, astNode.finish) + return { + name = string.format("%s@[%d:%d .. %d:%d]", + astNode.type, + startPosition.line + 1, startPosition.character + 1, + finishPosition.line + 1, finishPosition.character + 1), + attr = { + range = { + start = startOffset, + ["end"] = finishOffset + } + } + } +end + +---@param astNode parser.object +---@return psi.view.node | nil +local function collectPsi(astNode, state) + local psiNode = toPsiNode(astNode, state) + + if not psiNode then + return + end + + guide.eachChild(astNode, function(child) + if psiNode.children == nil then + psiNode.children = {} + end + + local psi = collectPsi(child, state) + if psi then + psiNode.children[#psiNode.children+1] = psi + end + end) + + if psiNode.children and psiNode.attr then + local range = psiNode.attr.range + if range.start > psiNode.children[1].attr.range.start then + range.start = psiNode.children[1].attr.range.start + end + if range["end"] < psiNode.children[#psiNode.children].attr.range["end"] then + range["end"] = psiNode.children[#psiNode.children].attr.range["end"] + end + end + + if not psiNode.children then + local subber = subString(state) + local showText = subber(astNode.start + 1, astNode.finish) + if string.len(showText) > 30 then + showText = showText:sub(0, 30).. " ... " + end + + psiNode.name = psiNode.name .. " " .. showText + end + + return psiNode +end + +return function(uri) + local state = files.getState(uri) + if not state then + return + end + + return { data = collectPsi(state.ast, state) } +end diff --git a/script/provider/provider.lua b/script/provider/provider.lua index 823abae5..3ab5bb19 100644 --- a/script/provider/provider.lua +++ b/script/provider/provider.lua @@ -1400,6 +1400,37 @@ m.register '$/api/report' { end } +m.register '$/psi/view' { + ---@async + function (params) + local uri = files.getRealUri(params.uri) + workspace.awaitReady(uri) + local _ <close> = progress.create(uri, lang.script.WINDOW_PROCESSING_TYPE_FORMATTING, 0.5) + if not files.exists(uri) then + return nil + end + local core = require 'core.view.psi-view' + local result = core(uri) + return result + end +} + +m.register '$/psi/select' { + ---@async + function(params) + local uri = files.getRealUri(params.uri) + workspace.awaitReady(uri) + local _<close> = progress.create(uri, lang.script.WINDOW_PROCESSING_TYPE_FORMATTING, 0.5) + if not files.exists(uri) then + return nil + end + local core = require 'core.view.psi-select' + local result = core(uri, params.position) + return result + end +} + + local function refreshStatusBar() local valid = config.get(nil, 'Lua.window.statusBar') for _, scp in ipairs(workspace.folders) do |