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.
This commit is contained in:
Jongwook Choi 2024-01-29 20:51:32 -05:00
parent d3e51603bc
commit 921aa52b8f

View File

@ -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() it('allows to iterate over nodes children', function()
insert(test_text) insert(test_text)
@ -121,7 +135,7 @@ void ui_refresh(void)
res = {} res = {}
for node, field in func_node:iter_children() do for node, field in func_node:iter_children() do
table.insert(res, {node:type(), field}) table.insert(res, { node:type(), field })
end end
return res return res
]]) ]])
@ -157,7 +171,7 @@ void ui_refresh(void)
local res = {} local res = {}
for _, node in ipairs(func_node:field("type")) do for _, node in ipairs(func_node:field("type")) do
table.insert(res, {node:type(), node:range()}) table.insert(res, { node:type(), node:range() })
end end
return res return res
]]) ]])
@ -173,34 +187,31 @@ void ui_refresh(void)
assert(res_fail) assert(res_fail)
end) 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() it('supports runtime queries', function()
---@type string[]
local ret = exec_lua [[ 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) end)
it('supports caching queries', function() it('supports caching queries', function()
local long_query = test_query:rep(100) local long_query = test_query:rep(100)
---@return number
local function q(n) local function q(n)
return exec_lua( return exec_lua(
[[ [[
local query, n = ... local query, n = ...
local before = vim.uv.hrtime() local before = vim.uv.hrtime()
for i=1,n,1 do for i=1, n, 1 do
cquery = vim.treesitter.query.parse("c", ...) cquery = vim.treesitter.query.parse("c", ...)
end end
local after = vim.uv.hrtime() local after = vim.uv.hrtime()
return after - before return after - before
]], ]],
long_query, long_query,
n n
) )
@ -217,126 +228,133 @@ void ui_refresh(void)
) )
end) end)
it('support query and iter by capture', function() it('supports query and iter by capture (iter_captures)', function()
insert(test_text) insert(test_text)
local res = exec_lua( local res = exec_lua(
[[ [[
cquery = vim.treesitter.query.parse("c", ...) cquery = vim.treesitter.query.parse("c", ...)
parser = vim.treesitter.get_parser(0, "c") parser = vim.treesitter.get_parser(0, "c")
tree = parser:parse()[1] tree = parser:parse()[1]
res = {} res = {}
for cid, node in cquery:iter_captures(tree:root(), 0, 7, 14) do 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 -- can't transmit node over RPC. just check the name and range
table.insert(res, {cquery.captures[cid], node:type(), node: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 },
}, res)
end)
it('support query and iter by match', 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 end
table.insert(res, {pattern, mrepr}) return res
end ]],
return res
]],
test_query test_query
) )
eq({ eq({
{ 3, { { 'type', 'primitive_type', 8, 2, 8, 6 } } }, { '@type', 'primitive_type', 8, 2, 8, 6 }, -- bool
{ 2, { { 'keyword', 'for', 9, 2, 9, 5 } } }, { '@keyword', 'for', 9, 2, 9, 5 }, -- for
{ 3, { { 'type', 'primitive_type', 9, 7, 9, 13 } } }, { '@type', 'primitive_type', 9, 7, 9, 13 }, -- size_t
{ 4, { { 'fieldarg', 'identifier', 11, 16, 11, 18 } } }, { '@minfunc', 'identifier', 11, 12, 11, 15 }, -- "MIN"(ui->width, width);
{ { '@fieldarg', 'identifier', 11, 16, 11, 18 }, -- ui
1, { '@min_id', 'identifier', 11, 27, 11, 32 }, -- width
{ { 'minfunc', 'identifier', 11, 12, 11, 15 }, { 'min_id', 'identifier', 11, 27, 11, 32 } }, { '@minfunc', 'identifier', 12, 13, 12, 16 }, -- "MIN"(ui->height, height);
}, { '@fieldarg', 'identifier', 12, 17, 12, 19 }, -- ui
{ 4, { { 'fieldarg', 'identifier', 12, 17, 12, 19 } } }, { '@min_id', 'identifier', 12, 29, 12, 35 }, -- height
{ { '@fieldarg', 'identifier', 13, 14, 13, 16 }, -- ui ; in BAR(..)
1,
{ { 'minfunc', 'identifier', 12, 13, 12, 16 }, { 'min_id', 'identifier', 12, 29, 12, 35 } },
},
{ 4, { { 'fieldarg', 'identifier', 13, 14, 13, 16 } } },
}, res) }, res)
end) end)
it('support query and iter by capture for quantifiers', 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() })
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) insert(test_text)
local res = exec_lua( local res = exec_lua(
[[ [[
cquery = vim.treesitter.query.parse("c", ...) cquery = vim.treesitter.query.parse("c", ...)
parser = vim.treesitter.get_parser(0, "c") parser = vim.treesitter.get_parser(0, "c")
tree = parser:parse()[1] tree = parser:parse()[1]
res = {} res = {}
for cid, node in cquery:iter_captures(tree:root(), 0, 7, 14) do 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 -- can't transmit node over RPC. just check the name and range
table.insert(res, {cquery.captures[cid], node:type(), node:range()}) table.insert(res, { '@' .. cquery.captures[cid], node:type(), node:range() })
end end
return res return res
]], ]],
'(expression_statement (assignment_expression (call_expression)))+ @funccall' '(expression_statement (assignment_expression (call_expression)))+ @funccall'
) )
eq({ eq({
{ 'funccall', 'expression_statement', 11, 4, 11, 34 }, { '@funccall', 'expression_statement', 11, 4, 11, 34 },
{ 'funccall', 'expression_statement', 12, 4, 12, 37 }, { '@funccall', 'expression_statement', 12, 4, 12, 37 },
{ 'funccall', 'expression_statement', 13, 4, 13, 34 }, { '@funccall', 'expression_statement', 13, 4, 13, 34 },
}, res) }, res)
end) end)
it('support query and iter by match for quantifiers', function() it('supports query and iter by match for quantifiers', function()
insert(test_text) insert(test_text)
local res = exec_lua( local res = exec_lua(
[[ [[
cquery = vim.treesitter.query.parse("c", ...) cquery = vim.treesitter.query.parse("c", ...)
parser = vim.treesitter.get_parser(0, "c") parser = vim.treesitter.get_parser(0, "c")
tree = parser:parse()[1] tree = parser:parse()[1]
res = {} res = {}
for pattern, match in cquery:iter_matches(tree:root(), 0, 7, 14, { all = true }) do 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 -- can't transmit node over RPC. just check the name and range
local mrepr = {} local mrepr = {}
for cid, nodes in pairs(match) do for cid, nodes in pairs(match) do
for _, node in ipairs(nodes) 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 end
table.insert(res, {pattern, mrepr})
end end
table.insert(res, {pattern, mrepr}) return res
end ]],
return res
]],
'(expression_statement (assignment_expression (call_expression)))+ @funccall' '(expression_statement (assignment_expression (call_expression)))+ @funccall'
) )
@ -344,9 +362,9 @@ void ui_refresh(void)
{ {
1, 1,
{ {
{ 'funccall', 'expression_statement', 11, 4, 11, 34 }, { '@funccall', 'expression_statement', 11, 4, 11, 34 },
{ 'funccall', 'expression_statement', 12, 4, 12, 37 }, { '@funccall', 'expression_statement', 12, 4, 12, 37 },
{ 'funccall', 'expression_statement', 13, 4, 13, 34 }, { '@funccall', 'expression_statement', 13, 4, 13, 34 },
}, },
}, },
}, res) }, res)
@ -369,7 +387,7 @@ void ui_refresh(void)
eq('void', res2) eq('void', res2)
end) 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 = [[ local text = [[
def run def run
a = <<~E a = <<~E
@ -378,25 +396,25 @@ end]]
eq( eq(
'', '',
exec_lua [[ exec_lua [[
local fake_node = {} local fake_node = {}
function fake_node:start() function fake_node:start()
return 3, 0, 23 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
end end
return 3, 0, 3, 0 function fake_node:end_()
end return 3, 0, 23
return vim.treesitter.get_node_text(fake_node, 0) 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) 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 = [[ local text = [[
```lua ```lua
{} {}
@ -421,12 +439,16 @@ end]]
it('can match special regex characters like \\ * + ( with `vim-match?`', function() it('can match special regex characters like \\ * + ( with `vim-match?`', function()
insert('char* astring = "\\n"; (1 + 1) * 2 != 2;') insert('char* astring = "\\n"; (1 + 1) * 2 != 2;')
---@type table
local res = exec_lua([[ local res = exec_lua([[
cquery = vim.treesitter.query.parse("c", '([_] @plus (#vim-match? @plus "^\\\\+$"))'.. query = (
'([_] @times (#vim-match? @times "^\\\\*$"))'.. '([_] @plus (#vim-match? @plus "^\\\\+$"))' ..
'([_] @paren (#vim-match? @paren "^\\\\($"))'.. '([_] @times (#vim-match? @times "^\\\\*$"))' ..
'([_] @escape (#vim-match? @escape "^\\\\\\\\n$"))'.. '([_] @paren (#vim-match? @paren "^\\\\($"))' ..
'([_] @string (#vim-match? @string "^\\"\\\\\\\\n\\"$"))') '([_] @escape (#vim-match? @escape "^\\\\\\\\n$"))' ..
'([_] @string (#vim-match? @string "^\\"\\\\\\\\n\\"$"))'
)
cquery = vim.treesitter.query.parse("c", query)
parser = vim.treesitter.get_parser(0, "c") parser = vim.treesitter.get_parser(0, "c")
tree = parser:parse()[1] tree = parser:parse()[1]
res = {} res = {}
@ -435,21 +457,21 @@ end]]
local mrepr = {} local mrepr = {}
for cid, nodes in pairs(match) do for cid, nodes in pairs(match) do
for _, node in ipairs(nodes) 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
end end
table.insert(res, {pattern, mrepr}) table.insert(res, { pattern, mrepr })
end end
return res return res
]]) ]])
eq({ eq({
{ 2, { { 'times', '*', 0, 4, 0, 5 } } }, { 2, { { '@times', '*', 0, 4, 0, 5 } } },
{ 5, { { 'string', 'string_literal', 0, 16, 0, 20 } } }, { 5, { { '@string', 'string_literal', 0, 16, 0, 20 } } },
{ 4, { { 'escape', 'escape_sequence', 0, 17, 0, 19 } } }, { 4, { { '@escape', 'escape_sequence', 0, 17, 0, 19 } } },
{ 3, { { 'paren', '(', 0, 22, 0, 23 } } }, { 3, { { '@paren', '(', 0, 22, 0, 23 } } },
{ 1, { { 'plus', '+', 0, 25, 0, 26 } } }, { 1, { { '@plus', '+', 0, 25, 0, 26 } } },
{ 2, { { 'times', '*', 0, 30, 0, 31 } } }, { 2, { { '@times', '*', 0, 30, 0, 31 } } },
}, res) }, res)
end) end)
@ -482,7 +504,7 @@ end]]
-- can't transmit node over RPC. just check the name, range, and text -- can't transmit node over RPC. just check the name, range, and text
local text = vim.treesitter.get_node_text(node, 0) local text = vim.treesitter.get_node_text(node, 0)
local range = {node:range()} 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 end
return res return res
end end
@ -514,12 +536,10 @@ end]]
}, res1) }, res1)
end) end)
it( it('allows loading query with escaped quotes and capture them `#{lua,vim}-match`?', function()
'allow loading query with escaped quotes and capture them with `lua-match?` and `vim-match?`', insert('char* astring = "Hello World!";')
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 "^\\"$"))') cquery = vim.treesitter.query.parse("c", '([_] @quote (#vim-match? @quote "^\\"$")) ([_] @quote (#lua-match? @quote "^\\"$"))')
parser = vim.treesitter.get_parser(0, "c") parser = vim.treesitter.get_parser(0, "c")
tree = parser:parse()[1] tree = parser:parse()[1]
@ -529,22 +549,21 @@ end]]
local mrepr = {} local mrepr = {}
for cid, nodes in pairs(match) do for cid, nodes in pairs(match) do
for _, node in ipairs(nodes) 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
end end
table.insert(res, {pattern, mrepr}) table.insert(res, { pattern, mrepr })
end end
return res return res
]]) ]])
eq({ eq({
{ 1, { { 'quote', '"', 0, 16, 0, 17 } } }, { 1, { { '@quote', '"', 0, 16, 0, 17 } } },
{ 2, { { 'quote', '"', 0, 16, 0, 17 } } }, { 2, { { '@quote', '"', 0, 16, 0, 17 } } },
{ 1, { { 'quote', '"', 0, 29, 0, 30 } } }, { 1, { { '@quote', '"', 0, 29, 0, 30 } } },
{ 2, { { 'quote', '"', 0, 29, 0, 30 } } }, { 2, { { '@quote', '"', 0, 29, 0, 30 } } },
}, res) }, res)
end end)
)
it('allows to add predicates', function() it('allows to add predicates', function()
insert([[ insert([[
@ -558,35 +577,35 @@ end]]
do do
local res = exec_lua( local res = exec_lua(
[[ [[
local query = vim.treesitter.query local query = vim.treesitter.query
local function is_main(match, pattern, bufnr, predicate) local function is_main(match, pattern, bufnr, predicate)
local nodes = match[ predicate[2] ] local nodes = match[ predicate[2] ]
for _, node in ipairs(nodes) do for _, node in ipairs(nodes) do
if vim.treesitter.get_node_text(node, bufnr) == 'main' then if vim.treesitter.get_node_text(node, bufnr) == 'main' then
return true return true
end
end
return false
end 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 -- Time bomb: update this in 0.12
if vim.fn.has('nvim-0.12') == 1 then if vim.fn.has('nvim-0.12') == 1 then
return 'Update this test to remove this message and { all = true } from add_predicate' return 'Update this test to remove this message and { all = true } from add_predicate'
end end
query.add_predicate("is-main?", is_main, { all = true }) query.add_predicate("is-main?", is_main, { all = true })
local query = query.parse("c", ...) local query = query.parse("c", ...)
local nodes = {} local nodes = {}
for _, node in query:iter_captures(parser:parse()[1]:root(), 0) do for _, node in query:iter_captures(parser:parse()[1]:root(), 0) do
table.insert(nodes, {node:range()}) table.insert(nodes, {node:range()})
end end
return nodes return nodes
]], ]],
custom_query custom_query
) )
@ -597,27 +616,27 @@ end]]
do do
local res = exec_lua( local res = exec_lua(
[[ [[
local query = vim.treesitter.query local query = vim.treesitter.query
local function is_main(match, pattern, bufnr, predicate) local function is_main(match, pattern, bufnr, predicate)
local node = match[ predicate[2] ] local node = match[ predicate[2] ]
return vim.treesitter.get_node_text(node, bufnr) == 'main' return vim.treesitter.get_node_text(node, bufnr) == 'main'
end 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 = {} local nodes = {}
for _, node in query:iter_captures(parser:parse()[1]:root(), 0) do for _, node in query:iter_captures(parser:parse()[1]:root(), 0) do
table.insert(nodes, {node:range()}) table.insert(nodes, {node:range()})
end end
return nodes return nodes
]], ]],
custom_query custom_query
) )
@ -657,14 +676,14 @@ end]]
api.nvim_buf_set_lines(0, 0, -1, true, vim.split(dedent(input), '\n')) api.nvim_buf_set_lines(0, 0, -1, true, vim.split(dedent(input), '\n'))
return exec_lua( return exec_lua(
[[ [[
local parser = vim.treesitter.get_parser(0, "lua") local parser = vim.treesitter.get_parser(0, "lua")
local query = vim.treesitter.query.parse("lua", ...) local query = vim.treesitter.query.parse("lua", ...)
local nodes = {} local nodes = {}
for _, node in query:iter_captures(parser:parse()[1]:root(), 0) do for _, node in query:iter_captures(parser:parse()[1]:root(), 0) do
nodes[#nodes+1] = { node:range() } nodes[#nodes+1] = { node:range() }
end end
return nodes return nodes
]], ]],
query query
) )
end end
@ -740,14 +759,14 @@ end]]
local result = exec_lua( local result = exec_lua(
[[ [[
local parser = vim.treesitter.get_parser(0, "lua") local parser = vim.treesitter.get_parser(0, "lua")
local query = vim.treesitter.query.parse("lua", ...) local query = vim.treesitter.query.parse("lua", ...)
local nodes = {} local nodes = {}
for _, node in query:iter_captures(parser:parse()[1]:root(), 0) do for _, node in query:iter_captures(parser:parse()[1]:root(), 0) do
nodes[#nodes+1] = { node:range() } nodes[#nodes+1] = { node:range() }
end end
return nodes return nodes
]], ]],
query query
) )
@ -765,37 +784,43 @@ end]]
insert(test_text) insert(test_text)
local res = exec_lua( local res = exec_lua(
[[ [[
cquery = vim.treesitter.query.parse("c", ...) cquery = vim.treesitter.query.parse("c", ...)
parser = vim.treesitter.get_parser(0, "c") parser = vim.treesitter.get_parser(0, "c")
tree = parser:parse()[1] tree = parser:parse()[1]
res = {} res = {}
for pattern, match in cquery:iter_matches(tree:root(), 0, 7, 14) do for pattern, match in cquery:iter_matches(tree:root(), 0, 7, 14) do
local mrepr = {} local mrepr = {}
for cid, node in pairs(match) do for cid, node in pairs(match) do
table.insert(mrepr, {cquery.captures[cid], node:type(), node:range()}) table.insert(mrepr, { '@' .. cquery.captures[cid], node:type(), node:range() })
end
table.insert(res, { pattern, mrepr })
end end
table.insert(res, {pattern, mrepr}) return res
end ]],
return res
]],
test_query test_query
) )
eq({ eq({
{ 3, { { 'type', 'primitive_type', 8, 2, 8, 6 } } }, { 3, { { '@type', 'primitive_type', 8, 2, 8, 6 } } },
{ 2, { { 'keyword', 'for', 9, 2, 9, 5 } } }, { 2, { { '@keyword', 'for', 9, 2, 9, 5 } } },
{ 3, { { 'type', 'primitive_type', 9, 7, 9, 13 } } }, { 3, { { '@type', 'primitive_type', 9, 7, 9, 13 } } },
{ 4, { { 'fieldarg', 'identifier', 11, 16, 11, 18 } } }, { 4, { { '@fieldarg', 'identifier', 11, 16, 11, 18 } } },
{ {
1, 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, 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) }, res)
end) end)
@ -882,17 +907,18 @@ end]]
local ret = exec_lua( local ret = exec_lua(
[[ [[
local str = ... local str = ...
local parser = vim.treesitter.get_string_parser(str, "c") local parser = vim.treesitter.get_string_parser(str, "c")
local nodes = {} local nodes = {}
local query = vim.treesitter.query.parse("c", '((identifier) @id (#eq? @id "foo"))') local query = vim.treesitter.query.parse("c", '((identifier) @id (#eq? @id "foo"))')
for _, node in query:iter_captures(parser:parse()[1]:root(), str) do for _, node in query:iter_captures(parser:parse()[1]:root(), str) do
table.insert(nodes, { node:range() }) table.insert(nodes, { node:range() })
end end
return nodes]], return nodes
]],
txt txt
) )
@ -907,18 +933,19 @@ end]]
local ret = exec_lua( local ret = exec_lua(
[[ [[
local str = ... local str = ...
local parser = vim.treesitter.get_string_parser(str, "c") local parser = vim.treesitter.get_string_parser(str, "c")
local nodes = {} local nodes = {}
local query = vim.treesitter.query.parse("c", '((identifier) @foo)') local query = vim.treesitter.query.parse("c", '((identifier) @foo)')
local first_child = parser:parse()[1]:root():child(1) local first_child = parser:parse()[1]:root():child(1)
for _, node in query:iter_captures(first_child, str) do for _, node in query:iter_captures(first_child, str) do
table.insert(nodes, { node:range() }) table.insert(nodes, { node:range() })
end end
return nodes]], return nodes
]],
txt txt
) )
@ -927,11 +954,11 @@ end]]
describe('when creating a language tree', function() describe('when creating a language tree', function()
local function get_ranges() local function get_ranges()
return exec_lua([[ return exec_lua [[
local result = {} local result = {}
parser:for_each_tree(function(tree) table.insert(result, {tree:root():range()}) end) parser:for_each_tree(function(tree) table.insert(result, {tree:root():range()}) end)
return result return result
]]) ]]
end end
before_each(function() before_each(function()
@ -948,10 +975,14 @@ int x = INT_MAX;
describe('when parsing regions independently', function() describe('when parsing regions independently', function()
it('should inject a language', function() it('should inject a language', function()
exec_lua([[ exec_lua([[
parser = vim.treesitter.get_parser(0, "c", { parser = vim.treesitter.get_parser(0, "c", {
injections = { injections = {
c = '(preproc_def (preproc_arg) @injection.content (#set! injection.language "c")) (preproc_function_def value: (preproc_arg) @injection.content (#set! injection.language "c"))'}}) c = (
parser:parse(true) '(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)')) eq('table', exec_lua('return type(parser:children().c)'))
@ -981,10 +1012,14 @@ int x = INT_MAX;
describe('when parsing regions combined', function() describe('when parsing regions combined', function()
it('should inject a language', function() it('should inject a language', function()
exec_lua([[ exec_lua([[
parser = vim.treesitter.get_parser(0, "c", { parser = vim.treesitter.get_parser(0, "c", {
injections = { 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))'}}) c = (
parser:parse(true) '(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)')) eq('table', exec_lua('return type(parser:children().c)'))
@ -1027,10 +1062,14 @@ int x = INT_MAX;
describe('when using injection.self', function() describe('when using injection.self', function()
it('should inject the source language', function() it('should inject the source language', function()
exec_lua([[ exec_lua([[
parser = vim.treesitter.get_parser(0, "c", { parser = vim.treesitter.get_parser(0, "c", {
injections = { injections = {
c = '(preproc_def (preproc_arg) @injection.content (#set! injection.self)) (preproc_function_def value: (preproc_arg) @injection.content (#set! injection.self))'}}) c = (
parser:parse(true) '(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)')) eq('table', exec_lua('return type(parser:children().c)'))
@ -1060,10 +1099,14 @@ int x = INT_MAX;
describe('when using the offset directive', function() describe('when using the offset directive', function()
it('should shift the range by the directive amount', function() it('should shift the range by the directive amount', function()
exec_lua([[ exec_lua([[
parser = vim.treesitter.get_parser(0, "c", { parser = vim.treesitter.get_parser(0, "c", {
injections = { 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"))'}}) c = (
parser:parse(true) '(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)')) eq('table', exec_lua('return type(parser:children().c)'))
@ -1078,13 +1121,13 @@ int x = INT_MAX;
end) end)
it('should list all directives', function() it('should list all directives', function()
local res_list = exec_lua [[ 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) eq({ 'gsub!', 'offset!', 'set!', 'trim!' }, res_list)
@ -1102,13 +1145,16 @@ int x = INT_MAX;
it('should return the correct language tree', function() it('should return the correct language tree', function()
local result = exec_lua([[ local result = exec_lua([[
parser = vim.treesitter.get_parser(0, "c", { parser = vim.treesitter.get_parser(0, "c", {
injections = { c = '(preproc_def (preproc_arg) @injection.content (#set! injection.language "c"))'}}) injections = {
parser:parse(true) 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) eq(true, result)
@ -1208,15 +1254,15 @@ int x = INT_MAX;
local function run_query() local function run_query()
return exec_lua( return exec_lua(
[[ [[
local query = vim.treesitter.query.parse("c", ...) local query = vim.treesitter.query.parse("c", ...)
parser = vim.treesitter.get_parser() parser = vim.treesitter.get_parser()
tree = parser:parse()[1] tree = parser:parse()[1]
res = {} res = {}
for id, node in query:iter_captures(tree:root()) do for id, node in query:iter_captures(tree:root()) do
table.insert(res, {query.captures[id], node:range()}) table.insert(res, {query.captures[id], node:range()})
end end
return res return res
]], ]],
query0 query0
) )
end end
@ -1258,14 +1304,14 @@ int x = INT_MAX;
local r = exec_lua( local r = exec_lua(
[[ [[
local parser = vim.treesitter.get_string_parser(..., 'lua') local parser = vim.treesitter.get_string_parser(..., 'lua')
parser:parse(true) parser:parse(true)
local ranges = {} local ranges = {}
parser:for_each_tree(function(tstree, tree) parser:for_each_tree(function(tstree, tree)
ranges[tree:lang()] = { tstree:root():range(true) } ranges[tree:lang()] = { tstree:root():range(true) }
end) end)
return ranges return ranges
]], ]],
source source
) )
@ -1281,14 +1327,14 @@ int x = INT_MAX;
local rb = exec_lua( local rb = exec_lua(
[[ [[
local r, source = ... local r, source = ...
local add_bytes = require('vim.treesitter._range').add_bytes local add_bytes = require('vim.treesitter._range').add_bytes
for lang, range in pairs(r) do for lang, range in pairs(r) do
r[lang] = {range[1], range[2], range[4], range[5]} r[lang] = {range[1], range[2], range[4], range[5]}
r[lang] = add_bytes(source, r[lang]) r[lang] = add_bytes(source, r[lang])
end end
return r return r
]], ]],
r, r,
source source
) )
@ -1448,7 +1494,7 @@ int x = INT_MAX;
) )
end) end)
describe('is_valid()', function() describe('languagetree is_valid()', function()
before_each(function() before_each(function()
insert(dedent [[ insert(dedent [[
Treesitter integration *treesitter* Treesitter integration *treesitter*