From bb8845340b1b9c2180fb19f049ff9deff5857d99 Mon Sep 17 00:00:00 2001 From: figsoda Date: Thu, 21 Jul 2022 12:08:37 +0100 Subject: feat(treesitter): allow capture text to be transformed Co-authored-by: Lewis Russell --- test/functional/treesitter/parser_spec.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'test/functional/treesitter/parser_spec.lua') diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua index f006ad4539..0f187f3d52 100644 --- a/test/functional/treesitter/parser_spec.lua +++ b/test/functional/treesitter/parser_spec.lua @@ -728,7 +728,7 @@ int x = INT_MAX; return list ]] - eq({ 'offset!', 'set!' }, res_list) + eq({ 'gsub!', 'offset!', 'set!' }, res_list) end) end) end) -- cgit From e1d5ad1cb87d43c3d75619e239312d4ab2029b45 Mon Sep 17 00:00:00 2001 From: figsoda Date: Mon, 26 Dec 2022 16:10:59 -0500 Subject: feat(treesitter): add metadata option for get_node_text --- test/functional/treesitter/parser_spec.lua | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'test/functional/treesitter/parser_spec.lua') diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua index 0f187f3d52..2d0d57fbd0 100644 --- a/test/functional/treesitter/parser_spec.lua +++ b/test/functional/treesitter/parser_spec.lua @@ -277,6 +277,9 @@ end]] function fake_node:end_() return 3, 0, 23 end + function fake_node:range() + return 3, 0, 3, 0 + end return vim.treesitter.get_node_text(fake_node, 0) == nil ]]) eq(true, result) @@ -296,6 +299,9 @@ end]] function fake_node:end_() return 1, 0, 7 end + function fake_node:range() + return 1, 0, 1, 0 + end return vim.treesitter.get_node_text(fake_node, 0) == '' ]]) eq(true, result) -- cgit From 8714a4009c0f0be0bb27a6b3eb486eeb3d9f3049 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Tue, 21 Feb 2023 17:09:18 +0000 Subject: feat(treesitter): add filetype -> lang API Problem: vim.treesitter does not know how to map a specific filetype to a parser. This creates problems since in a few places (including in vim.treesitter itself), the filetype is incorrectly used in place of lang. Solution: Add an API to enable this: - Add vim.treesitter.language.add() as a replacement for vim.treesitter.language.require_language(). - Optional arguments are now passed via an opts table. - Also takes a filetype (or list of filetypes) so we can keep track of what filetypes are associated with which langs. - Deprecated vim.treesitter.language.require_language(). - Add vim.treesitter.language.get_lang() which returns the associated lang for a given filetype. - Add vim.treesitter.language.register() to associate filetypes to a lang without loading the parser. --- test/functional/treesitter/parser_spec.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'test/functional/treesitter/parser_spec.lua') diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua index 2d0d57fbd0..2430021617 100644 --- a/test/functional/treesitter/parser_spec.lua +++ b/test/functional/treesitter/parser_spec.lua @@ -182,8 +182,9 @@ void ui_refresh(void) local firstrun = q(1) local manyruns = q(100) + local factor = is_os('win') and 3 or 4 -- First run should be at least 4x slower. - assert(400 * manyruns < firstrun, ('firstrun: %d ms, manyruns: %d ms'):format(firstrun / 1000, manyruns / 1000)) + assert(factor * 100 * manyruns < firstrun, ('firstrun: %d ms, manyruns: %d ms'):format(firstrun / 1000, manyruns / 1000)) end) it('support query and iter by capture', function() -- cgit From 75e53341f37eeeda7d9be7f934249f7e5e4397e9 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 23 Feb 2023 15:19:52 +0000 Subject: perf(treesitter): smarter languagetree invalidation Problem: Treesitter injections are slow because all injected trees are invalidated on every change. Solution: Implement smarter invalidation to avoid reparsing injected regions. - In on_bytes, try and update self._regions as best we can. This PR just offsets any regions after the change. - Add valid flags for each region in self._regions. - Call on_bytes recursively for all children. - We still need to run the query every time for the top level tree. I don't know how to avoid this. However, if the new injection ranges don't change, then we re-use the old trees and avoid reparsing children. This should result in roughly a 2-3x reduction in tree parsing when the comment injections are enabled. --- test/functional/treesitter/parser_spec.lua | 35 ++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'test/functional/treesitter/parser_spec.lua') diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua index 2430021617..fdd6403859 100644 --- a/test/functional/treesitter/parser_spec.lua +++ b/test/functional/treesitter/parser_spec.lua @@ -639,6 +639,17 @@ int x = INT_MAX; {1, 26, 1, 65}, -- READ_STRING(x, y) (char_u *)read_string((x), (size_t)(y)) {2, 29, 2, 68} -- READ_STRING_OK(x, y) (char_u *)read_string((x), (size_t)(y)) }, get_ranges()) + + helpers.feed('ggo') + 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, 65}, -- READ_STRING(x, y) (char_u *)read_string((x), (size_t)(y)) + {3, 29, 3, 68} -- READ_STRING_OK(x, y) (char_u *)read_string((x), (size_t)(y)) + }, get_ranges()) end) end) @@ -660,6 +671,18 @@ int x = INT_MAX; {1, 26, 2, 68} -- READ_STRING(x, y) (char_u *)read_string((x), (size_t)(y)) -- READ_STRING_OK(x, y) (char_u *)read_string((x), (size_t)(y)) }, get_ranges()) + + helpers.feed('ggo') + 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, 68} -- READ_STRING(x, y) (char_u *)read_string((x), (size_t)(y)) + -- READ_STRING_OK(x, y) (char_u *)read_string((x), (size_t)(y)) + }, get_ranges()) end) end) @@ -688,6 +711,18 @@ int x = INT_MAX; {1, 26, 2, 68} -- READ_STRING(x, y) (char_u *)read_string((x), (size_t)(y)) -- READ_STRING_OK(x, y) (char_u *)read_string((x), (size_t)(y)) }, get_ranges()) + + helpers.feed('ggo') + 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, 68} -- READ_STRING(x, y) (char_u *)read_string((x), (size_t)(y)) + -- READ_STRING_OK(x, y) (char_u *)read_string((x), (size_t)(y)) + }, get_ranges()) end) it("should not inject bad languages", function() -- cgit From 1df3f5ec6aca24cbe7b78ead5c37ad06a65c84e8 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 23 Feb 2023 17:05:20 +0000 Subject: feat(treesitter): upstream foldexpr from nvim-treesitter --- test/functional/treesitter/parser_spec.lua | 34 ++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'test/functional/treesitter/parser_spec.lua') diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua index fdd6403859..67aad4d1b7 100644 --- a/test/functional/treesitter/parser_spec.lua +++ b/test/functional/treesitter/parser_spec.lua @@ -871,4 +871,38 @@ int x = INT_MAX; end) end) end) + + it("can fold via foldexpr", function() + insert(test_text) + exec_lua([[vim.treesitter.get_parser(0, "c")]]) + + local levels = exec_lua([[ + local res = {} + for i = 1, vim.api.nvim_buf_line_count(0) do + res[i] = vim.treesitter.foldexpr(i) + end + return res + ]]) + + eq({ + [1] = '>1', + [2] = '1', + [3] = '1', + [4] = '1', + [5] = '>2', + [6] = '2', + [7] = '2', + [8] = '1', + [9] = '1', + [10] = '>2', + [11] = '2', + [12] = '2', + [13] = '2', + [14] = '2', + [15] = '>3', + [16] = '3', + [17] = '3', + [18] = '2', + [19] = '1' }, levels) + end) end) -- cgit From fb1db80f5ab707e188be3c60539fa38eaf996f24 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 2 Mar 2023 14:42:15 +0800 Subject: test(treesitter/parser_spec): correct time unit (#22471) --- test/functional/treesitter/parser_spec.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'test/functional/treesitter/parser_spec.lua') diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua index 67aad4d1b7..fd9822d1c0 100644 --- a/test/functional/treesitter/parser_spec.lua +++ b/test/functional/treesitter/parser_spec.lua @@ -182,9 +182,9 @@ void ui_refresh(void) local firstrun = q(1) local manyruns = q(100) - local factor = is_os('win') and 3 or 4 - -- First run should be at least 4x slower. - assert(factor * 100 * manyruns < firstrun, ('firstrun: %d ms, manyruns: %d ms'):format(firstrun / 1000, manyruns / 1000)) + -- First run should be at least 400x slower than an 100 subsequent runs. + local factor = is_os('win') and 300 or 400 + assert(factor * manyruns < firstrun, ('firstrun: %f ms, manyruns: %f ms'):format(firstrun / 1e6, manyruns / 1e6)) end) it('support query and iter by capture', function() -- cgit From 6d4f48182131c36d57589eefd4cefe3c70256d04 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Fri, 3 Mar 2023 09:44:02 +0000 Subject: fix(treesitter): disallow empty filetypes Fixes #22473 --- test/functional/treesitter/parser_spec.lua | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'test/functional/treesitter/parser_spec.lua') diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua index fd9822d1c0..27f2e81ab2 100644 --- a/test/functional/treesitter/parser_spec.lua +++ b/test/functional/treesitter/parser_spec.lua @@ -4,6 +4,7 @@ local clear = helpers.clear local eq = helpers.eq local insert = helpers.insert local exec_lua = helpers.exec_lua +local pcall_err = helpers.pcall_err local feed = helpers.feed local is_os = helpers.is_os local skip = helpers.skip @@ -124,6 +125,16 @@ void ui_refresh(void) }, res) end) + it('does not get parser for empty filetype', function() + insert(test_text); + + eq(".../language.lua:0: '' is not a valid 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); @@ -874,9 +885,10 @@ int x = INT_MAX; it("can fold via foldexpr", function() insert(test_text) - exec_lua([[vim.treesitter.get_parser(0, "c")]]) local levels = exec_lua([[ + vim.opt.filetype = 'c' + vim.treesitter.get_parser(0, "c") local res = {} for i = 1, vim.api.nvim_buf_line_count(0) do res[i] = vim.treesitter.foldexpr(i) -- cgit From c5b9643bf1b0f6d5166b4abf6a7c3f29532aefeb Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Fri, 10 Mar 2023 10:25:10 +0000 Subject: fix(treesitter): better lang handling of get_parser() --- test/functional/treesitter/parser_spec.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'test/functional/treesitter/parser_spec.lua') diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua index 27f2e81ab2..dd36c6c9e7 100644 --- a/test/functional/treesitter/parser_spec.lua +++ b/test/functional/treesitter/parser_spec.lua @@ -128,7 +128,9 @@ void ui_refresh(void) it('does not get parser for empty filetype', function() insert(test_text); - eq(".../language.lua:0: '' is not a valid filetype", + 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 -- cgit From 46b73bf22cb951151de9bf0712d42e194000b677 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 9 Mar 2023 15:28:55 +0000 Subject: perf(treesitter): more efficient foldexpr --- test/functional/treesitter/parser_spec.lua | 51 +++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 11 deletions(-) (limited to 'test/functional/treesitter/parser_spec.lua') diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua index dd36c6c9e7..0f00fcfe0d 100644 --- a/test/functional/treesitter/parser_spec.lua +++ b/test/functional/treesitter/parser_spec.lua @@ -888,18 +888,20 @@ int x = INT_MAX; it("can fold via foldexpr", function() insert(test_text) - local levels = exec_lua([[ - vim.opt.filetype = 'c' - vim.treesitter.get_parser(0, "c") - local res = {} - for i = 1, vim.api.nvim_buf_line_count(0) do - res[i] = vim.treesitter.foldexpr(i) - end - return res - ]]) + local function get_fold_levels() + return exec_lua([[ + local res = {} + for i = 1, vim.api.nvim_buf_line_count(0) do + res[i] = vim.treesitter.foldexpr(i) + end + return res + ]]) + end + + exec_lua([[vim.treesitter.get_parser(0, "c")]]) eq({ - [1] = '>1', + [1] = '>1', [2] = '1', [3] = '1', [4] = '1', @@ -917,6 +919,33 @@ int x = INT_MAX; [16] = '3', [17] = '3', [18] = '2', - [19] = '1' }, levels) + [19] = '1' }, get_fold_levels()) + + helpers.command('1,2d') + helpers.poke_eventloop() + + exec_lua([[vim.treesitter.get_parser():parse()]]) + + helpers.poke_eventloop() + helpers.sleep(100) + + eq({ + [1] = '0', + [2] = '0', + [3] = '>1', + [4] = '1', + [5] = '1', + [6] = '0', + [7] = '0', + [8] = '>1', + [9] = '1', + [10] = '1', + [11] = '1', + [12] = '1', + [13] = '>2', + [14] = '2', + [15] = '2', + [16] = '1', + [17] = '0' }, get_fold_levels()) end) end) -- cgit From 58bbc2ea0b3dfed13471e8cc0447d7598be24276 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Fri, 10 Mar 2023 16:40:27 +0000 Subject: refactor(treesitter): add Range type aliase for Range4|Range6 --- test/functional/treesitter/parser_spec.lua | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'test/functional/treesitter/parser_spec.lua') diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua index 0f00fcfe0d..c6ca65f9a1 100644 --- a/test/functional/treesitter/parser_spec.lua +++ b/test/functional/treesitter/parser_spec.lua @@ -196,7 +196,7 @@ void ui_refresh(void) local manyruns = q(100) -- First run should be at least 400x slower than an 100 subsequent runs. - local factor = is_os('win') and 300 or 400 + local factor = is_os('win') and 200 or 400 assert(factor * manyruns < firstrun, ('firstrun: %f ms, manyruns: %f ms'):format(firstrun / 1e6, manyruns / 1e6)) end) @@ -277,13 +277,13 @@ void ui_refresh(void) eq('void', res2) end) - it('support getting text where start of node is past EOF', function() + it('support getting text where start of node is one past EOF', function() local text = [[ def run a = <<~E end]] insert(text) - local result = exec_lua([[ + eq('', exec_lua[[ local fake_node = {} function fake_node:start() return 3, 0, 23 @@ -291,12 +291,14 @@ end]] function fake_node:end_() return 3, 0, 23 end - function fake_node:range() + function fake_node:range(bytes) + if bytes then + return 3, 0, 23, 3, 0, 23 + end return 3, 0, 3, 0 end - return vim.treesitter.get_node_text(fake_node, 0) == nil + return vim.treesitter.get_node_text(fake_node, 0) ]]) - eq(true, result) end) it('support getting empty text if node range is zero width', function() -- cgit From b466e1d289180fad212a93b173034787fd6be9a8 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Mon, 13 Mar 2023 04:15:24 +0100 Subject: test: unskip working Windows tests (#22537) Some tests that were previously not working have started to work again for unspecified reasons, so let's enable them. --- test/functional/treesitter/parser_spec.lua | 2 -- 1 file changed, 2 deletions(-) (limited to 'test/functional/treesitter/parser_spec.lua') diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua index c6ca65f9a1..e872861d2a 100644 --- a/test/functional/treesitter/parser_spec.lua +++ b/test/functional/treesitter/parser_spec.lua @@ -7,7 +7,6 @@ local exec_lua = helpers.exec_lua local pcall_err = helpers.pcall_err local feed = helpers.feed local is_os = helpers.is_os -local skip = helpers.skip before_each(clear) @@ -741,7 +740,6 @@ int x = INT_MAX; end) it("should not inject bad languages", function() - skip(is_os('win')) exec_lua([=[ vim.treesitter.add_directive("inject-bad!", function(match, _, _, pred, metadata) metadata.language = "{" -- cgit From cbbf8bd666c8419fdab80a0887948c8a36279c19 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Fri, 24 Mar 2023 14:43:14 +0000 Subject: feat(treesitter)!: deprecate top level indexes to modules (#22761) The following top level Treesitter functions have been moved: - vim.treesitter.inspect_language() -> vim.treesitter.language.inspect() - vim.treesitter.get_query_files() -> vim.treesitter.query.get_files() - vim.treesitter.set_query() -> vim.treesitter.query.set() - vim.treesitter.query.set_query() -> vim.treesitter.query.set() - vim.treesitter.get_query() -> vim.treesitter.query.get() - vim.treesitter.query.get_query() -> vim.treesitter.query.get() - vim.treesitter.parse_query() -> vim.treesitter.query.parse() - vim.treesitter.query.parse_query() -> vim.treesitter.query.parse() - vim.treesitter.add_predicate() -> vim.treesitter.query.add_predicate() - vim.treesitter.add_directive() -> vim.treesitter.query.add_directive() - vim.treesitter.list_predicates() -> vim.treesitter.query.list_predicates() - vim.treesitter.list_directives() -> vim.treesitter.query.list_directives() - vim.treesitter.query.get_range() -> vim.treesitter.get_range() - vim.treesitter.query.get_node_text() -> vim.treesitter.get_node_text() --- test/functional/treesitter/parser_spec.lua | 44 +++++++++++++++--------------- 1 file changed, 22 insertions(+), 22 deletions(-) (limited to 'test/functional/treesitter/parser_spec.lua') diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua index e872861d2a..72a8cd9e9b 100644 --- a/test/functional/treesitter/parser_spec.lua +++ b/test/functional/treesitter/parser_spec.lua @@ -23,7 +23,7 @@ describe('treesitter parser API', function() parser = vim.treesitter.get_parser(0, "c") tree = parser:parse()[1] root = tree:root() - lang = vim.treesitter.inspect_language('c') + lang = vim.treesitter.language.inspect('c') ]]) eq("", exec_lua("return tostring(tree)")) @@ -171,7 +171,7 @@ void ui_refresh(void) it("supports runtime queries", function() local ret = exec_lua [[ - return require"vim.treesitter.query".get_query("c", "highlights").captures[1] + return vim.treesitter.query.get("c", "highlights").captures[1] ]] eq('variable', ret) @@ -184,7 +184,7 @@ void ui_refresh(void) local query, n = ... local before = vim.loop.hrtime() for i=1,n,1 do - cquery = vim.treesitter.parse_query("c", ...) + cquery = vim.treesitter.query.parse("c", ...) end local after = vim.loop.hrtime() return after - before @@ -203,7 +203,7 @@ void ui_refresh(void) insert(test_text) local res = exec_lua([[ - cquery = vim.treesitter.parse_query("c", ...) + cquery = vim.treesitter.query.parse("c", ...) parser = vim.treesitter.get_parser(0, "c") tree = parser:parse()[1] res = {} @@ -232,7 +232,7 @@ void ui_refresh(void) insert(test_text) local res = exec_lua([[ - cquery = vim.treesitter.parse_query("c", ...) + cquery = vim.treesitter.query.parse("c", ...) parser = vim.treesitter.get_parser(0, "c") tree = parser:parse()[1] res = {} @@ -326,7 +326,7 @@ end]] insert('char* astring = "\\n"; (1 + 1) * 2 != 2;') local res = exec_lua([[ - cquery = vim.treesitter.parse_query("c", '([_] @plus (#vim-match? @plus "^\\\\+$"))'.. + cquery = vim.treesitter.query.parse("c", '([_] @plus (#vim-match? @plus "^\\\\+$"))'.. '([_] @times (#vim-match? @times "^\\\\*$"))'.. '([_] @paren (#vim-match? @paren "^\\\\($"))'.. '([_] @escape (#vim-match? @escape "^\\\\\\\\n$"))'.. @@ -376,7 +376,7 @@ end]] ]]) exec_lua([[ function get_query_result(query_text) - cquery = vim.treesitter.parse_query("c", query_text) + cquery = vim.treesitter.query.parse("c", query_text) parser = vim.treesitter.get_parser(0, "c") tree = parser:parse()[1] res = {} @@ -416,7 +416,7 @@ end]] insert('char* astring = "Hello World!";') local res = exec_lua([[ - cquery = vim.treesitter.parse_query("c", '([_] @quote (#vim-match? @quote "^\\"$")) ([_] @quote (#lua-match? @quote "^\\"$"))') + cquery = vim.treesitter.query.parse("c", '([_] @quote (#vim-match? @quote "^\\"$")) ([_] @quote (#lua-match? @quote "^\\"$"))') parser = vim.treesitter.get_parser(0, "c") tree = parser:parse()[1] res = {} @@ -449,7 +449,7 @@ end]] local custom_query = "((identifier) @main (#is-main? @main))" local res = exec_lua([[ - local query = require"vim.treesitter.query" + local query = vim.treesitter.query local function is_main(match, pattern, bufnr, predicate) local node = match[ predicate[2] ] @@ -461,7 +461,7 @@ end]] query.add_predicate("is-main?", is_main) - local query = query.parse_query("c", ...) + local query = query.parse("c", ...) local nodes = {} for _, node in query:iter_captures(parser:parse()[1]:root(), 0) do @@ -474,7 +474,7 @@ end]] eq({{0, 4, 0, 8}}, res) local res_list = exec_lua[[ - local query = require'vim.treesitter.query' + local query = vim.treesitter.query local list = query.list_predicates() @@ -533,7 +533,7 @@ end]] local res = exec_lua [[ parser = vim.treesitter.get_parser(0, "c") - query = vim.treesitter.parse_query("c", "(declaration) @decl") + query = vim.treesitter.query.parse("c", "(declaration) @decl") local nodes = {} for _, node in query:iter_captures(parser:parse()[1]:root(), 0) do @@ -581,7 +581,7 @@ end]] local parser = vim.treesitter.get_string_parser(str, "c") local nodes = {} - local query = vim.treesitter.parse_query("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() }) @@ -603,7 +603,7 @@ end]] local parser = vim.treesitter.get_string_parser(str, "c") local nodes = {} - local query = vim.treesitter.parse_query("c", '((identifier) @foo)') + local query = vim.treesitter.query.parse("c", '((identifier) @foo)') local first_child = parser:parse()[1]:root():child(1) for _, node in query:iter_captures(first_child, str) do @@ -703,7 +703,7 @@ int x = INT_MAX; describe("when providing parsing information through a directive", function() it("should inject a language", function() exec_lua([=[ - vim.treesitter.add_directive("inject-clang!", function(match, _, _, pred, metadata) + vim.treesitter.query.add_directive("inject-clang!", function(match, _, _, pred, metadata) metadata.language = "c" metadata.combined = true metadata.content = pred[2] @@ -741,7 +741,7 @@ int x = INT_MAX; it("should not inject bad languages", function() exec_lua([=[ - vim.treesitter.add_directive("inject-bad!", function(match, _, _, pred, metadata) + vim.treesitter.query.add_directive("inject-bad!", function(match, _, _, pred, metadata) metadata.language = "{" metadata.combined = true metadata.content = pred[2] @@ -774,7 +774,7 @@ int x = INT_MAX; end) it("should list all directives", function() local res_list = exec_lua[[ - local query = require'vim.treesitter.query' + local query = vim.treesitter.query local list = query.list_directives() @@ -820,7 +820,7 @@ int x = INT_MAX; local result = exec_lua([[ local result - query = vim.treesitter.parse_query("c", '((number_literal) @number (#set! "key" "value"))') + 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 @@ -840,10 +840,10 @@ int x = INT_MAX; ]]) local result = exec_lua([[ - local query = require("vim.treesitter.query") + local query = vim.treesitter.query local value - query = vim.treesitter.parse_query("c", '((number_literal) @number (#set! @number "key" "value"))') + 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 @@ -862,10 +862,10 @@ int x = INT_MAX; ]]) local result = exec_lua([[ - local query = require("vim.treesitter.query") + local query = vim.treesitter.query local result - query = vim.treesitter.parse_query("c", '((number_literal) @number (#set! @number "key" "value") (#set! @number "key2" "value2"))') + 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 -- cgit From d510bfbc8e447b1a60d5ec7faaa8f440eb4ef56f Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Sun, 2 Apr 2023 10:11:42 +0200 Subject: refactor: remove char_u (#22829) Closes https://github.com/neovim/neovim/issues/459 --- test/functional/treesitter/parser_spec.lua | 32 +++++++++++++++--------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'test/functional/treesitter/parser_spec.lua') diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua index 72a8cd9e9b..ea9958b12a 100644 --- a/test/functional/treesitter/parser_spec.lua +++ b/test/functional/treesitter/parser_spec.lua @@ -627,8 +627,8 @@ end]] before_each(function() insert([[ int x = INT_MAX; -#define READ_STRING(x, y) (char_u *)read_string((x), (size_t)(y)) -#define READ_STRING_OK(x, y) (char_u *)read_string((x), (size_t)(y)) +#define READ_STRING(x, y) (char *)read_string((x), (size_t)(y)) +#define READ_STRING_OK(x, y) (char *)read_string((x), (size_t)(y)) #define VALUE 123 #define VALUE1 123 #define VALUE2 123 @@ -650,8 +650,8 @@ int x = INT_MAX; {3, 14, 3, 17}, -- VALUE 123 {4, 15, 4, 18}, -- VALUE1 123 {5, 15, 5, 18}, -- VALUE2 123 - {1, 26, 1, 65}, -- READ_STRING(x, y) (char_u *)read_string((x), (size_t)(y)) - {2, 29, 2, 68} -- READ_STRING_OK(x, y) (char_u *)read_string((x), (size_t)(y)) + {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') @@ -661,8 +661,8 @@ int x = INT_MAX; {4, 14, 4, 17}, -- VALUE 123 {5, 15, 5, 18}, -- VALUE1 123 {6, 15, 6, 18}, -- VALUE2 123 - {2, 26, 2, 65}, -- READ_STRING(x, y) (char_u *)read_string((x), (size_t)(y)) - {3, 29, 3, 68} -- READ_STRING_OK(x, y) (char_u *)read_string((x), (size_t)(y)) + {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) @@ -682,8 +682,8 @@ int x = INT_MAX; {3, 14, 5, 18}, -- VALUE 123 -- VALUE1 123 -- VALUE2 123 - {1, 26, 2, 68} -- READ_STRING(x, y) (char_u *)read_string((x), (size_t)(y)) - -- READ_STRING_OK(x, y) (char_u *)read_string((x), (size_t)(y)) + {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') @@ -694,8 +694,8 @@ int x = INT_MAX; {4, 14, 6, 18}, -- VALUE 123 -- VALUE1 123 -- VALUE2 123 - {2, 26, 3, 68} -- READ_STRING(x, y) (char_u *)read_string((x), (size_t)(y)) - -- READ_STRING_OK(x, y) (char_u *)read_string((x), (size_t)(y)) + {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) @@ -722,8 +722,8 @@ int x = INT_MAX; {3, 14, 5, 18}, -- VALUE 123 -- VALUE1 123 -- VALUE2 123 - {1, 26, 2, 68} -- READ_STRING(x, y) (char_u *)read_string((x), (size_t)(y)) - -- READ_STRING_OK(x, y) (char_u *)read_string((x), (size_t)(y)) + {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') @@ -734,8 +734,8 @@ int x = INT_MAX; {4, 14, 6, 18}, -- VALUE 123 -- VALUE1 123 -- VALUE2 123 - {2, 26, 3, 68} -- READ_STRING(x, y) (char_u *)read_string((x), (size_t)(y)) - -- READ_STRING_OK(x, y) (char_u *)read_string((x), (size_t)(y)) + {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) @@ -768,8 +768,8 @@ int x = INT_MAX; {3, 15, 3, 16}, -- VALUE 123 {4, 16, 4, 17}, -- VALUE1 123 {5, 16, 5, 17}, -- VALUE2 123 - {1, 26, 1, 65}, -- READ_STRING(x, y) (char_u *)read_string((x), (size_t)(y)) - {2, 29, 2, 68} -- READ_STRING_OK(x, y) (char_u *)read_string((x), (size_t)(y)) + {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() -- cgit From e29bc03c046b3a137c2e36b4d34c119b277d62b2 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 6 Apr 2023 15:16:44 +0100 Subject: fix(treesitter): do not track ranges of the root tree (#22912) Fixes #22911 --- test/functional/treesitter/parser_spec.lua | 44 ++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) (limited to 'test/functional/treesitter/parser_spec.lua') diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua index ea9958b12a..9afce0b3a0 100644 --- a/test/functional/treesitter/parser_spec.lua +++ b/test/functional/treesitter/parser_spec.lua @@ -948,4 +948,48 @@ int x = INT_MAX; [16] = '1', [17] = '0' }, get_fold_levels()) end) + + it('tracks the root range properly (#22911)', function() + insert([[ + int main() { + int x = 3; + }]]) + + local query0 = [[ + (declaration) @declaration + (function_definition) @function + ]] + + exec_lua([[ + vim.treesitter.start(0, 'c') + ]]) + + local function run_query() + return exec_lua([[ + local query = vim.treesitter.query.parse("c", ...) + parser = vim.treesitter.get_parser() + tree = parser:parse()[1] + res = {} + for id, node in query:iter_captures(tree:root()) do + table.insert(res, {query.captures[id], node:range()}) + end + return res + ]], query0) + end + + eq({ + { 'function', 0, 0, 2, 1 }, + { 'declaration', 1, 2, 1, 12 } + }, run_query()) + + helpers.command'normal ggO' + insert('int a;') + + eq({ + { 'declaration', 0, 0, 0, 6 }, + { 'function', 1, 0, 3, 1 }, + { 'declaration', 2, 2, 2, 12 } + }, run_query()) + + end) end) -- cgit From 9ff59517cbf309d31f979a49b7dc82b237ecfcc4 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Sat, 13 May 2023 12:56:21 +0200 Subject: fix(treesitter): update c queries --- test/functional/treesitter/parser_spec.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'test/functional/treesitter/parser_spec.lua') diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua index 9afce0b3a0..60042ab2fd 100644 --- a/test/functional/treesitter/parser_spec.lua +++ b/test/functional/treesitter/parser_spec.lua @@ -483,7 +483,7 @@ end]] return list ]] - eq({ 'any-of?', 'contains?', 'eq?', 'is-main?', 'lua-match?', 'match?', 'vim-match?' }, res_list) + eq({ 'any-of?', 'contains?', 'eq?', 'has-ancestor?', 'has-parent?', 'is-main?', 'lua-match?', 'match?', 'vim-match?' }, res_list) end) -- cgit From 6b19170d44ca56cf65542ee184d2bc89c6d622a9 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Tue, 16 May 2023 16:41:47 +0100 Subject: fix(treesitter): correctly calculate bytes for text sources (#23655) Fixes #20419 --- test/functional/treesitter/parser_spec.lua | 56 +++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) (limited to 'test/functional/treesitter/parser_spec.lua') diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua index 60042ab2fd..14de07639b 100644 --- a/test/functional/treesitter/parser_spec.lua +++ b/test/functional/treesitter/parser_spec.lua @@ -486,7 +486,6 @@ end]] eq({ 'any-of?', 'contains?', 'eq?', 'has-ancestor?', 'has-parent?', 'is-main?', 'lua-match?', 'match?', 'vim-match?' }, res_list) end) - it('allows to set simple ranges', function() insert(test_text) @@ -528,6 +527,7 @@ end]] eq(range_tbl, { { { 0, 0, 0, 17, 1, 508 } } }) end) + it("allows to set complex ranges", function() insert(test_text) @@ -992,4 +992,58 @@ int x = INT_MAX; }, run_query()) end) + + it('handles ranges when source is a multiline string (#20419)', function() + local source = [==[ + vim.cmd[[ + set number + set cmdheight=2 + set lastsatus=2 + ]] + + set query = [[;; query + ((function_call + name: [ + (identifier) @_cdef_identifier + (_ _ (identifier) @_cdef_identifier) + ] + arguments: (arguments (string content: _ @injection.content))) + (#set! injection.language "c") + (#eq? @_cdef_identifier "cdef")) + ]] + ]==] + + local r = exec_lua([[ + local parser = vim.treesitter.get_string_parser(..., 'lua') + parser:parse() + local ranges = {} + parser:for_each_tree(function(tstree, tree) + ranges[tree:lang()] = { tstree:root():range(true) } + end) + return ranges + ]], source) + + eq({ + lua = { 0, 6, 6, 16, 4, 438 }, + query = { 6, 20, 113, 15, 6, 431 }, + 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 r, source = ... + local add_bytes = require('vim.treesitter._range').add_bytes + for lang, range in pairs(r) do + r[lang] = {range[1], range[2], range[4], range[5]} + r[lang] = add_bytes(source, r[lang]) + end + return r + ]], r, source) + + eq(rb, r) + + end) end) -- cgit From 2db719f6c2b677fcbc197b02fe52764a851523b2 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Sat, 3 Jun 2023 11:06:00 +0100 Subject: feat(lua): rename vim.loop -> vim.uv (#22846) --- test/functional/treesitter/parser_spec.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'test/functional/treesitter/parser_spec.lua') diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua index 14de07639b..e463382d07 100644 --- a/test/functional/treesitter/parser_spec.lua +++ b/test/functional/treesitter/parser_spec.lua @@ -182,11 +182,11 @@ void ui_refresh(void) local function q(n) return exec_lua ([[ local query, n = ... - local before = vim.loop.hrtime() + local before = vim.uv.hrtime() for i=1,n,1 do cquery = vim.treesitter.query.parse("c", ...) end - local after = vim.loop.hrtime() + local after = vim.uv.hrtime() return after - before ]], long_query, n) end -- cgit From c7e7f1d4b4b62c75bb54e652f25c6c6b8785a7f4 Mon Sep 17 00:00:00 2001 From: Jaehwang Jung Date: Wed, 28 Jun 2023 03:05:09 +0900 Subject: fix(treesitter): make foldexpr work without highlighting (#24167) Problem: Treesitter fold is not updated if treesitter hightlight is not active. More precisely, updating folds requires `LanguageTree:parse()`. Solution: Call `parse()` before computing folds and compute folds when lines are added/removed. This doesn't guarantee correctness of the folds, because some changes that don't add/remove line won't update the folds even if they should (e.g. adding pair of braces). But it is good enough for most cases, while not introducing big overhead. Also, if highlighting is active, it is likely that `TSHighlighter._on_buf` already ran `parse()` (or vice versa). --- test/functional/treesitter/parser_spec.lua | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) (limited to 'test/functional/treesitter/parser_spec.lua') diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua index e463382d07..d2f40bfe00 100644 --- a/test/functional/treesitter/parser_spec.lua +++ b/test/functional/treesitter/parser_spec.lua @@ -922,12 +922,6 @@ int x = INT_MAX; [19] = '1' }, get_fold_levels()) helpers.command('1,2d') - helpers.poke_eventloop() - - exec_lua([[vim.treesitter.get_parser():parse()]]) - - helpers.poke_eventloop() - helpers.sleep(100) eq({ [1] = '0', @@ -947,6 +941,29 @@ int x = INT_MAX; [15] = '2', [16] = '1', [17] = '0' }, get_fold_levels()) + + helpers.command('1put!') + + eq({ + [1] = '>1', + [2] = '1', + [3] = '1', + [4] = '1', + [5] = '>2', + [6] = '2', + [7] = '2', + [8] = '1', + [9] = '1', + [10] = '>2', + [11] = '2', + [12] = '2', + [13] = '2', + [14] = '2', + [15] = '>3', + [16] = '3', + [17] = '3', + [18] = '2', + [19] = '1' }, get_fold_levels()) end) it('tracks the root range properly (#22911)', function() -- cgit From 11844dde81c41bded54f2383b57f8eef406f2736 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Sat, 1 Jul 2023 11:08:06 +0200 Subject: feat(treesitter): bundle markdown parser and queries (#22481) * bundle split Markdown parser from https://github.com/MDeiml/tree-sitter-markdown * add queries from https://github.com/nvim-treesitter/nvim-treesitter/tree/main * upstream `#trim!` and `#inject-language!` directives Co-authored-by: dundargoc --- test/functional/treesitter/parser_spec.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'test/functional/treesitter/parser_spec.lua') diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua index d2f40bfe00..7cfe5b69de 100644 --- a/test/functional/treesitter/parser_spec.lua +++ b/test/functional/treesitter/parser_spec.lua @@ -783,7 +783,7 @@ int x = INT_MAX; return list ]] - eq({ 'gsub!', 'offset!', 'set!' }, res_list) + eq({ 'gsub!', 'inject-language!', 'offset!', 'set!', 'trim!' }, res_list) end) end) end) -- cgit From c44d819ae1f29cd34ee3b2350b5c702caed949c3 Mon Sep 17 00:00:00 2001 From: Jaehwang Jung Date: Fri, 7 Jul 2023 19:12:46 +0900 Subject: fix(treesitter): update folds in all relevant windows (#24230) Problem: When using treesitter foldexpr, * :diffput/get open diff folds, and * folds are not updated in other windows that contain the updated buffer. Solution: Update folds in all windows that contain the updated buffer and use expr foldmethod. --- test/functional/treesitter/parser_spec.lua | 81 ------------------------------ 1 file changed, 81 deletions(-) (limited to 'test/functional/treesitter/parser_spec.lua') diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua index 7cfe5b69de..ae26b92f52 100644 --- a/test/functional/treesitter/parser_spec.lua +++ b/test/functional/treesitter/parser_spec.lua @@ -885,87 +885,6 @@ int x = INT_MAX; end) end) - it("can fold via foldexpr", function() - insert(test_text) - - local function get_fold_levels() - return exec_lua([[ - local res = {} - for i = 1, vim.api.nvim_buf_line_count(0) do - res[i] = vim.treesitter.foldexpr(i) - end - return res - ]]) - end - - exec_lua([[vim.treesitter.get_parser(0, "c")]]) - - eq({ - [1] = '>1', - [2] = '1', - [3] = '1', - [4] = '1', - [5] = '>2', - [6] = '2', - [7] = '2', - [8] = '1', - [9] = '1', - [10] = '>2', - [11] = '2', - [12] = '2', - [13] = '2', - [14] = '2', - [15] = '>3', - [16] = '3', - [17] = '3', - [18] = '2', - [19] = '1' }, get_fold_levels()) - - helpers.command('1,2d') - - eq({ - [1] = '0', - [2] = '0', - [3] = '>1', - [4] = '1', - [5] = '1', - [6] = '0', - [7] = '0', - [8] = '>1', - [9] = '1', - [10] = '1', - [11] = '1', - [12] = '1', - [13] = '>2', - [14] = '2', - [15] = '2', - [16] = '1', - [17] = '0' }, get_fold_levels()) - - helpers.command('1put!') - - eq({ - [1] = '>1', - [2] = '1', - [3] = '1', - [4] = '1', - [5] = '>2', - [6] = '2', - [7] = '2', - [8] = '1', - [9] = '1', - [10] = '>2', - [11] = '2', - [12] = '2', - [13] = '2', - [14] = '2', - [15] = '>3', - [16] = '3', - [17] = '3', - [18] = '2', - [19] = '1' }, get_fold_levels()) - end) - it('tracks the root range properly (#22911)', function() insert([[ int main() { -- cgit From 41cefe513054edd1c12f235125220dbc6b4d9451 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Thu, 27 Jul 2023 12:45:08 +0200 Subject: build(deps): bump tree-sitter-c to v0.20.4 (#24495) --- test/functional/treesitter/parser_spec.lua | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'test/functional/treesitter/parser_spec.lua') diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua index ae26b92f52..f0144e6f6d 100644 --- a/test/functional/treesitter/parser_spec.lua +++ b/test/functional/treesitter/parser_spec.lua @@ -194,8 +194,8 @@ void ui_refresh(void) local firstrun = q(1) local manyruns = q(100) - -- First run should be at least 400x slower than an 100 subsequent runs. - local factor = is_os('win') and 200 or 400 + -- First run should be at least 200x slower than an 100 subsequent runs. + local factor = is_os('win') and 100 or 200 assert(factor * manyruns < firstrun, ('firstrun: %f ms, manyruns: %f ms'):format(firstrun / 1e6, manyruns / 1e6)) end) @@ -765,9 +765,9 @@ int x = INT_MAX; eq("table", exec_lua("return type(parser:children().c)")) eq({ {0, 0, 7, 0}, -- root tree - {3, 15, 3, 16}, -- VALUE 123 - {4, 16, 4, 17}, -- VALUE1 123 - {5, 16, 5, 17}, -- VALUE2 123 + {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()) -- cgit From 0211f889b9538f7df5fbcb06273d273fb071efff Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Mon, 7 Aug 2023 18:22:36 +0100 Subject: fix(treesitter): make sure injections don't return empty ranges (#24595) When an injection has not set include children, make sure not to add the injection if no ranges are determined. This could happen when there is an injection with a child that has the same range as itself. e.g. consider this Makefile snippet ```make foo: $(VAR) ``` Line 2 has an injection for bash and a make variable reference. If include-children isn't set (default), then there is no range on line 2 to inject since the variable reference needs to be excluded. This caused the language tree to return an empty range, which the parser now interprets to mean the full buffer. This caused makefiles to have completely broken highlighting. --- test/functional/treesitter/parser_spec.lua | 34 ++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'test/functional/treesitter/parser_spec.lua') diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua index f0144e6f6d..da84f435c9 100644 --- a/test/functional/treesitter/parser_spec.lua +++ b/test/functional/treesitter/parser_spec.lua @@ -982,4 +982,38 @@ int x = INT_MAX; eq(rb, r) end) + + it("does not produce empty injection ranges (#23409)", function() + insert [[ + Examples: >lua + local a = {} +< + ]] + + -- This is not a valid injection since (code) has children and include-children is not set + exec_lua [[ + parser1 = require('vim.treesitter.languagetree').new(0, "vimdoc", { + injections = { + vimdoc = "((codeblock (language) @injection.language (code) @injection.content))" + } + }) + parser1:parse() + ]] + + eq(0, exec_lua("return #vim.tbl_keys(parser1:children())")) + + exec_lua [[ + parser2 = require('vim.treesitter.languagetree').new(0, "vimdoc", { + injections = { + vimdoc = "((codeblock (language) @injection.language (code) @injection.content) (#set! injection.include-children))" + } + }) + parser2:parse() + ]] + + 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) + end) -- cgit From 31c4ed26bc278282898123ad21bb6fead401fd6f Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Fri, 11 Aug 2023 17:05:17 +0200 Subject: feat(treesitter): add injection language fallback (#24659) * feat(treesitter): add injection language fallback Problem: injection languages are often specified via aliases (e.g., filetype or in upper case), requiring custom directives. Solution: include lookup logic (try as parser name, then filetype, then lowercase) in LanguageTree itself and remove `#inject-language` directive. Co-authored-by: Lewis Russell --- test/functional/treesitter/parser_spec.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'test/functional/treesitter/parser_spec.lua') diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua index da84f435c9..834998bae7 100644 --- a/test/functional/treesitter/parser_spec.lua +++ b/test/functional/treesitter/parser_spec.lua @@ -783,7 +783,7 @@ int x = INT_MAX; return list ]] - eq({ 'gsub!', 'inject-language!', 'offset!', 'set!', 'trim!' }, res_list) + eq({ 'gsub!', 'offset!', 'set!', 'trim!' }, res_list) end) end) end) -- cgit From 2ca076e45fb3f1c08f6a1a374834df0701b8d778 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 10 Aug 2023 14:21:56 +0100 Subject: feat(treesitter)!: incremental injection parsing Problem: Treesitter highlighting is slow for large files with lots of injections. Solution: Only parse injections we are going to render during a redraw cycle. --- - `LanguageTree:parse()` will no longer parse injections by default and now requires an explicit range argument to be passed. - `TSHighlighter` now parses injections incrementally during on_win callbacks for the line range being rendered. - Plugins which require certain injections to be parsed must run `parser:parse({ start_row, end_row })` before using the tree. --- test/functional/treesitter/parser_spec.lua | 91 ++++++++++++++++++++++++------ 1 file changed, 75 insertions(+), 16 deletions(-) (limited to 'test/functional/treesitter/parser_spec.lua') diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua index 834998bae7..cc833a67cc 100644 --- a/test/functional/treesitter/parser_spec.lua +++ b/test/functional/treesitter/parser_spec.lua @@ -1,6 +1,7 @@ local helpers = require('test.functional.helpers')(after_each) local clear = helpers.clear +local dedent = helpers.dedent local eq = helpers.eq local insert = helpers.insert local exec_lua = helpers.exec_lua @@ -502,22 +503,12 @@ end]] local root = parser:parse()[1]:root() parser:set_included_regions({{root:child(0)}}) parser:invalidate() - return { parser:parse()[1]:root():range() } + return { parser:parse(true)[1]:root():range() } ]] eq({0, 0, 18, 1}, res2) - local range = exec_lua [[ - local res = {} - for _, region in ipairs(parser:included_regions()) do - for _, node in ipairs(region) do - table.insert(res, {node:range()}) - end - end - return res - ]] - - eq(range, { { 0, 0, 18, 1 } }) + eq({ { { 0, 0, 0, 18, 1, 512 } } }, exec_lua [[ return parser:included_regions() ]]) local range_tbl = exec_lua [[ parser:set_included_regions { { { 0, 0, 17, 1 } } } @@ -542,7 +533,7 @@ end]] parser:set_included_regions({nodes}) - local root = parser:parse()[1]:root() + local root = parser:parse(true)[1]:root() local res = {} for i=0,(root:named_child_count() - 1) do @@ -638,9 +629,11 @@ int x = INT_MAX; describe("when parsing regions independently", function() it("should inject a language", function() exec_lua([[ + vim.g.__ts_debug = 1 parser = vim.treesitter.get_parser(0, "c", { injections = { c = "(preproc_def (preproc_arg) @c) (preproc_function_def value: (preproc_arg) @c)"}}) + parser:parse(true) ]]) eq("table", exec_lua("return type(parser:children().c)")) @@ -673,6 +666,7 @@ int x = INT_MAX; parser = vim.treesitter.get_parser(0, "c", { injections = { c = "(preproc_def (preproc_arg) @c @combined) (preproc_function_def value: (preproc_arg) @c @combined)"}}) + parser:parse(true) ]]) eq("table", exec_lua("return type(parser:children().c)")) @@ -713,6 +707,7 @@ int x = INT_MAX; injections = { c = "(preproc_def ((preproc_arg) @_c (#inject-clang! @_c)))" .. "(preproc_function_def value: ((preproc_arg) @_a (#inject-clang! @_a)))"}}) + parser:parse(true) ]=]) eq("table", exec_lua("return type(parser:children().c)")) @@ -760,6 +755,7 @@ int x = INT_MAX; parser = vim.treesitter.get_parser(0, "c", { injections = { c = "(preproc_def ((preproc_arg) @c (#offset! @c 0 2 0 -1))) (preproc_function_def value: (preproc_arg) @c)"}}) + parser:parse(true) ]]) eq("table", exec_lua("return type(parser:children().c)")) @@ -800,6 +796,7 @@ int x = INT_MAX; local result = exec_lua([[ parser = vim.treesitter.get_parser(0, "c", { injections = { c = "(preproc_def (preproc_arg) @c)"}}) + parser:parse(true) local sub_tree = parser:language_for_range({1, 18, 1, 19}) @@ -951,7 +948,7 @@ int x = INT_MAX; local r = exec_lua([[ local parser = vim.treesitter.get_string_parser(..., 'lua') - parser:parse() + parser:parse(true) local ranges = {} parser:for_each_tree(function(tstree, tree) ranges[tree:lang()] = { tstree:root():range(true) } @@ -997,7 +994,7 @@ int x = INT_MAX; vimdoc = "((codeblock (language) @injection.language (code) @injection.content))" } }) - parser1:parse() + parser1:parse(true) ]] eq(0, exec_lua("return #vim.tbl_keys(parser1:children())")) @@ -1008,7 +1005,7 @@ int x = INT_MAX; vimdoc = "((codeblock (language) @injection.language (code) @injection.content) (#set! injection.include-children))" } }) - parser2:parse() + parser2:parse(true) ]] eq(1, exec_lua("return #vim.tbl_keys(parser2:children())")) @@ -1016,4 +1013,66 @@ int x = INT_MAX; end) + it("parsers injections incrementally", function() + insert(dedent[[ + >lua + local a = {} + < + + >lua + local b = {} + < + + >lua + local c = {} + < + + >lua + local d = {} + < + + >lua + local e = {} + < + + >lua + local f = {} + < + + >lua + local g = {} + < + ]]) + + exec_lua [[ + parser = require('vim.treesitter.languagetree').new(0, "vimdoc", { + injections = { + vimdoc = "((codeblock (language) @injection.language (code) @injection.content) (#set! injection.include-children))" + } + }) + ]] + + --- Do not parse injections by default + eq(0, exec_lua [[ + parser:parse() + return #vim.tbl_keys(parser:children()) + ]]) + + --- Only parse injections between lines 0, 2 + eq(1, exec_lua [[ + parser:parse({0, 2}) + return #parser:children().lua:trees() + ]]) + + eq(2, exec_lua [[ + parser:parse({2, 6}) + return #parser:children().lua:trees() + ]]) + + eq(7, exec_lua [[ + parser:parse(true) + return #parser:children().lua:trees() + ]]) + end) + end) -- cgit From 8179d68dc1a90f47bfb307d73e71adc98883ae00 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Sun, 13 Aug 2023 08:03:56 +0100 Subject: fix(treesitter): logger memory leak --- test/functional/treesitter/parser_spec.lua | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'test/functional/treesitter/parser_spec.lua') diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua index cc833a67cc..ae3b0483c5 100644 --- a/test/functional/treesitter/parser_spec.lua +++ b/test/functional/treesitter/parser_spec.lua @@ -9,10 +9,13 @@ local pcall_err = helpers.pcall_err local feed = helpers.feed local is_os = helpers.is_os -before_each(clear) - describe('treesitter parser API', function() - clear() + before_each(function() + clear() + exec_lua[[ + vim.g.__ts_debug = 1 + ]] + end) it('parses buffer', function() insert([[ @@ -629,7 +632,6 @@ int x = INT_MAX; describe("when parsing regions independently", function() it("should inject a language", function() exec_lua([[ - vim.g.__ts_debug = 1 parser = vim.treesitter.get_parser(0, "c", { injections = { c = "(preproc_def (preproc_arg) @c) (preproc_function_def value: (preproc_arg) @c)"}}) -- cgit From fc0ee871de2f56dbb80879c912203a6372c54e1c Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Sat, 12 Aug 2023 17:54:04 +0200 Subject: fix(treesitter)!: remove deprecated legacy injection format --- test/functional/treesitter/parser_spec.lua | 63 ++---------------------------- 1 file changed, 4 insertions(+), 59 deletions(-) (limited to 'test/functional/treesitter/parser_spec.lua') diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua index ae3b0483c5..ae7cf58293 100644 --- a/test/functional/treesitter/parser_spec.lua +++ b/test/functional/treesitter/parser_spec.lua @@ -634,7 +634,7 @@ int x = INT_MAX; exec_lua([[ parser = vim.treesitter.get_parser(0, "c", { injections = { - c = "(preproc_def (preproc_arg) @c) (preproc_function_def value: (preproc_arg) @c)"}}) + c = '(preproc_def (preproc_arg) @injection.content (#set! injection.language "c")) (preproc_function_def value: (preproc_arg) @injection.content (#set! injection.language "c"))'}}) parser:parse(true) ]]) @@ -667,7 +667,7 @@ int x = INT_MAX; exec_lua([[ parser = vim.treesitter.get_parser(0, "c", { injections = { - c = "(preproc_def (preproc_arg) @c @combined) (preproc_function_def value: (preproc_arg) @c @combined)"}}) + c = '(preproc_def (preproc_arg) @injection.content (#set! injection.language "c") (#set! injection.combined)) (preproc_function_def value: (preproc_arg) @injection.content (#set! injection.language "c") (#set! injection.combined))'}}) parser:parse(true) ]]) @@ -696,67 +696,12 @@ int x = INT_MAX; end) end) - describe("when providing parsing information through a directive", function() - it("should inject a language", function() - exec_lua([=[ - vim.treesitter.query.add_directive("inject-clang!", function(match, _, _, pred, metadata) - metadata.language = "c" - metadata.combined = true - metadata.content = pred[2] - end) - - parser = vim.treesitter.get_parser(0, "c", { - injections = { - c = "(preproc_def ((preproc_arg) @_c (#inject-clang! @_c)))" .. - "(preproc_function_def value: ((preproc_arg) @_a (#inject-clang! @_a)))"}}) - parser:parse(true) - ]=]) - - 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)) - }, get_ranges()) - - helpers.feed('ggo') - 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)) - }, get_ranges()) - end) - - it("should not inject bad languages", function() - exec_lua([=[ - vim.treesitter.query.add_directive("inject-bad!", function(match, _, _, pred, metadata) - metadata.language = "{" - metadata.combined = true - metadata.content = pred[2] - end) - - parser = vim.treesitter.get_parser(0, "c", { - injections = { - c = "(preproc_function_def value: ((preproc_arg) @_a (#inject-bad! @_a)))"}}) - ]=]) - end) - end) - describe("when using the offset directive", function() it("should shift the range by the directive amount", function() exec_lua([[ parser = vim.treesitter.get_parser(0, "c", { injections = { - c = "(preproc_def ((preproc_arg) @c (#offset! @c 0 2 0 -1))) (preproc_function_def value: (preproc_arg) @c)"}}) + c = '(preproc_def ((preproc_arg) @injection.content (#set! injection.language "c") (#offset! @injection.content 0 2 0 -1))) (preproc_function_def value: (preproc_arg) @injection.content (#set! injection.language "c"))'}}) parser:parse(true) ]]) @@ -797,7 +742,7 @@ int x = INT_MAX; it("should return the correct language tree", function() local result = exec_lua([[ parser = vim.treesitter.get_parser(0, "c", { - injections = { c = "(preproc_def (preproc_arg) @c)"}}) + injections = { c = '(preproc_def (preproc_arg) @injection.content (#set! injection.language "c"))'}}) parser:parse(true) local sub_tree = parser:language_for_range({1, 18, 1, 19}) -- cgit From c6ec7fa8d741d6301701067ecd095bf02e7a741a Mon Sep 17 00:00:00 2001 From: Amaan Qureshi Date: Tue, 22 Aug 2023 00:51:38 -0400 Subject: feat(treesitter): add 'injection.self' and 'injection.parent' Co-authored-by: ObserverOfTime --- test/functional/treesitter/parser_spec.lua | 33 ++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'test/functional/treesitter/parser_spec.lua') diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua index ae7cf58293..56af0c8738 100644 --- a/test/functional/treesitter/parser_spec.lua +++ b/test/functional/treesitter/parser_spec.lua @@ -696,6 +696,39 @@ int x = INT_MAX; end) end) + describe("when using injection.self", function() + it("should inject the source language", function() + exec_lua([[ + parser = vim.treesitter.get_parser(0, "c", { + injections = { + c = '(preproc_def (preproc_arg) @injection.content (#set! injection.self)) (preproc_function_def value: (preproc_arg) @injection.content (#set! injection.self))'}}) + parser:parse(true) + ]]) + + 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)) + }, get_ranges()) + + helpers.feed('ggo') + 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)) + }, get_ranges()) + end) + end) + describe("when using the offset directive", function() it("should shift the range by the directive amount", function() exec_lua([[ -- cgit From 845d5b8b64190e0e09a6a6dd97bdbc0e6f96eb02 Mon Sep 17 00:00:00 2001 From: Amaan Qureshi Date: Wed, 19 Jul 2023 05:02:49 -0400 Subject: feat(treesitter): improve query error message --- test/functional/treesitter/parser_spec.lua | 40 ++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) (limited to 'test/functional/treesitter/parser_spec.lua') diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua index 56af0c8738..37dde37a64 100644 --- a/test/functional/treesitter/parser_spec.lua +++ b/test/functional/treesitter/parser_spec.lua @@ -1055,4 +1055,44 @@ int x = INT_MAX; ]]) end) + it('fails to load queries', function() + local function test(exp, cquery) + eq(exp, pcall_err(exec_lua, "vim.treesitter.query.parse('c', ...)", cquery)) + end + + -- Invalid node type + test( + '.../query.lua:0: Query error at 1:2. Invalid node type "dentifier":\n'.. + '(dentifier) @variable\n'.. + ' ^', + '(dentifier) @variable') + + -- Impossible pattern + test( + '.../query.lua:0: Query error at 1:13. Impossible pattern:\n'.. + '(identifier (identifier) @variable)\n'.. + ' ^', + '(identifier (identifier) @variable)') + + -- Invalid syntax + test( + '.../query.lua:0: Query error at 1:13. Invalid syntax:\n'.. + '(identifier @variable\n'.. + ' ^', + '(identifier @variable') + + -- Invalid field name + test( + '.../query.lua:0: Query error at 1:15. Invalid field name "invalid_field":\n'.. + '((identifier) invalid_field: (identifier))\n'.. + ' ^', + '((identifier) invalid_field: (identifier))') + + -- Invalid capture name + test( + '.../query.lua:0: Query error at 1:30. Invalid capture name "ok.capture":\n'.. + '((identifier) @id (#eq? @id @ok.capture))\n'.. + ' ^', + '((identifier) @id (#eq? @id @ok.capture))') + end) end) -- cgit From dd0e77d48a843fc9730fe4ef7567330daf8dfb81 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 31 Aug 2023 14:11:15 +0100 Subject: fix(query_error): multiline bug --- test/functional/treesitter/parser_spec.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'test/functional/treesitter/parser_spec.lua') diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua index 37dde37a64..8222bb59c4 100644 --- a/test/functional/treesitter/parser_spec.lua +++ b/test/functional/treesitter/parser_spec.lua @@ -1090,9 +1090,9 @@ int x = INT_MAX; -- Invalid capture name test( - '.../query.lua:0: Query error at 1:30. Invalid capture name "ok.capture":\n'.. - '((identifier) @id (#eq? @id @ok.capture))\n'.. - ' ^', - '((identifier) @id (#eq? @id @ok.capture))') + '.../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) end) -- cgit From 72ed99319dd662f0e35b58e888b57f98ac3b3eec Mon Sep 17 00:00:00 2001 From: Dmytro Soltys Date: Mon, 27 Nov 2023 13:34:32 +0100 Subject: fix(treesitter): don't invalidate parser when discovering injections When parsing with a range, languagetree looks up injections and adds them if needed. This explicitly invalidates parser, making `is_valid` report `false` both when including and excluding children. This is an attempt to describe desired behaviour of `is_valid` in tests, with what ended up being a single line change to satisfy them. --- test/functional/treesitter/parser_spec.lua | 117 +++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) (limited to 'test/functional/treesitter/parser_spec.lua') diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua index 8222bb59c4..6f386115ae 100644 --- a/test/functional/treesitter/parser_spec.lua +++ b/test/functional/treesitter/parser_spec.lua @@ -1095,4 +1095,121 @@ int x = INT_MAX; ' ^', '((identifier) @id \n(#eq? @id\n@ok.capture\n))') end) + + describe('is_valid()', function() + before_each(function() + insert(dedent[[ + Treesitter integration *treesitter* + + Nvim integrates the `tree-sitter` library for incremental parsing of buffers: + https://tree-sitter.github.io/tree-sitter/ + + ]]) + + feed(':set ft=help') + + exec_lua [[ + vim.treesitter.get_parser(0, "vimdoc", { + injections = { + vimdoc = "((codeblock (language) @injection.language (code) @injection.content) (#set! injection.include-children))" + } + }) + ]] + end) + + it('is valid excluding, invalid including children initially', function() + 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 full parse', function() + exec_lua('vim.treesitter.get_parser():parse(true)') + 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 fully valid after a parsing a range on parsed tree', 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) + + describe('when adding content with injections', function() + before_each(function() + feed('G') + insert(dedent[[ + >lua + local a = {} + < + + ]]) + end) + + it('is fully invalid after changes', function() + eq(false, 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 rangeless parse', function() + exec_lua('vim.treesitter.get_parser():parse()') + 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[[ + >lua + local a = {} + < + + >lua + local a = {} + < + + ]]) + + exec_lua('vim.treesitter.get_parser():parse(true)') + + feed('Gd3k') + end) + + it('is fully invalid after changes', function() + eq(false, 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 rangeless parse', function() + exec_lua('vim.treesitter.get_parser():parse()') + 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 modified child tree', 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 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) -- cgit