diff options
author | Gregory Anders <8965202+gpanders@users.noreply.github.com> | 2024-09-01 13:01:53 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-09-01 18:01:53 +0000 |
commit | 6913c5e1d975a11262d08b3339d50b579e6b6bb8 (patch) | |
tree | e69809ec7eb0c7cb14b505eaf56f9de19b02a349 /runtime/lua/vim | |
parent | 318c0415d5b10b44fee4afa06994734f1beb7e71 (diff) | |
download | rneovim-6913c5e1d975a11262d08b3339d50b579e6b6bb8.tar.gz rneovim-6913c5e1d975a11262d08b3339d50b579e6b6bb8.tar.bz2 rneovim-6913c5e1d975a11262d08b3339d50b579e6b6bb8.zip |
feat(treesitter)!: default to correct behavior for quantified captures (#30193)
For context, see https://github.com/neovim/neovim/pull/24738. Before
that PR, Nvim did not correctly handle captures with quantifiers. That
PR made the correct behavior opt-in to minimize breaking changes, with
the intention that the correct behavior would eventually become the
default. Users can still opt-in to the old (incorrect) behavior for now,
but this option will eventually be removed completely.
BREAKING CHANGE: Any plugin which uses `Query:iter_matches()` must
update their call sites to expect an array of nodes in the `match`
table, rather than a single node.
Diffstat (limited to 'runtime/lua/vim')
-rw-r--r-- | runtime/lua/vim/treesitter/_fold.lua | 4 | ||||
-rw-r--r-- | runtime/lua/vim/treesitter/_query_linter.lua | 2 | ||||
-rw-r--r-- | runtime/lua/vim/treesitter/languagetree.lua | 8 | ||||
-rw-r--r-- | runtime/lua/vim/treesitter/query.lua | 28 | ||||
-rw-r--r-- | runtime/lua/vim/ui.lua | 2 |
5 files changed, 15 insertions, 29 deletions
diff --git a/runtime/lua/vim/treesitter/_fold.lua b/runtime/lua/vim/treesitter/_fold.lua index 27590eff5d..7375beaf9d 100644 --- a/runtime/lua/vim/treesitter/_fold.lua +++ b/runtime/lua/vim/treesitter/_fold.lua @@ -131,9 +131,7 @@ local function compute_folds_levels(bufnr, info, srow, erow, parse_injections) -- Collect folds starting from srow - 1, because we should first subtract the folds that end at -- srow - 1 from the level of srow - 1 to get accurate level of srow. - for _, match, metadata in - query:iter_matches(tree:root(), bufnr, math.max(srow - 1, 0), erow, { all = true }) - do + for _, match, metadata in query:iter_matches(tree:root(), bufnr, math.max(srow - 1, 0), erow) do for id, nodes in pairs(match) do if query.captures[id] == 'fold' then local range = ts.get_range(nodes[1], bufnr, metadata[id]) diff --git a/runtime/lua/vim/treesitter/_query_linter.lua b/runtime/lua/vim/treesitter/_query_linter.lua index 8654b89c9b..ea1ae5416a 100644 --- a/runtime/lua/vim/treesitter/_query_linter.lua +++ b/runtime/lua/vim/treesitter/_query_linter.lua @@ -176,7 +176,7 @@ function M.lint(buf, opts) parser:parse() parser:for_each_tree(function(tree, ltree) if ltree:lang() == 'query' then - for _, match, _ in query:iter_matches(tree:root(), buf, 0, -1, { all = true }) do + for _, match, _ in query:iter_matches(tree:root(), buf, 0, -1) do local lang_context = { lang = lang, parser_info = parser_info, diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua index d43a0a5d0b..cc9ffeaa29 100644 --- a/runtime/lua/vim/treesitter/languagetree.lua +++ b/runtime/lua/vim/treesitter/languagetree.lua @@ -833,13 +833,7 @@ function LanguageTree:_get_injections() local start_line, _, end_line, _ = root_node:range() for pattern, match, metadata in - self._injection_query:iter_matches( - root_node, - self._source, - start_line, - end_line + 1, - { all = true } - ) + self._injection_query:iter_matches(root_node, self._source, start_line, end_line + 1) do local lang, combined, ranges = self:_get_injection(match, metadata) if lang then diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua index 8e21353154..bd0574b8b7 100644 --- a/runtime/lua/vim/treesitter/query.lua +++ b/runtime/lua/vim/treesitter/query.lua @@ -620,8 +620,8 @@ local directive_handlers = { --- @field force? boolean --- --- Use the correct implementation of the match table where capture IDs map to ---- a list of nodes instead of a single node. Defaults to false (for backward ---- compatibility). This option will eventually become the default and removed. +--- a list of nodes instead of a single node. Defaults to true. This option will +--- be removed in a future release. --- @field all? boolean --- Adds a new predicate to be used in queries @@ -629,7 +629,7 @@ local directive_handlers = { ---@param name string Name of the predicate, without leading # ---@param handler fun(match: table<integer,TSNode[]>, pattern: integer, source: integer|string, predicate: any[], metadata: vim.treesitter.query.TSMetadata) --- - see |vim.treesitter.query.add_directive()| for argument meanings ----@param opts vim.treesitter.query.add_predicate.Opts +---@param opts? vim.treesitter.query.add_predicate.Opts function M.add_predicate(name, handler, opts) -- Backward compatibility: old signature had "force" as boolean argument if type(opts) == 'boolean' then @@ -642,7 +642,7 @@ function M.add_predicate(name, handler, opts) error(string.format('Overriding existing predicate %s', name)) end - if opts.all then + if opts.all ~= false then predicate_handlers[name] = handler else --- @param match table<integer, TSNode[]> @@ -894,16 +894,10 @@ end --- index of the pattern in the query, a table mapping capture indices to a list --- of nodes, and metadata from any directives processing the match. --- ---- WARNING: Set `all=true` to ensure all matching nodes in a match are ---- returned, otherwise only the last node in a match is returned, breaking captures ---- involving quantifiers such as `(comment)+ @comment`. The default option ---- `all=false` is only provided for backward compatibility and will be removed ---- after Nvim 0.10. ---- --- Example: --- --- ```lua ---- for pattern, match, metadata in cquery:iter_matches(tree:root(), bufnr, 0, -1, { all = true }) do +--- for pattern, match, metadata in cquery:iter_matches(tree:root(), bufnr, 0, -1) do --- for id, nodes in pairs(match) do --- local name = query.captures[id] --- for _, node in ipairs(nodes) do @@ -925,9 +919,9 @@ end --- - max_start_depth (integer) if non-zero, sets the maximum start depth --- for each match. This is used to prevent traversing too deep into a tree. --- - match_limit (integer) Set the maximum number of in-progress matches (Default: 256). ---- - all (boolean) When set, the returned match table maps capture IDs to a list of nodes. ---- Older versions of iter_matches incorrectly mapped capture IDs to a single node, which is ---- incorrect behavior. This option will eventually become the default and removed. +--- - all (boolean) When `false` (default `true`), the returned table maps capture IDs to a single +--- (last) node instead of the full list of matching nodes. This option is only for backward +--- compatibility and will be removed in a future release. --- ---@return (fun(): integer, table<integer, TSNode[]>, vim.treesitter.query.TSMetadata): pattern id, match, metadata function Query:iter_matches(node, source, start, stop, opts) @@ -960,10 +954,10 @@ function Query:iter_matches(node, source, start, stop, opts) local captures = match:captures() - if not opts.all then + if opts.all == false then -- Convert the match table into the old buggy version for backward - -- compatibility. This is slow. Plugin authors, if you're reading this, set the "all" - -- option! + -- compatibility. This is slow, but we only do it when the caller explicitly opted into it by + -- setting `all` to `false`. local old_match = {} ---@type table<integer, TSNode> for k, v in pairs(captures or {}) do old_match[k] = v[#v] diff --git a/runtime/lua/vim/ui.lua b/runtime/lua/vim/ui.lua index c2b19e92c0..2d3b828ea1 100644 --- a/runtime/lua/vim/ui.lua +++ b/runtime/lua/vim/ui.lua @@ -196,7 +196,7 @@ function M._get_urls() local query = vim.treesitter.query.get(lang, 'highlights') if query then local tree = assert(ltree:tree_for_range(range)) - for _, match, metadata in query:iter_matches(tree:root(), bufnr, row, row + 1, { all = true }) do + for _, match, metadata in query:iter_matches(tree:root(), bufnr, row, row + 1) do for id, nodes in pairs(match) do for _, node in ipairs(nodes) do if vim.treesitter.node_contains(node, range) then |