diff options
Diffstat (limited to 'script/core')
-rw-r--r-- | script/core/view/psi-select.lua | 13 | ||||
-rw-r--r-- | script/core/view/psi-view.lua | 84 |
2 files changed, 97 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..b6cdae8c --- /dev/null +++ b/script/core/view/psi-view.lua @@ -0,0 +1,84 @@ +local files = require("files") +local guide = require("parser.guide") + + +---@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 +---@return psi.view.node | nil +local function toPsiNode(astNode, state) + if not astNode then + return + end + if astNode.type == "doc" then + return + end + + local startOffset = guide.positionToOffset(state, astNode.start) + local finishOffset = guide.positionToOffset(state, astNode.finish) + return { + name = string.format("%s@%d..%d", astNode.type, startOffset, finishOffset), + 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 + -- psiNode.name = psiNode.name + -- 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 |