commit c57a85e0eda067ea28ca5853358947332aceecfd
parent 0a789a81821343c8287219b646c787435567a2be
Author: Riley Bruins <ribru17@hotmail.com>
Date: Fri, 14 Jun 2024 17:54:10 -0700
perf(treesitter): remove unnecessary foldexpr loop
Instead of looping over all captured nodes, just take the end range from
the last node in the list. This uses the fact that nodes returned by
iter_matches are ordered by their range (earlier to later).
Diffstat:
2 files changed, 61 insertions(+), 10 deletions(-)
diff --git a/runtime/lua/vim/treesitter/_fold.lua b/runtime/lua/vim/treesitter/_fold.lua
@@ -139,16 +139,12 @@ local function compute_folds_levels(bufnr, info, srow, erow, parse_injections)
local range = ts.get_range(nodes[1], bufnr, metadata[id])
local start, _, stop, stop_col = Range.unpack4(range)
- for i = 2, #nodes, 1 do
- local node_range = ts.get_range(nodes[i], bufnr, metadata[id])
- local node_start, _, node_stop, node_stop_col = Range.unpack4(node_range)
- if node_start < start then
- start = node_start
- end
- if node_stop > stop then
- stop = node_stop
- stop_col = node_stop_col
- end
+ if #nodes > 1 then
+ -- assumes nodes are ordered by range
+ local end_range = ts.get_range(nodes[#nodes], bufnr, metadata[id])
+ local _, _, end_stop, end_stop_col = Range.unpack4(end_range)
+ stop = end_stop
+ stop_col = end_stop_col
end
if stop_col == 0 then
diff --git a/test/functional/treesitter/query_spec.lua b/test/functional/treesitter/query_spec.lua
@@ -249,6 +249,61 @@ void ui_refresh(void)
}, res)
end)
+ it('returns quantified matches in order of range #29344', function()
+ insert([[
+ int main() {
+ int a, b, c, d, e, f, g, h, i;
+ a = MIN(0, 1);
+ b = MIN(0, 1);
+ c = MIN(0, 1);
+ d = MIN(0, 1);
+ e = MIN(0, 1);
+ f = MIN(0, 1);
+ g = MIN(0, 1);
+ h = MIN(0, 1);
+ i = MIN(0, 1);
+ }
+ ]])
+
+ local res = exec_lua(
+ [[
+ cquery = vim.treesitter.query.parse("c", ...)
+ parser = vim.treesitter.get_parser(0, "c")
+ tree = parser:parse()[1]
+ res = {}
+ for pattern, match in cquery:iter_matches(tree:root(), 0, 7, 14, { all = true }) do
+ -- can't transmit node over RPC. just check the name and range
+ local mrepr = {}
+ for cid, nodes in pairs(match) do
+ for _, node in ipairs(nodes) do
+ table.insert(mrepr, { '@' .. cquery.captures[cid], node:type(), node:range() })
+ end
+ end
+ table.insert(res, {pattern, mrepr})
+ end
+ return res
+ ]],
+ '(expression_statement (assignment_expression (call_expression)))+ @funccall'
+ )
+
+ eq({
+ {
+ 1,
+ {
+ { '@funccall', 'expression_statement', 2, 2, 2, 16 },
+ { '@funccall', 'expression_statement', 3, 2, 3, 16 },
+ { '@funccall', 'expression_statement', 4, 2, 4, 16 },
+ { '@funccall', 'expression_statement', 5, 2, 5, 16 },
+ { '@funccall', 'expression_statement', 6, 2, 6, 16 },
+ { '@funccall', 'expression_statement', 7, 2, 7, 16 },
+ { '@funccall', 'expression_statement', 8, 2, 8, 16 },
+ { '@funccall', 'expression_statement', 9, 2, 9, 16 },
+ { '@funccall', 'expression_statement', 10, 2, 10, 16 },
+ },
+ },
+ }, res)
+ end)
+
it('can match special regex characters like \\ * + ( with `vim-match?`', function()
insert('char* astring = "\\n"; (1 + 1) * 2 != 2;')