diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/lua/treesitter.c | 127 |
1 files changed, 61 insertions, 66 deletions
diff --git a/src/nvim/lua/treesitter.c b/src/nvim/lua/treesitter.c index c53e208b00..0515bbfe53 100644 --- a/src/nvim/lua/treesitter.c +++ b/src/nvim/lua/treesitter.c @@ -23,11 +23,6 @@ #include "nvim/buffer.h" typedef struct { - TSParser *parser; - TSTree *tree; // internal tree, used for editing/reparsing -} TSLua_parser; - -typedef struct { TSQueryCursor *cursor; int predicated_match; } TSLua_cursor; @@ -40,8 +35,6 @@ static struct luaL_Reg parser_meta[] = { { "__gc", parser_gc }, { "__tostring", parser_tostring }, { "parse", parser_parse }, - { "edit", parser_edit }, - { "tree", parser_tree }, { "set_included_ranges", parser_set_ranges }, { "included_ranges", parser_get_ranges }, { NULL, NULL } @@ -51,6 +44,8 @@ static struct luaL_Reg tree_meta[] = { { "__gc", tree_gc }, { "__tostring", tree_tostring }, { "root", tree_root }, + { "edit", tree_edit }, + { "copy", tree_copy }, { NULL, NULL } }; @@ -247,39 +242,32 @@ int tslua_push_parser(lua_State *L) return luaL_error(L, "no such language: %s", lang_name); } - TSParser *parser = ts_parser_new(); + TSParser **parser = lua_newuserdata(L, sizeof(TSParser *)); + *parser = ts_parser_new(); - if (!ts_parser_set_language(parser, lang)) { - ts_parser_delete(parser); + if (!ts_parser_set_language(*parser, lang)) { + ts_parser_delete(*parser); return luaL_error(L, "Failed to load language : %s", lang_name); } - TSLua_parser *p = lua_newuserdata(L, sizeof(TSLua_parser)); // [udata] - p->parser = parser; - p->tree = NULL; - lua_getfield(L, LUA_REGISTRYINDEX, "treesitter_parser"); // [udata, meta] lua_setmetatable(L, -2); // [udata] return 1; } -static TSLua_parser *parser_check(lua_State *L) +static TSParser ** parser_check(lua_State *L, uint16_t index) { - return luaL_checkudata(L, 1, "treesitter_parser"); + return luaL_checkudata(L, index, "treesitter_parser"); } static int parser_gc(lua_State *L) { - TSLua_parser *p = parser_check(L); + TSParser **p = parser_check(L, 1); if (!p) { return 0; } - ts_parser_delete(p->parser); - if (p->tree) { - ts_tree_delete(p->tree); - } - + ts_parser_delete(*p); return 0; } @@ -344,11 +332,17 @@ static void push_ranges(lua_State *L, static int parser_parse(lua_State *L) { - TSLua_parser *p = parser_check(L); - if (!p) { + TSParser **p = parser_check(L, 1); + if (!p || !(*p)) { return 0; } + TSTree *old_tree = NULL; + if (!lua_isnil(L, 2)) { + TSTree **tmp = tree_check(L, 2); + old_tree = tmp ? *tmp : NULL; + } + TSTree *new_tree = NULL; size_t len; const char *str; @@ -358,14 +352,14 @@ static int parser_parse(lua_State *L) // This switch is necessary because of the behavior of lua_isstring, that // consider numbers as strings... - switch (lua_type(L, 2)) { + switch (lua_type(L, 3)) { case LUA_TSTRING: - str = lua_tolstring(L, 2, &len); - new_tree = ts_parser_parse_string(p->parser, p->tree, str, len); + str = lua_tolstring(L, 3, &len); + new_tree = ts_parser_parse_string(*p, old_tree, str, len); break; case LUA_TNUMBER: - bufnr = lua_tointeger(L, 2); + bufnr = lua_tointeger(L, 3); buf = handle_get_buffer(bufnr); if (!buf) { @@ -373,7 +367,7 @@ static int parser_parse(lua_State *L) } input = (TSInput){ (void *)buf, input_cb, TSInputEncodingUTF8 }; - new_tree = ts_parser_parse(p->parser, p->tree, input); + new_tree = ts_parser_parse(*p, old_tree, input); break; @@ -387,46 +381,42 @@ static int parser_parse(lua_State *L) return luaL_error(L, "An error occured when parsing."); } + // The new tree will be pushed to the stack, without copy, owwership is now to + // the lua GC. + // Old tree is still owned by the lua GC. uint32_t n_ranges = 0; - TSRange *changed = p->tree ? ts_tree_get_changed_ranges(p->tree, new_tree, - &n_ranges) : NULL; - if (p->tree) { - ts_tree_delete(p->tree); - } - p->tree = new_tree; + TSRange *changed = old_tree ? ts_tree_get_changed_ranges( + old_tree, new_tree, &n_ranges) : NULL; - tslua_push_tree(L, p->tree); + tslua_push_tree(L, new_tree, false); // [tree] - push_ranges(L, changed, n_ranges); + push_ranges(L, changed, n_ranges); // [tree, ranges] xfree(changed); return 2; } -static int parser_tree(lua_State *L) +static int tree_copy(lua_State *L) { - TSLua_parser *p = parser_check(L); - if (!p) { + TSTree **tree = tree_check(L, 1); + if (!(*tree)) { return 0; } - tslua_push_tree(L, p->tree); + tslua_push_tree(L, *tree, true); // [tree] + return 1; } -static int parser_edit(lua_State *L) +static int tree_edit(lua_State *L) { if (lua_gettop(L) < 10) { - lua_pushstring(L, "not enough args to parser:edit()"); + lua_pushstring(L, "not enough args to tree:edit()"); return lua_error(L); } - TSLua_parser *p = parser_check(L); - if (!p) { - return 0; - } - - if (!p->tree) { + TSTree **tree = tree_check(L, 1); + if (!(*tree)) { return 0; } @@ -440,7 +430,7 @@ static int parser_edit(lua_State *L) TSInputEdit edit = { start_byte, old_end_byte, new_end_byte, start_point, old_end_point, new_end_point }; - ts_tree_edit(p->tree, &edit); + ts_tree_edit(*tree, &edit); return 0; } @@ -453,8 +443,8 @@ static int parser_set_ranges(lua_State *L) "not enough args to parser:set_included_ranges()"); } - TSLua_parser *p = parser_check(L); - if (!p || !p->tree) { + TSParser **p = parser_check(L, 1); + if (!p) { return 0; } @@ -490,7 +480,7 @@ static int parser_set_ranges(lua_State *L) } // This memcpies ranges, thus we can free it afterwards - ts_parser_set_included_ranges(p->parser, ranges, tbl_len); + ts_parser_set_included_ranges(*p, ranges, tbl_len); xfree(ranges); return 0; @@ -498,16 +488,15 @@ static int parser_set_ranges(lua_State *L) static int parser_get_ranges(lua_State *L) { - TSLua_parser *p = parser_check(L); - if (!p || !p->parser) { + TSParser **p = parser_check(L, 1); + if (!p) { return 0; } unsigned int len; - const TSRange *ranges = ts_parser_included_ranges(p->parser, &len); + const TSRange *ranges = ts_parser_included_ranges(*p, &len); push_ranges(L, ranges, len); - return 1; } @@ -517,14 +506,20 @@ static int parser_get_ranges(lua_State *L) /// push tree interface on lua stack. /// /// This makes a copy of the tree, so ownership of the argument is unaffected. -void tslua_push_tree(lua_State *L, TSTree *tree) +void tslua_push_tree(lua_State *L, TSTree *tree, bool do_copy) { if (tree == NULL) { lua_pushnil(L); return; } TSTree **ud = lua_newuserdata(L, sizeof(TSTree *)); // [udata] - *ud = ts_tree_copy(tree); + + if (do_copy) { + *ud = ts_tree_copy(tree); + } else { + *ud = tree; + } + lua_getfield(L, LUA_REGISTRYINDEX, "treesitter_tree"); // [udata, meta] lua_setmetatable(L, -2); // [udata] @@ -537,20 +532,20 @@ void tslua_push_tree(lua_State *L, TSTree *tree) lua_setfenv(L, -2); // [udata] } -static TSTree *tree_check(lua_State *L) +static TSTree **tree_check(lua_State *L, uint16_t index) { - TSTree **ud = luaL_checkudata(L, 1, "treesitter_tree"); - return *ud; + TSTree **ud = luaL_checkudata(L, index, "treesitter_tree"); + return ud; } static int tree_gc(lua_State *L) { - TSTree *tree = tree_check(L); + TSTree **tree = tree_check(L, 1); if (!tree) { return 0; } - ts_tree_delete(tree); + ts_tree_delete(*tree); return 0; } @@ -562,11 +557,11 @@ static int tree_tostring(lua_State *L) static int tree_root(lua_State *L) { - TSTree *tree = tree_check(L); + TSTree **tree = tree_check(L, 1); if (!tree) { return 0; } - TSNode root = ts_tree_root_node(tree); + TSNode root = ts_tree_root_node(*tree); push_node(L, root, 1); return 1; } |