diff options
Diffstat (limited to 'runtime/lua/vim/treesitter.lua')
-rw-r--r-- | runtime/lua/vim/treesitter.lua | 64 |
1 files changed, 38 insertions, 26 deletions
diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index db544c1ab1..ed7d31e1f7 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -76,36 +76,48 @@ end --- --- If needed, this will create the parser. --- +--- If no parser can be created, an error is thrown. Set `opts.error = false` to suppress this and +--- return nil (and an error message) instead. WARNING: This behavior will become default in Nvim +--- 0.12 and the option will be removed. +--- ---@param bufnr (integer|nil) Buffer the parser should be tied to (default: current buffer) ---@param lang (string|nil) Language of this parser (default: from buffer filetype) ---@param opts (table|nil) Options to pass to the created language tree --- ----@return vim.treesitter.LanguageTree object to use for parsing +---@return vim.treesitter.LanguageTree? object to use for parsing +---@return string? error message, if applicable function M.get_parser(bufnr, lang, opts) opts = opts or {} + local should_error = opts.error == nil or opts.error if bufnr == nil or bufnr == 0 then bufnr = api.nvim_get_current_buf() end if not valid_lang(lang) then - lang = M.language.get_lang(vim.bo[bufnr].filetype) or vim.bo[bufnr].filetype + lang = M.language.get_lang(vim.bo[bufnr].filetype) end if not valid_lang(lang) then if not parsers[bufnr] then - error( - string.format( - 'There is no parser available for buffer %d and one could not be' - .. ' created because lang could not be determined. Either pass lang' - .. ' or set the buffer filetype', - bufnr - ) - ) + local err_msg = + string.format('Parser not found for buffer %s: language could not be determined', bufnr) + if should_error then + error(err_msg) + end + return nil, err_msg end elseif parsers[bufnr] == nil or parsers[bufnr]:lang() ~= lang then - assert(lang, 'lang should be valid') - parsers[bufnr] = M._create_parser(bufnr, lang, opts) + local parser = vim.F.npcall(M._create_parser, bufnr, lang, opts) + if not parser then + local err_msg = + string.format('Parser could not be created for buffer %s and language "%s"', bufnr, lang) + if should_error then + error(err_msg) + end + return nil, err_msg + end + parsers[bufnr] = parser end parsers[bufnr]:register_cbs(opts.buf_attach_cbs) @@ -140,16 +152,8 @@ function M.is_ancestor(dest, source) return false end - local current = source ---@type TSNode? - while current ~= nil do - if current == dest then - return true - end - - current = current:parent() - end - - return false + -- child_containing_descendant returns nil if dest is a direct parent + return source:parent() == dest or dest:child_containing_descendant(source) ~= nil end --- Returns the node's range or an unpacked range table @@ -257,7 +261,7 @@ end ---@param row integer Position row ---@param col integer Position column --- ----@return {capture: string, lang: string, metadata: table}[] +---@return {capture: string, lang: string, metadata: vim.treesitter.query.TSMetadata}[] function M.get_captures_at_pos(bufnr, row, col) if bufnr == 0 then bufnr = api.nvim_get_current_buf() @@ -335,13 +339,16 @@ end --- --- 0-indexed (row, col) tuple. Defaults to cursor position in the --- current window. Required if {bufnr} is not the current buffer ---- @field pos { [1]: integer, [2]: integer }? +--- @field pos [integer, integer]? --- --- Parser language. (default: from buffer filetype) --- @field lang string? --- --- Ignore injected languages (default true) --- @field ignore_injections boolean? +--- +--- Include anonymous nodes (default false) +--- @field include_anonymous boolean? --- Returns the smallest named node at the given position --- @@ -383,11 +390,14 @@ function M.get_node(opts) local ts_range = { row, col, row, col } - local root_lang_tree = M.get_parser(bufnr, opts.lang) + local root_lang_tree = M.get_parser(bufnr, opts.lang, { error = false }) if not root_lang_tree then return end + if opts.include_anonymous then + return root_lang_tree:node_for_range(ts_range, opts) + end return root_lang_tree:named_node_for_range(ts_range, opts) end @@ -413,7 +423,7 @@ end ---@param lang (string|nil) Language of the parser (default: from buffer filetype) function M.start(bufnr, lang) bufnr = bufnr or api.nvim_get_current_buf() - local parser = M.get_parser(bufnr, lang) + local parser = assert(M.get_parser(bufnr, lang, { error = false })) M.highlighter.new(parser) end @@ -437,6 +447,7 @@ end --- --- Can also be shown with `:InspectTree`. [:InspectTree]() --- +---@since 11 ---@param opts table|nil Optional options table with the following possible keys: --- - lang (string|nil): The language of the source buffer. If omitted, detect --- from the filetype of the source buffer. @@ -460,6 +471,7 @@ end --- vim.wo.foldexpr = 'v:lua.vim.treesitter.foldexpr()' --- ``` --- +---@since 11 ---@param lnum integer|nil Line number to calculate fold level for ---@return string function M.foldexpr(lnum) |