aboutsummaryrefslogtreecommitdiff
path: root/test/functional/treesitter/highlight_spec.lua
diff options
context:
space:
mode:
Diffstat (limited to 'test/functional/treesitter/highlight_spec.lua')
-rw-r--r--test/functional/treesitter/highlight_spec.lua429
1 files changed, 283 insertions, 146 deletions
diff --git a/test/functional/treesitter/highlight_spec.lua b/test/functional/treesitter/highlight_spec.lua
index 69984b3233..b5a6cb5c17 100644
--- a/test/functional/treesitter/highlight_spec.lua
+++ b/test/functional/treesitter/highlight_spec.lua
@@ -8,10 +8,9 @@ local exec_lua = n.exec_lua
local feed = n.feed
local command = n.command
local api = n.api
+local fn = n.fn
local eq = t.eq
-before_each(clear)
-
local hl_query_c = [[
(ERROR) @error
@@ -65,6 +64,46 @@ static int nlua_schedule(lua_State *const lstate)
return 0;
}]]
+local hl_grid_legacy_c = [[
+ {2:^/// Schedule Lua callback on main loop's event queue} |
+ {3:static} {3:int} nlua_schedule(lua_State *{3:const} lstate) |
+ { |
+ {4:if} (lua_type(lstate, {5:1}) != LUA_TFUNCTION |
+ || lstate != lstate) { |
+ lua_pushliteral(lstate, {5:"vim.schedule: expected function"}); |
+ {4:return} lua_error(lstate); |
+ } |
+ |
+ LuaRef cb = nlua_ref(lstate, {5:1}); |
+ |
+ multiqueue_put(main_loop.events, nlua_schedule_event, |
+ {5:1}, ({3:void} *)({3:ptrdiff_t})cb); |
+ {4:return} {5:0}; |
+ } |
+ {1:~ }|*2
+ |
+]]
+
+local hl_grid_ts_c = [[
+ {2:^/// Schedule Lua callback on main loop's event queue} |
+ {3:static} {3:int} {11:nlua_schedule}({3:lua_State} *{3:const} lstate) |
+ { |
+ {4:if} ({11:lua_type}(lstate, {5:1}) != {5:LUA_TFUNCTION} |
+ || {6:lstate} != {6:lstate}) { |
+ {11:lua_pushliteral}(lstate, {5:"vim.schedule: expected function"}); |
+ {4:return} {11:lua_error}(lstate); |
+ } |
+ |
+ {7:LuaRef} cb = {11:nlua_ref}(lstate, {5:1}); |
+ |
+ multiqueue_put(main_loop.events, {11:nlua_schedule_event}, |
+ {5:1}, ({3:void} *)({3:ptrdiff_t})cb); |
+ {4:return} {5:0}; |
+ } |
+ {1:~ }|*2
+ |
+]]
+
local test_text_c = [[
void ui_refresh(void)
{
@@ -117,9 +156,10 @@ local injection_grid_expected_c = [[
]]
describe('treesitter highlighting (C)', function()
- local screen
+ local screen --- @type test.functional.ui.screen
before_each(function()
+ clear()
screen = Screen.new(65, 18)
screen:attach()
screen:set_default_attr_ids {
@@ -136,16 +176,49 @@ describe('treesitter highlighting (C)', function()
[11] = { foreground = Screen.colors.Cyan4 },
}
- exec_lua([[ hl_query = ... ]], hl_query_c)
command [[ hi link @error ErrorMsg ]]
command [[ hi link @warning WarningMsg ]]
end)
+ it('starting and stopping treesitter highlight works', function()
+ command('setfiletype c | syntax on')
+ fn.setreg('r', hl_text_c)
+ feed('i<C-R><C-O>r<Esc>gg')
+ -- legacy syntax highlighting is used by default
+ screen:expect(hl_grid_legacy_c)
+
+ exec_lua(function()
+ vim.treesitter.query.set('c', 'highlights', hl_query_c)
+ vim.treesitter.start()
+ end)
+ -- treesitter highlighting is used
+ screen:expect(hl_grid_ts_c)
+
+ exec_lua(function()
+ vim.treesitter.stop()
+ end)
+ -- legacy syntax highlighting is used
+ screen:expect(hl_grid_legacy_c)
+
+ exec_lua(function()
+ vim.treesitter.start()
+ end)
+ -- treesitter highlighting is used
+ screen:expect(hl_grid_ts_c)
+
+ exec_lua(function()
+ vim.treesitter.stop()
+ end)
+ -- legacy syntax highlighting is used
+ screen:expect(hl_grid_legacy_c)
+ end)
+
it('is updated with edits', function()
insert(hl_text_c)
+ feed('gg')
screen:expect {
grid = [[
- /// Schedule Lua callback on main loop's event queue |
+ ^/// Schedule Lua callback on main loop's event queue |
static int nlua_schedule(lua_State *const lstate) |
{ |
if (lua_type(lstate, 1) != LUA_TFUNCTION |
@@ -159,38 +232,18 @@ describe('treesitter highlighting (C)', function()
multiqueue_put(main_loop.events, nlua_schedule_event, |
1, (void *)(ptrdiff_t)cb); |
return 0; |
- ^} |
+ } |
{1:~ }|*2
|
]],
}
- exec_lua [[
- local parser = vim.treesitter.get_parser(0, "c")
+ exec_lua(function()
+ 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 = [[
- {2:/// Schedule Lua callback on main loop's event queue} |
- {3:static} {3:int} {11:nlua_schedule}({3:lua_State} *{3:const} lstate) |
- { |
- {4:if} ({11:lua_type}(lstate, {5:1}) != {5:LUA_TFUNCTION} |
- || {6:lstate} != {6:lstate}) { |
- {11:lua_pushliteral}(lstate, {5:"vim.schedule: expected function"}); |
- {4:return} {11:lua_error}(lstate); |
- } |
- |
- {7:LuaRef} cb = {11:nlua_ref}(lstate, {5:1}); |
- |
- multiqueue_put(main_loop.events, {11:nlua_schedule_event}, |
- {5:1}, ({3:void} *)({3:ptrdiff_t})cb); |
- {4:return} {5:0}; |
- ^} |
- {1:~ }|*2
- |
- ]],
- }
+ highlighter.new(parser, { queries = { c = hl_query_c } })
+ end)
+ screen:expect(hl_grid_ts_c)
feed('5Goc<esc>dd')
@@ -316,10 +369,10 @@ describe('treesitter highlighting (C)', function()
it('is updated with :sort', function()
insert(test_text_c)
- exec_lua [[
- local parser = vim.treesitter.get_parser(0, "c")
- test_hl = vim.treesitter.highlighter.new(parser, {queries = {c = hl_query}})
- ]]
+ exec_lua(function()
+ local parser = vim.treesitter.get_parser(0, 'c')
+ vim.treesitter.highlighter.new(parser, { queries = { c = hl_query_c } })
+ end)
screen:expect {
grid = [[
{3:int} width = {5:INT_MAX}, height = {5:INT_MAX}; |
@@ -422,19 +475,19 @@ describe('treesitter highlighting (C)', function()
]],
}
- exec_lua [[
- parser = vim.treesitter.get_parser(0, "c")
- query = vim.treesitter.query.parse("c", "(declaration) @decl")
+ exec_lua(function()
+ local parser = vim.treesitter.get_parser(0, 'c')
+ local query = vim.treesitter.query.parse('c', '(declaration) @decl')
local nodes = {}
for _, node in query:iter_captures(parser:parse()[1]:root(), 0, 0, 19) do
table.insert(nodes, node)
end
- parser:set_included_regions({nodes})
+ parser:set_included_regions({ nodes })
- local hl = vim.treesitter.highlighter.new(parser, {queries = {c = "(identifier) @type"}})
- ]]
+ vim.treesitter.highlighter.new(parser, { queries = { c = '(identifier) @type' } })
+ end)
screen:expect {
grid = [[
@@ -465,13 +518,15 @@ describe('treesitter highlighting (C)', function()
screen:expect { grid = injection_grid_c }
- exec_lua [[
- local parser = vim.treesitter.get_parser(0, "c", {
- injections = {c = '(preproc_def (preproc_arg) @injection.content (#set! injection.language "c")) (preproc_function_def value: (preproc_arg) @injection.content (#set! injection.language "c"))'}
+ exec_lua(function()
+ local parser = vim.treesitter.get_parser(0, 'c', {
+ injections = {
+ c = '(preproc_def (preproc_arg) @injection.content (#set! injection.language "c")) (preproc_function_def value: (preproc_arg) @injection.content (#set! injection.language "c"))',
+ },
})
local highlighter = vim.treesitter.highlighter
- test_hl = highlighter.new(parser, {queries = {c = hl_query}})
- ]]
+ highlighter.new(parser, { queries = { c = hl_query_c } })
+ end)
screen:expect { grid = injection_grid_expected_c }
end)
@@ -481,14 +536,16 @@ describe('treesitter highlighting (C)', function()
screen:expect { grid = injection_grid_c }
- exec_lua [[
- vim.treesitter.language.register("c", "foo")
- local parser = vim.treesitter.get_parser(0, "c", {
- injections = {c = '(preproc_def (preproc_arg) @injection.content (#set! injection.language "foo")) (preproc_function_def value: (preproc_arg) @injection.content (#set! injection.language "foo"))'}
+ exec_lua(function()
+ vim.treesitter.language.register('c', 'foo')
+ local parser = vim.treesitter.get_parser(0, 'c', {
+ injections = {
+ c = '(preproc_def (preproc_arg) @injection.content (#set! injection.language "foo")) (preproc_function_def value: (preproc_arg) @injection.content (#set! injection.language "foo"))',
+ },
})
local highlighter = vim.treesitter.highlighter
- test_hl = highlighter.new(parser, {queries = {c = hl_query}})
- ]]
+ highlighter.new(parser, { queries = { c = hl_query_c } })
+ end)
screen:expect { grid = injection_grid_expected_c }
end)
@@ -502,13 +559,14 @@ describe('treesitter highlighting (C)', function()
}
]])
- exec_lua [[
- local injection_query = '(preproc_def (preproc_arg) @injection.content (#set! injection.language "c")) (preproc_function_def value: (preproc_arg) @injection.content (#set! injection.language "c"))'
- vim.treesitter.query.set("c", "highlights", hl_query)
- vim.treesitter.query.set("c", "injections", injection_query)
+ exec_lua(function()
+ local injection_query =
+ '(preproc_def (preproc_arg) @injection.content (#set! injection.language "c")) (preproc_function_def value: (preproc_arg) @injection.content (#set! injection.language "c"))'
+ vim.treesitter.query.set('c', 'highlights', hl_query_c)
+ vim.treesitter.query.set('c', 'injections', injection_query)
- vim.treesitter.highlighter.new(vim.treesitter.get_parser(0, "c"))
- ]]
+ vim.treesitter.highlighter.new(vim.treesitter.get_parser(0, 'c'))
+ end)
screen:expect {
grid = [[
@@ -526,40 +584,21 @@ describe('treesitter highlighting (C)', function()
it('supports highlighting with custom highlight groups', function()
insert(hl_text_c)
+ feed('gg')
- exec_lua [[
- local parser = vim.treesitter.get_parser(0, "c")
- test_hl = vim.treesitter.highlighter.new(parser, {queries = {c = hl_query}})
- ]]
+ exec_lua(function()
+ local parser = vim.treesitter.get_parser(0, 'c')
+ vim.treesitter.highlighter.new(parser, { queries = { c = hl_query_c } })
+ end)
- 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) |
- { |
- {4:if} ({11:lua_type}(lstate, {5:1}) != {5:LUA_TFUNCTION} |
- || {6:lstate} != {6:lstate}) { |
- {11:lua_pushliteral}(lstate, {5:"vim.schedule: expected function"}); |
- {4:return} {11:lua_error}(lstate); |
- } |
- |
- {7:LuaRef} cb = {11:nlua_ref}(lstate, {5:1}); |
- |
- multiqueue_put(main_loop.events, {11:nlua_schedule_event}, |
- {5:1}, ({3:void} *)({3:ptrdiff_t})cb); |
- {4:return} {5:0}; |
- ^} |
- {1:~ }|*2
- |
- ]],
- }
+ screen:expect(hl_grid_ts_c)
-- 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 = [[
- {2:/// Schedule Lua callback on main loop's event queue} |
+ {2:^/// Schedule Lua callback on main loop's event queue} |
{3:static} {3:int} {11:nlua_schedule}({3:lua_State} *{3:const} lstate) |
{ |
{4:if} ({11:lua_type}(lstate, {5:1}) != {5:LUA_TFUNCTION} |
@@ -573,7 +612,7 @@ describe('treesitter highlighting (C)', function()
multiqueue_put(main_loop.events, {11:nlua_schedule_event}, |
{5:1}, ({3:void} *)({3:ptrdiff_t})cb); |
{4:return} {5:0}; |
- ^} |
+ } |
{1:~ }|*2
|
]],
@@ -590,10 +629,14 @@ describe('treesitter highlighting (C)', function()
}
]])
- exec_lua [[
- local parser = vim.treesitter.get_parser(0, "c")
- test_hl = vim.treesitter.highlighter.new(parser, {queries = {c = hl_query..'\n((translation_unit) @constant (#set! "priority" 101))\n'}})
- ]]
+ exec_lua(function()
+ local parser = vim.treesitter.get_parser(0, 'c')
+ vim.treesitter.highlighter.new(parser, {
+ queries = {
+ c = hl_query_c .. '\n((translation_unit) @constant (#set! "priority" 101))\n',
+ },
+ })
+ end)
-- expect everything to have Constant highlight
screen:expect {
grid = [[
@@ -640,11 +683,14 @@ describe('treesitter highlighting (C)', function()
hi link @foo.bar Type
hi link @foo String
]]
- 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"}})
- ]]
+ exec_lua(function()
+ local parser = vim.treesitter.get_parser(0, 'c', {})
+ local highlighter = vim.treesitter.highlighter
+ highlighter.new(
+ parser,
+ { queries = { c = '(primitive_type) @foo.bar (string_literal) @foo' } }
+ )
+ end)
screen:expect {
grid = [[
@@ -672,10 +718,12 @@ describe('treesitter highlighting (C)', function()
insert(hl_text_c)
-- conceal can be empty or a single cchar.
- exec_lua [=[
+ exec_lua(function()
vim.opt.cole = 2
- local parser = vim.treesitter.get_parser(0, "c")
- test_hl = vim.treesitter.highlighter.new(parser, {queries = {c = [[
+ local parser = vim.treesitter.get_parser(0, 'c')
+ vim.treesitter.highlighter.new(parser, {
+ queries = {
+ c = [[
("static" @keyword
(#set! conceal "R"))
@@ -688,8 +736,10 @@ describe('treesitter highlighting (C)', function()
arguments: (argument_list) @arguments)
(#eq? @function "multiqueue_put")
(#set! @function conceal "V"))
- ]]}})
- ]=]
+ ]],
+ },
+ })
+ end)
screen:expect {
grid = [[
@@ -746,11 +796,11 @@ describe('treesitter highlighting (C)', function()
int z = 6;
]])
- exec_lua([[
+ exec_lua(function()
local query = '((declaration)+ @string)'
vim.treesitter.query.set('c', 'highlights', query)
vim.treesitter.highlighter.new(vim.treesitter.get_parser(0, 'c'))
- ]])
+ end)
screen:expect {
grid = [[
@@ -776,14 +826,10 @@ describe('treesitter highlighting (C)', function()
declarator: (pointer_declarator) @variable.parameter)
]]
- exec_lua(
- [[
- local query = ...
+ exec_lua(function()
vim.treesitter.query.set('c', 'highlights', query)
vim.treesitter.highlighter.new(vim.treesitter.get_parser(0, 'c'))
- ]],
- query
- )
+ end)
screen:expect {
grid = [[
@@ -800,6 +846,7 @@ describe('treesitter highlighting (lua)', function()
local screen
before_each(function()
+ clear()
screen = Screen.new(65, 18)
screen:attach()
screen:set_default_attr_ids {
@@ -817,10 +864,10 @@ describe('treesitter highlighting (lua)', function()
ffi.cdef("int (*fun)(int, char *);")
]]
- exec_lua [[
+ exec_lua(function()
vim.bo.filetype = 'lua'
vim.treesitter.start()
- ]]
+ end)
screen:expect {
grid = [[
@@ -838,6 +885,7 @@ describe('treesitter highlighting (help)', function()
local screen
before_each(function()
+ clear()
screen = Screen.new(40, 6)
screen:attach()
screen:set_default_attr_ids {
@@ -846,9 +894,45 @@ describe('treesitter highlighting (help)', function()
[3] = { bold = true, foreground = Screen.colors.Brown },
[4] = { foreground = Screen.colors.Cyan4 },
[5] = { foreground = Screen.colors.Magenta1 },
+ title = { bold = true, foreground = Screen.colors.Magenta1 },
+ h1_delim = { nocombine = true, underdouble = true },
+ h2_delim = { nocombine = true, underline = true },
}
end)
+ it('defaults in vimdoc/highlights.scm', function()
+ -- Avoid regressions when syncing upstream vimdoc queries.
+
+ insert [[
+ ==============================================================================
+ NVIM DOCUMENTATION
+
+ ------------------------------------------------------------------------------
+ ABOUT NVIM *tag-1* *tag-2*
+
+ |news| News
+ |nvim| NVim
+ ]]
+
+ feed('gg')
+ exec_lua(function()
+ vim.wo.wrap = false
+ vim.bo.filetype = 'help'
+ vim.treesitter.start()
+ end)
+
+ screen:expect({
+ grid = [[
+ {h1_delim:^========================================}|
+ {title:NVIM DOCUMENTATION} |
+ |
+ {h2_delim:----------------------------------------}|
+ {title:ABOUT NVIM} |
+ |
+ ]],
+ })
+ end)
+
it('correctly redraws added/removed injections', function()
insert [[
>ruby
@@ -857,10 +941,10 @@ describe('treesitter highlighting (help)', function()
<
]]
- exec_lua [[
+ exec_lua(function()
vim.bo.filetype = 'help'
vim.treesitter.start()
- ]]
+ end)
screen:expect {
grid = [[
@@ -912,15 +996,15 @@ describe('treesitter highlighting (help)', function()
]]
]=])
- exec_lua [[
- parser = vim.treesitter.get_parser(0, "lua", {
+ exec_lua(function()
+ local parser = vim.treesitter.get_parser(0, 'lua', {
injections = {
- lua = '(string content: (_) @injection.content (#set! injection.language lua))'
- }
+ lua = '(string content: (_) @injection.content (#set! injection.language lua))',
+ },
})
vim.treesitter.highlighter.new(parser)
- ]]
+ end)
screen:expect {
grid = [=[
@@ -936,9 +1020,10 @@ describe('treesitter highlighting (help)', function()
end)
describe('treesitter highlighting (nested injections)', function()
- local screen
+ local screen --- @type test.functional.ui.screen
before_each(function()
+ clear()
screen = Screen.new(80, 7)
screen:attach()
screen:set_default_attr_ids {
@@ -964,11 +1049,11 @@ vim.cmd([[
]])
]=]
- exec_lua [[
+ exec_lua(function()
vim.opt.scrolloff = 0
vim.bo.filetype = 'lua'
vim.treesitter.start()
- ]]
+ end)
-- invalidate the language tree
feed('ggi--[[<ESC>04x')
@@ -1006,41 +1091,93 @@ describe('treesitter highlighting (markdown)', function()
local screen
before_each(function()
+ clear()
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 },
- }
+ exec_lua(function()
+ vim.bo.filetype = 'markdown'
+ vim.treesitter.start()
+ end)
end)
it('supports hyperlinks', function()
local url = 'https://example.com'
insert(string.format('[This link text](%s) is a hyperlink.', url))
- exec_lua([[
- vim.bo.filetype = 'markdown'
- vim.treesitter.start()
- ]])
+ screen:add_extra_attr_ids({
+ [100] = { foreground = Screen.colors.DarkCyan, url = 'https://example.com' },
+ [101] = {
+ foreground = Screen.colors.SlateBlue,
+ url = 'https://example.com',
+ underline = true,
+ },
+ })
+ screen:expect({
+ grid = [[
+ {25:[}{100:This link text}{25:](}{101:https://example.com}{25:)} is|
+ a hyperlink^. |
+ {1:~ }|*3
+ |
+ ]],
+ })
+ end)
- screen:expect {
+ it('works with spellchecked and smoothscrolled topline', function()
+ insert([[
+- $f(0)=\sum_{k=1}^{\infty}\frac{2}{\pi^{2}k^{2}}+\lim_{w \to 0}x$.
+
+```c
+printf('Hello World!');
+```
+ ]])
+ command('set spell smoothscroll')
+ feed('gg<C-E>')
+ screen:add_extra_attr_ids({ [100] = { undercurl = true, special = Screen.colors.Red } })
+ screen:expect({
grid = [[
- {4:[}{6:This link text}{4:](}{7:https://example.com}{4:)} is|
- a hyperlink^. |
- {2:~ }|*3
- |
- ]],
- 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.Magenta },
- [6] = { foreground = Screen.colors.Cyan4, url = url },
- [7] = { underline = true, foreground = Screen.colors.SlateBlue },
- },
- }
+ {1:<<<}k^{2}}+\{100:lim}_{w \to 0}x$^. |
+ |
+ {18:```}{15:c} |
+ {25:printf}{16:(}{26:'Hello World!'}{16:);} |
+ {18:```} |
+ |
+ ]],
+ })
end)
end)
+
+it('starting and stopping treesitter highlight in init.lua works #29541', function()
+ t.write_file(
+ 'Xinit.lua',
+ [[
+ vim.bo.ft = 'c'
+ vim.treesitter.start()
+ vim.treesitter.stop()
+ ]]
+ )
+ finally(function()
+ os.remove('Xinit.lua')
+ end)
+ clear({ args = { '-u', 'Xinit.lua' } })
+ eq('', api.nvim_get_vvar('errmsg'))
+
+ local 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 },
+ }
+
+ fn.setreg('r', hl_text_c)
+ feed('i<C-R><C-O>r<Esc>gg')
+ -- legacy syntax highlighting is used
+ screen:expect(hl_grid_legacy_c)
+end)