aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/lua/vim/treesitter/languagetree.lua10
-rw-r--r--test/functional/treesitter/parser_spec.lua44
2 files changed, 53 insertions, 1 deletions
diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua
index 703d2a1f6d..4aa07d1b96 100644
--- a/runtime/lua/vim/treesitter/languagetree.lua
+++ b/runtime/lua/vim/treesitter/languagetree.lua
@@ -57,6 +57,7 @@ local Range = require('vim.treesitter._range')
---@field private _injection_query Query Queries defining injected languages
---@field private _opts table Options
---@field private _parser TSParser Parser for language
+---@field private _has_regions boolean
---@field private _regions Range6[][]?
---List of regions this tree should manage and parse. If nil then regions are
---taken from _trees. This is mostly a short-lived cache for included_regions()
@@ -440,6 +441,8 @@ end
---@private
---@param new_regions Range6[][] List of regions this tree should manage and parse.
function LanguageTree:set_included_regions(new_regions)
+ self._has_regions = true
+
-- Transform the tables from 4 element long to 6 element long (with byte offset)
for _, region in ipairs(new_regions) do
for i, range in ipairs(region) do
@@ -468,7 +471,8 @@ function LanguageTree:included_regions()
return self._regions
end
- if #self._trees == 0 then
+ if not self._has_regions or #self._trees == 0 then
+ -- treesitter.c will default empty ranges to { -1, -1, -1, -1, -1, -1}
return { {} }
end
@@ -744,6 +748,10 @@ function LanguageTree:_edit(
-- Validate regions after editing the tree
self:_iter_regions(function(_, region)
+ if #region == 0 then
+ -- empty region, use the full source
+ return false
+ end
for _, r in ipairs(region) do
if Range.intercepts(r, changed_range) then
return false
diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua
index ea9958b12a..9afce0b3a0 100644
--- a/test/functional/treesitter/parser_spec.lua
+++ b/test/functional/treesitter/parser_spec.lua
@@ -948,4 +948,48 @@ int x = INT_MAX;
[16] = '1',
[17] = '0' }, get_fold_levels())
end)
+
+ it('tracks the root range properly (#22911)', function()
+ insert([[
+ int main() {
+ int x = 3;
+ }]])
+
+ local query0 = [[
+ (declaration) @declaration
+ (function_definition) @function
+ ]]
+
+ exec_lua([[
+ vim.treesitter.start(0, 'c')
+ ]])
+
+ local function run_query()
+ return exec_lua([[
+ local query = vim.treesitter.query.parse("c", ...)
+ parser = vim.treesitter.get_parser()
+ tree = parser:parse()[1]
+ res = {}
+ for id, node in query:iter_captures(tree:root()) do
+ table.insert(res, {query.captures[id], node:range()})
+ end
+ return res
+ ]], query0)
+ end
+
+ eq({
+ { 'function', 0, 0, 2, 1 },
+ { 'declaration', 1, 2, 1, 12 }
+ }, run_query())
+
+ helpers.command'normal ggO'
+ insert('int a;')
+
+ eq({
+ { 'declaration', 0, 0, 0, 6 },
+ { 'function', 1, 0, 3, 1 },
+ { 'declaration', 2, 2, 2, 12 }
+ }, run_query())
+
+ end)
end)