mirror of
https://github.com/nvim-treesitter/nvim-treesitter.git
synced 2026-07-17 02:40:09 -04:00
Add predicates module
This commit is contained in:
parent
6f01384cb2
commit
5462fc92cb
2 changed files with 70 additions and 1 deletions
|
|
@ -2,6 +2,7 @@ local api = vim.api
|
||||||
local ts = vim.treesitter
|
local ts = vim.treesitter
|
||||||
local utils = require'nvim-treesitter.utils'
|
local utils = require'nvim-treesitter.utils'
|
||||||
local parsers = require'nvim-treesitter.parsers'
|
local parsers = require'nvim-treesitter.parsers'
|
||||||
|
local predicates = require'nvim-treesitter.query_predicates'
|
||||||
|
|
||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
|
|
@ -129,7 +130,7 @@ function M.iter_prepared_matches(query, qnode, bufnr, start_row, end_row)
|
||||||
|
|
||||||
local matches = query:iter_matches(qnode, bufnr, start_row, end_row)
|
local matches = query:iter_matches(qnode, bufnr, start_row, end_row)
|
||||||
|
|
||||||
return function()
|
local function iterator()
|
||||||
local pattern, match = matches()
|
local pattern, match = matches()
|
||||||
if pattern ~= nil then
|
if pattern ~= nil then
|
||||||
local prepared_match = {}
|
local prepared_match = {}
|
||||||
|
|
@ -147,15 +148,25 @@ function M.iter_prepared_matches(query, qnode, bufnr, start_row, end_row)
|
||||||
local preds = query.info.patterns[pattern]
|
local preds = query.info.patterns[pattern]
|
||||||
if preds then
|
if preds then
|
||||||
for _, pred in pairs(preds) do
|
for _, pred in pairs(preds) do
|
||||||
|
-- functions
|
||||||
if pred[1] == "set!" and type(pred[2]) == "string" then
|
if pred[1] == "set!" and type(pred[2]) == "string" then
|
||||||
insert_to_path(prepared_match, split(pred[2]), pred[3])
|
insert_to_path(prepared_match, split(pred[2]), pred[3])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- predicates
|
||||||
|
if type(pred[1]) == 'string' then
|
||||||
|
if not predicates.check_predicate(query, prepared_match, pred) or
|
||||||
|
not predicates.check_negated_predicate(query, prepared_match, pred) then
|
||||||
|
return iterator()
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return prepared_match
|
return prepared_match
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
return iterator
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Return all nodes corresponding to a specific capture path (like @definition.var, @reference.type)
|
--- Return all nodes corresponding to a specific capture path (like @definition.var, @reference.type)
|
||||||
|
|
|
||||||
58
lua/nvim-treesitter/query_predicates.lua
Normal file
58
lua/nvim-treesitter/query_predicates.lua
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
local utils = require'nvim-treesitter.utils'
|
||||||
|
|
||||||
|
local M = {}
|
||||||
|
|
||||||
|
local function get_nth_child(node, n)
|
||||||
|
if node:named_child_count() > n then
|
||||||
|
return node:named_child(n)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function get_node(query, match, pred_item)
|
||||||
|
return utils.get_at_path(match, query.captures[pred_item]..'.node')
|
||||||
|
end
|
||||||
|
|
||||||
|
function M.check_predicate(query, match, pred)
|
||||||
|
local check_function = M[string.gsub('check_'..pred[1], "%?$", '')]
|
||||||
|
if check_function then
|
||||||
|
return check_function(query, match, pred)
|
||||||
|
else
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function M.check_negated_predicate(query, match, pred)
|
||||||
|
local check_function = M[string.gsub('check_'..string.sub(pred[1], #"not-" + 1), "%?$", '')]
|
||||||
|
if check_function then
|
||||||
|
return not check_function(query, match, pred)
|
||||||
|
else
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function M.check_first(query, match, pred)
|
||||||
|
if #pred ~= 2 then error("first? must have exactly one argument!") end
|
||||||
|
local node = get_node(query, match, pred[2])
|
||||||
|
if node and node:parent() then
|
||||||
|
return get_nth_child(node:parent(), 0) == node
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function M.check_last(query, match, pred)
|
||||||
|
if #pred ~= 2 then error("first? must have exactly one argument!") end
|
||||||
|
local node = get_node(query, match, pred[2])
|
||||||
|
if node and node:parent() then
|
||||||
|
local num_children = node:parent():named_child_count()
|
||||||
|
return get_nth_child(node:parent(), num_children - 1) == node
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function M.check_nth(query, match, pred)
|
||||||
|
if #pred ~= 3 then error("nth? must have exactly two arguments!") end
|
||||||
|
local node = get_node(query, match, pred[2])
|
||||||
|
if node and node:parent() then
|
||||||
|
return get_nth_child(node:parent(), pred[3] - 1) == node
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return M
|
||||||
Loading…
Add table
Add a link
Reference in a new issue