Merge pull request #15434 from Dkendal/feature-lua-treesitter-sibling

feat(treesitter): add next, prev sibling method
This commit is contained in:
Thomas Vigouroux 2021-08-23 09:14:40 +02:00 committed by GitHub
commit 34b60ec894
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 122 additions and 0 deletions

View File

@ -86,6 +86,18 @@ Node methods *lua-treesitter-node*
tsnode:parent() *tsnode:parent()*
Get the node's immediate parent.
tsnode:next_sibling() *tsnode:next_sibling()*
Get the node's next sibling.
tsnode:prev_sibling() *tsnode:prev_sibling()*
Get the node's previous sibling.
tsnode:next_named_sibling() *tsnode:next_named_sibling()*
Get the node's next named sibling.
tsnode:prev_named_sibling() *tsnode:prev_named_sibling()*
Get the node's previous named sibling.
tsnode:iter_children() *tsnode:iter_children()*
Iterates over all the direct children of {tsnode}, regardless of
wether they are named or not.

View File

@ -80,6 +80,10 @@ static struct luaL_Reg node_meta[] = {
{ "parent", node_parent },
{ "iter_children", node_iter_children },
{ "_rawquery", node_rawquery },
{ "next_sibling", node_next_sibling },
{ "prev_sibling", node_prev_sibling },
{ "next_named_sibling", node_next_named_sibling },
{ "prev_named_sibling", node_prev_named_sibling },
{ NULL, NULL }
};
@ -990,6 +994,50 @@ static int node_parent(lua_State *L)
return 1;
}
static int node_next_sibling(lua_State *L)
{
TSNode node;
if (!node_check(L, 1, &node)) {
return 0;
}
TSNode sibling = ts_node_next_sibling(node);
push_node(L, sibling, 1);
return 1;
}
static int node_prev_sibling(lua_State *L)
{
TSNode node;
if (!node_check(L, 1, &node)) {
return 0;
}
TSNode sibling = ts_node_prev_sibling(node);
push_node(L, sibling, 1);
return 1;
}
static int node_next_named_sibling(lua_State *L)
{
TSNode node;
if (!node_check(L, 1, &node)) {
return 0;
}
TSNode sibling = ts_node_next_named_sibling(node);
push_node(L, sibling, 1);
return 1;
}
static int node_prev_named_sibling(lua_State *L)
{
TSNode node;
if (!node_check(L, 1, &node)) {
return 0;
}
TSNode sibling = ts_node_prev_named_sibling(node);
push_node(L, sibling, 1);
return 1;
}
/// assumes the match table being on top of the stack
static void set_match(lua_State *L, TSQueryMatch *match, int nodeidx)
{

View File

@ -0,0 +1,62 @@
local helpers = require('test.functional.helpers')(after_each)
local clear = helpers.clear
local eq = helpers.eq
local exec_lua = helpers.exec_lua
local insert = helpers.insert
local pending_c_parser = helpers.pending_c_parser
before_each(clear)
local function lua_eval(lua_expr)
return exec_lua("return " .. lua_expr)
end
describe('treesitter node API', function()
clear()
if pending_c_parser(pending) then
return
end
it('can move between siblings', function()
insert([[
int main(int x, int y, int z) {
return x + y * z
}
]])
exec_lua([[
query = require"vim.treesitter.query"
parser = vim.treesitter.get_parser(0, "c")
tree = parser:parse()[1]
root = tree:root()
lang = vim.treesitter.inspect_language('c')
function node_text(node)
return query.get_node_text(node, 0)
end
]])
exec_lua 'node = root:descendant_for_range(0, 11, 0, 16)'
eq('int x', lua_eval('node_text(node)'))
exec_lua 'node = node:next_sibling()'
eq(',', lua_eval('node_text(node)'))
exec_lua 'node = node:next_sibling()'
eq('int y', lua_eval('node_text(node)'))
exec_lua 'node = node:prev_sibling()'
eq(',', lua_eval('node_text(node)'))
exec_lua 'node = node:prev_sibling()'
eq('int x', lua_eval('node_text(node)'))
exec_lua 'node = node:next_named_sibling()'
eq('int y', lua_eval('node_text(node)'))
exec_lua 'node = node:prev_named_sibling()'
eq('int x', lua_eval('node_text(node)'))
end)
end)