mirror of
https://github.com/neovim/neovim.git
synced 2024-12-23 20:55:18 -07:00
fix(treesitter): logger memory leak
This commit is contained in:
parent
e3ce025e55
commit
8179d68dc1
@ -156,6 +156,7 @@ function LanguageTree:_set_logger()
|
|||||||
|
|
||||||
local lang = self:lang()
|
local lang = self:lang()
|
||||||
|
|
||||||
|
vim.fn.mkdir(vim.fn.stdpath('log'), 'p')
|
||||||
local logfilename = vim.fs.joinpath(vim.fn.stdpath('log'), 'treesitter.log')
|
local logfilename = vim.fs.joinpath(vim.fn.stdpath('log'), 'treesitter.log')
|
||||||
|
|
||||||
local logfile, openerr = io.open(logfilename, 'a+')
|
local logfile, openerr = io.open(logfilename, 'a+')
|
||||||
@ -208,7 +209,8 @@ function LanguageTree:_log(...)
|
|||||||
|
|
||||||
local info = debug.getinfo(2, 'nl')
|
local info = debug.getinfo(2, 'nl')
|
||||||
local nregions = #self:included_regions()
|
local nregions = #self:included_regions()
|
||||||
local prefix = string.format('%s:%d: (#regions=%d) ', info.name, info.currentline, nregions)
|
local prefix =
|
||||||
|
string.format('%s:%d: (#regions=%d) ', info.name or '???', info.currentline or 0, nregions)
|
||||||
|
|
||||||
local msg = { prefix }
|
local msg = { prefix }
|
||||||
for _, x in ipairs(args) do
|
for _, x in ipairs(args) do
|
||||||
|
@ -1302,6 +1302,9 @@ LuaRef nlua_ref(lua_State *lstate, nlua_ref_state_t *ref_state, int index)
|
|||||||
return ref;
|
return ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(lewis6991): Currently cannot be run in __gc metamethods as they are
|
||||||
|
// invoked in lua_close() which can be invoked after the ref_markers map is
|
||||||
|
// destroyed in nlua_common_free_all_mem.
|
||||||
LuaRef nlua_ref_global(lua_State *lstate, int index)
|
LuaRef nlua_ref_global(lua_State *lstate, int index)
|
||||||
{
|
{
|
||||||
return nlua_ref(lstate, nlua_global_refs, index);
|
return nlua_ref(lstate, nlua_global_refs, index);
|
||||||
|
@ -325,6 +325,17 @@ static TSParser **parser_check(lua_State *L, uint16_t index)
|
|||||||
return luaL_checkudata(L, index, TS_META_PARSER);
|
return luaL_checkudata(L, index, TS_META_PARSER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void logger_gc(TSLogger logger)
|
||||||
|
{
|
||||||
|
if (!logger.log) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TSLuaLoggerOpts *opts = (TSLuaLoggerOpts *)logger.payload;
|
||||||
|
luaL_unref(opts->lstate, LUA_REGISTRYINDEX, opts->cb);
|
||||||
|
xfree(opts);
|
||||||
|
}
|
||||||
|
|
||||||
static int parser_gc(lua_State *L)
|
static int parser_gc(lua_State *L)
|
||||||
{
|
{
|
||||||
TSParser **p = parser_check(L, 1);
|
TSParser **p = parser_check(L, 1);
|
||||||
@ -332,12 +343,7 @@ static int parser_gc(lua_State *L)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
TSLogger logger = ts_parser_logger(*p);
|
logger_gc(ts_parser_logger(*p));
|
||||||
if (logger.log) {
|
|
||||||
TSLuaLoggerOpts *opts = (TSLuaLoggerOpts *)logger.payload;
|
|
||||||
xfree(opts);
|
|
||||||
}
|
|
||||||
|
|
||||||
ts_parser_delete(*p);
|
ts_parser_delete(*p);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -698,7 +704,7 @@ static void logger_cb(void *payload, TSLogType logtype, const char *s)
|
|||||||
|
|
||||||
lua_State *lstate = opts->lstate;
|
lua_State *lstate = opts->lstate;
|
||||||
|
|
||||||
nlua_pushref(lstate, opts->cb);
|
lua_rawgeti(lstate, LUA_REGISTRYINDEX, opts->cb);
|
||||||
lua_pushstring(lstate, logtype == TSLogTypeParse ? "parse" : "lex");
|
lua_pushstring(lstate, logtype == TSLogTypeParse ? "parse" : "lex");
|
||||||
lua_pushstring(lstate, s);
|
lua_pushstring(lstate, s);
|
||||||
if (lua_pcall(lstate, 2, 0, 0)) {
|
if (lua_pcall(lstate, 2, 0, 0)) {
|
||||||
@ -726,11 +732,13 @@ static int parser_set_logger(lua_State *L)
|
|||||||
}
|
}
|
||||||
|
|
||||||
TSLuaLoggerOpts *opts = xmalloc(sizeof(TSLuaLoggerOpts));
|
TSLuaLoggerOpts *opts = xmalloc(sizeof(TSLuaLoggerOpts));
|
||||||
|
lua_pushvalue(L, 4);
|
||||||
|
LuaRef ref = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||||
|
|
||||||
*opts = (TSLuaLoggerOpts){
|
*opts = (TSLuaLoggerOpts){
|
||||||
.lex = lua_toboolean(L, 2),
|
.lex = lua_toboolean(L, 2),
|
||||||
.parse = lua_toboolean(L, 3),
|
.parse = lua_toboolean(L, 3),
|
||||||
.cb = nlua_ref_global(L, 4),
|
.cb = ref,
|
||||||
.lstate = L
|
.lstate = L
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -753,7 +761,7 @@ static int parser_get_logger(lua_State *L)
|
|||||||
TSLogger logger = ts_parser_logger(*p);
|
TSLogger logger = ts_parser_logger(*p);
|
||||||
if (logger.log) {
|
if (logger.log) {
|
||||||
TSLuaLoggerOpts *opts = (TSLuaLoggerOpts *)logger.payload;
|
TSLuaLoggerOpts *opts = (TSLuaLoggerOpts *)logger.payload;
|
||||||
nlua_pushref(L, opts->cb);
|
lua_rawgeti(L, LUA_REGISTRYINDEX, opts->cb);
|
||||||
} else {
|
} else {
|
||||||
lua_pushnil(L);
|
lua_pushnil(L);
|
||||||
}
|
}
|
||||||
|
@ -9,10 +9,13 @@ local pcall_err = helpers.pcall_err
|
|||||||
local feed = helpers.feed
|
local feed = helpers.feed
|
||||||
local is_os = helpers.is_os
|
local is_os = helpers.is_os
|
||||||
|
|
||||||
before_each(clear)
|
|
||||||
|
|
||||||
describe('treesitter parser API', function()
|
describe('treesitter parser API', function()
|
||||||
clear()
|
before_each(function()
|
||||||
|
clear()
|
||||||
|
exec_lua[[
|
||||||
|
vim.g.__ts_debug = 1
|
||||||
|
]]
|
||||||
|
end)
|
||||||
|
|
||||||
it('parses buffer', function()
|
it('parses buffer', function()
|
||||||
insert([[
|
insert([[
|
||||||
@ -629,7 +632,6 @@ int x = INT_MAX;
|
|||||||
describe("when parsing regions independently", function()
|
describe("when parsing regions independently", function()
|
||||||
it("should inject a language", function()
|
it("should inject a language", function()
|
||||||
exec_lua([[
|
exec_lua([[
|
||||||
vim.g.__ts_debug = 1
|
|
||||||
parser = vim.treesitter.get_parser(0, "c", {
|
parser = vim.treesitter.get_parser(0, "c", {
|
||||||
injections = {
|
injections = {
|
||||||
c = "(preproc_def (preproc_arg) @c) (preproc_function_def value: (preproc_arg) @c)"}})
|
c = "(preproc_def (preproc_arg) @c) (preproc_function_def value: (preproc_arg) @c)"}})
|
||||||
|
Loading…
Reference in New Issue
Block a user