98 lines
2.7 KiB
Lua
98 lines
2.7 KiB
Lua
---@module 'tsql.token_select'
|
|
---@class mod_token_select
|
|
local M = {}
|
|
|
|
---@class mod_ts_query
|
|
M.ts_query = {}
|
|
---@class TSQuery
|
|
---@field query string the passthru for treesitter language parser
|
|
M.TSQuery = {}
|
|
M.TSQuery.__index = M.TSQuery
|
|
|
|
---@type Ctor<{query: string}, TSQuery>
|
|
function M.TSQuery.new(q)
|
|
local self = q
|
|
setmetatable(self, M.TSQuery)
|
|
self.__index = M.TSQuery
|
|
return self
|
|
end
|
|
|
|
---@class FileLoc
|
|
---@field row_0 number 0-index row location
|
|
---@field col_0 number 0-index col location
|
|
M.FileLoc = {}
|
|
M.FileLoc.__index = M.FileLoc
|
|
|
|
---@type Ctor<{row_0: number, col_0: number}, FileLoc>
|
|
function M.FileLoc.new(file_loc)
|
|
assert(file_loc ~= nil)
|
|
local self = file_loc
|
|
setmetatable(self, M.FileLoc)
|
|
self.__index = M.FileLoc
|
|
return self
|
|
end
|
|
|
|
---@class QNode
|
|
---@field start FileLoc
|
|
---@field end_ex_col FileLoc
|
|
---@field buf QBuf
|
|
M.QNode = {}
|
|
M.QNode.__index = M.QNode
|
|
|
|
---@type Ctor<{start: FileLoc, end_ex_col: FileLoc, buf: QBuf}, QNode>
|
|
function M.QNode.new(qnode)
|
|
assert(qnode ~= nil)
|
|
local self = qnode
|
|
setmetatable(self, M.QNode)
|
|
self.__index = M.QNode
|
|
return self
|
|
end
|
|
|
|
---@param treesitter_query string the passthru for treesitter language
|
|
---parser
|
|
---@return TSQuery
|
|
function M.ts_query.from_scm(treesitter_query)
|
|
return M.TSQuery.new {
|
|
query = treesitter_query
|
|
}
|
|
end
|
|
|
|
---@param files QBuf[]
|
|
---@return QNode[]
|
|
function M.TSQuery:find_nodes(files)
|
|
local result = {}
|
|
for _, file in ipairs(files) do
|
|
if file.lang == nil then
|
|
goto continue
|
|
end
|
|
local sts, parser = pcall(vim.treesitter.get_parser, file.bufnr, file.filetype)
|
|
if not sts then
|
|
-- NOTE: no parser for language
|
|
goto continue
|
|
end
|
|
local tree = parser:parse()[1]
|
|
local root = tree:root()
|
|
---@type Query
|
|
local sts, query = pcall(vim.treesitter.query.parse, file.lang, self.query)
|
|
if not sts then
|
|
error("Error parsing query \"" .. self.query .. "\" on lang " .. file.lang .. " for file " .. file.path)
|
|
end
|
|
|
|
for _, match, _ in query:iter_matches(root, file.bufnr, 0, -1) do
|
|
for id, node in pairs(match) do
|
|
local start_row, start_col, end_row, end_col = node:range(false)
|
|
local start = M.FileLoc.new { row_0 = start_row, col_0 = start_col }
|
|
-- CORRECTNESS, see repl.md
|
|
local end_ex_col = M.FileLoc.new { row_0 = end_row, col_0 = end_col }
|
|
local qnode = M.QNode.new { buf = file, start = start, end_ex_col = end_ex_col }
|
|
|
|
table.insert(result, qnode)
|
|
end
|
|
end
|
|
::continue::
|
|
end
|
|
return result
|
|
end
|
|
|
|
return M
|