aboutsummaryrefslogtreecommitdiff
path: root/test/functional/treesitter
diff options
context:
space:
mode:
Diffstat (limited to 'test/functional/treesitter')
-rw-r--r--test/functional/treesitter/fold_spec.lua553
-rw-r--r--test/functional/treesitter/highlight_spec.lua475
-rw-r--r--test/functional/treesitter/inspect_tree_spec.lua115
-rw-r--r--test/functional/treesitter/language_spec.lua88
-rw-r--r--test/functional/treesitter/node_spec.lua19
-rw-r--r--test/functional/treesitter/parser_spec.lua961
-rw-r--r--test/functional/treesitter/utils_spec.lua1
7 files changed, 1456 insertions, 756 deletions
diff --git a/test/functional/treesitter/fold_spec.lua b/test/functional/treesitter/fold_spec.lua
index a8abbc002b..9428432f66 100644
--- a/test/functional/treesitter/fold_spec.lua
+++ b/test/functional/treesitter/fold_spec.lua
@@ -5,6 +5,7 @@ local insert = helpers.insert
local exec_lua = helpers.exec_lua
local command = helpers.command
local feed = helpers.feed
+local poke_eventloop = helpers.poke_eventloop
local Screen = require('test.functional.ui.screen')
before_each(clear)
@@ -12,6 +13,11 @@ before_each(clear)
describe('treesitter foldexpr', function()
clear()
+ before_each(function()
+ -- open folds to avoid deleting entire folded region
+ exec_lua([[vim.opt.foldlevel = 9]])
+ end)
+
local test_text = [[
void ui_refresh(void)
{
@@ -33,6 +39,12 @@ void ui_refresh(void)
}
}]]
+ local function parse(lang)
+ exec_lua(
+ ([[vim.treesitter.get_parser(0, %s):parse()]]):format(lang and '"' .. lang .. '"' or 'nil')
+ )
+ end
+
local function get_fold_levels()
return exec_lua([[
local res = {}
@@ -43,10 +55,10 @@ void ui_refresh(void)
]])
end
- it("can compute fold levels", function()
+ it('can compute fold levels', function()
insert(test_text)
- exec_lua([[vim.treesitter.get_parser(0, "c")]])
+ parse('c')
eq({
[1] = '>1',
@@ -67,16 +79,17 @@ void ui_refresh(void)
[16] = '3',
[17] = '3',
[18] = '2',
- [19] = '1' }, get_fold_levels())
-
+ [19] = '1',
+ }, get_fold_levels())
end)
- it("recomputes fold levels after lines are added/removed", function()
+ it('recomputes fold levels after lines are added/removed', function()
insert(test_text)
- exec_lua([[vim.treesitter.get_parser(0, "c")]])
+ parse('c')
command('1,2d')
+ poke_eventloop()
eq({
[1] = '0',
@@ -95,9 +108,11 @@ void ui_refresh(void)
[14] = '2',
[15] = '2',
[16] = '1',
- [17] = '0' }, get_fold_levels())
+ [17] = '0',
+ }, get_fold_levels())
command('1put!')
+ poke_eventloop()
eq({
[1] = '>1',
@@ -118,26 +133,295 @@ void ui_refresh(void)
[16] = '3',
[17] = '3',
[18] = '2',
- [19] = '1' }, get_fold_levels())
+ [19] = '1',
+ }, get_fold_levels())
+ end)
+
+ it('handles changes close to start/end of folds', function()
+ insert([[
+# h1
+t1
+# h2
+t2]])
+
+ exec_lua([[vim.treesitter.query.set('markdown', 'folds', '(section) @fold')]])
+ parse('markdown')
+
+ eq({
+ [1] = '>1',
+ [2] = '1',
+ [3] = '>1',
+ [4] = '1',
+ }, get_fold_levels())
+
+ feed('2ggo<Esc>')
+ poke_eventloop()
+
+ eq({
+ [1] = '>1',
+ [2] = '1',
+ [3] = '1',
+ [4] = '>1',
+ [5] = '1',
+ }, get_fold_levels())
+
+ feed('dd')
+ poke_eventloop()
+
+ eq({
+ [1] = '>1',
+ [2] = '1',
+ [3] = '>1',
+ [4] = '1',
+ }, get_fold_levels())
+
+ feed('2ggdd')
+ poke_eventloop()
+
+ eq({
+ [1] = '0',
+ [2] = '>1',
+ [3] = '1',
+ }, get_fold_levels())
+
+ feed('u')
+ poke_eventloop()
+
+ eq({
+ [1] = '>1',
+ [2] = '1',
+ [3] = '>1',
+ [4] = '1',
+ }, get_fold_levels())
+
+ feed('3ggdd')
+ poke_eventloop()
+
+ eq({
+ [1] = '>1',
+ [2] = '1',
+ [3] = '1',
+ }, get_fold_levels())
+
+ feed('u')
+ poke_eventloop()
+
+ eq({
+ [1] = '>1',
+ [2] = '1',
+ [3] = '>1',
+ [4] = '1',
+ }, get_fold_levels())
+
+ feed('3ggI#<Esc>')
+ parse()
+ poke_eventloop()
+
+ eq({
+ [1] = '>1',
+ [2] = '1',
+ [3] = '>2',
+ [4] = '2',
+ }, get_fold_levels())
+
+ feed('x')
+ parse()
+ poke_eventloop()
+
+ eq({
+ [1] = '>1',
+ [2] = '1',
+ [3] = '>1',
+ [4] = '1',
+ }, get_fold_levels())
end)
- it("updates folds in all windows", function()
+ it('handles changes that trigger multiple on_bytes', function()
+ insert([[
+function f()
+ asdf()
+ asdf()
+end
+-- comment]])
+
+ exec_lua(
+ [[vim.treesitter.query.set('lua', 'folds', '[(function_declaration) (parameters) (arguments)] @fold')]]
+ )
+ parse('lua')
+
+ eq({
+ [1] = '>1',
+ [2] = '1',
+ [3] = '1',
+ [4] = '1',
+ [5] = '0',
+ }, get_fold_levels())
+
+ command('1,4join')
+ poke_eventloop()
+
+ eq({
+ [1] = '0',
+ [2] = '0',
+ }, get_fold_levels())
+
+ feed('u')
+ poke_eventloop()
+
+ eq({
+ [1] = '>1',
+ [2] = '1',
+ [3] = '1',
+ [4] = '1',
+ [5] = '0',
+ }, get_fold_levels())
+ end)
+
+ it('handles multiple folds that overlap at the end and start', function()
+ insert([[
+function f()
+ g(
+ function()
+ asdf()
+ end, function()
+ end
+ )
+end]])
+
+ exec_lua(
+ [[vim.treesitter.query.set('lua', 'folds', '[(function_declaration) (function_definition) (parameters) (arguments)] @fold')]]
+ )
+ parse('lua')
+
+ -- If fold1.stop = fold2.start, then move fold1's stop up so that fold2.start gets proper level.
+ eq({
+ [1] = '>1',
+ [2] = '>2',
+ [3] = '>3',
+ [4] = '3',
+ [5] = '>3',
+ [6] = '3',
+ [7] = '2',
+ [8] = '1',
+ }, get_fold_levels())
+
+ command('1,8join')
+ feed('u')
+ poke_eventloop()
+
+ eq({
+ [1] = '>1',
+ [2] = '>2',
+ [3] = '>3',
+ [4] = '3',
+ [5] = '>3',
+ [6] = '3',
+ [7] = '2',
+ [8] = '1',
+ }, get_fold_levels())
+ end)
+
+ it('handles multiple folds that start at the same line', function()
+ insert([[
+function f(a)
+ if #(g({
+ k = v,
+ })) > 0 then
+ return
+ end
+end]])
+
+ exec_lua(
+ [[vim.treesitter.query.set('lua', 'folds', '[(if_statement) (function_declaration) (parameters) (arguments) (table_constructor)] @fold')]]
+ )
+ parse('lua')
+
+ eq({
+ [1] = '>1',
+ [2] = '>3',
+ [3] = '3',
+ [4] = '3',
+ [5] = '2',
+ [6] = '2',
+ [7] = '1',
+ }, get_fold_levels())
+
+ command('2,6join')
+ poke_eventloop()
+
+ eq({
+ [1] = '>1',
+ [2] = '1',
+ [3] = '1',
+ }, get_fold_levels())
+
+ feed('u')
+ poke_eventloop()
+
+ eq({
+ [1] = '>1',
+ [2] = '>3',
+ [3] = '3',
+ [4] = '3',
+ [5] = '2',
+ [6] = '2',
+ [7] = '1',
+ }, get_fold_levels())
+ end)
+
+ it('takes account of relevant options', function()
+ insert([[
+# h1
+t1
+## h2
+t2
+### h3
+t3]])
+
+ exec_lua([[vim.treesitter.query.set('markdown', 'folds', '(section) @fold')]])
+ parse('markdown')
+
+ command([[set foldminlines=2]])
+
+ eq({
+ [1] = '>1',
+ [2] = '1',
+ [3] = '>2',
+ [4] = '2',
+ [5] = '2',
+ [6] = '2',
+ }, get_fold_levels())
+
+ command([[set foldminlines=1 foldnestmax=1]])
+
+ eq({
+ [1] = '>1',
+ [2] = '1',
+ [3] = '1',
+ [4] = '1',
+ [5] = '1',
+ [6] = '1',
+ }, get_fold_levels())
+ end)
+
+ it('updates folds in all windows', function()
local screen = Screen.new(60, 48)
screen:attach()
screen:set_default_attr_ids({
- [1] = {background = Screen.colors.Grey, foreground = Screen.colors.DarkBlue};
- [2] = {bold = true, foreground = Screen.colors.Blue1};
- [3] = {bold = true, reverse = true};
- [4] = {reverse = true};
+ [1] = { background = Screen.colors.Grey, foreground = Screen.colors.DarkBlue },
+ [2] = { bold = true, foreground = Screen.colors.Blue1 },
+ [3] = { bold = true, reverse = true },
+ [4] = { reverse = true },
})
- exec_lua([[vim.treesitter.get_parser(0, "c")]])
- command([[set foldmethod=expr foldexpr=v:lua.vim.treesitter.foldexpr() foldcolumn=1 foldlevel=9]])
+ parse('c')
+ command([[set foldmethod=expr foldexpr=v:lua.vim.treesitter.foldexpr() foldcolumn=1]])
command('split')
insert(test_text)
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1:-}void ui_refresh(void) |
{1:│}{ |
{1:│} int width = INT_MAX, height = INT_MAX; |
@@ -157,10 +441,7 @@ void ui_refresh(void)
{1:3} } |
{1:2} } |
{1:│}^} |
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*4
{3:[No Name] [+] }|
{1:-}void ui_refresh(void) |
{1:│}{ |
@@ -181,16 +462,16 @@ void ui_refresh(void)
{1:3} } |
{1:2} } |
{1:│}} |
- {2:~ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*3
{4:[No Name] [+] }|
|
- ]]}
+ ]],
+ }
command('1,2d')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1: } ^int width = INT_MAX, height = INT_MAX; |
{1: } bool ext_widgets[kUIExtCount]; |
{1:-} for (UIExtension i = 0; (int)i < kUIExtCount; i++) { |
@@ -208,12 +489,7 @@ void ui_refresh(void)
{1:2} } |
{1:│} } |
{1: }} |
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*6
{3:[No Name] [+] }|
{1: } int width = INT_MAX, height = INT_MAX; |
{1: } bool ext_widgets[kUIExtCount]; |
@@ -232,19 +508,16 @@ void ui_refresh(void)
{1:2} } |
{1:│} } |
{1: }} |
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*5
{4:[No Name] [+] }|
|
- ]]}
-
+ ]],
+ }
feed([[O<C-u><C-r>"<BS><Esc>]])
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1:-}void ui_refresh(void) |
{1:│}^{ |
{1:│} int width = INT_MAX, height = INT_MAX; |
@@ -264,10 +537,7 @@ void ui_refresh(void)
{1:3} } |
{1:2} } |
{1:│}} |
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*4
{3:[No Name] [+] }|
{1:-}void ui_refresh(void) |
{1:│}{ |
@@ -288,21 +558,21 @@ void ui_refresh(void)
{1:3} } |
{1:2} } |
{1:│}} |
- {2:~ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*3
{4:[No Name] [+] }|
|
- ]]}
-
+ ]],
+ }
end)
it("doesn't open folds in diff mode", function()
local screen = Screen.new(60, 36)
screen:attach()
- exec_lua([[vim.treesitter.get_parser(0, "c")]])
- command([[set foldmethod=expr foldexpr=v:lua.vim.treesitter.foldexpr() foldcolumn=1 foldlevel=9]])
+ parse('c')
+ command(
+ [[set foldmethod=expr foldexpr=v:lua.vim.treesitter.foldexpr() foldcolumn=1 foldlevel=9]]
+ )
insert(test_text)
command('16d')
@@ -312,7 +582,8 @@ void ui_refresh(void)
command('windo diffthis')
feed('do')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1:+ }{2:+-- 9 lines: void ui_refresh(void)·······················}|
{1: } for (size_t i = 0; i < ui_count; i++) { |
{1: } UI *ui = uis[i]; |
@@ -324,12 +595,7 @@ void ui_refresh(void)
{1: } } |
{1: } } |
{1: }} |
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
+ {3:~ }|*6
{4:[No Name] [+] }|
{1:+ }{2:+-- 9 lines: void ui_refresh(void)·······················}|
{1: } for (size_t i = 0; i < ui_count; i++) { |
@@ -342,133 +608,70 @@ void ui_refresh(void)
{1: } ^} |
{1: } } |
{1: }} |
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
+ {3:~ }|*5
{5:[No Name] [+] }|
|
- ]], attr_ids={
- [1] = {background = Screen.colors.Grey, foreground = Screen.colors.Blue4};
- [2] = {background = Screen.colors.LightGrey, foreground = Screen.colors.Blue4};
- [3] = {foreground = Screen.colors.Blue, bold = true};
- [4] = {reverse = true};
- [5] = {reverse = true, bold = true};
- }}
- end)
-
-end)
-
-describe('treesitter foldtext', function()
- local test_text = [[
-void qsort(void *base, size_t nel, size_t width, int (*compar)(const void *, const void *))
-{
- int width = INT_MAX, height = INT_MAX;
- bool ext_widgets[kUIExtCount];
- for (UIExtension i = 0; (int)i < kUIExtCount; i++) {
- ext_widgets[i] = true;
- }
-
- bool inclusive = ui_override();
- for (size_t i = 0; i < ui_count; i++) {
- UI *ui = uis[i];
- width = MIN(ui->width, width);
- height = MIN(ui->height, height);
- foo = BAR(ui->bazaar, bazaar);
- for (UIExtension j = 0; (int)j < kUIExtCount; j++) {
- ext_widgets[j] &= (ui->ui_ext[j] || inclusive);
+ ]],
+ attr_ids = {
+ [1] = { background = Screen.colors.Grey, foreground = Screen.colors.Blue4 },
+ [2] = { background = Screen.colors.LightGrey, foreground = Screen.colors.Blue4 },
+ [3] = { foreground = Screen.colors.Blue, bold = true },
+ [4] = { reverse = true },
+ [5] = { reverse = true, bold = true },
+ },
}
- }
-}]]
- local screen
+ end)
- before_each(function()
- screen = Screen.new(60, 5)
+ it("doesn't open folds that are not touched", function()
+ local screen = Screen.new(40, 8)
screen:set_default_attr_ids({
- [0] = {foreground = Screen.colors.Blue, bold = true},
- [1] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.LightGray};
- [2] = {bold = true, background = Screen.colors.LightGray, foreground = Screen.colors.SeaGreen};
- [3] = {foreground = Screen.colors.DarkCyan, background = Screen.colors.LightGray};
- [4] = {foreground = Screen.colors.SlateBlue, background = Screen.colors.LightGray};
- [5] = {bold = true, background = Screen.colors.LightGray, foreground = Screen.colors.Brown};
- [6] = {background = Screen.colors.Red1};
- [7] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.Red};
- [8] = {foreground = Screen.colors.Brown, bold = true, background = Screen.colors.Red};
- [9] = {foreground = Screen.colors.SlateBlue, background = Screen.colors.Red};
- [10] = {bold = true};
+ [1] = { foreground = Screen.colors.DarkBlue, background = Screen.colors.Gray },
+ [2] = { foreground = Screen.colors.DarkBlue, background = Screen.colors.LightGray },
+ [3] = { foreground = Screen.colors.Blue1, bold = true },
+ [4] = { bold = true },
})
screen:attach()
- end)
- it('displays highlighted content', function()
- command([[set foldmethod=manual foldtext=v:lua.vim.treesitter.foldtext() updatetime=50]])
- insert(test_text)
- exec_lua([[vim.treesitter.get_parser(0, "c")]])
-
- feed('ggVGzf')
- screen:expect{grid=[[
- {2:^void}{1: }{3:qsort}{4:(}{2:void}{1: }{5:*}{3:base}{4:,}{1: }{2:size_t}{1: }{3:nel}{4:,}{1: }{2:size_t}{1: }{3:width}{4:,}{1: }{2:int}{1: }{4:(}{5:*}{3:compa}|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- |
- ]]}
- end)
-
- it('handles deep nested captures', function()
- command([[set foldmethod=manual foldtext=v:lua.vim.treesitter.foldtext() updatetime=50]])
insert([[
-function FoldInfo.new()
- return setmetatable({
- start_counts = {},
- stop_counts = {},
- levels0 = {},
- levels = {},
- }, FoldInfo)
-end]])
- exec_lua([[vim.treesitter.get_parser(0, "lua")]])
-
- feed('ggjVGkzfgg')
- screen:expect{grid=[[
- ^function FoldInfo.new() |
- {1: }{5:return}{1: }{4:setmetatable({}{1:·····································}|
- end |
- {0:~ }|
- |
- ]]}
-
- command('hi! Visual guibg=Red')
- feed('GVgg')
- screen:expect{grid=[[
- ^f{6:unction FoldInfo.new()} |
- {7: }{8:return}{7: }{9:setmetatable({}{7:·····································}|
- {6:end} |
- {0:~ }|
- {10:-- VISUAL LINE --} |
- ]]}
-
- feed('10l<C-V>')
- screen:expect{grid=[[
- {6:function F}^oldInfo.new() |
- {7: }{8:return}{7: }{9:se}{4:tmetatable({}{1:·····································}|
- {6:end} |
- {0:~ }|
- {10:-- VISUAL BLOCK --} |
- ]]}
- end)
-
- it('falls back to default', function()
- command([[set foldmethod=manual foldtext=v:lua.vim.treesitter.foldtext()]])
- insert(test_text)
+# h1
+t1
+# h2
+t2]])
+ exec_lua([[vim.treesitter.query.set('markdown', 'folds', '(section) @fold')]])
+ parse('markdown')
+ command(
+ [[set foldmethod=expr foldexpr=v:lua.vim.treesitter.foldexpr() foldcolumn=1 foldlevel=0]]
+ )
+
+ feed('ggzojo')
+ poke_eventloop()
+
+ screen:expect {
+ grid = [[
+ {1:-}# h1 |
+ {1:│}t1 |
+ {1:│}^ |
+ {1:+}{2:+-- 2 lines: # h2·····················}|
+ {3:~ }|*3
+ {4:-- INSERT --} |
+ ]],
+ }
- feed('ggVGzf')
- screen:expect{grid=[[
- {1:^+-- 19 lines: void qsort(void *base, size_t nel, size_t widt}|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- |
- ]]}
+ feed('<Esc>u')
+ -- TODO(tomtomjhj): `u` spuriously opens the fold (#26499).
+ feed('zMggzo')
+
+ feed('dd')
+ poke_eventloop()
+
+ screen:expect {
+ grid = [[
+ {1:-}^t1 |
+ {1:-}# h2 |
+ {1:│}t2 |
+ {3:~ }|*4
+ 1 line less; before #2 {MATCH:.*}|
+ ]],
+ }
end)
end)
diff --git a/test/functional/treesitter/highlight_spec.lua b/test/functional/treesitter/highlight_spec.lua
index e037c9e215..2bf230fe69 100644
--- a/test/functional/treesitter/highlight_spec.lua
+++ b/test/functional/treesitter/highlight_spec.lua
@@ -6,7 +6,7 @@ local insert = helpers.insert
local exec_lua = helpers.exec_lua
local feed = helpers.feed
local command = helpers.command
-local meths = helpers.meths
+local api = helpers.api
local eq = helpers.eq
before_each(clear)
@@ -100,17 +100,7 @@ local injection_grid_c = [[
return 42; \ |
} |
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*11
|
]]
@@ -121,17 +111,7 @@ local injection_grid_expected_c = [[
{4:return} {5:42}; \ |
} |
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*11
|
]]
@@ -142,17 +122,17 @@ describe('treesitter highlighting (C)', function()
screen = Screen.new(65, 18)
screen:attach()
screen:set_default_attr_ids {
- [1] = {bold = true, foreground = Screen.colors.Blue1};
- [2] = {foreground = Screen.colors.Blue1};
- [3] = {bold = true, foreground = Screen.colors.SeaGreen4};
- [4] = {bold = true, foreground = Screen.colors.Brown};
- [5] = {foreground = Screen.colors.Magenta};
- [6] = {foreground = Screen.colors.Red};
- [7] = {bold = true, foreground = Screen.colors.SlateBlue};
- [8] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red};
- [9] = {foreground = Screen.colors.Magenta, background = Screen.colors.Red};
- [10] = {foreground = Screen.colors.Red, background = Screen.colors.Red};
- [11] = {foreground = Screen.colors.Cyan4};
+ [1] = { bold = true, foreground = Screen.colors.Blue1 },
+ [2] = { foreground = Screen.colors.Blue1 },
+ [3] = { bold = true, foreground = Screen.colors.SeaGreen4 },
+ [4] = { bold = true, foreground = Screen.colors.Brown },
+ [5] = { foreground = Screen.colors.Magenta },
+ [6] = { foreground = Screen.colors.Red },
+ [7] = { bold = true, foreground = Screen.colors.SlateBlue },
+ [8] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red },
+ [9] = { foreground = Screen.colors.Magenta, background = Screen.colors.Red },
+ [10] = { foreground = Screen.colors.Red, background = Screen.colors.Red },
+ [11] = { foreground = Screen.colors.Cyan4 },
}
exec_lua([[ hl_query = ... ]], hl_query_c)
@@ -162,7 +142,8 @@ describe('treesitter highlighting (C)', function()
it('is updated with edits', function()
insert(hl_text_c)
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
/// Schedule Lua callback on main loop's event queue |
static int nlua_schedule(lua_State *const lstate) |
{ |
@@ -178,17 +159,18 @@ describe('treesitter highlighting (C)', function()
1, (void *)(ptrdiff_t)cb); |
return 0; |
^} |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
- ]]}
+ ]],
+ }
exec_lua [[
local parser = vim.treesitter.get_parser(0, "c")
local highlighter = vim.treesitter.highlighter
test_hl = highlighter.new(parser, {queries = {c = hl_query}})
]]
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{2:/// Schedule Lua callback on main loop's event queue} |
{3:static} {3:int} {11:nlua_schedule}({3:lua_State} *{3:const} lstate) |
{ |
@@ -204,14 +186,15 @@ describe('treesitter highlighting (C)', function()
{5:1}, ({3:void} *)({3:ptrdiff_t})cb); |
{4:return} {5:0}; |
^} |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
- ]]}
+ ]],
+ }
- feed("5Goc<esc>dd")
+ feed('5Goc<esc>dd')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{2:/// Schedule Lua callback on main loop's event queue} |
{3:static} {3:int} {11:nlua_schedule}({3:lua_State} *{3:const} lstate) |
{ |
@@ -227,13 +210,14 @@ describe('treesitter highlighting (C)', function()
{5:1}, ({3:void} *)({3:ptrdiff_t})cb); |
{4:return} {5:0}; |
} |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
- ]]}
+ ]],
+ }
feed('7Go*/<esc>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{2:/// Schedule Lua callback on main loop's event queue} |
{3:static} {3:int} {11:nlua_schedule}({3:lua_State} *{3:const} lstate) |
{ |
@@ -252,10 +236,12 @@ describe('treesitter highlighting (C)', function()
} |
{1:~ }|
|
- ]]}
+ ]],
+ }
feed('3Go/*<esc>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{2:/// Schedule Lua callback on main loop's event queue} |
{3:static} {3:int} {11:nlua_schedule}({3:lua_State} *{3:const} lstate) |
{ |
@@ -274,11 +260,13 @@ describe('treesitter highlighting (C)', function()
{4:return} {5:0}; |
{8:}} |
|
- ]]}
+ ]],
+ }
- feed("gg$")
- feed("~")
- screen:expect{grid=[[
+ feed('gg$')
+ feed('~')
+ screen:expect {
+ grid = [[
{2:/// Schedule Lua callback on main loop's event queu^E} |
{3:static} {3:int} {11:nlua_schedule}({3:lua_State} *{3:const} lstate) |
{ |
@@ -297,11 +285,12 @@ describe('treesitter highlighting (C)', function()
{4:return} {5:0}; |
{8:}} |
|
- ]]}
-
+ ]],
+ }
- feed("re")
- screen:expect{grid=[[
+ feed('re')
+ screen:expect {
+ grid = [[
{2:/// Schedule Lua callback on main loop's event queu^e} |
{3:static} {3:int} {11:nlua_schedule}({3:lua_State} *{3:const} lstate) |
{ |
@@ -320,7 +309,8 @@ describe('treesitter highlighting (C)', function()
{4:return} {5:0}; |
{8:}} |
|
- ]]}
+ ]],
+ }
end)
it('is updated with :sort', function()
@@ -329,7 +319,8 @@ describe('treesitter highlighting (C)', function()
local parser = vim.treesitter.get_parser(0, "c")
test_hl = vim.treesitter.highlighter.new(parser, {queries = {c = hl_query}})
]]
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{3:int} width = {5:INT_MAX}, height = {5:INT_MAX}; |
{3:bool} ext_widgets[kUIExtCount]; |
{4:for} ({3:UIExtension} i = {5:0}; ({3:int})i < kUIExtCount; i++) { |
@@ -348,10 +339,12 @@ describe('treesitter highlighting (C)', function()
} |
^} |
|
- ]]}
+ ]],
+ }
- feed ":sort<cr>"
- screen:expect{grid=[[
+ feed ':sort<cr>'
+ screen:expect {
+ grid = [[
^ |
ext_widgets[j] &= (ui->ui_ext[j] || inclusive); |
{3:UI} *ui = uis[i]; |
@@ -366,15 +359,16 @@ describe('treesitter highlighting (C)', function()
{4:for} ({3:UIExtension} i = {5:0}; ({3:int})i < kUIExtCount; i++) { |
{4:for} ({3:size_t} i = {5:0}; i < ui_count; i++) { |
{3:int} width = {5:INT_MAX}, height = {5:INT_MAX}; |
- } |
- } |
+ } |*2
{3:void} ui_refresh({3:void}) |
:sort |
- ]]}
+ ]],
+ }
- feed "u"
+ feed 'u'
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{3:int} width = {5:INT_MAX}, height = {5:INT_MAX}; |
{3:bool} ext_widgets[kUIExtCount]; |
{4:for} ({3:UIExtension} i = {5:0}; ({3:int})i < kUIExtCount; i++) { |
@@ -393,17 +387,19 @@ describe('treesitter highlighting (C)', function()
} |
^} |
19 changes; before #2 {MATCH:.*}|
- ]]}
+ ]],
+ }
end)
- it("supports with custom parser", function()
+ it('supports with custom parser', function()
screen:set_default_attr_ids {
- [1] = {bold = true, foreground = Screen.colors.SeaGreen4};
+ [1] = { bold = true, foreground = Screen.colors.SeaGreen4 },
}
insert(test_text_c)
- screen:expect{ grid= [[
+ screen:expect {
+ grid = [[
int width = INT_MAX, height = INT_MAX; |
bool ext_widgets[kUIExtCount]; |
for (UIExtension i = 0; (int)i < kUIExtCount; i++) { |
@@ -422,7 +418,8 @@ describe('treesitter highlighting (C)', function()
} |
^} |
|
- ]] }
+ ]],
+ }
exec_lua [[
parser = vim.treesitter.get_parser(0, "c")
@@ -438,7 +435,8 @@ describe('treesitter highlighting (C)', function()
local hl = vim.treesitter.highlighter.new(parser, {queries = {c = "(identifier) @type"}})
]]
- screen:expect{ grid = [[
+ screen:expect {
+ grid = [[
int {1:width} = {1:INT_MAX}, {1:height} = {1:INT_MAX}; |
bool {1:ext_widgets}[{1:kUIExtCount}]; |
for (UIExtension {1:i} = 0; (int)i < kUIExtCount; i++) { |
@@ -457,13 +455,14 @@ describe('treesitter highlighting (C)', function()
} |
^} |
|
- ]] }
+ ]],
+ }
end)
- it("supports injected languages", function()
+ it('supports injected languages', function()
insert(injection_text_c)
- screen:expect{grid=injection_grid_c}
+ screen:expect { grid = injection_grid_c }
exec_lua [[
local parser = vim.treesitter.get_parser(0, "c", {
@@ -473,13 +472,13 @@ describe('treesitter highlighting (C)', function()
test_hl = highlighter.new(parser, {queries = {c = hl_query}})
]]
- screen:expect{grid=injection_grid_expected_c}
+ screen:expect { grid = injection_grid_expected_c }
end)
it("supports injecting by ft name in metadata['injection.language']", function()
insert(injection_text_c)
- screen:expect{grid=injection_grid_c}
+ screen:expect { grid = injection_grid_c }
exec_lua [[
vim.treesitter.language.register("c", "foo")
@@ -490,10 +489,10 @@ describe('treesitter highlighting (C)', function()
test_hl = highlighter.new(parser, {queries = {c = hl_query}})
]]
- screen:expect{grid=injection_grid_expected_c}
+ screen:expect { grid = injection_grid_expected_c }
end)
- it("supports overriding queries, like ", function()
+ it('supports overriding queries, like ', function()
insert([[
int x = INT_MAX;
#define READ_STRING(x, y) (char *)read_string((x), (size_t)(y))
@@ -510,29 +509,21 @@ describe('treesitter highlighting (C)', function()
vim.treesitter.highlighter.new(vim.treesitter.get_parser(0, "c"))
]]
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{3:int} x = {5:INT_MAX}; |
#define {5:READ_STRING}(x, y) ({3:char} *)read_string((x), ({3:size_t})(y)) |
#define foo {3:void} main() { \ |
{4:return} {5:42}; \ |
} |
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*11
|
- ]]}
+ ]],
+ }
end)
- it("supports highlighting with custom highlight groups", function()
+ it('supports highlighting with custom highlight groups', function()
insert(hl_text_c)
exec_lua [[
@@ -540,7 +531,8 @@ describe('treesitter highlighting (C)', function()
test_hl = vim.treesitter.highlighter.new(parser, {queries = {c = hl_query}})
]]
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{2:/// Schedule Lua callback on main loop's event queue} |
{3:static} {3:int} {11:nlua_schedule}({3:lua_State} *{3:const} lstate) |
{ |
@@ -556,15 +548,16 @@ describe('treesitter highlighting (C)', function()
{5:1}, ({3:void} *)({3:ptrdiff_t})cb); |
{4:return} {5:0}; |
^} |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
- ]]}
+ ]],
+ }
-- This will change ONLY the literal strings to look like comments
-- The only literal string is the "vim.schedule: expected function" in this test.
exec_lua [[vim.cmd("highlight link @string.nonexistent_specializer comment")]]
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{2:/// Schedule Lua callback on main loop's event queue} |
{3:static} {3:int} {11:nlua_schedule}({3:lua_State} *{3:const} lstate) |
{ |
@@ -580,14 +573,14 @@ describe('treesitter highlighting (C)', function()
{5:1}, ({3:void} *)({3:ptrdiff_t})cb); |
{4:return} {5:0}; |
^} |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
- ]]}
- screen:expect{ unchanged=true }
+ ]],
+ }
+ screen:expect { unchanged = true }
end)
- it("supports highlighting with priority", function()
+ it('supports highlighting with priority', function()
insert([[
int x = INT_MAX;
#define READ_STRING(x, y) (char *)read_string((x), (size_t)(y))
@@ -601,120 +594,80 @@ describe('treesitter highlighting (C)', function()
test_hl = vim.treesitter.highlighter.new(parser, {queries = {c = hl_query..'\n((translation_unit) @constant (#set! "priority" 101))\n'}})
]]
-- expect everything to have Constant highlight
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{12:int}{8: x = INT_MAX;} |
{8:#define READ_STRING(x, y) (}{12:char}{8: *)read_string((x), (}{12:size_t}{8:)(y))} |
{8:#define foo }{12:void}{8: main() { \} |
{8: }{12:return}{8: 42; \} |
{8: }} |
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- |
- ]], attr_ids={
- [1] = {bold = true, foreground = Screen.colors.Blue1};
- [8] = {foreground = Screen.colors.Magenta1};
- -- bold will not be overwritten at the moment
- [12] = {bold = true, foreground = Screen.colors.Magenta1};
- }}
+ {1:~ }|*11
+ |
+ ]],
+ attr_ids = {
+ [1] = { bold = true, foreground = Screen.colors.Blue1 },
+ [8] = { foreground = Screen.colors.Magenta1 },
+ -- bold will not be overwritten at the moment
+ [12] = { bold = true, foreground = Screen.colors.Magenta1 },
+ },
+ }
eq({
- {capture='constant', metadata = { priority='101' }, lang='c' };
- {capture='type', metadata = { }, lang='c' };
+ { capture = 'constant', metadata = { priority = '101' }, lang = 'c' },
+ { capture = 'type', metadata = {}, lang = 'c' },
}, exec_lua [[ return vim.treesitter.get_captures_at_pos(0, 0, 2) ]])
- end)
+ end)
- it("allows to use captures with dots (don't use fallback when specialization of foo exists)", function()
- insert([[
+ it(
+ "allows to use captures with dots (don't use fallback when specialization of foo exists)",
+ function()
+ insert([[
char* x = "Will somebody ever read this?";
]])
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
char* x = "Will somebody ever read this?"; |
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*15
|
- ]]}
+ ]],
+ }
- command [[
+ command [[
hi link @foo.bar Type
hi link @foo String
]]
- exec_lua [[
+ exec_lua [[
local parser = vim.treesitter.get_parser(0, "c", {})
local highlighter = vim.treesitter.highlighter
test_hl = highlighter.new(parser, {queries = {c = "(primitive_type) @foo.bar (string_literal) @foo"}})
]]
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{3:char}* x = {5:"Will somebody ever read this?"}; |
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*15
|
- ]]}
+ ]],
+ }
- -- clearing specialization reactivates fallback
- command [[ hi clear @foo.bar ]]
- screen:expect{grid=[[
+ -- clearing specialization reactivates fallback
+ command [[ hi clear @foo.bar ]]
+ screen:expect {
+ grid = [[
{5:char}* x = {5:"Will somebody ever read this?"}; |
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*15
|
- ]]}
- end)
+ ]],
+ }
+ end
+ )
- it("supports conceal attribute", function()
+ it('supports conceal attribute', function()
insert(hl_text_c)
-- conceal can be empty or a single cchar.
@@ -723,15 +676,16 @@ describe('treesitter highlighting (C)', function()
local parser = vim.treesitter.get_parser(0, "c")
test_hl = vim.treesitter.highlighter.new(parser, {queries = {c = [[
("static" @keyword
- (set! conceal "R"))
+ (#set! conceal "R"))
((identifier) @Identifier
- (set! conceal "")
- (eq? @Identifier "lstate"))
+ (#set! conceal "")
+ (#eq? @Identifier "lstate"))
]]}})
]=]
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
/// Schedule Lua callback on main loop's event queue |
{4:R} int nlua_schedule(lua_State *const ) |
{ |
@@ -747,33 +701,60 @@ describe('treesitter highlighting (C)', function()
1, (void *)(ptrdiff_t)cb); |
return 0; |
^} |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
- ]]}
+ ]],
+ }
end)
- it("@foo.bar groups has the correct fallback behavior", function()
- local get_hl = function(name) return meths.get_hl_by_name(name,1).foreground end
- meths.set_hl(0, "@foo", {fg = 1})
- meths.set_hl(0, "@foo.bar", {fg = 2})
- meths.set_hl(0, "@foo.bar.baz", {fg = 3})
-
- eq(1, get_hl"@foo")
- eq(1, get_hl"@foo.a.b.c.d")
- eq(2, get_hl"@foo.bar")
- eq(2, get_hl"@foo.bar.a.b.c.d")
- eq(3, get_hl"@foo.bar.baz")
- eq(3, get_hl"@foo.bar.baz.d")
+ it('@foo.bar groups has the correct fallback behavior', function()
+ local get_hl = function(name)
+ return api.nvim_get_hl_by_name(name, 1).foreground
+ end
+ api.nvim_set_hl(0, '@foo', { fg = 1 })
+ api.nvim_set_hl(0, '@foo.bar', { fg = 2 })
+ api.nvim_set_hl(0, '@foo.bar.baz', { fg = 3 })
+
+ eq(1, get_hl '@foo')
+ eq(1, get_hl '@foo.a.b.c.d')
+ eq(2, get_hl '@foo.bar')
+ eq(2, get_hl '@foo.bar.a.b.c.d')
+ eq(3, get_hl '@foo.bar.baz')
+ eq(3, get_hl '@foo.bar.baz.d')
-- lookup is case insensitive
- eq(2, get_hl"@FOO.BAR.SPAM")
+ eq(2, get_hl '@FOO.BAR.SPAM')
+
+ api.nvim_set_hl(0, '@foo.missing.exists', { fg = 3 })
+ eq(1, get_hl '@foo.missing')
+ eq(3, get_hl '@foo.missing.exists')
+ eq(3, get_hl '@foo.missing.exists.bar')
+ eq(nil, get_hl '@total.nonsense.but.a.lot.of.dots')
+ end)
- meths.set_hl(0, "@foo.missing.exists", {fg = 3})
- eq(1, get_hl"@foo.missing")
- eq(3, get_hl"@foo.missing.exists")
- eq(3, get_hl"@foo.missing.exists.bar")
- eq(nil, get_hl"@total.nonsense.but.a.lot.of.dots")
+ it('supports multiple nodes assigned to the same capture #17060', function()
+ insert([[
+ int x = 4;
+ int y = 5;
+ int z = 6;
+ ]])
+
+ exec_lua([[
+ local query = '((declaration)+ @string)'
+ vim.treesitter.query.set('c', 'highlights', query)
+ vim.treesitter.highlighter.new(vim.treesitter.get_parser(0, 'c'))
+ ]])
+
+ screen:expect {
+ grid = [[
+ {5:int x = 4;} |
+ {5:int y = 5;} |
+ {5:int z = 6;} |
+ ^ |
+ {1:~ }|*13
+ |
+ ]],
+ }
end)
end)
@@ -784,16 +765,16 @@ describe('treesitter highlighting (help)', function()
screen = Screen.new(40, 6)
screen:attach()
screen:set_default_attr_ids {
- [1] = {foreground = Screen.colors.Blue1};
- [2] = {bold = true, foreground = Screen.colors.Blue1};
- [3] = {bold = true, foreground = Screen.colors.Brown};
- [4] = {foreground = Screen.colors.Cyan4};
- [5] = {foreground = Screen.colors.Magenta1};
+ [1] = { foreground = Screen.colors.Blue1 },
+ [2] = { bold = true, foreground = Screen.colors.Blue1 },
+ [3] = { bold = true, foreground = Screen.colors.Brown },
+ [4] = { foreground = Screen.colors.Cyan4 },
+ [5] = { foreground = Screen.colors.Magenta1 },
}
end)
- it("correctly redraws added/removed injections", function()
- insert[[
+ it('correctly redraws added/removed injections', function()
+ insert [[
>ruby
-- comment
local this_is = 'actually_lua'
@@ -805,38 +786,43 @@ describe('treesitter highlighting (help)', function()
vim.treesitter.start()
]]
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1:>ruby} |
{1: -- comment} |
{1: local this_is = 'actually_lua'} |
- < |
+ {1:<} |
^ |
|
- ]]}
+ ]],
+ }
- helpers.curbufmeths.set_text(0, 1, 0, 5, {'lua'})
+ helpers.api.nvim_buf_set_text(0, 0, 1, 0, 5, { 'lua' })
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1:>lua} |
{1: -- comment} |
{1: }{3:local}{1: }{4:this_is}{1: }{3:=}{1: }{5:'actually_lua'} |
- < |
+ {1:<} |
^ |
|
- ]]}
+ ]],
+ }
- helpers.curbufmeths.set_text(0, 1, 0, 4, {'ruby'})
+ helpers.api.nvim_buf_set_text(0, 0, 1, 0, 4, { 'ruby' })
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1:>ruby} |
{1: -- comment} |
{1: local this_is = 'actually_lua'} |
- < |
+ {1:<} |
^ |
|
- ]]}
+ ]],
+ }
end)
-
end)
describe('treesitter highlighting (nested injections)', function()
@@ -846,15 +832,15 @@ describe('treesitter highlighting (nested injections)', function()
screen = Screen.new(80, 7)
screen:attach()
screen:set_default_attr_ids {
- [1] = {foreground = Screen.colors.SlateBlue};
- [2] = {bold = true, foreground = Screen.colors.Brown};
- [3] = {foreground = Screen.colors.Cyan4};
- [4] = {foreground = Screen.colors.Fuchsia};
+ [1] = { foreground = Screen.colors.SlateBlue },
+ [2] = { bold = true, foreground = Screen.colors.Brown },
+ [3] = { foreground = Screen.colors.Cyan4 },
+ [4] = { foreground = Screen.colors.Fuchsia },
}
end)
- it("correctly redraws nested injections (GitHub #25252)", function()
- insert[=[
+ it('correctly redraws nested injections (GitHub #25252)', function()
+ insert [=[
function foo() print("Lua!") end
local lorem = {
@@ -875,9 +861,10 @@ vim.cmd([[
]]
-- invalidate the language tree
- feed("ggi--[[<ESC>04x")
+ feed('ggi--[[<ESC>04x')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{2:^function} {3:foo}{1:()} {1:print(}{4:"Lua!"}{1:)} {2:end} |
|
{2:local} {3:lorem} {2:=} {1:{} |
@@ -885,12 +872,14 @@ vim.cmd([[
{3:bar} {2:=} {1:{},} |
{1:}} |
|
- ]]}
+ ]],
+ }
-- spam newline insert/delete to invalidate Lua > Vim > Lua region
- feed("3jo<ESC>ddko<ESC>ddko<ESC>ddko<ESC>ddk0")
+ feed('3jo<ESC>ddko<ESC>ddko<ESC>ddko<ESC>ddk0')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{2:function} {3:foo}{1:()} {1:print(}{4:"Lua!"}{1:)} {2:end} |
|
{2:local} {3:lorem} {2:=} {1:{} |
@@ -898,7 +887,7 @@ vim.cmd([[
{3:bar} {2:=} {1:{},} |
{1:}} |
|
- ]]}
+ ]],
+ }
end)
-
end)
diff --git a/test/functional/treesitter/inspect_tree_spec.lua b/test/functional/treesitter/inspect_tree_spec.lua
new file mode 100644
index 0000000000..a3d44ff906
--- /dev/null
+++ b/test/functional/treesitter/inspect_tree_spec.lua
@@ -0,0 +1,115 @@
+local helpers = require('test.functional.helpers')(after_each)
+local clear = helpers.clear
+local insert = helpers.insert
+local dedent = helpers.dedent
+local eq = helpers.eq
+local exec_lua = helpers.exec_lua
+local feed = helpers.feed
+
+describe('vim.treesitter.inspect_tree', function()
+ before_each(clear)
+
+ local expect_tree = function(x)
+ local expected = vim.split(vim.trim(dedent(x)), '\n')
+ local actual = helpers.buf_lines(0) ---@type string[]
+ eq(expected, actual)
+ end
+
+ it('working', function()
+ insert([[
+ print()
+ ]])
+
+ exec_lua([[
+ vim.treesitter.start(0, 'lua')
+ vim.treesitter.inspect_tree()
+ ]])
+
+ expect_tree [[
+ (chunk ; [0, 0] - [2, 0]
+ (function_call ; [0, 0] - [0, 7]
+ name: (identifier) ; [0, 0] - [0, 5]
+ arguments: (arguments))) ; [0, 5] - [0, 7]
+ ]]
+ end)
+
+ it('can toggle to show anonymous nodes', function()
+ insert([[
+ print()
+ ]])
+
+ exec_lua([[
+ vim.treesitter.start(0, 'lua')
+ vim.treesitter.inspect_tree()
+ ]])
+ feed('a')
+
+ expect_tree [[
+ (chunk ; [0, 0] - [2, 0]
+ (function_call ; [0, 0] - [0, 7]
+ name: (identifier) ; [0, 0] - [0, 5]
+ arguments: (arguments ; [0, 5] - [0, 7]
+ "(" ; [0, 5] - [0, 6]
+ ")"))) ; [0, 6] - [0, 7]
+ ]]
+ end)
+
+ it('works for injected trees', function()
+ insert([[
+ ```lua
+ return
+ ```
+ ]])
+
+ exec_lua([[
+ vim.treesitter.start(0, 'markdown')
+ vim.treesitter.get_parser():parse()
+ vim.treesitter.inspect_tree()
+ ]])
+
+ expect_tree [[
+ (document ; [0, 0] - [4, 0]
+ (section ; [0, 0] - [4, 0]
+ (fenced_code_block ; [0, 0] - [3, 0]
+ (fenced_code_block_delimiter) ; [0, 0] - [0, 3]
+ (info_string ; [0, 3] - [0, 6]
+ (language)) ; [0, 3] - [0, 6]
+ (block_continuation) ; [1, 0] - [1, 0]
+ (code_fence_content ; [1, 0] - [2, 0]
+ (chunk ; [1, 0] - [2, 0]
+ (return_statement)) ; [1, 0] - [1, 6]
+ (block_continuation)) ; [2, 0] - [2, 0]
+ (fenced_code_block_delimiter)))) ; [2, 0] - [2, 3]
+ ]]
+ end)
+
+ it('can toggle to show languages', function()
+ insert([[
+ ```lua
+ return
+ ```
+ ]])
+
+ exec_lua([[
+ vim.treesitter.start(0, 'markdown')
+ vim.treesitter.get_parser():parse()
+ vim.treesitter.inspect_tree()
+ ]])
+ feed('I')
+
+ expect_tree [[
+ (document ; [0, 0] - [4, 0] markdown
+ (section ; [0, 0] - [4, 0] markdown
+ (fenced_code_block ; [0, 0] - [3, 0] markdown
+ (fenced_code_block_delimiter) ; [0, 0] - [0, 3] markdown
+ (info_string ; [0, 3] - [0, 6] markdown
+ (language)) ; [0, 3] - [0, 6] markdown
+ (block_continuation) ; [1, 0] - [1, 0] markdown
+ (code_fence_content ; [1, 0] - [2, 0] markdown
+ (chunk ; [1, 0] - [2, 0] lua
+ (return_statement)) ; [1, 0] - [1, 6] lua
+ (block_continuation)) ; [2, 0] - [2, 0] markdown
+ (fenced_code_block_delimiter)))) ; [2, 0] - [2, 3] markdown
+ ]]
+ end)
+end)
diff --git a/test/functional/treesitter/language_spec.lua b/test/functional/treesitter/language_spec.lua
index 9b871a72fb..65d9e0e81c 100644
--- a/test/functional/treesitter/language_spec.lua
+++ b/test/functional/treesitter/language_spec.lua
@@ -13,27 +13,43 @@ before_each(clear)
describe('treesitter language API', function()
-- error tests not requiring a parser library
it('handles missing language', function()
- eq(".../language.lua:0: no parser for 'borklang' language, see :help treesitter-parsers",
- pcall_err(exec_lua, "parser = vim.treesitter.get_parser(0, 'borklang')"))
+ eq(
+ ".../language.lua:0: no parser for 'borklang' language, see :help treesitter-parsers",
+ pcall_err(exec_lua, "parser = vim.treesitter.get_parser(0, 'borklang')")
+ )
-- actual message depends on platform
- matches("Failed to load parser for language 'borklang': uv_dlopen: .+",
- pcall_err(exec_lua, "parser = vim.treesitter.language.add('borklang', { path = 'borkbork.so' })"))
+ matches(
+ "Failed to load parser for language 'borklang': uv_dlopen: .+",
+ pcall_err(
+ exec_lua,
+ "parser = vim.treesitter.language.add('borklang', { path = 'borkbork.so' })"
+ )
+ )
eq(false, exec_lua("return pcall(vim.treesitter.language.add, 'borklang')"))
- eq(false, exec_lua("return pcall(vim.treesitter.language.add, 'borklang', { path = 'borkbork.so' })"))
+ eq(
+ false,
+ exec_lua("return pcall(vim.treesitter.language.add, 'borklang', { path = 'borkbork.so' })")
+ )
- eq(".../language.lua:0: no parser for 'borklang' language, see :help treesitter-parsers",
- pcall_err(exec_lua, "parser = vim.treesitter.language.inspect('borklang')"))
+ eq(
+ ".../language.lua:0: no parser for 'borklang' language, see :help treesitter-parsers",
+ pcall_err(exec_lua, "parser = vim.treesitter.language.inspect('borklang')")
+ )
- matches("Failed to load parser: uv_dlsym: .+",
- pcall_err(exec_lua, 'vim.treesitter.language.add("c", { symbol_name = "borklang" })'))
+ matches(
+ 'Failed to load parser: uv_dlsym: .+',
+ pcall_err(exec_lua, 'vim.treesitter.language.add("c", { symbol_name = "borklang" })')
+ )
end)
it('shows error for invalid language name', function()
- eq(".../language.lua:0: '/foo/' is not a valid language name",
- pcall_err(exec_lua, 'vim.treesitter.language.add("/foo/")'))
+ eq(
+ ".../language.lua:0: '/foo/' is not a valid language name",
+ pcall_err(exec_lua, 'vim.treesitter.language.add("/foo/")')
+ )
end)
it('inspects language', function()
@@ -52,40 +68,45 @@ describe('treesitter language API', function()
return {keys, lang.fields, symbols}
]]))
- eq({fields=true, symbols=true, _abi_version=true}, keys)
+ eq({ fields = true, symbols = true, _abi_version = true }, keys)
local fset = {}
- for _,f in pairs(fields) do
- eq("string", type(f))
+ for _, f in pairs(fields) do
+ eq('string', type(f))
fset[f] = true
end
- eq(true, fset["directive"])
- eq(true, fset["initializer"])
+ eq(true, fset['directive'])
+ eq(true, fset['initializer'])
local has_named, has_anonymous
- for _,s in pairs(symbols) do
- eq("string", type(s[1]))
- eq("boolean", type(s[2]))
- if s[1] == "for_statement" and s[2] == true then
+ for _, s in pairs(symbols) do
+ eq('string', type(s[1]))
+ eq('boolean', type(s[2]))
+ if s[1] == 'for_statement' and s[2] == true then
has_named = true
- elseif s[1] == "|=" and s[2] == false then
+ elseif s[1] == '|=' and s[2] == false then
has_anonymous = true
end
end
- eq({true,true}, {has_named,has_anonymous})
+ eq({ true, true }, { has_named, has_anonymous })
end)
- it('checks if vim.treesitter.get_parser tries to create a new parser on filetype change', function ()
- command("set filetype=c")
- -- Should not throw an error when filetype is c
- eq('c', exec_lua("return vim.treesitter.get_parser(0):lang()"))
- command("set filetype=borklang")
- -- Should throw an error when filetype changes to borklang
- eq(".../language.lua:0: no parser for 'borklang' language, see :help treesitter-parsers",
- pcall_err(exec_lua, "new_parser = vim.treesitter.get_parser(0, 'borklang')"))
- end)
+ it(
+ 'checks if vim.treesitter.get_parser tries to create a new parser on filetype change',
+ function()
+ command('set filetype=c')
+ -- Should not throw an error when filetype is c
+ eq('c', exec_lua('return vim.treesitter.get_parser(0):lang()'))
+ command('set filetype=borklang')
+ -- Should throw an error when filetype changes to borklang
+ eq(
+ ".../language.lua:0: no parser for 'borklang' language, see :help treesitter-parsers",
+ pcall_err(exec_lua, "new_parser = vim.treesitter.get_parser(0, 'borklang')")
+ )
+ end
+ )
- it('retrieve the tree given a range', function ()
+ it('retrieve the tree given a range', function()
insert([[
int main() {
int x = 3;
@@ -99,7 +120,7 @@ describe('treesitter language API', function()
eq('<node translation_unit>', exec_lua('return tostring(tree:root())'))
end)
- it('retrieve the node given a range', function ()
+ it('retrieve the node given a range', function()
insert([[
int main() {
int x = 3;
@@ -113,4 +134,3 @@ describe('treesitter language API', function()
eq('<node primitive_type>', exec_lua('return tostring(node)'))
end)
end)
-
diff --git a/test/functional/treesitter/node_spec.lua b/test/functional/treesitter/node_spec.lua
index eef75d0e91..f114d36823 100644
--- a/test/functional/treesitter/node_spec.lua
+++ b/test/functional/treesitter/node_spec.lua
@@ -9,7 +9,7 @@ local assert_alive = helpers.assert_alive
before_each(clear)
local function lua_eval(lua_expr)
- return exec_lua("return " .. lua_expr)
+ return exec_lua('return ' .. lua_expr)
end
describe('treesitter node API', function()
@@ -40,6 +40,20 @@ describe('treesitter node API', function()
assert_alive()
end)
+ it('get_node() with lang given', function()
+ -- this buffer doesn't have filetype set!
+ insert('local foo = function() end')
+ exec_lua([[
+ node = vim.treesitter.get_node({
+ bufnr = 0,
+ pos = { 0, 6 }, -- on "foo"
+ lang = 'lua',
+ })
+ ]])
+ eq('foo', lua_eval('vim.treesitter.get_node_text(node, 0)'))
+ eq('identifier', lua_eval('node:type()'))
+ end)
+
it('can move between siblings', function()
insert([[
int main(int x, int y, int z) {
@@ -48,14 +62,13 @@ describe('treesitter node API', function()
]])
exec_lua([[
- query = require"vim.treesitter.query"
parser = vim.treesitter.get_parser(0, "c")
tree = parser:parse()[1]
root = tree:root()
lang = vim.treesitter.language.inspect('c')
function node_text(node)
- return query.get_node_text(node, 0)
+ return vim.treesitter.get_node_text(node, 0)
end
]])
diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua
index 6f386115ae..875b772fec 100644
--- a/test/functional/treesitter/parser_spec.lua
+++ b/test/functional/treesitter/parser_spec.lua
@@ -8,11 +8,13 @@ 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()
clear()
- exec_lua[[
+ exec_lua [[
vim.g.__ts_debug = 1
]]
end)
@@ -30,59 +32,62 @@ describe('treesitter parser API', function()
lang = vim.treesitter.language.inspect('c')
]])
- eq("<tree>", exec_lua("return tostring(tree)"))
- eq("<node translation_unit>", exec_lua("return tostring(root)"))
- eq({0,0,3,0}, exec_lua("return {root:range()}"))
-
- eq(1, exec_lua("return root:child_count()"))
- exec_lua("child = root:child(0)")
- eq("<node function_definition>", exec_lua("return tostring(child)"))
- eq({0,0,2,1}, exec_lua("return {child:range()}"))
-
- eq("function_definition", exec_lua("return child:type()"))
- eq(true, exec_lua("return child:named()"))
- eq("number", type(exec_lua("return child:symbol()")))
- eq({'function_definition', true}, exec_lua("return lang.symbols[child:symbol()]"))
-
- exec_lua("anon = root:descendant_for_range(0,8,0,9)")
- eq("(", exec_lua("return anon:type()"))
- eq(false, exec_lua("return anon:named()"))
- eq("number", type(exec_lua("return anon:symbol()")))
- eq({'(', false}, exec_lua("return lang.symbols[anon:symbol()]"))
-
- exec_lua("descendant = root:descendant_for_range(1,2,1,12)")
- eq("<node declaration>", exec_lua("return tostring(descendant)"))
- eq({1,2,1,12}, exec_lua("return {descendant:range()}"))
- eq("(declaration type: (primitive_type) declarator: (init_declarator declarator: (identifier) value: (number_literal)))", exec_lua("return descendant:sexpr()"))
-
- feed("2G7|ay")
+ eq('<tree>', exec_lua('return tostring(tree)'))
+ eq('<node translation_unit>', exec_lua('return tostring(root)'))
+ eq({ 0, 0, 3, 0 }, exec_lua('return {root:range()}'))
+
+ eq(1, exec_lua('return root:child_count()'))
+ exec_lua('child = root:child(0)')
+ eq('<node function_definition>', exec_lua('return tostring(child)'))
+ eq({ 0, 0, 2, 1 }, exec_lua('return {child:range()}'))
+
+ eq('function_definition', exec_lua('return child:type()'))
+ eq(true, exec_lua('return child:named()'))
+ eq('number', type(exec_lua('return child:symbol()')))
+ eq({ 'function_definition', true }, exec_lua('return lang.symbols[child:symbol()]'))
+
+ exec_lua('anon = root:descendant_for_range(0,8,0,9)')
+ eq('(', exec_lua('return anon:type()'))
+ eq(false, exec_lua('return anon:named()'))
+ eq('number', type(exec_lua('return anon:symbol()')))
+ eq({ '(', false }, exec_lua('return lang.symbols[anon:symbol()]'))
+
+ exec_lua('descendant = root:descendant_for_range(1,2,1,12)')
+ eq('<node declaration>', exec_lua('return tostring(descendant)'))
+ eq({ 1, 2, 1, 12 }, exec_lua('return {descendant:range()}'))
+ eq(
+ '(declaration type: (primitive_type) declarator: (init_declarator declarator: (identifier) value: (number_literal)))',
+ exec_lua('return descendant:sexpr()')
+ )
+
+ feed('2G7|ay')
exec_lua([[
tree2 = parser:parse()[1]
root2 = tree2:root()
descendant2 = root2:descendant_for_range(1,2,1,13)
]])
- eq(false, exec_lua("return tree2 == tree1"))
- eq(false, exec_lua("return root2 == root"))
- eq("<node declaration>", exec_lua("return tostring(descendant2)"))
- eq({1,2,1,13}, exec_lua("return {descendant2:range()}"))
+ eq(false, exec_lua('return tree2 == tree1'))
+ eq(false, exec_lua('return root2 == root'))
+ eq('<node declaration>', exec_lua('return tostring(descendant2)'))
+ eq({ 1, 2, 1, 13 }, exec_lua('return {descendant2:range()}'))
- eq(true, exec_lua("return child == child"))
+ eq(true, exec_lua('return child == child'))
-- separate lua object, but represents same node
- eq(true, exec_lua("return child == root:child(0)"))
- eq(false, exec_lua("return child == descendant2"))
- eq(false, exec_lua("return child == nil"))
- eq(false, exec_lua("return child == tree"))
+ eq(true, exec_lua('return child == root:child(0)'))
+ eq(false, exec_lua('return child == descendant2'))
+ eq(false, exec_lua('return child == nil'))
+ eq(false, exec_lua('return child == tree'))
- eq("string", exec_lua("return type(child:id())"))
- eq(true, exec_lua("return child:id() == child:id()"))
+ eq('string', exec_lua('return type(child:id())'))
+ eq(true, exec_lua('return child:id() == child:id()'))
-- separate lua object, but represents same node
- eq(true, exec_lua("return child:id() == root:child(0):id()"))
- eq(false, exec_lua("return child:id() == descendant2:id()"))
- eq(false, exec_lua("return child:id() == nil"))
- eq(false, exec_lua("return child:id() == tree"))
+ eq(true, exec_lua('return child:id() == root:child(0):id()'))
+ eq(false, exec_lua('return child:id() == descendant2:id()'))
+ eq(false, exec_lua('return child:id() == nil'))
+ eq(false, exec_lua('return child:id() == tree'))
-- unchanged buffer: return the same tree
- eq(true, exec_lua("return parser:parse()[1] == tree2"))
+ eq(true, exec_lua('return parser:parse()[1] == tree2'))
end)
local test_text = [[
@@ -107,7 +112,7 @@ void ui_refresh(void)
}]]
it('allows to iterate over nodes children', function()
- insert(test_text);
+ insert(test_text)
local res = exec_lua([[
parser = vim.treesitter.get_parser(0, "c")
@@ -122,26 +127,28 @@ void ui_refresh(void)
]])
eq({
- {"primitive_type", "type"},
- {"function_declarator", "declarator"},
- {"compound_statement", "body"}
+ { 'primitive_type', 'type' },
+ { 'function_declarator', 'declarator' },
+ { 'compound_statement', 'body' },
}, res)
end)
it('does not get parser for empty filetype', function()
- insert(test_text);
+ insert(test_text)
- eq('.../treesitter.lua:0: There is no parser available for buffer 1 and one'
- .. ' could not be created because lang could not be determined. Either'
- .. ' pass lang or set the buffer filetype',
- pcall_err(exec_lua, 'vim.treesitter.get_parser(0)'))
+ eq(
+ '.../treesitter.lua:0: There is no parser available for buffer 1 and one'
+ .. ' could not be created because lang could not be determined. Either'
+ .. ' pass lang or set the buffer filetype',
+ pcall_err(exec_lua, 'vim.treesitter.get_parser(0)')
+ )
-- Must provide language for buffers with an empty filetype
exec_lua("vim.treesitter.get_parser(0, 'c')")
end)
it('allows to get a child by field', function()
- insert(test_text);
+ insert(test_text)
local res = exec_lua([[
parser = vim.treesitter.get_parser(0, "c")
@@ -155,7 +162,7 @@ void ui_refresh(void)
return res
]])
- eq({{ "primitive_type", 0, 0, 0, 4 }}, res)
+ eq({ { 'primitive_type', 0, 0, 0, 4 } }, res)
local res_fail = exec_lua([[
parser = vim.treesitter.get_parser(0, "c")
@@ -166,14 +173,14 @@ void ui_refresh(void)
assert(res_fail)
end)
- local query = [[
- ((call_expression function: (identifier) @minfunc (argument_list (identifier) @min_id)) (eq? @minfunc "MIN"))
+ 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()
local ret = exec_lua [[
return vim.treesitter.query.get("c", "highlights").captures[1]
]]
@@ -181,10 +188,11 @@ void ui_refresh(void)
eq('variable', ret)
end)
- it("supports caching queries", function()
- local long_query = query:rep(100)
+ it('supports caching queries', function()
+ local long_query = test_query:rep(100)
local function q(n)
- return exec_lua ([[
+ return exec_lua(
+ [[
local query, n = ...
local before = vim.uv.hrtime()
for i=1,n,1 do
@@ -192,7 +200,10 @@ void ui_refresh(void)
end
local after = vim.uv.hrtime()
return after - before
- ]], long_query, n)
+ ]],
+ long_query,
+ n
+ )
end
local firstrun = q(1)
@@ -200,13 +211,17 @@ void ui_refresh(void)
-- 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))
+ assert(
+ factor * manyruns < firstrun,
+ ('firstrun: %f ms, manyruns: %f ms'):format(firstrun / 1e6, manyruns / 1e6)
+ )
end)
it('support query and iter by capture', function()
insert(test_text)
- local res = exec_lua([[
+ local res = exec_lua(
+ [[
cquery = vim.treesitter.query.parse("c", ...)
parser = vim.treesitter.get_parser(0, "c")
tree = parser:parse()[1]
@@ -216,50 +231,124 @@ void ui_refresh(void)
table.insert(res, {cquery.captures[cid], node:type(), node:range()})
end
return res
- ]], query)
+ ]],
+ 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 },
+ { '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([[
+ 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
+ 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,node in pairs(match) do
- table.insert(mrepr, {cquery.captures[cid], node:type(), node:range()})
+ 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
- ]], query)
+ ]],
+ 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('support 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({
- { 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 } } }
+ { '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()
+ 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)
@@ -286,7 +375,9 @@ def run
a = <<~E
end]]
insert(text)
- eq('', exec_lua[[
+ eq(
+ '',
+ exec_lua [[
local fake_node = {}
function fake_node:start()
return 3, 0, 23
@@ -301,7 +392,8 @@ 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()
@@ -338,11 +430,13 @@ end]]
parser = vim.treesitter.get_parser(0, "c")
tree = parser:parse()[1]
res = {}
- for pattern, match in cquery:iter_matches(tree:root(), 0) do
+ 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,node in pairs(match) do
- table.insert(mrepr, {cquery.captures[cid], node:type(), node:range()})
+ 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
@@ -350,12 +444,12 @@ end]]
]])
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)
@@ -394,54 +488,63 @@ end]]
end
]])
- local res0 = exec_lua([[return get_query_result(...)]],
- [[((primitive_type) @c-keyword (#any-of? @c-keyword "int" "float"))]])
+ 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" },
+ { '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(...)]],
+ 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\""},
+ { '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('allow loading query with escaped quotes and capture them with `lua-match?` and `vim-match?`', function()
- insert('char* astring = "Hello World!";')
+ it(
+ 'allow loading query with escaped quotes and capture them with `lua-match?` and `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]
res = {}
- for pattern, match in cquery:iter_matches(tree:root(), 0) do
+ 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,node in pairs(match) do
- table.insert(mrepr, {cquery.captures[cid], node:type(), node:range()})
+ 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)
+ 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([[
@@ -450,44 +553,250 @@ end]]
}
]])
- local custom_query = "((identifier) @main (#is-main? @main))"
+ local custom_query = '((identifier) @main (#is-main? @main))'
- local res = exec_lua([[
- local query = vim.treesitter.query
+ 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")
- local function is_main(match, pattern, bufnr, predicate)
- local node = match[ predicate[2] ]
+ -- 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
+ )
- return query.get_node_text(node, bufnr)
+ eq({ { 0, 4, 0, 8 } }, res)
end
- local parser = vim.treesitter.get_parser(0, "c")
+ -- Once with the old API. Remove this whole 'do' block in 0.12
+ do
+ local res = exec_lua(
+ [[
+ local query = vim.treesitter.query
- query.add_predicate("is-main?", is_main)
+ local function is_main(match, pattern, bufnr, predicate)
+ local node = match[ predicate[2] ]
- local query = query.parse("c", ...)
+ return vim.treesitter.get_node_text(node, bufnr) == 'main'
+ end
- local nodes = {}
- for _, node in query:iter_captures(parser:parse()[1]:root(), 0) do
- table.insert(nodes, {node:range()})
+ 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
- return nodes
- ]], custom_query)
+ do
+ local res = exec_lua [[
+ local query = vim.treesitter.query
- eq({{0, 4, 0, 8}}, res)
+ local t = {}
+ for _, v in ipairs(query.list_predicates()) do
+ t[v] = true
+ end
- local res_list = exec_lua[[
- local query = vim.treesitter.query
+ return t
+ ]]
- local list = query.list_predicates()
+ eq(true, res['is-main?'])
+ end
+ end)
- table.sort(list)
+ 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
+ ]])
- return list
+ local query = [[
+ (((comment (comment_content))+) @bar
+ (#lua-match? @bar "Comment"))
]]
- eq({ 'any-of?', 'contains?', 'eq?', 'has-ancestor?', 'has-parent?', 'is-main?', 'lua-match?', 'match?', 'vim-match?' }, res_list)
+ 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()
@@ -498,7 +807,7 @@ end]]
return { parser:parse()[1]:root():range() }
]]
- eq({0, 0, 19, 0}, res)
+ eq({ 0, 0, 19, 0 }, res)
-- The following sets the included ranges for the current parser
-- As stated here, this only includes the function (thus the whole buffer, without the last line)
@@ -509,7 +818,7 @@ end]]
return { parser:parse(true)[1]:root():range() }
]]
- eq({0, 0, 18, 1}, res2)
+ eq({ 0, 0, 18, 1 }, res2)
eq({ { { 0, 0, 0, 18, 1, 512 } } }, exec_lua [[ return parser:included_regions() ]])
@@ -522,7 +831,7 @@ end]]
eq(range_tbl, { { { 0, 0, 0, 17, 1, 508 } } })
end)
- it("allows to set complex ranges", function()
+ it('allows to set complex ranges', function()
insert(test_text)
local res = exec_lua [[
@@ -552,10 +861,11 @@ end]]
{ 8, 2, 8, 33 },
{ 9, 7, 9, 20 },
{ 10, 4, 10, 20 },
- { 14, 9, 14, 27 } }, res)
+ { 14, 9, 14, 27 },
+ }, res)
end)
- it("allows to create string parsers", function()
+ it('allows to create string parsers', function()
local ret = exec_lua [[
local parser = vim.treesitter.get_string_parser("int foo = 42;", "c")
return { parser:parse()[1]:root():range() }
@@ -564,35 +874,39 @@ end]]
eq({ 0, 0, 0, 13 }, ret)
end)
- it("allows to run queries with string parsers", function()
+ it('allows to run queries with string parsers', function()
local txt = [[
int foo = 42;
int bar = 13;
]]
- local ret = exec_lua([[
+ 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) @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
table.insert(nodes, { node:range() })
end
- return nodes]], txt)
+ return nodes]],
+ txt
+ )
- eq({ {0, 10, 0, 13} }, ret)
+ eq({ { 0, 10, 0, 13 } }, ret)
end)
- it("should use node range when omitted", function()
+ it('should use node range when omitted', function()
local txt = [[
int foo = 42;
int bar = 13;
]]
- local ret = exec_lua([[
+ local ret = exec_lua(
+ [[
local str = ...
local parser = vim.treesitter.get_string_parser(str, "c")
@@ -604,12 +918,14 @@ end]]
table.insert(nodes, { node:range() })
end
- return nodes]], txt)
+ return nodes]],
+ txt
+ )
- eq({ {1, 10, 1, 13} }, ret)
+ eq({ { 1, 10, 1, 13 } }, ret)
end)
- describe("when creating a language tree", function()
+ describe('when creating a language tree', function()
local function get_ranges()
return exec_lua([[
local result = {}
@@ -629,8 +945,8 @@ int x = INT_MAX;
]])
end)
- describe("when parsing regions independently", function()
- it("should inject a language", function()
+ describe('when parsing regions independently', function()
+ it('should inject a language', function()
exec_lua([[
parser = vim.treesitter.get_parser(0, "c", {
injections = {
@@ -638,32 +954,32 @@ int x = INT_MAX;
parser:parse(true)
]])
- eq("table", exec_lua("return type(parser:children().c)"))
- eq(5, exec_lua("return #parser:children().c:trees()"))
+ eq('table', exec_lua('return type(parser:children().c)'))
+ eq(5, exec_lua('return #parser:children().c:trees()'))
eq({
- {0, 0, 7, 0}, -- root tree
- {3, 14, 3, 17}, -- VALUE 123
- {4, 15, 4, 18}, -- VALUE1 123
- {5, 15, 5, 18}, -- VALUE2 123
- {1, 26, 1, 63}, -- READ_STRING(x, y) (char *)read_string((x), (size_t)(y))
- {2, 29, 2, 66} -- READ_STRING_OK(x, y) (char *)read_string((x), (size_t)(y))
+ { 0, 0, 7, 0 }, -- root tree
+ { 3, 14, 3, 17 }, -- VALUE 123
+ { 4, 15, 4, 18 }, -- VALUE1 123
+ { 5, 15, 5, 18 }, -- VALUE2 123
+ { 1, 26, 1, 63 }, -- READ_STRING(x, y) (char *)read_string((x), (size_t)(y))
+ { 2, 29, 2, 66 }, -- READ_STRING_OK(x, y) (char *)read_string((x), (size_t)(y))
}, get_ranges())
helpers.feed('ggo<esc>')
- eq(5, exec_lua("return #parser:children().c:trees()"))
+ eq(5, exec_lua('return #parser:children().c:trees()'))
eq({
- {0, 0, 8, 0}, -- root tree
- {4, 14, 4, 17}, -- VALUE 123
- {5, 15, 5, 18}, -- VALUE1 123
- {6, 15, 6, 18}, -- VALUE2 123
- {2, 26, 2, 63}, -- READ_STRING(x, y) (char *)read_string((x), (size_t)(y))
- {3, 29, 3, 66} -- READ_STRING_OK(x, y) (char *)read_string((x), (size_t)(y))
+ { 0, 0, 8, 0 }, -- root tree
+ { 4, 14, 4, 17 }, -- VALUE 123
+ { 5, 15, 5, 18 }, -- VALUE1 123
+ { 6, 15, 6, 18 }, -- VALUE2 123
+ { 2, 26, 2, 63 }, -- READ_STRING(x, y) (char *)read_string((x), (size_t)(y))
+ { 3, 29, 3, 66 }, -- READ_STRING_OK(x, y) (char *)read_string((x), (size_t)(y))
}, get_ranges())
end)
end)
- describe("when parsing regions combined", function()
- it("should inject a language", function()
+ describe('when parsing regions combined', function()
+ it('should inject a language', function()
exec_lua([[
parser = vim.treesitter.get_parser(0, "c", {
injections = {
@@ -671,33 +987,45 @@ int x = INT_MAX;
parser:parse(true)
]])
- eq("table", exec_lua("return type(parser:children().c)"))
- eq(2, exec_lua("return #parser:children().c:trees()"))
+ eq('table', exec_lua('return type(parser:children().c)'))
+ eq(2, exec_lua('return #parser:children().c:trees()'))
eq({
- {0, 0, 7, 0}, -- root tree
- {3, 14, 5, 18}, -- VALUE 123
- -- VALUE1 123
- -- VALUE2 123
- {1, 26, 2, 66} -- READ_STRING(x, y) (char *)read_string((x), (size_t)(y))
- -- READ_STRING_OK(x, y) (char *)read_string((x), (size_t)(y))
+ { 0, 0, 7, 0 }, -- root tree
+ { 3, 14, 5, 18 }, -- VALUE 123
+ -- VALUE1 123
+ -- VALUE2 123
+ { 1, 26, 2, 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('ggo<esc>')
- eq("table", exec_lua("return type(parser:children().c)"))
- eq(2, exec_lua("return #parser:children().c:trees()"))
+ 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, 6, 18}, -- VALUE 123
- -- VALUE1 123
- -- VALUE2 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))
+ { 0, 0, 8, 0 }, -- root tree
+ { 4, 14, 6, 18 }, -- VALUE 123
+ -- VALUE1 123
+ -- VALUE2 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())
+
+ 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)
- describe("when using injection.self", function()
- it("should inject the source language", function()
+ describe('when using injection.self', function()
+ it('should inject the source language', function()
exec_lua([[
parser = vim.treesitter.get_parser(0, "c", {
injections = {
@@ -705,32 +1033,32 @@ int x = INT_MAX;
parser:parse(true)
]])
- eq("table", exec_lua("return type(parser:children().c)"))
- eq(5, exec_lua("return #parser:children().c:trees()"))
+ eq('table', exec_lua('return type(parser:children().c)'))
+ eq(5, exec_lua('return #parser:children().c:trees()'))
eq({
- {0, 0, 7, 0}, -- root tree
- {3, 14, 3, 17}, -- VALUE 123
- {4, 15, 4, 18}, -- VALUE1 123
- {5, 15, 5, 18}, -- VALUE2 123
- {1, 26, 1, 63}, -- READ_STRING(x, y) (char *)read_string((x), (size_t)(y))
- {2, 29, 2, 66} -- READ_STRING_OK(x, y) (char *)read_string((x), (size_t)(y))
+ { 0, 0, 7, 0 }, -- root tree
+ { 3, 14, 3, 17 }, -- VALUE 123
+ { 4, 15, 4, 18 }, -- VALUE1 123
+ { 5, 15, 5, 18 }, -- VALUE2 123
+ { 1, 26, 1, 63 }, -- READ_STRING(x, y) (char *)read_string((x), (size_t)(y))
+ { 2, 29, 2, 66 }, -- READ_STRING_OK(x, y) (char *)read_string((x), (size_t)(y))
}, get_ranges())
helpers.feed('ggo<esc>')
- eq(5, exec_lua("return #parser:children().c:trees()"))
+ eq(5, exec_lua('return #parser:children().c:trees()'))
eq({
- {0, 0, 8, 0}, -- root tree
- {4, 14, 4, 17}, -- VALUE 123
- {5, 15, 5, 18}, -- VALUE1 123
- {6, 15, 6, 18}, -- VALUE2 123
- {2, 26, 2, 63}, -- READ_STRING(x, y) (char *)read_string((x), (size_t)(y))
- {3, 29, 3, 66} -- READ_STRING_OK(x, y) (char *)read_string((x), (size_t)(y))
+ { 0, 0, 8, 0 }, -- root tree
+ { 4, 14, 4, 17 }, -- VALUE 123
+ { 5, 15, 5, 18 }, -- VALUE1 123
+ { 6, 15, 6, 18 }, -- VALUE2 123
+ { 2, 26, 2, 63 }, -- READ_STRING(x, y) (char *)read_string((x), (size_t)(y))
+ { 3, 29, 3, 66 }, -- READ_STRING_OK(x, y) (char *)read_string((x), (size_t)(y))
}, get_ranges())
end)
end)
- describe("when using the offset directive", function()
- it("should shift the range by the directive amount", function()
+ 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 = {
@@ -738,18 +1066,18 @@ int x = INT_MAX;
parser:parse(true)
]])
- eq("table", exec_lua("return type(parser:children().c)"))
+ eq('table', exec_lua('return type(parser:children().c)'))
eq({
- {0, 0, 7, 0}, -- root tree
- {3, 16, 3, 16}, -- VALUE 123
- {4, 17, 4, 17}, -- VALUE1 123
- {5, 17, 5, 17}, -- VALUE2 123
- {1, 26, 1, 63}, -- READ_STRING(x, y) (char *)read_string((x), (size_t)(y))
- {2, 29, 2, 66} -- READ_STRING_OK(x, y) (char *)read_string((x), (size_t)(y))
+ { 0, 0, 7, 0 }, -- root tree
+ { 3, 16, 3, 16 }, -- VALUE 123
+ { 4, 17, 4, 17 }, -- VALUE1 123
+ { 5, 17, 5, 17 }, -- VALUE2 123
+ { 1, 26, 1, 63 }, -- READ_STRING(x, y) (char *)read_string((x), (size_t)(y))
+ { 2, 29, 2, 66 }, -- READ_STRING_OK(x, y) (char *)read_string((x), (size_t)(y))
}, get_ranges())
end)
- it("should list all directives", function()
- local res_list = exec_lua[[
+ it('should list all directives', function()
+ local res_list = exec_lua [[
local query = vim.treesitter.query
local list = query.list_directives()
@@ -764,7 +1092,7 @@ int x = INT_MAX;
end)
end)
- describe("when getting the language for a range", function()
+ describe('when getting the language for a range', function()
before_each(function()
insert([[
int x = INT_MAX;
@@ -772,7 +1100,7 @@ int x = INT_MAX;
]])
end)
- it("should return the correct language tree", function()
+ 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"))'}})
@@ -787,9 +1115,9 @@ int x = INT_MAX;
end)
end)
- describe("when getting/setting match data", function()
- describe("when setting for the whole match", function()
- it("should set/get the data correctly", function()
+ describe('when getting/setting match data', function()
+ describe('when setting for the whole match', function()
+ it('should set/get the data correctly', function()
insert([[
int x = 3;
]])
@@ -800,18 +1128,18 @@ int x = INT_MAX;
query = vim.treesitter.query.parse("c", '((number_literal) @number (#set! "key" "value"))')
parser = vim.treesitter.get_parser(0, "c")
- for pattern, match, metadata in query:iter_matches(parser:parse()[1]:root(), 0) do
+ for pattern, match, metadata in query:iter_matches(parser:parse()[1]:root(), 0, 0, -1, { all = true }) do
result = metadata.key
end
return result
]])
- eq(result, "value")
+ eq(result, 'value')
end)
- describe("when setting a key on a capture", function()
- it("it should create the nested table", function()
+ describe('when setting a key on a capture', function()
+ it('it should create the nested table', function()
insert([[
int x = 3;
]])
@@ -823,17 +1151,17 @@ int x = INT_MAX;
query = vim.treesitter.query.parse("c", '((number_literal) @number (#set! @number "key" "value"))')
parser = vim.treesitter.get_parser(0, "c")
- for pattern, match, metadata in query:iter_matches(parser:parse()[1]:root(), 0) do
+ for pattern, match, metadata in query:iter_matches(parser:parse()[1]:root(), 0, 0, -1, { all = true }) do
for _, nested_tbl in pairs(metadata) do
return nested_tbl.key
end
end
]])
- eq(result, "value")
+ eq(result, 'value')
end)
- it("it should not overwrite the nested table", function()
+ it('it should not overwrite the nested table', function()
insert([[
int x = 3;
]])
@@ -845,15 +1173,15 @@ int x = INT_MAX;
query = vim.treesitter.query.parse("c", '((number_literal) @number (#set! @number "key" "value") (#set! @number "key2" "value2"))')
parser = vim.treesitter.get_parser(0, "c")
- for pattern, match, metadata in query:iter_matches(parser:parse()[1]:root(), 0) do
+ for pattern, match, metadata in query:iter_matches(parser:parse()[1]:root(), 0, 0, -1, { all = true }) do
for _, nested_tbl in pairs(metadata) do
return nested_tbl
end
end
]])
local expected = {
- ["key"] = "value",
- ["key2"] = "value2",
+ ['key'] = 'value',
+ ['key2'] = 'value2',
}
eq(expected, result)
@@ -878,7 +1206,8 @@ int x = INT_MAX;
]])
local function run_query()
- return exec_lua([[
+ return exec_lua(
+ [[
local query = vim.treesitter.query.parse("c", ...)
parser = vim.treesitter.get_parser()
tree = parser:parse()[1]
@@ -887,23 +1216,24 @@ int x = INT_MAX;
table.insert(res, {query.captures[id], node:range()})
end
return res
- ]], query0)
+ ]],
+ query0
+ )
end
eq({
{ 'function', 0, 0, 2, 1 },
- { 'declaration', 1, 2, 1, 12 }
+ { 'declaration', 1, 2, 1, 12 },
}, run_query())
- helpers.command'normal ggO'
+ helpers.command 'normal ggO'
insert('int a;')
eq({
{ 'declaration', 0, 0, 0, 6 },
{ 'function', 1, 0, 3, 1 },
- { 'declaration', 2, 2, 2, 12 }
+ { 'declaration', 2, 2, 2, 12 },
}, run_query())
-
end)
it('handles ranges when source is a multiline string (#20419)', function()
@@ -926,7 +1256,8 @@ int x = INT_MAX;
]]
]==]
- local r = exec_lua([[
+ local r = exec_lua(
+ [[
local parser = vim.treesitter.get_string_parser(..., 'lua')
parser:parse(true)
local ranges = {}
@@ -934,19 +1265,22 @@ int x = INT_MAX;
ranges[tree:lang()] = { tstree:root():range(true) }
end)
return ranges
- ]], source)
+ ]],
+ source
+ )
eq({
lua = { 0, 6, 6, 16, 4, 438 },
query = { 6, 20, 113, 15, 6, 431 },
- vim = { 1, 0, 16, 4, 6, 89 }
+ vim = { 1, 0, 16, 4, 6, 89 },
}, r)
-- The above ranges are provided directly from treesitter, however query directives may mutate
-- the ranges but only provide a Range4. Strip the byte entries from the ranges and make sure
-- add_bytes() produces the same result.
- local rb = exec_lua([[
+ local rb = exec_lua(
+ [[
local r, source = ...
local add_bytes = require('vim.treesitter._range').add_bytes
for lang, range in pairs(r) do
@@ -954,13 +1288,15 @@ int x = INT_MAX;
r[lang] = add_bytes(source, r[lang])
end
return r
- ]], r, source)
+ ]],
+ r,
+ source
+ )
eq(rb, r)
-
end)
- it("does not produce empty injection ranges (#23409)", function()
+ it('does not produce empty injection ranges (#23409)', function()
insert [[
Examples: >lua
local a = {}
@@ -977,7 +1313,7 @@ int x = INT_MAX;
parser1:parse(true)
]]
- eq(0, exec_lua("return #vim.tbl_keys(parser1:children())"))
+ eq(0, exec_lua('return #vim.tbl_keys(parser1:children())'))
exec_lua [[
parser2 = require('vim.treesitter.languagetree').new(0, "vimdoc", {
@@ -988,13 +1324,12 @@ int x = INT_MAX;
parser2:parse(true)
]]
- eq(1, exec_lua("return #vim.tbl_keys(parser2:children())"))
- eq( { { { 1, 0, 21, 2, 0, 42 } } }, exec_lua("return parser2:children().lua:included_regions()"))
-
+ eq(1, exec_lua('return #vim.tbl_keys(parser2:children())'))
+ eq({ { { 1, 0, 21, 2, 0, 42 } } }, exec_lua('return parser2:children().lua:included_regions()'))
end)
- it("parsers injections incrementally", function()
- insert(dedent[[
+ it('parsers injections incrementally', function()
+ insert(dedent [[
>lua
local a = {}
<
@@ -1033,26 +1368,38 @@ int x = INT_MAX;
]]
--- Do not parse injections by default
- eq(0, exec_lua [[
+ eq(
+ 0,
+ exec_lua [[
parser:parse()
return #vim.tbl_keys(parser:children())
- ]])
+ ]]
+ )
--- Only parse injections between lines 0, 2
- eq(1, exec_lua [[
+ eq(
+ 1,
+ exec_lua [[
parser:parse({0, 2})
return #parser:children().lua:trees()
- ]])
+ ]]
+ )
- eq(2, exec_lua [[
+ eq(
+ 2,
+ exec_lua [[
parser:parse({2, 6})
return #parser:children().lua:trees()
- ]])
+ ]]
+ )
- eq(7, exec_lua [[
+ eq(
+ 7,
+ exec_lua [[
parser:parse(true)
return #parser:children().lua:trees()
- ]])
+ ]]
+ )
end)
it('fails to load queries', function()
@@ -1062,43 +1409,48 @@ int x = INT_MAX;
-- Invalid node type
test(
- '.../query.lua:0: Query error at 1:2. Invalid node type "dentifier":\n'..
- '(dentifier) @variable\n'..
- ' ^',
- '(dentifier) @variable')
+ '.../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)')
+ '.../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')
+ '.../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))')
+ '.../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))')
+ '.../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('is_valid()', function()
before_each(function()
- insert(dedent[[
+ insert(dedent [[
Treesitter integration *treesitter*
Nvim integrates the `tree-sitter` library for incremental parsing of buffers:
@@ -1137,7 +1489,7 @@ int x = INT_MAX;
describe('when adding content with injections', function()
before_each(function()
feed('G')
- insert(dedent[[
+ insert(dedent [[
>lua
local a = {}
<
@@ -1156,23 +1508,29 @@ int x = INT_MAX;
eq(false, exec_lua('return vim.treesitter.get_parser():is_valid()'))
end)
- it('is fully valid after a range parse that leads to parsing not parsed injections', function()
- exec_lua('vim.treesitter.get_parser():parse({5, 7})')
- eq(true, exec_lua('return vim.treesitter.get_parser():is_valid(true)'))
- eq(true, exec_lua('return vim.treesitter.get_parser():is_valid()'))
- end)
-
- it('is valid excluding, invalid including children after a range parse that does not lead to parsing not parsed injections', function()
- exec_lua('vim.treesitter.get_parser():parse({2, 4})')
- eq(true, exec_lua('return vim.treesitter.get_parser():is_valid(true)'))
- eq(false, exec_lua('return vim.treesitter.get_parser():is_valid()'))
- end)
+ it(
+ 'is fully valid after a range parse that leads to parsing not parsed injections',
+ function()
+ exec_lua('vim.treesitter.get_parser():parse({5, 7})')
+ eq(true, exec_lua('return vim.treesitter.get_parser():is_valid(true)'))
+ eq(true, exec_lua('return vim.treesitter.get_parser():is_valid()'))
+ end
+ )
+
+ it(
+ 'is valid excluding, invalid including children after a range parse that does not lead to parsing not parsed injections',
+ function()
+ exec_lua('vim.treesitter.get_parser():parse({2, 4})')
+ eq(true, exec_lua('return vim.treesitter.get_parser():is_valid(true)'))
+ eq(false, exec_lua('return vim.treesitter.get_parser():is_valid()'))
+ end
+ )
end)
describe('when removing content with injections', function()
before_each(function()
feed('G')
- insert(dedent[[
+ insert(dedent [[
>lua
local a = {}
<
@@ -1205,11 +1563,14 @@ int x = INT_MAX;
eq(true, exec_lua('return vim.treesitter.get_parser():is_valid()'))
end)
- it('is valid excluding, invalid including children after a range parse that does not lead to parsing modified child tree', function()
- exec_lua('vim.treesitter.get_parser():parse({2, 4})')
- eq(true, exec_lua('return vim.treesitter.get_parser():is_valid(true)'))
- eq(false, exec_lua('return vim.treesitter.get_parser():is_valid()'))
- end)
+ it(
+ 'is valid excluding, invalid including children after a range parse that does not lead to parsing modified child tree',
+ function()
+ exec_lua('vim.treesitter.get_parser():parse({2, 4})')
+ eq(true, exec_lua('return vim.treesitter.get_parser():is_valid(true)'))
+ eq(false, exec_lua('return vim.treesitter.get_parser():is_valid()'))
+ end
+ )
end)
end)
end)
diff --git a/test/functional/treesitter/utils_spec.lua b/test/functional/treesitter/utils_spec.lua
index 9c07959098..2734c22499 100644
--- a/test/functional/treesitter/utils_spec.lua
+++ b/test/functional/treesitter/utils_spec.lua
@@ -11,7 +11,6 @@ describe('treesitter utils', function()
before_each(clear)
it('can find an ancestor', function()
-
insert([[
int main() {
int x = 3;