Skip to content

Commit c838d93

Browse files
committed
test(ui): cover stack preview treesitter highlight cases
1 parent 70b958b commit c838d93

1 file changed

Lines changed: 246 additions & 0 deletions

File tree

tests/stack_view_spec.lua

Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,4 +428,250 @@ describe("peekstack.ui.stack_view", function()
428428

429429
vim.fn.delete(tmpfile)
430430
end)
431+
432+
it("applies treesitter highlights to preview lines when available", function()
433+
local tmpfile = vim.fn.tempname() .. ".lua"
434+
vim.fn.writefile({ "local value = 42" }, tmpfile)
435+
436+
local original_get_parser = vim.treesitter.get_parser
437+
local original_query_get = vim.treesitter.query.get
438+
local ok, err = pcall(function()
439+
vim.api.nvim_set_hl(0, "@keyword.peekstack_test_ts", { link = "Keyword" })
440+
441+
local fake_node = {
442+
range = function()
443+
return 0, 0, 0, 5
444+
end,
445+
}
446+
local fake_root = {
447+
range = function()
448+
return 0, 0, 0, 20
449+
end,
450+
}
451+
local fake_tree = {
452+
root = function()
453+
return fake_root
454+
end,
455+
lang = function()
456+
return "peekstack_test_ts"
457+
end,
458+
}
459+
local fake_query = {
460+
captures = { "keyword" },
461+
}
462+
fake_query.iter_captures = function(_self, _root, _bufnr, _start_row, _end_row)
463+
local emitted = false
464+
return function()
465+
if emitted then
466+
return nil
467+
end
468+
emitted = true
469+
return 1, fake_node
470+
end
471+
end
472+
473+
vim.treesitter.get_parser = function(_bufnr)
474+
return {
475+
parse = function() end,
476+
trees = function()
477+
return { fake_tree }
478+
end,
479+
}
480+
end
481+
vim.treesitter.query.get = function(_lang, _query_name)
482+
return fake_query
483+
end
484+
485+
local loc = helpers.make_location({
486+
uri = vim.uri_from_fname(tmpfile),
487+
range = { start = { line = 0, character = 0 }, ["end"] = { line = 0, character = 0 } },
488+
})
489+
local model = stack.push(loc)
490+
assert.is_not_nil(model)
491+
492+
stack_view.open()
493+
local state = stack_view._get_state()
494+
stack_view._render(state)
495+
496+
local lines = vim.api.nvim_buf_get_lines(state.bufnr, 0, -1, false)
497+
local preview_line_nr = nil
498+
for idx, line in ipairs(lines) do
499+
if line:find("local value = 42", 1, true) then
500+
preview_line_nr = idx
501+
break
502+
end
503+
end
504+
assert.is_not_nil(preview_line_nr)
505+
506+
local ns = vim.api.nvim_create_namespace("PeekstackStackView")
507+
local extmarks = vim.api.nvim_buf_get_extmarks(state.bufnr, ns, 0, -1, { details = true })
508+
local found = false
509+
for _, mark in ipairs(extmarks) do
510+
local row = mark[2]
511+
local details = mark[4] or {}
512+
if row == preview_line_nr - 1 and details.hl_group == "@keyword.peekstack_test_ts" then
513+
found = true
514+
break
515+
end
516+
end
517+
assert.is_true(found, "treesitter highlight should be applied to preview line")
518+
end)
519+
520+
vim.treesitter.get_parser = original_get_parser
521+
vim.treesitter.query.get = original_query_get
522+
vim.fn.delete(tmpfile)
523+
if not ok then
524+
error(err)
525+
end
526+
end)
527+
528+
it("falls back to default preview highlight when treesitter parser fails", function()
529+
local tmpfile = vim.fn.tempname() .. ".lua"
530+
vim.fn.writefile({ "local x = 42" }, tmpfile)
531+
532+
local original_get_parser = vim.treesitter.get_parser
533+
local ok, err = pcall(function()
534+
vim.treesitter.get_parser = function(_bufnr)
535+
error("parser unavailable")
536+
end
537+
538+
local loc = helpers.make_location({
539+
uri = vim.uri_from_fname(tmpfile),
540+
range = { start = { line = 0, character = 0 }, ["end"] = { line = 0, character = 0 } },
541+
})
542+
local model = stack.push(loc)
543+
assert.is_not_nil(model)
544+
545+
stack_view.open()
546+
local state = stack_view._get_state()
547+
assert.has_no.errors(function()
548+
stack_view._render(state)
549+
end)
550+
551+
local lines = vim.api.nvim_buf_get_lines(state.bufnr, 0, -1, false)
552+
local preview_line_nr = nil
553+
for idx, line in ipairs(lines) do
554+
if line:find("local x = 42", 1, true) then
555+
preview_line_nr = idx
556+
break
557+
end
558+
end
559+
assert.is_not_nil(preview_line_nr)
560+
561+
local ns = vim.api.nvim_create_namespace("PeekstackStackView")
562+
local extmarks = vim.api.nvim_buf_get_extmarks(state.bufnr, ns, 0, -1, { details = true })
563+
local found = false
564+
for _, mark in ipairs(extmarks) do
565+
local row = mark[2]
566+
local details = mark[4] or {}
567+
if row == preview_line_nr - 1 and details.hl_group == "PeekstackStackViewPreview" then
568+
found = true
569+
break
570+
end
571+
end
572+
assert.is_true(found, "default preview highlight should remain when treesitter fails")
573+
end)
574+
575+
vim.treesitter.get_parser = original_get_parser
576+
vim.fn.delete(tmpfile)
577+
if not ok then
578+
error(err)
579+
end
580+
end)
581+
582+
it("clamps treesitter highlight range on truncated preview lines", function()
583+
local tmpfile = vim.fn.tempname() .. ".lua"
584+
vim.fn.writefile({ string.rep("a", 400) }, tmpfile)
585+
586+
local original_get_parser = vim.treesitter.get_parser
587+
local original_query_get = vim.treesitter.query.get
588+
local ok, err = pcall(function()
589+
vim.api.nvim_set_hl(0, "@string.peekstack_test_trunc", { link = "String" })
590+
591+
local fake_node = {
592+
range = function()
593+
return 0, 0, 0, 400
594+
end,
595+
}
596+
local fake_root = {
597+
range = function()
598+
return 0, 0, 0, 400
599+
end,
600+
}
601+
local fake_tree = {
602+
root = function()
603+
return fake_root
604+
end,
605+
lang = function()
606+
return "peekstack_test_trunc"
607+
end,
608+
}
609+
local fake_query = {
610+
captures = { "string" },
611+
}
612+
fake_query.iter_captures = function(_self, _root, _bufnr, _start_row, _end_row)
613+
local emitted = false
614+
return function()
615+
if emitted then
616+
return nil
617+
end
618+
emitted = true
619+
return 1, fake_node
620+
end
621+
end
622+
623+
vim.treesitter.get_parser = function(_bufnr)
624+
return {
625+
parse = function() end,
626+
trees = function()
627+
return { fake_tree }
628+
end,
629+
}
630+
end
631+
vim.treesitter.query.get = function(_lang, _query_name)
632+
return fake_query
633+
end
634+
635+
local loc = helpers.make_location({
636+
uri = vim.uri_from_fname(tmpfile),
637+
range = { start = { line = 0, character = 0 }, ["end"] = { line = 0, character = 0 } },
638+
})
639+
local model = stack.push(loc)
640+
assert.is_not_nil(model)
641+
642+
stack_view.open()
643+
local state = stack_view._get_state()
644+
assert.has_no.errors(function()
645+
stack_view._render(state)
646+
end)
647+
648+
local lines = vim.api.nvim_buf_get_lines(state.bufnr, 0, -1, false)
649+
local preview_line_nr = nil
650+
for idx, line in ipairs(lines) do
651+
if line:find("^ a", 1, false) then
652+
preview_line_nr = idx
653+
break
654+
end
655+
end
656+
assert.is_not_nil(preview_line_nr)
657+
local preview_len = #lines[preview_line_nr]
658+
659+
local ns = vim.api.nvim_create_namespace("PeekstackStackView")
660+
local extmarks = vim.api.nvim_buf_get_extmarks(state.bufnr, ns, 0, -1, { details = true })
661+
for _, mark in ipairs(extmarks) do
662+
local row = mark[2]
663+
local details = mark[4] or {}
664+
if row == preview_line_nr - 1 and details.hl_group == "@string.peekstack_test_trunc" then
665+
assert.is_true((details.end_col or 0) <= preview_len)
666+
end
667+
end
668+
end)
669+
670+
vim.treesitter.get_parser = original_get_parser
671+
vim.treesitter.query.get = original_query_get
672+
vim.fn.delete(tmpfile)
673+
if not ok then
674+
error(err)
675+
end
676+
end)
431677
end)

0 commit comments

Comments
 (0)