commit 7fa292c52d7bf63d59730946ef220befe4d51900
parent 0b66ab42c76c41494a9d7fc715d310f1a1da929d
Author: Jaehwang Jung <tomtomjhj@gmail.com>
Date: Sat, 23 Dec 2023 19:45:19 +0900
fix(treesitter): outdated highlight due to tree with outdated region
Problem:
A region managed by an injected parser may shrink after re-running the
injection query. If the updated region goes out of the range to be
parsed, then the corresponding tree will remain outdated, possibly
retaining the nodes that shouldn't exist anymore. This results in
outdated highlights.
Solution:
Re-parse an invalid tree if its region intersects the range to be
parsed.
Diffstat:
2 files changed, 19 insertions(+), 1 deletion(-)
diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua
@@ -348,7 +348,13 @@ function LanguageTree:_parse_regions(range)
-- If there are no ranges, set to an empty list
-- so the included ranges in the parser are cleared.
for i, ranges in pairs(self:included_regions()) do
- if not self._valid[i] and intercepts_region(ranges, range) then
+ if
+ not self._valid[i]
+ and (
+ intercepts_region(ranges, range)
+ or (self._trees[i] and intercepts_region(self._trees[i]:included_ranges(false), range))
+ )
+ then
self._parser:set_included_ranges(ranges)
local parse_time, tree, tree_changes =
tcall(self._parser.parse, self._parser, self._trees[i], self._source, true)
diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua
@@ -693,6 +693,18 @@ int x = INT_MAX;
{2, 26, 3, 66} -- READ_STRING(x, y) (char *)read_string((x), (size_t)(y))
-- READ_STRING_OK(x, y) (char *)read_string((x), (size_t)(y))
}, get_ranges())
+
+ helpers.feed('7ggI//<esc>')
+ exec_lua([[parser:parse({6, 7})]])
+ eq("table", exec_lua("return type(parser:children().c)"))
+ eq(2, exec_lua("return #parser:children().c:trees()"))
+ eq({
+ {0, 0, 8, 0}, -- root tree
+ {4, 14, 5, 18}, -- VALUE 123
+ -- VALUE1 123
+ {2, 26, 3, 66} -- READ_STRING(x, y) (char *)read_string((x), (size_t)(y))
+ -- READ_STRING_OK(x, y) (char *)read_string((x), (size_t)(y))
+ }, get_ranges())
end)
end)