From 921aa52b8f4dc94fa596fe019fc6c1aded9b7355 Mon Sep 17 00:00:00 2001 From: Jongwook Choi Date: Mon, 29 Jan 2024 20:51:32 -0500 Subject: test(treesitter): improve the style of treesitter/parser_spec General refactoring, including: - Improve whitespace and indentation - Prefix captures with `@` - Add more comments on `iter_capture()` tests - Move `test_query` up closer to the fixture source string No behavioral changes are made. --- test/functional/treesitter/parser_spec.lua | 616 ++++++++++++++++------------- 1 file changed, 331 insertions(+), 285 deletions(-) (limited to 'test/functional/treesitter/parser_spec.lua') diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua index 24f395c1ef..236ea9050a 100644 --- a/test/functional/treesitter/parser_spec.lua +++ b/test/functional/treesitter/parser_spec.lua @@ -111,6 +111,20 @@ void ui_refresh(void) } }]] + local test_query = [[ + ((call_expression + function: (identifier) @minfunc + (argument_list (identifier) @min_id)) + (#eq? @minfunc "MIN") + ) + + "for" @keyword + + (primitive_type) @type + + (field_expression argument: (identifier) @fieldarg) + ]] + it('allows to iterate over nodes children', function() insert(test_text) @@ -121,7 +135,7 @@ void ui_refresh(void) res = {} for node, field in func_node:iter_children() do - table.insert(res, {node:type(), field}) + table.insert(res, { node:type(), field }) end return res ]]) @@ -157,7 +171,7 @@ void ui_refresh(void) local res = {} for _, node in ipairs(func_node:field("type")) do - table.insert(res, {node:type(), node:range()}) + table.insert(res, { node:type(), node:range() }) end return res ]]) @@ -173,34 +187,31 @@ void ui_refresh(void) assert(res_fail) end) - local test_query = [[ - ((call_expression function: (identifier) @minfunc (argument_list (identifier) @min_id)) (#eq? @minfunc "MIN")) - "for" @keyword - (primitive_type) @type - (field_expression argument: (identifier) @fieldarg) - ]] - it('supports runtime queries', function() + ---@type string[] local ret = exec_lua [[ - return vim.treesitter.query.get("c", "highlights").captures[1] + return vim.treesitter.query.get("c", "highlights").captures ]] - eq('variable', ret) + -- see $VIMRUNTIME/queries/c/highlights.scm + eq('variable', ret[1]) + eq('keyword', ret[2]) end) it('supports caching queries', function() local long_query = test_query:rep(100) + ---@return number local function q(n) return exec_lua( [[ - local query, n = ... - local before = vim.uv.hrtime() - for i=1,n,1 do - cquery = vim.treesitter.query.parse("c", ...) - end - local after = vim.uv.hrtime() - return after - before - ]], + local query, n = ... + local before = vim.uv.hrtime() + for i=1, n, 1 do + cquery = vim.treesitter.query.parse("c", ...) + end + local after = vim.uv.hrtime() + return after - before + ]], long_query, n ) @@ -217,126 +228,133 @@ void ui_refresh(void) ) end) - it('support query and iter by capture', function() + it('supports query and iter by capture (iter_captures)', function() insert(test_text) local res = exec_lua( [[ - cquery = vim.treesitter.query.parse("c", ...) - parser = vim.treesitter.get_parser(0, "c") - tree = parser:parse()[1] - res = {} - for cid, node in cquery:iter_captures(tree:root(), 0, 7, 14) do - -- can't transmit node over RPC. just check the name and range - table.insert(res, {cquery.captures[cid], node:type(), node:range()}) - end - return res - ]], + cquery = vim.treesitter.query.parse("c", ...) + parser = vim.treesitter.get_parser(0, "c") + tree = parser:parse()[1] + res = {} + for cid, node in cquery:iter_captures(tree:root(), 0, 7, 14) do + -- can't transmit node over RPC. just check the name and range + table.insert(res, { '@' .. cquery.captures[cid], node:type(), node:range() }) + end + return res + ]], test_query ) eq({ - { 'type', 'primitive_type', 8, 2, 8, 6 }, - { 'keyword', 'for', 9, 2, 9, 5 }, - { 'type', 'primitive_type', 9, 7, 9, 13 }, - { 'minfunc', 'identifier', 11, 12, 11, 15 }, - { 'fieldarg', 'identifier', 11, 16, 11, 18 }, - { 'min_id', 'identifier', 11, 27, 11, 32 }, - { 'minfunc', 'identifier', 12, 13, 12, 16 }, - { 'fieldarg', 'identifier', 12, 17, 12, 19 }, - { 'min_id', 'identifier', 12, 29, 12, 35 }, - { 'fieldarg', 'identifier', 13, 14, 13, 16 }, + { '@type', 'primitive_type', 8, 2, 8, 6 }, -- bool + { '@keyword', 'for', 9, 2, 9, 5 }, -- for + { '@type', 'primitive_type', 9, 7, 9, 13 }, -- size_t + { '@minfunc', 'identifier', 11, 12, 11, 15 }, -- "MIN"(ui->width, width); + { '@fieldarg', 'identifier', 11, 16, 11, 18 }, -- ui + { '@min_id', 'identifier', 11, 27, 11, 32 }, -- width + { '@minfunc', 'identifier', 12, 13, 12, 16 }, -- "MIN"(ui->height, height); + { '@fieldarg', 'identifier', 12, 17, 12, 19 }, -- ui + { '@min_id', 'identifier', 12, 29, 12, 35 }, -- height + { '@fieldarg', 'identifier', 13, 14, 13, 16 }, -- ui ; in BAR(..) }, res) end) - it('support query and iter by match', function() + it('supports query and iter by match (iter_matches)', function() insert(test_text) + ---@type table 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()}) + 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 - table.insert(res, {pattern, mrepr}) - end - return res - ]], + return res + ]], test_query ) eq({ - { 3, { { 'type', 'primitive_type', 8, 2, 8, 6 } } }, - { 2, { { 'keyword', 'for', 9, 2, 9, 5 } } }, - { 3, { { 'type', 'primitive_type', 9, 7, 9, 13 } } }, - { 4, { { 'fieldarg', 'identifier', 11, 16, 11, 18 } } }, + { 3, { { '@type', 'primitive_type', 8, 2, 8, 6 } } }, + { 2, { { '@keyword', 'for', 9, 2, 9, 5 } } }, + { 3, { { '@type', 'primitive_type', 9, 7, 9, 13 } } }, + { 4, { { '@fieldarg', 'identifier', 11, 16, 11, 18 } } }, { 1, - { { 'minfunc', 'identifier', 11, 12, 11, 15 }, { 'min_id', 'identifier', 11, 27, 11, 32 } }, + { + { '@minfunc', 'identifier', 11, 12, 11, 15 }, + { '@min_id', 'identifier', 11, 27, 11, 32 }, + }, }, - { 4, { { 'fieldarg', 'identifier', 12, 17, 12, 19 } } }, + { 4, { { '@fieldarg', 'identifier', 12, 17, 12, 19 } } }, { 1, - { { 'minfunc', 'identifier', 12, 13, 12, 16 }, { 'min_id', 'identifier', 12, 29, 12, 35 } }, + { + { '@minfunc', 'identifier', 12, 13, 12, 16 }, + { '@min_id', 'identifier', 12, 29, 12, 35 }, + }, }, - { 4, { { 'fieldarg', 'identifier', 13, 14, 13, 16 } } }, + { 4, { { '@fieldarg', 'identifier', 13, 14, 13, 16 } } }, }, res) end) - it('support query and iter by capture for quantifiers', function() + it('supports query and iter by capture for quantifiers', function() insert(test_text) local res = exec_lua( [[ - cquery = vim.treesitter.query.parse("c", ...) - parser = vim.treesitter.get_parser(0, "c") - tree = parser:parse()[1] - res = {} - for cid, node in cquery:iter_captures(tree:root(), 0, 7, 14) do - -- can't transmit node over RPC. just check the name and range - table.insert(res, {cquery.captures[cid], node:type(), node:range()}) - end - return res - ]], + cquery = vim.treesitter.query.parse("c", ...) + parser = vim.treesitter.get_parser(0, "c") + tree = parser:parse()[1] + res = {} + for cid, node in cquery:iter_captures(tree:root(), 0, 7, 14) do + -- can't transmit node over RPC. just check the name and range + table.insert(res, { '@' .. cquery.captures[cid], node:type(), node:range() }) + end + return res + ]], '(expression_statement (assignment_expression (call_expression)))+ @funccall' ) eq({ - { 'funccall', 'expression_statement', 11, 4, 11, 34 }, - { 'funccall', 'expression_statement', 12, 4, 12, 37 }, - { 'funccall', 'expression_statement', 13, 4, 13, 34 }, + { '@funccall', 'expression_statement', 11, 4, 11, 34 }, + { '@funccall', 'expression_statement', 12, 4, 12, 37 }, + { '@funccall', 'expression_statement', 13, 4, 13, 34 }, }, res) end) - it('support query and iter by match for quantifiers', function() + it('supports query and iter by match for quantifiers', function() insert(test_text) 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()}) + 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 - table.insert(res, {pattern, mrepr}) - end - return res - ]], + return res + ]], '(expression_statement (assignment_expression (call_expression)))+ @funccall' ) @@ -344,9 +362,9 @@ void ui_refresh(void) { 1, { - { 'funccall', 'expression_statement', 11, 4, 11, 34 }, - { 'funccall', 'expression_statement', 12, 4, 12, 37 }, - { 'funccall', 'expression_statement', 13, 4, 13, 34 }, + { '@funccall', 'expression_statement', 11, 4, 11, 34 }, + { '@funccall', 'expression_statement', 12, 4, 12, 37 }, + { '@funccall', 'expression_statement', 13, 4, 13, 34 }, }, }, }, res) @@ -369,7 +387,7 @@ void ui_refresh(void) eq('void', res2) end) - it('support getting text where start of node is one past EOF', function() + it('supports getting text where start of node is one past EOF', function() local text = [[ def run a = <<~E @@ -378,25 +396,25 @@ end]] eq( '', exec_lua [[ - local fake_node = {} - function fake_node:start() - return 3, 0, 23 - end - function fake_node:end_() - return 3, 0, 23 - end - function fake_node:range(bytes) - if bytes then - return 3, 0, 23, 3, 0, 23 + local fake_node = {} + function fake_node:start() + return 3, 0, 23 end - return 3, 0, 3, 0 - end - return vim.treesitter.get_node_text(fake_node, 0) - ]] + function fake_node:end_() + return 3, 0, 23 + end + function fake_node:range(bytes) + if bytes then + return 3, 0, 23, 3, 0, 23 + end + return 3, 0, 3, 0 + end + return vim.treesitter.get_node_text(fake_node, 0) + ]] ) end) - it('support getting empty text if node range is zero width', function() + it('supports getting empty text if node range is zero width', function() local text = [[ ```lua {} @@ -421,12 +439,16 @@ end]] it('can match special regex characters like \\ * + ( with `vim-match?`', function() insert('char* astring = "\\n"; (1 + 1) * 2 != 2;') + ---@type table local res = exec_lua([[ - cquery = vim.treesitter.query.parse("c", '([_] @plus (#vim-match? @plus "^\\\\+$"))'.. - '([_] @times (#vim-match? @times "^\\\\*$"))'.. - '([_] @paren (#vim-match? @paren "^\\\\($"))'.. - '([_] @escape (#vim-match? @escape "^\\\\\\\\n$"))'.. - '([_] @string (#vim-match? @string "^\\"\\\\\\\\n\\"$"))') + query = ( + '([_] @plus (#vim-match? @plus "^\\\\+$"))' .. + '([_] @times (#vim-match? @times "^\\\\*$"))' .. + '([_] @paren (#vim-match? @paren "^\\\\($"))' .. + '([_] @escape (#vim-match? @escape "^\\\\\\\\n$"))' .. + '([_] @string (#vim-match? @string "^\\"\\\\\\\\n\\"$"))' + ) + cquery = vim.treesitter.query.parse("c", query) parser = vim.treesitter.get_parser(0, "c") tree = parser:parse()[1] res = {} @@ -435,21 +457,21 @@ end]] 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()}) + table.insert(mrepr, { '@' .. cquery.captures[cid], node:type(), node:range() }) end end - table.insert(res, {pattern, mrepr}) + table.insert(res, { pattern, mrepr }) end return res ]]) eq({ - { 2, { { 'times', '*', 0, 4, 0, 5 } } }, - { 5, { { 'string', 'string_literal', 0, 16, 0, 20 } } }, - { 4, { { 'escape', 'escape_sequence', 0, 17, 0, 19 } } }, - { 3, { { 'paren', '(', 0, 22, 0, 23 } } }, - { 1, { { 'plus', '+', 0, 25, 0, 26 } } }, - { 2, { { 'times', '*', 0, 30, 0, 31 } } }, + { 2, { { '@times', '*', 0, 4, 0, 5 } } }, + { 5, { { '@string', 'string_literal', 0, 16, 0, 20 } } }, + { 4, { { '@escape', 'escape_sequence', 0, 17, 0, 19 } } }, + { 3, { { '@paren', '(', 0, 22, 0, 23 } } }, + { 1, { { '@plus', '+', 0, 25, 0, 26 } } }, + { 2, { { '@times', '*', 0, 30, 0, 31 } } }, }, res) end) @@ -482,7 +504,7 @@ end]] -- can't transmit node over RPC. just check the name, range, and text local text = vim.treesitter.get_node_text(node, 0) local range = {node:range()} - table.insert(res, {cquery.captures[cid], node:type(), range, text}) + table.insert(res, { cquery.captures[cid], node:type(), range, text }) end return res end @@ -514,12 +536,10 @@ end]] }, res1) end) - it( - 'allow loading query with escaped quotes and capture them with `lua-match?` and `vim-match?`', - function() - insert('char* astring = "Hello World!";') + it('allows loading query with escaped quotes and capture them `#{lua,vim}-match`?', function() + insert('char* astring = "Hello World!";') - local res = exec_lua([[ + local res = exec_lua([[ cquery = vim.treesitter.query.parse("c", '([_] @quote (#vim-match? @quote "^\\"$")) ([_] @quote (#lua-match? @quote "^\\"$"))') parser = vim.treesitter.get_parser(0, "c") tree = parser:parse()[1] @@ -529,22 +549,21 @@ end]] 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()}) + table.insert(mrepr, { '@' .. cquery.captures[cid], node:type(), node:range() }) end end - table.insert(res, {pattern, mrepr}) + table.insert(res, { pattern, mrepr }) end return res ]]) - eq({ - { 1, { { 'quote', '"', 0, 16, 0, 17 } } }, - { 2, { { 'quote', '"', 0, 16, 0, 17 } } }, - { 1, { { 'quote', '"', 0, 29, 0, 30 } } }, - { 2, { { 'quote', '"', 0, 29, 0, 30 } } }, - }, res) - end - ) + eq({ + { 1, { { '@quote', '"', 0, 16, 0, 17 } } }, + { 2, { { '@quote', '"', 0, 16, 0, 17 } } }, + { 1, { { '@quote', '"', 0, 29, 0, 30 } } }, + { 2, { { '@quote', '"', 0, 29, 0, 30 } } }, + }, res) + end) it('allows to add predicates', function() insert([[ @@ -558,35 +577,35 @@ end]] do local res = exec_lua( [[ - local query = vim.treesitter.query + local query = vim.treesitter.query - local function is_main(match, pattern, bufnr, predicate) - local nodes = match[ predicate[2] ] - for _, node in ipairs(nodes) do - if vim.treesitter.get_node_text(node, bufnr) == 'main' then - return true + local function is_main(match, pattern, bufnr, predicate) + local nodes = match[ predicate[2] ] + for _, node in ipairs(nodes) do + if vim.treesitter.get_node_text(node, bufnr) == 'main' then + return true + end + end + return false end - end - return false - end - local parser = vim.treesitter.get_parser(0, "c") + local parser = vim.treesitter.get_parser(0, "c") - -- Time bomb: update this in 0.12 - if vim.fn.has('nvim-0.12') == 1 then - return 'Update this test to remove this message and { all = true } from add_predicate' - end - query.add_predicate("is-main?", is_main, { all = true }) + -- Time bomb: update this in 0.12 + if vim.fn.has('nvim-0.12') == 1 then + return 'Update this test to remove this message and { all = true } from add_predicate' + end + query.add_predicate("is-main?", is_main, { all = true }) - local query = query.parse("c", ...) + local query = query.parse("c", ...) - local nodes = {} - for _, node in query:iter_captures(parser:parse()[1]:root(), 0) do - table.insert(nodes, {node:range()}) - end + local nodes = {} + for _, node in query:iter_captures(parser:parse()[1]:root(), 0) do + table.insert(nodes, {node:range()}) + end - return nodes - ]], + return nodes + ]], custom_query ) @@ -597,27 +616,27 @@ end]] do local res = exec_lua( [[ - local query = vim.treesitter.query + local query = vim.treesitter.query - local function is_main(match, pattern, bufnr, predicate) - local node = match[ predicate[2] ] + local function is_main(match, pattern, bufnr, predicate) + local node = match[ predicate[2] ] - return vim.treesitter.get_node_text(node, bufnr) == 'main' - end + return vim.treesitter.get_node_text(node, bufnr) == 'main' + end - local parser = vim.treesitter.get_parser(0, "c") + local parser = vim.treesitter.get_parser(0, "c") - query.add_predicate("is-main?", is_main, true) + query.add_predicate("is-main?", is_main, true) - local query = query.parse("c", ...) + local query = query.parse("c", ...) - local nodes = {} - for _, node in query:iter_captures(parser:parse()[1]:root(), 0) do - table.insert(nodes, {node:range()}) - end + local nodes = {} + for _, node in query:iter_captures(parser:parse()[1]:root(), 0) do + table.insert(nodes, {node:range()}) + end - return nodes - ]], + return nodes + ]], custom_query ) @@ -657,14 +676,14 @@ end]] api.nvim_buf_set_lines(0, 0, -1, true, vim.split(dedent(input), '\n')) return exec_lua( [[ - local parser = vim.treesitter.get_parser(0, "lua") - local query = vim.treesitter.query.parse("lua", ...) - local nodes = {} - for _, node in query:iter_captures(parser:parse()[1]:root(), 0) do - nodes[#nodes+1] = { node:range() } - end - return nodes - ]], + local parser = vim.treesitter.get_parser(0, "lua") + local query = vim.treesitter.query.parse("lua", ...) + local nodes = {} + for _, node in query:iter_captures(parser:parse()[1]:root(), 0) do + nodes[#nodes+1] = { node:range() } + end + return nodes + ]], query ) end @@ -740,14 +759,14 @@ end]] local result = exec_lua( [[ - local parser = vim.treesitter.get_parser(0, "lua") - local query = vim.treesitter.query.parse("lua", ...) - local nodes = {} - for _, node in query:iter_captures(parser:parse()[1]:root(), 0) do - nodes[#nodes+1] = { node:range() } - end - return nodes - ]], + local parser = vim.treesitter.get_parser(0, "lua") + local query = vim.treesitter.query.parse("lua", ...) + local nodes = {} + for _, node in query:iter_captures(parser:parse()[1]:root(), 0) do + nodes[#nodes+1] = { node:range() } + end + return nodes + ]], query ) @@ -765,37 +784,43 @@ end]] insert(test_text) 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) do - local mrepr = {} - for cid, node in pairs(match) do - table.insert(mrepr, {cquery.captures[cid], node:type(), node:range()}) + 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) do + local mrepr = {} + for cid, node in pairs(match) do + table.insert(mrepr, { '@' .. cquery.captures[cid], node:type(), node:range() }) + end + table.insert(res, { pattern, mrepr }) end - table.insert(res, {pattern, mrepr}) - end - return res - ]], + return res + ]], test_query ) eq({ - { 3, { { 'type', 'primitive_type', 8, 2, 8, 6 } } }, - { 2, { { 'keyword', 'for', 9, 2, 9, 5 } } }, - { 3, { { 'type', 'primitive_type', 9, 7, 9, 13 } } }, - { 4, { { 'fieldarg', 'identifier', 11, 16, 11, 18 } } }, + { 3, { { '@type', 'primitive_type', 8, 2, 8, 6 } } }, + { 2, { { '@keyword', 'for', 9, 2, 9, 5 } } }, + { 3, { { '@type', 'primitive_type', 9, 7, 9, 13 } } }, + { 4, { { '@fieldarg', 'identifier', 11, 16, 11, 18 } } }, { 1, - { { 'minfunc', 'identifier', 11, 12, 11, 15 }, { 'min_id', 'identifier', 11, 27, 11, 32 } }, + { + { '@minfunc', 'identifier', 11, 12, 11, 15 }, + { '@min_id', 'identifier', 11, 27, 11, 32 }, + }, }, - { 4, { { 'fieldarg', 'identifier', 12, 17, 12, 19 } } }, + { 4, { { '@fieldarg', 'identifier', 12, 17, 12, 19 } } }, { 1, - { { 'minfunc', 'identifier', 12, 13, 12, 16 }, { 'min_id', 'identifier', 12, 29, 12, 35 } }, + { + { '@minfunc', 'identifier', 12, 13, 12, 16 }, + { '@min_id', 'identifier', 12, 29, 12, 35 }, + }, }, - { 4, { { 'fieldarg', 'identifier', 13, 14, 13, 16 } } }, + { 4, { { '@fieldarg', 'identifier', 13, 14, 13, 16 } } }, }, res) end) @@ -882,17 +907,18 @@ end]] local ret = exec_lua( [[ - local str = ... - local parser = vim.treesitter.get_string_parser(str, "c") + local str = ... + local parser = vim.treesitter.get_string_parser(str, "c") - local nodes = {} - local query = vim.treesitter.query.parse("c", '((identifier) @id (#eq? @id "foo"))') + local nodes = {} + local query = vim.treesitter.query.parse("c", '((identifier) @id (#eq? @id "foo"))') - for _, node in query:iter_captures(parser:parse()[1]:root(), str) do - table.insert(nodes, { node:range() }) - end + for _, node in query:iter_captures(parser:parse()[1]:root(), str) do + table.insert(nodes, { node:range() }) + end - return nodes]], + return nodes + ]], txt ) @@ -907,18 +933,19 @@ end]] local ret = exec_lua( [[ - local str = ... - local parser = vim.treesitter.get_string_parser(str, "c") + local str = ... + local parser = vim.treesitter.get_string_parser(str, "c") - local nodes = {} - local query = vim.treesitter.query.parse("c", '((identifier) @foo)') - local first_child = parser:parse()[1]:root():child(1) + local nodes = {} + local query = vim.treesitter.query.parse("c", '((identifier) @foo)') + local first_child = parser:parse()[1]:root():child(1) - for _, node in query:iter_captures(first_child, str) do - table.insert(nodes, { node:range() }) - end + for _, node in query:iter_captures(first_child, str) do + table.insert(nodes, { node:range() }) + end - return nodes]], + return nodes + ]], txt ) @@ -927,11 +954,11 @@ end]] describe('when creating a language tree', function() local function get_ranges() - return exec_lua([[ - local result = {} - parser:for_each_tree(function(tree) table.insert(result, {tree:root():range()}) end) - return result - ]]) + return exec_lua [[ + local result = {} + parser:for_each_tree(function(tree) table.insert(result, {tree:root():range()}) end) + return result + ]] end before_each(function() @@ -948,10 +975,14 @@ int x = INT_MAX; describe('when parsing regions independently', function() it('should inject a language', function() exec_lua([[ - parser = vim.treesitter.get_parser(0, "c", { - injections = { - c = '(preproc_def (preproc_arg) @injection.content (#set! injection.language "c")) (preproc_function_def value: (preproc_arg) @injection.content (#set! injection.language "c"))'}}) - parser:parse(true) + parser = vim.treesitter.get_parser(0, "c", { + injections = { + c = ( + '(preproc_def (preproc_arg) @injection.content (#set! injection.language "c")) ' .. + '(preproc_function_def value: (preproc_arg) @injection.content (#set! injection.language "c"))' + ) + }}) + parser:parse(true) ]]) eq('table', exec_lua('return type(parser:children().c)')) @@ -981,10 +1012,14 @@ int x = INT_MAX; describe('when parsing regions combined', function() it('should inject a language', function() exec_lua([[ - parser = vim.treesitter.get_parser(0, "c", { - injections = { - c = '(preproc_def (preproc_arg) @injection.content (#set! injection.language "c") (#set! injection.combined)) (preproc_function_def value: (preproc_arg) @injection.content (#set! injection.language "c") (#set! injection.combined))'}}) - parser:parse(true) + parser = vim.treesitter.get_parser(0, "c", { + injections = { + c = ( + '(preproc_def (preproc_arg) @injection.content (#set! injection.language "c") (#set! injection.combined)) ' .. + '(preproc_function_def value: (preproc_arg) @injection.content (#set! injection.language "c") (#set! injection.combined))' + ) + }}) + parser:parse(true) ]]) eq('table', exec_lua('return type(parser:children().c)')) @@ -1027,10 +1062,14 @@ int x = INT_MAX; describe('when using injection.self', function() it('should inject the source language', function() exec_lua([[ - parser = vim.treesitter.get_parser(0, "c", { - injections = { - c = '(preproc_def (preproc_arg) @injection.content (#set! injection.self)) (preproc_function_def value: (preproc_arg) @injection.content (#set! injection.self))'}}) - parser:parse(true) + parser = vim.treesitter.get_parser(0, "c", { + injections = { + c = ( + '(preproc_def (preproc_arg) @injection.content (#set! injection.self)) ' .. + '(preproc_function_def value: (preproc_arg) @injection.content (#set! injection.self))' + ) + }}) + parser:parse(true) ]]) eq('table', exec_lua('return type(parser:children().c)')) @@ -1060,10 +1099,14 @@ int x = INT_MAX; describe('when using the offset directive', function() it('should shift the range by the directive amount', function() exec_lua([[ - parser = vim.treesitter.get_parser(0, "c", { - injections = { - c = '(preproc_def ((preproc_arg) @injection.content (#set! injection.language "c") (#offset! @injection.content 0 2 0 -1))) (preproc_function_def value: (preproc_arg) @injection.content (#set! injection.language "c"))'}}) - parser:parse(true) + parser = vim.treesitter.get_parser(0, "c", { + injections = { + c = ( + '(preproc_def ((preproc_arg) @injection.content (#set! injection.language "c") (#offset! @injection.content 0 2 0 -1))) ' .. + '(preproc_function_def value: (preproc_arg) @injection.content (#set! injection.language "c"))' + ) + }}) + parser:parse(true) ]]) eq('table', exec_lua('return type(parser:children().c)')) @@ -1078,13 +1121,13 @@ int x = INT_MAX; end) it('should list all directives', function() local res_list = exec_lua [[ - local query = vim.treesitter.query + local query = vim.treesitter.query - local list = query.list_directives() + local list = query.list_directives() - table.sort(list) + table.sort(list) - return list + return list ]] eq({ 'gsub!', 'offset!', 'set!', 'trim!' }, res_list) @@ -1102,13 +1145,16 @@ int x = INT_MAX; it('should return the correct language tree', function() local result = exec_lua([[ - parser = vim.treesitter.get_parser(0, "c", { - injections = { c = '(preproc_def (preproc_arg) @injection.content (#set! injection.language "c"))'}}) - parser:parse(true) + parser = vim.treesitter.get_parser(0, "c", { + injections = { + c = '(preproc_def (preproc_arg) @injection.content (#set! injection.language "c"))' + } + }) + parser:parse(true) - local sub_tree = parser:language_for_range({1, 18, 1, 19}) + local sub_tree = parser:language_for_range({1, 18, 1, 19}) - return sub_tree == parser:children().c + return sub_tree == parser:children().c ]]) eq(true, result) @@ -1208,15 +1254,15 @@ int x = INT_MAX; 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 - ]], + 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 @@ -1258,14 +1304,14 @@ int x = INT_MAX; local r = exec_lua( [[ - local parser = vim.treesitter.get_string_parser(..., 'lua') - parser:parse(true) - local ranges = {} - parser:for_each_tree(function(tstree, tree) - ranges[tree:lang()] = { tstree:root():range(true) } - end) - return ranges - ]], + local parser = vim.treesitter.get_string_parser(..., 'lua') + parser:parse(true) + local ranges = {} + parser:for_each_tree(function(tstree, tree) + ranges[tree:lang()] = { tstree:root():range(true) } + end) + return ranges + ]], source ) @@ -1281,14 +1327,14 @@ int x = INT_MAX; local rb = exec_lua( [[ - local r, source = ... - local add_bytes = require('vim.treesitter._range').add_bytes - for lang, range in pairs(r) do - r[lang] = {range[1], range[2], range[4], range[5]} - r[lang] = add_bytes(source, r[lang]) - end - return r - ]], + local r, source = ... + local add_bytes = require('vim.treesitter._range').add_bytes + for lang, range in pairs(r) do + r[lang] = {range[1], range[2], range[4], range[5]} + r[lang] = add_bytes(source, r[lang]) + end + return r + ]], r, source ) @@ -1448,7 +1494,7 @@ int x = INT_MAX; ) end) - describe('is_valid()', function() + describe('languagetree is_valid()', function() before_each(function() insert(dedent [[ Treesitter integration *treesitter* -- cgit From ca239ecd07f7142a6b7241de586230578581f409 Mon Sep 17 00:00:00 2001 From: Jongwook Choi Date: Sat, 23 Mar 2024 23:38:38 -0400 Subject: test(treesitter): separate out query-related tests into query_spec Move test cases that are more about treesitter query API rather than parser API or LanguageTree out of "treesitter/parser_spec", and collect them in another test suite "treesitter/query_spec". --- test/functional/treesitter/parser_spec.lua | 661 ----------------------------- 1 file changed, 661 deletions(-) (limited to 'test/functional/treesitter/parser_spec.lua') diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua index 236ea9050a..5af53202a6 100644 --- a/test/functional/treesitter/parser_spec.lua +++ b/test/functional/treesitter/parser_spec.lua @@ -7,9 +7,6 @@ local insert = helpers.insert local exec_lua = helpers.exec_lua local pcall_err = helpers.pcall_err local feed = helpers.feed -local is_os = helpers.is_os -local api = helpers.api -local fn = helpers.fn describe('treesitter parser API', function() before_each(function() @@ -111,20 +108,6 @@ void ui_refresh(void) } }]] - local test_query = [[ - ((call_expression - function: (identifier) @minfunc - (argument_list (identifier) @min_id)) - (#eq? @minfunc "MIN") - ) - - "for" @keyword - - (primitive_type) @type - - (field_expression argument: (identifier) @fieldarg) - ]] - it('allows to iterate over nodes children', function() insert(test_text) @@ -187,189 +170,6 @@ void ui_refresh(void) assert(res_fail) end) - it('supports runtime queries', function() - ---@type string[] - local ret = exec_lua [[ - return vim.treesitter.query.get("c", "highlights").captures - ]] - - -- see $VIMRUNTIME/queries/c/highlights.scm - eq('variable', ret[1]) - eq('keyword', ret[2]) - end) - - it('supports caching queries', function() - local long_query = test_query:rep(100) - ---@return number - local function q(n) - return exec_lua( - [[ - local query, n = ... - local before = vim.uv.hrtime() - for i=1, n, 1 do - cquery = vim.treesitter.query.parse("c", ...) - end - local after = vim.uv.hrtime() - return after - before - ]], - long_query, - n - ) - end - - local firstrun = q(1) - local manyruns = q(100) - - -- First run should be at least 200x slower than an 100 subsequent runs. - local factor = is_os('win') and 100 or 200 - assert( - factor * manyruns < firstrun, - ('firstrun: %f ms, manyruns: %f ms'):format(firstrun / 1e6, manyruns / 1e6) - ) - end) - - it('supports query and iter by capture (iter_captures)', function() - insert(test_text) - - local res = exec_lua( - [[ - cquery = vim.treesitter.query.parse("c", ...) - parser = vim.treesitter.get_parser(0, "c") - tree = parser:parse()[1] - res = {} - for cid, node in cquery:iter_captures(tree:root(), 0, 7, 14) do - -- can't transmit node over RPC. just check the name and range - table.insert(res, { '@' .. cquery.captures[cid], node:type(), node:range() }) - end - return res - ]], - test_query - ) - - eq({ - { '@type', 'primitive_type', 8, 2, 8, 6 }, -- bool - { '@keyword', 'for', 9, 2, 9, 5 }, -- for - { '@type', 'primitive_type', 9, 7, 9, 13 }, -- size_t - { '@minfunc', 'identifier', 11, 12, 11, 15 }, -- "MIN"(ui->width, width); - { '@fieldarg', 'identifier', 11, 16, 11, 18 }, -- ui - { '@min_id', 'identifier', 11, 27, 11, 32 }, -- width - { '@minfunc', 'identifier', 12, 13, 12, 16 }, -- "MIN"(ui->height, height); - { '@fieldarg', 'identifier', 12, 17, 12, 19 }, -- ui - { '@min_id', 'identifier', 12, 29, 12, 35 }, -- height - { '@fieldarg', 'identifier', 13, 14, 13, 16 }, -- ui ; in BAR(..) - }, res) - end) - - it('supports query and iter by match (iter_matches)', function() - insert(test_text) - - ---@type table - 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 - ]], - test_query - ) - - eq({ - { 3, { { '@type', 'primitive_type', 8, 2, 8, 6 } } }, - { 2, { { '@keyword', 'for', 9, 2, 9, 5 } } }, - { 3, { { '@type', 'primitive_type', 9, 7, 9, 13 } } }, - { 4, { { '@fieldarg', 'identifier', 11, 16, 11, 18 } } }, - { - 1, - { - { '@minfunc', 'identifier', 11, 12, 11, 15 }, - { '@min_id', 'identifier', 11, 27, 11, 32 }, - }, - }, - { 4, { { '@fieldarg', 'identifier', 12, 17, 12, 19 } } }, - { - 1, - { - { '@minfunc', 'identifier', 12, 13, 12, 16 }, - { '@min_id', 'identifier', 12, 29, 12, 35 }, - }, - }, - { 4, { { '@fieldarg', 'identifier', 13, 14, 13, 16 } } }, - }, res) - end) - - it('supports query and iter by capture for quantifiers', function() - insert(test_text) - - local res = exec_lua( - [[ - cquery = vim.treesitter.query.parse("c", ...) - parser = vim.treesitter.get_parser(0, "c") - tree = parser:parse()[1] - res = {} - for cid, node in cquery:iter_captures(tree:root(), 0, 7, 14) do - -- can't transmit node over RPC. just check the name and range - table.insert(res, { '@' .. cquery.captures[cid], node:type(), node:range() }) - end - return res - ]], - '(expression_statement (assignment_expression (call_expression)))+ @funccall' - ) - - eq({ - { '@funccall', 'expression_statement', 11, 4, 11, 34 }, - { '@funccall', 'expression_statement', 12, 4, 12, 37 }, - { '@funccall', 'expression_statement', 13, 4, 13, 34 }, - }, res) - end) - - it('supports query and iter by match for quantifiers', function() - insert(test_text) - - 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', 11, 4, 11, 34 }, - { '@funccall', 'expression_statement', 12, 4, 12, 37 }, - { '@funccall', 'expression_statement', 13, 4, 13, 34 }, - }, - }, - }, res) - end) - it('supports getting text of multiline node', function() insert(test_text) local res = exec_lua([[ @@ -436,394 +236,6 @@ end]] eq(true, result) end) - it('can match special regex characters like \\ * + ( with `vim-match?`', function() - insert('char* astring = "\\n"; (1 + 1) * 2 != 2;') - - ---@type table - local res = exec_lua([[ - query = ( - '([_] @plus (#vim-match? @plus "^\\\\+$"))' .. - '([_] @times (#vim-match? @times "^\\\\*$"))' .. - '([_] @paren (#vim-match? @paren "^\\\\($"))' .. - '([_] @escape (#vim-match? @escape "^\\\\\\\\n$"))' .. - '([_] @string (#vim-match? @string "^\\"\\\\\\\\n\\"$"))' - ) - cquery = vim.treesitter.query.parse("c", query) - parser = vim.treesitter.get_parser(0, "c") - tree = parser:parse()[1] - res = {} - for pattern, match in cquery:iter_matches(tree:root(), 0, 0, -1, { 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 - ]]) - - eq({ - { 2, { { '@times', '*', 0, 4, 0, 5 } } }, - { 5, { { '@string', 'string_literal', 0, 16, 0, 20 } } }, - { 4, { { '@escape', 'escape_sequence', 0, 17, 0, 19 } } }, - { 3, { { '@paren', '(', 0, 22, 0, 23 } } }, - { 1, { { '@plus', '+', 0, 25, 0, 26 } } }, - { 2, { { '@times', '*', 0, 30, 0, 31 } } }, - }, res) - end) - - it('supports builtin query predicate any-of?', function() - insert([[ - #include - - int main(void) { - int i; - for(i=1; i<=100; i++) { - if(((i%3)||(i%5))== 0) - printf("number= %d FizzBuzz\n", i); - else if((i%3)==0) - printf("number= %d Fizz\n", i); - else if((i%5)==0) - printf("number= %d Buzz\n", i); - else - printf("number= %d\n",i); - } - return 0; - } - ]]) - exec_lua([[ - function get_query_result(query_text) - cquery = vim.treesitter.query.parse("c", query_text) - parser = vim.treesitter.get_parser(0, "c") - tree = parser:parse()[1] - res = {} - for cid, node in cquery:iter_captures(tree:root(), 0) do - -- can't transmit node over RPC. just check the name, range, and text - local text = vim.treesitter.get_node_text(node, 0) - local range = {node:range()} - table.insert(res, { cquery.captures[cid], node:type(), range, text }) - end - return res - end - ]]) - - local res0 = exec_lua( - [[return get_query_result(...)]], - [[((primitive_type) @c-keyword (#any-of? @c-keyword "int" "float"))]] - ) - eq({ - { 'c-keyword', 'primitive_type', { 2, 2, 2, 5 }, 'int' }, - { 'c-keyword', 'primitive_type', { 3, 4, 3, 7 }, 'int' }, - }, res0) - - local res1 = exec_lua( - [[return get_query_result(...)]], - [[ - ((string_literal) @fizzbuzz-strings (#any-of? @fizzbuzz-strings - "\"number= %d FizzBuzz\\n\"" - "\"number= %d Fizz\\n\"" - "\"number= %d Buzz\\n\"" - )) - ]] - ) - eq({ - { 'fizzbuzz-strings', 'string_literal', { 6, 15, 6, 38 }, '"number= %d FizzBuzz\\n"' }, - { 'fizzbuzz-strings', 'string_literal', { 8, 15, 8, 34 }, '"number= %d Fizz\\n"' }, - { 'fizzbuzz-strings', 'string_literal', { 10, 15, 10, 34 }, '"number= %d Buzz\\n"' }, - }, res1) - end) - - it('allows loading query with escaped quotes and capture them `#{lua,vim}-match`?', function() - insert('char* astring = "Hello World!";') - - local res = exec_lua([[ - cquery = vim.treesitter.query.parse("c", '([_] @quote (#vim-match? @quote "^\\"$")) ([_] @quote (#lua-match? @quote "^\\"$"))') - parser = vim.treesitter.get_parser(0, "c") - tree = parser:parse()[1] - res = {} - for pattern, match in cquery:iter_matches(tree:root(), 0, 0, -1, { 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 - ]]) - - eq({ - { 1, { { '@quote', '"', 0, 16, 0, 17 } } }, - { 2, { { '@quote', '"', 0, 16, 0, 17 } } }, - { 1, { { '@quote', '"', 0, 29, 0, 30 } } }, - { 2, { { '@quote', '"', 0, 29, 0, 30 } } }, - }, res) - end) - - it('allows to add predicates', function() - insert([[ - int main(void) { - return 0; - } - ]]) - - local custom_query = '((identifier) @main (#is-main? @main))' - - do - local res = exec_lua( - [[ - local query = vim.treesitter.query - - local function is_main(match, pattern, bufnr, predicate) - local nodes = match[ predicate[2] ] - for _, node in ipairs(nodes) do - if vim.treesitter.get_node_text(node, bufnr) == 'main' then - return true - end - end - return false - end - - local parser = vim.treesitter.get_parser(0, "c") - - -- Time bomb: update this in 0.12 - if vim.fn.has('nvim-0.12') == 1 then - return 'Update this test to remove this message and { all = true } from add_predicate' - end - query.add_predicate("is-main?", is_main, { all = true }) - - local query = query.parse("c", ...) - - local nodes = {} - for _, node in query:iter_captures(parser:parse()[1]:root(), 0) do - table.insert(nodes, {node:range()}) - end - - return nodes - ]], - custom_query - ) - - eq({ { 0, 4, 0, 8 } }, res) - end - - -- Once with the old API. Remove this whole 'do' block in 0.12 - do - local res = exec_lua( - [[ - local query = vim.treesitter.query - - local function is_main(match, pattern, bufnr, predicate) - local node = match[ predicate[2] ] - - return vim.treesitter.get_node_text(node, bufnr) == 'main' - end - - local parser = vim.treesitter.get_parser(0, "c") - - query.add_predicate("is-main?", is_main, true) - - local query = query.parse("c", ...) - - local nodes = {} - for _, node in query:iter_captures(parser:parse()[1]:root(), 0) do - table.insert(nodes, {node:range()}) - end - - return nodes - ]], - custom_query - ) - - -- Remove this 'do' block in 0.12 - eq(0, fn.has('nvim-0.12')) - eq({ { 0, 4, 0, 8 } }, res) - end - - do - local res = exec_lua [[ - local query = vim.treesitter.query - - local t = {} - for _, v in ipairs(query.list_predicates()) do - t[v] = true - end - - return t - ]] - - eq(true, res['is-main?']) - end - end) - - it('supports "all" and "any" semantics for predicates on quantified captures #24738', function() - local query_all = [[ - (((comment (comment_content))+) @bar - (#lua-match? @bar "Yes")) - ]] - - local query_any = [[ - (((comment (comment_content))+) @bar - (#any-lua-match? @bar "Yes")) - ]] - - local function test(input, query) - api.nvim_buf_set_lines(0, 0, -1, true, vim.split(dedent(input), '\n')) - return exec_lua( - [[ - local parser = vim.treesitter.get_parser(0, "lua") - local query = vim.treesitter.query.parse("lua", ...) - local nodes = {} - for _, node in query:iter_captures(parser:parse()[1]:root(), 0) do - nodes[#nodes+1] = { node:range() } - end - return nodes - ]], - query - ) - end - - eq( - {}, - test( - [[ - -- Yes - -- No - -- Yes - ]], - query_all - ) - ) - - eq( - { - { 0, 2, 0, 8 }, - { 1, 2, 1, 8 }, - { 2, 2, 2, 8 }, - }, - test( - [[ - -- Yes - -- Yes - -- Yes - ]], - query_all - ) - ) - - eq( - {}, - test( - [[ - -- No - -- No - -- No - ]], - query_any - ) - ) - - eq( - { - { 0, 2, 0, 7 }, - { 1, 2, 1, 8 }, - { 2, 2, 2, 7 }, - }, - test( - [[ - -- No - -- Yes - -- No - ]], - query_any - ) - ) - end) - - it('supports any- prefix to match any capture when using quantifiers #24738', function() - insert([[ - -- Comment - -- Comment - -- Comment - ]]) - - local query = [[ - (((comment (comment_content))+) @bar - (#lua-match? @bar "Comment")) - ]] - - local result = exec_lua( - [[ - local parser = vim.treesitter.get_parser(0, "lua") - local query = vim.treesitter.query.parse("lua", ...) - local nodes = {} - for _, node in query:iter_captures(parser:parse()[1]:root(), 0) do - nodes[#nodes+1] = { node:range() } - end - return nodes - ]], - query - ) - - eq({ - { 0, 2, 0, 12 }, - { 1, 2, 1, 12 }, - { 2, 2, 2, 12 }, - }, result) - end) - - it('supports the old broken version of iter_matches #24738', function() - -- Delete this test in 0.12 when iter_matches is removed - eq(0, fn.has('nvim-0.12')) - - insert(test_text) - 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) do - local mrepr = {} - for cid, node in pairs(match) do - table.insert(mrepr, { '@' .. cquery.captures[cid], node:type(), node:range() }) - end - table.insert(res, { pattern, mrepr }) - end - return res - ]], - test_query - ) - - eq({ - { 3, { { '@type', 'primitive_type', 8, 2, 8, 6 } } }, - { 2, { { '@keyword', 'for', 9, 2, 9, 5 } } }, - { 3, { { '@type', 'primitive_type', 9, 7, 9, 13 } } }, - { 4, { { '@fieldarg', 'identifier', 11, 16, 11, 18 } } }, - { - 1, - { - { '@minfunc', 'identifier', 11, 12, 11, 15 }, - { '@min_id', 'identifier', 11, 27, 11, 32 }, - }, - }, - { 4, { { '@fieldarg', 'identifier', 12, 17, 12, 19 } } }, - { - 1, - { - { '@minfunc', 'identifier', 12, 13, 12, 16 }, - { '@min_id', 'identifier', 12, 29, 12, 35 }, - }, - }, - { 4, { { '@fieldarg', 'identifier', 13, 14, 13, 16 } } }, - }, res) - end) - it('allows to set simple ranges', function() insert(test_text) @@ -925,33 +337,6 @@ end]] eq({ { 0, 10, 0, 13 } }, ret) end) - it('should use node range when omitted', function() - local txt = [[ - int foo = 42; - int bar = 13; - ]] - - local ret = exec_lua( - [[ - local str = ... - local parser = vim.treesitter.get_string_parser(str, "c") - - local nodes = {} - local query = vim.treesitter.query.parse("c", '((identifier) @foo)') - local first_child = parser:parse()[1]:root():child(1) - - for _, node in query:iter_captures(first_child, str) do - table.insert(nodes, { node:range() }) - end - - return nodes - ]], - txt - ) - - eq({ { 1, 10, 1, 13 } }, ret) - end) - describe('when creating a language tree', function() local function get_ranges() return exec_lua [[ @@ -1448,52 +833,6 @@ int x = INT_MAX; ) end) - it('fails to load queries', function() - local function test(exp, cquery) - eq(exp, pcall_err(exec_lua, "vim.treesitter.query.parse('c', ...)", cquery)) - end - - -- Invalid node type - test( - '.../query.lua:0: Query error at 1:2. Invalid node type "dentifier":\n' - .. '(dentifier) @variable\n' - .. ' ^', - '(dentifier) @variable' - ) - - -- Impossible pattern - test( - '.../query.lua:0: Query error at 1:13. Impossible pattern:\n' - .. '(identifier (identifier) @variable)\n' - .. ' ^', - '(identifier (identifier) @variable)' - ) - - -- Invalid syntax - test( - '.../query.lua:0: Query error at 1:13. Invalid syntax:\n' - .. '(identifier @variable\n' - .. ' ^', - '(identifier @variable' - ) - - -- Invalid field name - test( - '.../query.lua:0: Query error at 1:15. Invalid field name "invalid_field":\n' - .. '((identifier) invalid_field: (identifier))\n' - .. ' ^', - '((identifier) invalid_field: (identifier))' - ) - - -- Invalid capture name - test( - '.../query.lua:0: Query error at 3:2. Invalid capture name "ok.capture":\n' - .. '@ok.capture\n' - .. ' ^', - '((identifier) @id \n(#eq? @id\n@ok.capture\n))' - ) - end) - describe('languagetree is_valid()', function() before_each(function() insert(dedent [[ -- cgit