diff --git a/src/nvim/lua/treesitter.c b/src/nvim/lua/treesitter.c index 7eee8b7022..b02aff64c4 100644 --- a/src/nvim/lua/treesitter.c +++ b/src/nvim/lua/treesitter.c @@ -476,20 +476,20 @@ static void push_ranges(lua_State *L, const TSRange *ranges, const size_t length for (size_t i = 0; i < length; i++) { lua_createtable(L, include_bytes ? 6 : 4, 0); int j = 1; - lua_pushinteger(L, ranges[i].start_point.row); + lua_pushnumber(L, (lua_Number)ranges[i].start_point.row); lua_rawseti(L, -2, j++); - lua_pushinteger(L, ranges[i].start_point.column); + lua_pushnumber(L, (lua_Number)ranges[i].start_point.column); lua_rawseti(L, -2, j++); if (include_bytes) { - lua_pushinteger(L, ranges[i].start_byte); + lua_pushnumber(L, (lua_Number)ranges[i].start_byte); lua_rawseti(L, -2, j++); } - lua_pushinteger(L, ranges[i].end_point.row); + lua_pushnumber(L, (lua_Number)ranges[i].end_point.row); lua_rawseti(L, -2, j++); - lua_pushinteger(L, ranges[i].end_point.column); + lua_pushnumber(L, (lua_Number)ranges[i].end_point.column); lua_rawseti(L, -2, j++); if (include_bytes) { - lua_pushinteger(L, ranges[i].end_byte); + lua_pushnumber(L, (lua_Number)ranges[i].end_byte); lua_rawseti(L, -2, j++); } @@ -596,6 +596,16 @@ static void range_err(lua_State *L) luaL_error(L, "Ranges can only be made from 6 element long tables or nodes."); } +static uint32_t lua_checkuint32(lua_State *L, int index) +{ + lua_Number value = luaL_checknumber(L, index); + uint32_t converted = (uint32_t)value; + if (value < 0 || value > (lua_Number)UINT32_MAX || (lua_Number)converted != value) { + luaL_error(L, "Range value out of bounds"); + } + return converted; +} + // Use the top of the stack (without popping it) to create a TSRange, it can be // either a lua table or a TSNode static void range_from_lua(lua_State *L, TSRange *range) @@ -609,27 +619,27 @@ static void range_from_lua(lua_State *L, TSRange *range) } lua_rawgeti(L, -1, 1); // [ range, start_row] - uint32_t start_row = (uint32_t)luaL_checkinteger(L, -1); + uint32_t start_row = lua_checkuint32(L, -1); lua_pop(L, 1); lua_rawgeti(L, -1, 2); // [ range, start_col] - uint32_t start_col = (uint32_t)luaL_checkinteger(L, -1); + uint32_t start_col = lua_checkuint32(L, -1); lua_pop(L, 1); lua_rawgeti(L, -1, 3); // [ range, start_byte] - uint32_t start_byte = (uint32_t)luaL_checkinteger(L, -1); + uint32_t start_byte = lua_checkuint32(L, -1); lua_pop(L, 1); lua_rawgeti(L, -1, 4); // [ range, end_row] - uint32_t end_row = (uint32_t)luaL_checkinteger(L, -1); + uint32_t end_row = lua_checkuint32(L, -1); lua_pop(L, 1); lua_rawgeti(L, -1, 5); // [ range, end_col] - uint32_t end_col = (uint32_t)luaL_checkinteger(L, -1); + uint32_t end_col = lua_checkuint32(L, -1); lua_pop(L, 1); lua_rawgeti(L, -1, 6); // [ range, end_byte] - uint32_t end_byte = (uint32_t)luaL_checkinteger(L, -1); + uint32_t end_byte = lua_checkuint32(L, -1); lua_pop(L, 1); // [ range ] *range = (TSRange) { diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua index bbc0798b82..8678761e6e 100644 --- a/test/functional/treesitter/parser_spec.lua +++ b/test/functional/treesitter/parser_spec.lua @@ -90,6 +90,23 @@ describe('treesitter parser API', function() eq(true, exec_lua('return parser:parse()[1] == tree2')) end) + it('preserves full-document included ranges', function() + insert([[ + local _ = 1 + ]]) + + eq( + { + { 0, 0, 0, 4294967295, 4294967295, 4294967295 }, + }, + exec_lua(function() + local parser = vim.treesitter.get_parser(0, 'lua') + local tree = parser:parse()[1] + return tree:included_ranges(true) + end) + ) + end) + it('respects eol settings when parsing buffer', function() insert([[ int main() {