From 36d71e775a44526abd70b2720a589a1113c650d7 Mon Sep 17 00:00:00 2001 From: Thomas Vigouroux Date: Sun, 7 Jun 2020 14:19:38 +0200 Subject: [PATCH 1/9] treesitter: simplify puhstree call process --- src/nvim/lua/executor.c | 12 +----------- src/nvim/lua/treesitter.c | 8 +++++++- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 327ed6d6b7..4b47b34d8a 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -1128,21 +1128,11 @@ void ex_luafile(exarg_T *const eap) } } -static int create_tslua_parser(lua_State *L) -{ - if (lua_gettop(L) < 1 || !lua_isstring(L, 1)) { - return luaL_error(L, "string expected"); - } - - const char *lang_name = lua_tostring(L, 1); - return tslua_push_parser(L, lang_name); -} - static void nlua_add_treesitter(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL { tslua_init(lstate); - lua_pushcfunction(lstate, create_tslua_parser); + lua_pushcfunction(lstate, tslua_push_parser); lua_setfield(lstate, -2, "_create_ts_parser"); lua_pushcfunction(lstate, tslua_add_language); diff --git a/src/nvim/lua/treesitter.c b/src/nvim/lua/treesitter.c index 51d9549033..3447af9114 100644 --- a/src/nvim/lua/treesitter.c +++ b/src/nvim/lua/treesitter.c @@ -214,8 +214,14 @@ int tslua_inspect_lang(lua_State *L) return 1; } -int tslua_push_parser(lua_State *L, const char *lang_name) +int tslua_push_parser(lua_State *L) { + + // Gather language + if (lua_gettop(L) < 1 || !lua_isstring(L, 1)) { + return luaL_error(L, "string expected"); + } + const char *lang_name = lua_tostring(L, 1); TSLanguage *lang = pmap_get(cstr_t)(langs, lang_name); if (!lang) { return luaL_error(L, "no such language: %s", lang_name); From 333f3f19db612acc893791f04624da174efe04b5 Mon Sep 17 00:00:00 2001 From: Thomas Vigouroux Date: Sun, 7 Jun 2020 16:37:11 +0200 Subject: [PATCH 2/9] treesitter: add set_included_ranges to the parser This is the first step towards language injection using treesitter. --- runtime/lua/vim/treesitter.lua | 6 +++ src/nvim/lua/treesitter.c | 88 ++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+) diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index c502e45bd0..d5bc8e0a1b 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -30,6 +30,12 @@ function Parser:_on_lines(bufnr, _, start_row, old_stop_row, stop_row, old_byte_ self.valid = false end +function Parser:set_included_ranges(ranges) + self._parser:set_included_ranges(self.bufnr, ranges) + -- The buffer will need to be parsed again later + self.valid = false +end + local M = { parse_query = vim._ts_parse_query, } diff --git a/src/nvim/lua/treesitter.c b/src/nvim/lua/treesitter.c index 3447af9114..9e3bbb38fc 100644 --- a/src/nvim/lua/treesitter.c +++ b/src/nvim/lua/treesitter.c @@ -20,6 +20,7 @@ #include "nvim/lua/treesitter.h" #include "nvim/api/private/handle.h" #include "nvim/memline.h" +#include "nvim/buffer.h" typedef struct { TSParser *parser; @@ -41,6 +42,7 @@ static struct luaL_Reg parser_meta[] = { { "parse_buf", parser_parse_buf }, { "edit", parser_edit }, { "tree", parser_tree }, + { "set_included_ranges", parser_set_ranges }, { NULL, NULL } }; @@ -383,6 +385,92 @@ static int parser_edit(lua_State *L) return 0; } +static int parser_set_ranges(lua_State *L) { + if (lua_gettop(L) < 3) { + lua_pushstring(L, "not enough args to parser:set_ranges()"); + return lua_error(L); + } + + TSLua_parser *p = parser_check(L); + if (!p || !p->tree) { + return 0; + } + + int bufnr = lua_tointeger(L, 2); + + if (! lua_istable(L, 3)) { + lua_pushstring(L, "argument for parser:set_ranges() should be a table."); + return lua_error(L); + } + + size_t tbl_len = lua_objlen(L, 3); + TSRange *ranges = xmalloc(sizeof(TSRange) * tbl_len); + + + // [ parser, ranges ] + for (size_t index = 0; index < tbl_len; index++) { + lua_rawgeti(L, 3, index + 1); // [ parser, ranges, range ] + + if (!lua_istable(L, -1)) { + xfree(ranges); + lua_pushstring(L, "argument for parser:set_ranges() should be a table of tables."); + return lua_error(L); + } + + if (lua_objlen(L, -1) < 4 ) { + xfree(ranges); + lua_pushstring(L, "argument for parser:set_ranges() should be a table of ranges of 4 elements."); + return lua_error(L); + } + + lua_rawgeti(L, -1, 1); // [ parser, ranges, range, num ] + unsigned int start_row = lua_tointeger(L, -1); + lua_pop(L, 1); // [ parser, ranges, range ] + + + lua_rawgeti(L, -1, 2); // [ parser, ranges, range, num ] + unsigned int start_col = lua_tointeger(L, -1); + lua_pop(L, 1); // [ parser, ranges, range ] + + lua_rawgeti(L, -1, 3); // [ parser, ranges, range, num ] + unsigned int stop_row = lua_tointeger(L, -1); + lua_pop(L, 1); // [ parser, ranges, range ] + + lua_rawgeti(L, -1, 4); // [ parser, ranges, range, num ] + unsigned int stop_col = lua_tointeger(L, -1); + lua_pop(L, 1); // [ parser, ranges, range ] + + buf_T * buf = buflist_findnr(bufnr); + + if (!buf) { + buf = curbuf; + } + + // TODO: For sure that's wrong, try to find a way to get the byte offset directly + uint32_t start_byte = ml_find_line_or_offset(buf, start_row, NULL, false) + start_col; + uint32_t stop_byte = ml_find_line_or_offset(buf, stop_row, NULL, false) + stop_col; + + ranges[index] = (TSRange) { + .start_point = (TSPoint) { + .row = start_row, + .column = start_col + }, + .end_point = (TSPoint) { + .row = stop_row, + .column = stop_col + }, + .start_byte = start_byte, + .end_byte = stop_byte + }; + } + + // This memcpies ranges, thus we can free it. + ts_parser_set_included_ranges(p->parser, ranges, tbl_len); + xfree(ranges); + + return 0; +} + // Tree methods From ac18403d6e58a08956f9465998f2223df4e19108 Mon Sep 17 00:00:00 2001 From: Thomas Vigouroux Date: Sun, 14 Jun 2020 18:50:22 +0200 Subject: [PATCH 3/9] treesitter: test newly added set_included_ranges --- src/nvim/lua/treesitter.c | 5 ++-- test/functional/lua/treesitter_spec.lua | 40 +++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/nvim/lua/treesitter.c b/src/nvim/lua/treesitter.c index 9e3bbb38fc..6176a1b7c3 100644 --- a/src/nvim/lua/treesitter.c +++ b/src/nvim/lua/treesitter.c @@ -447,8 +447,9 @@ static int parser_set_ranges(lua_State *L) { } // TODO: For sure that's wrong, try to find a way to get the byte offset directly - uint32_t start_byte = ml_find_line_or_offset(buf, start_row, NULL, false) + start_col; - uint32_t stop_byte = ml_find_line_or_offset(buf, stop_row, NULL, false) + stop_col; + // Lines are 0 based for consistency + uint32_t start_byte = ml_find_line_or_offset(buf, start_row + 1, NULL, false) + start_col; + uint32_t stop_byte = ml_find_line_or_offset(buf, stop_row + 1, NULL, false) + stop_col; ranges[index] = (TSRange) { .start_point = (TSPoint) { diff --git a/test/functional/lua/treesitter_spec.lua b/test/functional/lua/treesitter_spec.lua index ecee471386..1fd93d5f56 100644 --- a/test/functional/lua/treesitter_spec.lua +++ b/test/functional/lua/treesitter_spec.lua @@ -404,4 +404,44 @@ static int nlua_schedule(lua_State *const lstate) end eq({true,true}, {has_named,has_anonymous}) end) + it('allows to set ranges', function() + if not check_parser() then return end + + insert(test_text) + + local res = exec_lua([[ + parser = vim.treesitter.get_parser(0, "c") + return { parser:parse():root():range() } + ]]) + + eq({0, 0, 19, 0}, res) + + local res = exec_lua([[ + parser:set_included_ranges({{0, 0, 1, 0}}) + parser.valid = false + return { parser:parse():root():range() } + ]]) + + eq({0, 0, 1, 0}, res) + + -- Pick random samples + local res = exec_lua([[ + parser:set_included_ranges({{8, 0, 9, 0}, {12, 0, 13 ,0}}) + local root = parser:parse():root() + return {{root:child(0):range()}, {root:child(1):range()}} + ]]) + + eq({{ + 8, + 2, + 8, + 33 + }, + { + 12, + 4, + 12, + 37 + }}, res) + end) end) From 75a1239eb51a805837111ac60e5dbddfadc8cb6f Mon Sep 17 00:00:00 2001 From: Thomas Vigouroux Date: Sun, 14 Jun 2020 19:03:36 +0200 Subject: [PATCH 4/9] treesitter: fix some clint errors Also fixes some mismatches on the name of the function --- src/nvim/lua/treesitter.c | 45 ++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/src/nvim/lua/treesitter.c b/src/nvim/lua/treesitter.c index 6176a1b7c3..6e554d9b54 100644 --- a/src/nvim/lua/treesitter.c +++ b/src/nvim/lua/treesitter.c @@ -218,7 +218,6 @@ int tslua_inspect_lang(lua_State *L) int tslua_push_parser(lua_State *L) { - // Gather language if (lua_gettop(L) < 1 || !lua_isstring(L, 1)) { return luaL_error(L, "string expected"); @@ -385,7 +384,8 @@ static int parser_edit(lua_State *L) return 0; } -static int parser_set_ranges(lua_State *L) { +static int parser_set_ranges(lua_State *L) +{ if (lua_gettop(L) < 3) { lua_pushstring(L, "not enough args to parser:set_ranges()"); return lua_error(L); @@ -398,8 +398,8 @@ static int parser_set_ranges(lua_State *L) { int bufnr = lua_tointeger(L, 2); - if (! lua_istable(L, 3)) { - lua_pushstring(L, "argument for parser:set_ranges() should be a table."); + if (!lua_istable(L, 3)) { + lua_pushstring(L, "argument for parser:set_included_ranges() should be a table."); return lua_error(L); } @@ -409,36 +409,40 @@ static int parser_set_ranges(lua_State *L) { // [ parser, ranges ] for (size_t index = 0; index < tbl_len; index++) { - lua_rawgeti(L, 3, index + 1); // [ parser, ranges, range ] + lua_rawgeti(L, 3, index + 1); // [ parser, ranges, range ] if (!lua_istable(L, -1)) { xfree(ranges); - lua_pushstring(L, "argument for parser:set_ranges() should be a table of tables."); + lua_pushstring( + L, + "argument for parser:set_included_ranges() should be a table of tables."); return lua_error(L); } - if (lua_objlen(L, -1) < 4 ) { + if (lua_objlen(L, -1) < 4) { xfree(ranges); - lua_pushstring(L, "argument for parser:set_ranges() should be a table of ranges of 4 elements."); + lua_pushstring( + L, + "argument for parser:set_included_ranges() should be a table of ranges of 4 elements."); return lua_error(L); } - lua_rawgeti(L, -1, 1); // [ parser, ranges, range, num ] + lua_rawgeti(L, -1, 1); // [ parser, ranges, range, num ] unsigned int start_row = lua_tointeger(L, -1); - lua_pop(L, 1); // [ parser, ranges, range ] + lua_pop(L, 1); // [ parser, ranges, range ] - lua_rawgeti(L, -1, 2); // [ parser, ranges, range, num ] + lua_rawgeti(L, -1, 2); // [ parser, ranges, range, num ] unsigned int start_col = lua_tointeger(L, -1); - lua_pop(L, 1); // [ parser, ranges, range ] + lua_pop(L, 1); // [ parser, ranges, range ] - lua_rawgeti(L, -1, 3); // [ parser, ranges, range, num ] + lua_rawgeti(L, -1, 3); // [ parser, ranges, range, num ] unsigned int stop_row = lua_tointeger(L, -1); - lua_pop(L, 1); // [ parser, ranges, range ] + lua_pop(L, 1); // [ parser, ranges, range ] - lua_rawgeti(L, -1, 4); // [ parser, ranges, range, num ] + lua_rawgeti(L, -1, 4); // [ parser, ranges, range, num ] unsigned int stop_col = lua_tointeger(L, -1); - lua_pop(L, 1); // [ parser, ranges, range ] + lua_pop(L, 1); // [ parser, ranges, range ] buf_T * buf = buflist_findnr(bufnr); @@ -446,10 +450,13 @@ static int parser_set_ranges(lua_State *L) { buf = curbuf; } - // TODO: For sure that's wrong, try to find a way to get the byte offset directly + // TODO(vigoux): For sure that's wrong, try to find a way to get the + // byte offset directly // Lines are 0 based for consistency - uint32_t start_byte = ml_find_line_or_offset(buf, start_row + 1, NULL, false) + start_col; - uint32_t stop_byte = ml_find_line_or_offset(buf, stop_row + 1, NULL, false) + stop_col; + uint32_t start_byte = + ml_find_line_or_offset(buf, start_row + 1, NULL, false) + start_col; + uint32_t stop_byte = + ml_find_line_or_offset(buf, stop_row + 1, NULL, false) + stop_col; ranges[index] = (TSRange) { .start_point = (TSPoint) { From 558893b1b979d2ec9006ee496c19648edbbf5b1c Mon Sep 17 00:00:00 2001 From: Thomas Vigouroux Date: Sun, 14 Jun 2020 19:14:52 +0200 Subject: [PATCH 5/9] treesitter: add some documentation for parsers --- runtime/doc/lua.txt | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt index 5a49d36503..00126f668b 100644 --- a/runtime/doc/lua.txt +++ b/runtime/doc/lua.txt @@ -512,6 +512,9 @@ retained for the lifetime of a buffer but this is subject to change. A plugin should keep a reference to the parser object as long as it wants incremental updates. +Parser methods *lua-treesitter-parser* + +tsparser:parse() *tsparser:parse()* Whenever you need to access the current syntax tree, parse the buffer: > tstree = parser:parse() @@ -528,6 +531,16 @@ shouldn't be done directly in the change callback anyway as they will be very frequent. Rather a plugin that does any kind of analysis on a tree should use a timer to throttle too frequent updates. +tsparser:set_included_ranges(ranges) *tsparser:set_included_ranges()* + Changes the ranges the parser should consider. This is used for + language injection. `ranges` should be of the form (all zero-based): > + { + {start_node, end_node}, + ... + } +< + NOTE: `start_node` and `end_node` are both inclusive. + Tree methods *lua-treesitter-tree* tstree:root() *tstree:root()* From b652f74ca3a6722ad0d185a0f4093907a6af65d7 Mon Sep 17 00:00:00 2001 From: Thomas Vigouroux Date: Tue, 16 Jun 2020 08:17:25 +0200 Subject: [PATCH 6/9] treesitter: use nodes to mark ranges --- runtime/lua/vim/treesitter.lua | 2 +- src/nvim/lua/treesitter.c | 121 +++++++++++------------- test/functional/lua/treesitter_spec.lua | 45 +++++---- 3 files changed, 83 insertions(+), 85 deletions(-) diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index d5bc8e0a1b..f356673839 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -31,7 +31,7 @@ function Parser:_on_lines(bufnr, _, start_row, old_stop_row, stop_row, old_byte_ end function Parser:set_included_ranges(ranges) - self._parser:set_included_ranges(self.bufnr, ranges) + self._parser:set_included_ranges(ranges) -- The buffer will need to be parsed again later self.valid = false end diff --git a/src/nvim/lua/treesitter.c b/src/nvim/lua/treesitter.c index 6e554d9b54..aa76ff33a4 100644 --- a/src/nvim/lua/treesitter.c +++ b/src/nvim/lua/treesitter.c @@ -386,8 +386,8 @@ static int parser_edit(lua_State *L) static int parser_set_ranges(lua_State *L) { - if (lua_gettop(L) < 3) { - lua_pushstring(L, "not enough args to parser:set_ranges()"); + if (lua_gettop(L) < 2) { + lua_pushstring(L, "not enough args to parser:set_included_ranges()"); return lua_error(L); } @@ -396,20 +396,18 @@ static int parser_set_ranges(lua_State *L) return 0; } - int bufnr = lua_tointeger(L, 2); - - if (!lua_istable(L, 3)) { + if (!lua_istable(L, 2)) { lua_pushstring(L, "argument for parser:set_included_ranges() should be a table."); return lua_error(L); } - size_t tbl_len = lua_objlen(L, 3); + size_t tbl_len = lua_objlen(L, 2); TSRange *ranges = xmalloc(sizeof(TSRange) * tbl_len); // [ parser, ranges ] for (size_t index = 0; index < tbl_len; index++) { - lua_rawgeti(L, 3, index + 1); // [ parser, ranges, range ] + lua_rawgeti(L, 2, index + 1); // [ parser, ranges, range ] if (!lua_istable(L, -1)) { xfree(ranges); @@ -419,60 +417,47 @@ static int parser_set_ranges(lua_State *L) return lua_error(L); } - if (lua_objlen(L, -1) < 4) { + if (lua_objlen(L, -1) != 2) { xfree(ranges); lua_pushstring( L, - "argument for parser:set_included_ranges() should be a table of ranges of 4 elements."); + "argument for parser:set_included_ranges() should be a table of ranges of 2 elements."); return lua_error(L); } - lua_rawgeti(L, -1, 1); // [ parser, ranges, range, num ] - unsigned int start_row = lua_tointeger(L, -1); - lua_pop(L, 1); // [ parser, ranges, range ] - - lua_rawgeti(L, -1, 2); // [ parser, ranges, range, num ] - unsigned int start_col = lua_tointeger(L, -1); - lua_pop(L, 1); // [ parser, ranges, range ] - - lua_rawgeti(L, -1, 3); // [ parser, ranges, range, num ] - unsigned int stop_row = lua_tointeger(L, -1); - lua_pop(L, 1); // [ parser, ranges, range ] - - lua_rawgeti(L, -1, 4); // [ parser, ranges, range, num ] - unsigned int stop_col = lua_tointeger(L, -1); - lua_pop(L, 1); // [ parser, ranges, range ] - - buf_T * buf = buflist_findnr(bufnr); - - if (!buf) { - buf = curbuf; + lua_rawgeti(L, -1, 1); // [ parser, ranges, range, start_node ] + TSNode start_node; + if (!node_check(L, -1, &start_node)) { + xfree(ranges); + lua_pushstring( + L, + "ranges should be tables of nodes."); + return lua_error(L); } + lua_pop(L, 1); // [ parser, ranges, range ] - // TODO(vigoux): For sure that's wrong, try to find a way to get the - // byte offset directly - // Lines are 0 based for consistency - uint32_t start_byte = - ml_find_line_or_offset(buf, start_row + 1, NULL, false) + start_col; - uint32_t stop_byte = - ml_find_line_or_offset(buf, stop_row + 1, NULL, false) + stop_col; + lua_rawgeti(L, -1, 1); // [ parser, ranges, range, stop_node ] + TSNode stop_node; + if (!node_check(L, -1, &stop_node)) { + xfree(ranges); + lua_pushstring( + L, + "ranges should be tables of nodes."); + return lua_error(L); + } + lua_pop(L, 1); // [ parser, ranges, range ] ranges[index] = (TSRange) { - .start_point = (TSPoint) { - .row = start_row, - .column = start_col - }, - .end_point = (TSPoint) { - .row = stop_row, - .column = stop_col - }, - .start_byte = start_byte, - .end_byte = stop_byte + .start_point = ts_node_start_point(start_node), + .end_point = ts_node_end_point(stop_node), + .start_byte = ts_node_start_byte(start_node), + .end_byte = ts_node_end_byte(stop_node) }; + lua_pop(L, 1); // [ parser, ranges ] } - // This memcpies ranges, thus we can free it. + // This memcpies ranges, thus we can free it afterwards ts_parser_set_included_ranges(p->parser, ranges, tbl_len); xfree(ranges); @@ -561,9 +546,9 @@ static void push_node(lua_State *L, TSNode node, int uindex) lua_setfenv(L, -2); // [udata] } -static bool node_check(lua_State *L, TSNode *res) +static bool node_check(lua_State *L, int index, TSNode *res) { - TSNode *ud = luaL_checkudata(L, 1, "treesitter_node"); + TSNode *ud = luaL_checkudata(L, index, "treesitter_node"); if (ud) { *res = *ud; return true; @@ -575,7 +560,7 @@ static bool node_check(lua_State *L, TSNode *res) static int node_tostring(lua_State *L) { TSNode node; - if (!node_check(L, &node)) { + if (!node_check(L,1, &node)) { return 0; } lua_pushstring(L, " Date: Tue, 23 Jun 2020 09:08:56 +0200 Subject: [PATCH 7/9] treesitter: fix lint --- src/nvim/lua/treesitter.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/nvim/lua/treesitter.c b/src/nvim/lua/treesitter.c index aa76ff33a4..913be5afe8 100644 --- a/src/nvim/lua/treesitter.c +++ b/src/nvim/lua/treesitter.c @@ -387,8 +387,9 @@ static int parser_edit(lua_State *L) static int parser_set_ranges(lua_State *L) { if (lua_gettop(L) < 2) { - lua_pushstring(L, "not enough args to parser:set_included_ranges()"); - return lua_error(L); + return luaL_error( + L, + "not enough args to parser:set_included_ranges()"); } TSLua_parser *p = parser_check(L); @@ -397,8 +398,9 @@ static int parser_set_ranges(lua_State *L) } if (!lua_istable(L, 2)) { - lua_pushstring(L, "argument for parser:set_included_ranges() should be a table."); - return lua_error(L); + return luaL_error( + L, + "argument for parser:set_included_ranges() should be a table."); } size_t tbl_len = lua_objlen(L, 2); @@ -411,18 +413,16 @@ static int parser_set_ranges(lua_State *L) if (!lua_istable(L, -1)) { xfree(ranges); - lua_pushstring( + return luaL_error( L, "argument for parser:set_included_ranges() should be a table of tables."); - return lua_error(L); } if (lua_objlen(L, -1) != 2) { xfree(ranges); - lua_pushstring( + return luaL_error( L, "argument for parser:set_included_ranges() should be a table of ranges of 2 elements."); - return lua_error(L); } @@ -560,7 +560,7 @@ static bool node_check(lua_State *L, int index, TSNode *res) static int node_tostring(lua_State *L) { TSNode node; - if (!node_check(L,1, &node)) { + if (!node_check(L, 1, &node)) { return 0; } lua_pushstring(L, " Date: Fri, 26 Jun 2020 20:11:16 +0200 Subject: [PATCH 8/9] treesitter: separate tests into smaller pieces --- test/functional/lua/treesitter_spec.lua | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/test/functional/lua/treesitter_spec.lua b/test/functional/lua/treesitter_spec.lua index 539c2b5e7c..16a7f365a8 100644 --- a/test/functional/lua/treesitter_spec.lua +++ b/test/functional/lua/treesitter_spec.lua @@ -404,7 +404,7 @@ static int nlua_schedule(lua_State *const lstate) end eq({true,true}, {has_named,has_anonymous}) end) - it('allows to set ranges', function() + it('allows to set simple ranges', function() if not check_parser() then return end insert(test_text) @@ -416,6 +416,8 @@ static int nlua_schedule(lua_State *const lstate) eq({0, 0, 19, 0}, res) + -- The following sets the included ranges for the current parser + -- As stated here, this only includes the function (thus the whole buffer, without the last line) local res = exec_lua([[ local root = parser:parse():root() parser:set_included_ranges({{root:child(0), root:child(0)}}) @@ -424,9 +426,15 @@ static int nlua_schedule(lua_State *const lstate) ]]) eq({0, 0, 18, 1}, res) + end) + it("allows to set complex ranges", function() + if not check_parser() then return end + + insert(test_text) + - -- Pick random samples local res = exec_lua([[ + parser = vim.treesitter.get_parser(0, "c") query = vim.treesitter.parse_query("c", "(declaration) @decl") local nodes = {} From 69816f5e134f0e965352367b5928835794da1698 Mon Sep 17 00:00:00 2001 From: Thomas Vigouroux Date: Mon, 29 Jun 2020 23:02:30 +0200 Subject: [PATCH 9/9] treesitter: use single nodes in set_ranges fixup! treesitter: fix lint --- src/nvim/lua/treesitter.c | 43 ++++--------------------- test/functional/lua/treesitter_spec.lua | 8 ++--- 2 files changed, 11 insertions(+), 40 deletions(-) diff --git a/src/nvim/lua/treesitter.c b/src/nvim/lua/treesitter.c index 913be5afe8..ddf54720a7 100644 --- a/src/nvim/lua/treesitter.c +++ b/src/nvim/lua/treesitter.c @@ -411,50 +411,21 @@ static int parser_set_ranges(lua_State *L) for (size_t index = 0; index < tbl_len; index++) { lua_rawgeti(L, 2, index + 1); // [ parser, ranges, range ] - if (!lua_istable(L, -1)) { + TSNode node; + if (!node_check(L, -1, &node)) { xfree(ranges); return luaL_error( - L, - "argument for parser:set_included_ranges() should be a table of tables."); - } - - if (lua_objlen(L, -1) != 2) { - xfree(ranges); - return luaL_error( - L, - "argument for parser:set_included_ranges() should be a table of ranges of 2 elements."); - } - - - lua_rawgeti(L, -1, 1); // [ parser, ranges, range, start_node ] - TSNode start_node; - if (!node_check(L, -1, &start_node)) { - xfree(ranges); - lua_pushstring( L, "ranges should be tables of nodes."); - return lua_error(L); } - lua_pop(L, 1); // [ parser, ranges, range ] - - lua_rawgeti(L, -1, 1); // [ parser, ranges, range, stop_node ] - TSNode stop_node; - if (!node_check(L, -1, &stop_node)) { - xfree(ranges); - lua_pushstring( - L, - "ranges should be tables of nodes."); - return lua_error(L); - } - lua_pop(L, 1); // [ parser, ranges, range ] + lua_pop(L, 1); // [ parser, ranges ] ranges[index] = (TSRange) { - .start_point = ts_node_start_point(start_node), - .end_point = ts_node_end_point(stop_node), - .start_byte = ts_node_start_byte(start_node), - .end_byte = ts_node_end_byte(stop_node) + .start_point = ts_node_start_point(node), + .end_point = ts_node_end_point(node), + .start_byte = ts_node_start_byte(node), + .end_byte = ts_node_end_byte(node) }; - lua_pop(L, 1); // [ parser, ranges ] } // This memcpies ranges, thus we can free it afterwards diff --git a/test/functional/lua/treesitter_spec.lua b/test/functional/lua/treesitter_spec.lua index 16a7f365a8..ab0224a911 100644 --- a/test/functional/lua/treesitter_spec.lua +++ b/test/functional/lua/treesitter_spec.lua @@ -418,14 +418,14 @@ static int nlua_schedule(lua_State *const lstate) -- The following sets the included ranges for the current parser -- As stated here, this only includes the function (thus the whole buffer, without the last line) - local res = exec_lua([[ + local res2 = exec_lua([[ local root = parser:parse():root() - parser:set_included_ranges({{root:child(0), root:child(0)}}) + parser:set_included_ranges({root:child(0)}) parser.valid = false return { parser:parse():root():range() } ]]) - eq({0, 0, 18, 1}, res) + eq({0, 0, 18, 1}, res2) end) it("allows to set complex ranges", function() if not check_parser() then return end @@ -439,7 +439,7 @@ static int nlua_schedule(lua_State *const lstate) local nodes = {} for _, node in query:iter_captures(parser:parse():root(), 0, 0, 19) do - table.insert(nodes, { node, node }) + table.insert(nodes, node) end parser:set_included_ranges(nodes)