diff options
Diffstat (limited to 'runtime/doc/treesitter.txt')
-rw-r--r-- | runtime/doc/treesitter.txt | 904 |
1 files changed, 535 insertions, 369 deletions
diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt index 917863eef8..9bdc6b8d24 100644 --- a/runtime/doc/treesitter.txt +++ b/runtime/doc/treesitter.txt @@ -18,150 +18,129 @@ changes. This documentation may also not fully reflect the latest changes. PARSER FILES *treesitter-parsers* Parsers are the heart of tree-sitter. They are libraries that tree-sitter will -search for in the `parser` runtime directory. By default, Nvim bundles only -parsers for C, Lua, and Vimscript, but parsers can be installed manually or -via a plugin like https://github.com/nvim-treesitter/nvim-treesitter. -Parsers are searched for as `parser/{lang}.*` in any 'runtimepath' directory. -If multiple parsers for the same language are found, the first one is used. -(This typically implies the priority "user config > plugins > bundled". +search for in the `parser` runtime directory. By default, Nvim bundles parsers +for C, Lua, Vimscript, Vimdoc and Treesitter query files, but parsers can be +installed manually or via a plugin like +https://github.com/nvim-treesitter/nvim-treesitter. Parsers are searched for +as `parser/{lang}.*` in any 'runtimepath' directory. If multiple parsers for +the same language are found, the first one is used. (This typically implies +the priority "user config > plugins > bundled". A parser can also be loaded manually using a full path: >lua - vim.treesitter.require_language("python", "/path/to/python.so") + vim.treesitter.language.add('python', { path = "/path/to/python.so" }) < ============================================================================== -LANGUAGE TREES *treesitter-languagetree* - *LanguageTree* - -As buffers can contain multiple languages (e.g., Vimscript commands in a Lua -file), multiple parsers may be needed to parse the full buffer. These are -combined in a |LanguageTree| object. - -To create a LanguageTree (parser object) for a buffer and a given language, -use >lua - - tsparser = vim.treesitter.get_parser(bufnr, lang) -< -`bufnr=0` can be used for current buffer. `lang` will default to 'filetype'. -Currently, the parser will be retained for the lifetime of a buffer but this -is subject to change. A plugin should keep a reference to the parser object as -long as it wants incremental updates. - -Whenever you need to access the current syntax tree, parse the buffer: >lua - - tstree = tsparser:parse() -< -This will return a table of immutable |treesitter-tree|s that represent the -current state of the buffer. When the plugin wants to access the state after a -(possible) edit it should call `parse()` again. If the buffer wasn't edited, -the same tree will be returned again without extra work. If the buffer was -parsed before, incremental parsing will be done of the changed parts. - -Note: To use the parser directly inside a |nvim_buf_attach()| Lua callback, -you must call |vim.treesitter.get_parser()| before you register your callback. -But preferably parsing shouldn't be done directly in the change callback -anyway as they will be very frequent. Rather a plugin that does any kind of -analysis on a tree should use a timer to throttle too frequent updates. - -See |lua-treesitter-languagetree| for the list of available methods. - -============================================================================== TREESITTER TREES *treesitter-tree* - *tstree* + *TSTree* A "treesitter tree" represents the parsed contents of a buffer, which can be -used to perform further analysis. It is a |luaref-userdata| reference to an -object held by the tree-sitter library. +used to perform further analysis. It is a |userdata| reference to an object +held by the tree-sitter library. -An instance `tstree` of a treesitter tree supports the following methods. +An instance `TSTree` of a treesitter tree supports the following methods. -tstree:root() *tstree:root()* +TSTree:root() *TSTree:root()* Return the root node of this tree. -tstree:copy() *tstree:copy()* - Returns a copy of the `tstree`. +TSTree:copy() *TSTree:copy()* + Returns a copy of the `TSTree`. ============================================================================== TREESITTER NODES *treesitter-node* - *tsnode* + *TSNode* A "treesitter node" represents one specific element of the parsed contents of -a buffer, which can be captured by a |Query| for, e.g., highlighting. It is a -|luaref-userdata| reference to an object held by the tree-sitter library. +a buffer, which can be captured by a |Query| for, e.g., highlighting. It is +a |userdata| reference to an object held by the tree-sitter library. -An instance `tsnode` of a treesitter node supports the following methods. +An instance `TSNode` of a treesitter node supports the following methods. -tsnode:parent() *tsnode:parent()* +TSNode:parent() *TSNode:parent()* Get the node's immediate parent. -tsnode:next_sibling() *tsnode:next_sibling()* +TSNode:next_sibling() *TSNode:next_sibling()* Get the node's next sibling. -tsnode:prev_sibling() *tsnode:prev_sibling()* +TSNode:prev_sibling() *TSNode:prev_sibling()* Get the node's previous sibling. -tsnode:next_named_sibling() *tsnode:next_named_sibling()* +TSNode:next_named_sibling() *TSNode:next_named_sibling()* Get the node's next named sibling. -tsnode:prev_named_sibling() *tsnode:prev_named_sibling()* +TSNode:prev_named_sibling() *TSNode:prev_named_sibling()* Get the node's previous named sibling. -tsnode:iter_children() *tsnode:iter_children()* - Iterates over all the direct children of {tsnode}, regardless of whether +TSNode:iter_children() *TSNode:iter_children()* + Iterates over all the direct children of {TSNode}, regardless of whether they are named or not. Returns the child node plus the eventual field name corresponding to this child node. -tsnode:field({name}) *tsnode:field()* +TSNode:field({name}) *TSNode:field()* Returns a table of the nodes corresponding to the {name} field. -tsnode:child_count() *tsnode:child_count()* +TSNode:child_count() *TSNode:child_count()* Get the node's number of children. -tsnode:child({index}) *tsnode:child()* +TSNode:child({index}) *TSNode:child()* Get the node's child at the given {index}, where zero represents the first child. -tsnode:named_child_count() *tsnode:named_child_count()* +TSNode:named_child_count() *TSNode:named_child_count()* Get the node's number of named children. -tsnode:named_child({index}) *tsnode:named_child()* +TSNode:named_child({index}) *TSNode:named_child()* Get the node's named child at the given {index}, where zero represents the first named child. -tsnode:start() *tsnode:start()* +TSNode:start() *TSNode:start()* Get the node's start position. Return three values: the row, column and total byte count (all zero-based). -tsnode:end_() *tsnode:end_()* +TSNode:end_() *TSNode:end_()* Get the node's end position. Return three values: the row, column and total byte count (all zero-based). -tsnode:range() *tsnode:range()* - Get the range of the node. Return four values: the row, column of the - start position, then the row, column of the end position. +TSNode:range({include_bytes}) *TSNode:range()* + Get the range of the node. + + Return four or six values: + - start row + - start column + - start byte (if {include_bytes} is `true`) + - end row + - end column + - end byte (if {include_bytes} is `true`) -tsnode:type() *tsnode:type()* +TSNode:type() *TSNode:type()* Get the node's type as a string. -tsnode:symbol() *tsnode:symbol()* +TSNode:symbol() *TSNode:symbol()* Get the node's type as a numerical id. -tsnode:named() *tsnode:named()* +TSNode:named() *TSNode:named()* Check if the node is named. Named nodes correspond to named rules in the grammar, whereas anonymous nodes correspond to string literals in the grammar. -tsnode:missing() *tsnode:missing()* +TSNode:missing() *TSNode:missing()* Check if the node is missing. Missing nodes are inserted by the parser in order to recover from certain kinds of syntax errors. -tsnode:has_error() *tsnode:has_error()* +TSNode:extra() *TSNode:extra()* + Check if the node is extra. Extra nodes represent things like comments, + which are not required by the grammar but can appear anywhere. + +TSNode:has_changes() *TSNode:has_changes()* + Check if a syntax node has been edited. + +TSNode:has_error() *TSNode:has_error()* Check if the node is a syntax error or contains any syntax errors. -tsnode:sexpr() *tsnode:sexpr()* +TSNode:sexpr() *TSNode:sexpr()* Get an S-expression representing the node as a string. -tsnode:id() *tsnode:id()* +TSNode:id() *TSNode:id()* Get an unique identifier for the node inside its own tree. No guarantees are made about this identifier's internal representation, @@ -171,20 +150,29 @@ tsnode:id() *tsnode:id()* Note: The `id` is not guaranteed to be unique for nodes from different trees. - *tsnode:descendant_for_range()* -tsnode:descendant_for_range({start_row}, {start_col}, {end_row}, {end_col}) +TSNode:tree() *TSNode:tree()* + Get the |TSTree| of the node. + *TSNode:descendant_for_range()* +TSNode:descendant_for_range({start_row}, {start_col}, {end_row}, {end_col}) Get the smallest node within this node that spans the given range of (row, column) positions - *tsnode:named_descendant_for_range()* -tsnode:named_descendant_for_range({start_row}, {start_col}, {end_row}, {end_col}) + *TSNode:named_descendant_for_range()* +TSNode:named_descendant_for_range({start_row}, {start_col}, {end_row}, {end_col}) Get the smallest named node within this node that spans the given range of (row, column) positions + *TSNode:equal()* +TSNode:equal({node}) + Check if {node} refers to the same node within the same tree. + + *TSNode:byte_length()* +TSNode:byte_length() + Return the number of bytes spanned by this node. ============================================================================== TREESITTER QUERIES *treesitter-query* -Treesitter queries are a way to extract information about a parsed |tstree|, +Treesitter queries are a way to extract information about a parsed |TSTree|, e.g., for the purpose of highlighting. Briefly, a `query` consists of one or more patterns. A `pattern` is defined over node types in the syntax tree. A `match` corresponds to specific elements of the syntax tree which match a @@ -202,7 +190,7 @@ Nvim looks for queries as `*.scm` files in a `queries` directory under purpose, e.g., `queries/lua/highlights.scm` for highlighting Lua files. By default, the first query on `runtimepath` is used (which usually implies that user config takes precedence over plugins, which take precedence over -queries bundled with Neovim). If a query should extend other queries instead +queries bundled with Nvim). If a query should extend other queries instead of replacing them, use |treesitter-query-modeline-extends|. See |lua-treesitter-query| for the list of available methods for working with @@ -212,7 +200,7 @@ treesitter queries from Lua. TREESITTER QUERY PREDICATES *treesitter-predicates* Predicates are special scheme nodes that are evaluated to conditionally capture -nodes. For example, the `eq?` predicate can be used as follows: > +nodes. For example, the `eq?` predicate can be used as follows: >query ((identifier) @foo (#eq? @foo "foo")) < @@ -221,13 +209,13 @@ to only match identifier corresponding to the `"foo"` text. The following predicates are built in: `eq?` *treesitter-predicate-eq?* - Match a string against the text corresponding to a node: > + Match a string against the text corresponding to a node: >query ((identifier) @foo (#eq? @foo "foo")) ((node1) @left (node2) @right (#eq? @left @right)) < `match?` *treesitter-predicate-match?* `vim-match?` *treesitter-predicate-vim-match?* - Match a |regexp| against the text corresponding to a node: > + Match a |regexp| against the text corresponding to a node: >query ((identifier) @constant (#match? @constant "^[A-Z_]+$")) < Note: The `^` and `$` anchors will match the start and end of the node's text. @@ -237,31 +225,43 @@ The following predicates are built in: similar to `match?` `contains?` *treesitter-predicate-contains?* - Match a string against parts of the text corresponding to a node: > + Match a string against parts of the text corresponding to a node: >query ((identifier) @foo (#contains? @foo "foo")) ((identifier) @foo-bar (#contains? @foo-bar "foo" "bar")) < `any-of?` *treesitter-predicate-any-of?* Match any of the given strings against the text corresponding to - a node: > + a node: >query ((identifier) @foo (#any-of? @foo "foo" "bar")) < This is the recommended way to check if the node matches one of many keywords, as it has been optimized for this. + `has-ancestor?` *treesitter-predicate-has-ancestor?* + Match any of the given node types against all ancestors of a node: >query + ((identifier) @variable.builtin + (#any-of? @variable.builtin "begin" "end") + (#has-ancestor? @variable.builtin range_expression)) +< + `has-parent?` *treesitter-predicate-has-parent?* + Match any of the given node types against the direct ancestor of a + node: >query + (((field_expression + (field_identifier) @method)) @_parent + (#has-parent? @_parent template_method function_declarator)) +< *lua-treesitter-not-predicate* Each predicate has a `not-` prefixed predicate that is just the negation of the predicate. Further predicates can be added via |vim.treesitter.query.add_predicate()|. -Use |vim.treesitter.query.list_predicates()| to list all available -predicates. +Use |vim.treesitter.query.list_predicates()| to list all available predicates. TREESITTER QUERY DIRECTIVES *treesitter-directives* Treesitter directives store metadata for a node or match and perform side -effects. For example, the `set!` directive sets metadata on the match or node: > +effects. For example, the `set!` directive sets metadata on the match or node: >query ((identifier) @foo (#set! "type" "parameter")) < @@ -277,7 +277,7 @@ The following directives are built in: {key} {value} - Examples: > + Examples: >query ((identifier) @foo (#set! @foo "kind" "parameter")) ((node1) @left (node2) @right (#set! "type" "pair")) < @@ -293,18 +293,37 @@ The following directives are built in: {end_row} {end_col} - Example: > + Example: >query ((identifier) @constant (#offset! @constant 0 1 0 -1)) < + `gsub!` *treesitter-directive-gsub!* + Transforms the content of the node using a Lua pattern. This will set + a new `metadata[capture_id].text`. + + Parameters: ~ + {capture_id} + {pattern} + + Example: >query + (#gsub! @_node ".*%.(.*)" "%1") +< + `trim!` *treesitter-directive-trim!* + Trim blank lines from the end of the node. This will set a new + `metadata[capture_id].range`. + + Parameters: ~ + {capture_id} + Example: >query + (#trim! @fold) +< Further directives can be added via |vim.treesitter.query.add_directive()|. -Use |vim.treesitter.query.list_directives()| to list all available -directives. +Use |vim.treesitter.query.list_directives()| to list all available directives. TREESITTER QUERY MODELINES *treesitter-query-modeline* -Neovim supports to customize the behavior of the queries using a set of +Nvim supports to customize the behavior of the queries using a set of "modelines", that is comments in the queries starting with `;`. Here are the currently supported modeline alternatives: @@ -323,11 +342,12 @@ currently supported modeline alternatives: a base depends on your 'runtimepath' value. Note: These modeline comments must be at the top of the query, but can be -repeated, for example, the following two modeline blocks are both valid: > - +repeated, for example, the following two modeline blocks are both valid: +>query ;; inherits: foo,bar ;; extends - +< +>query ;; extends ;; ;; inherits: baz @@ -336,14 +356,14 @@ repeated, for example, the following two modeline blocks are both valid: > TREESITTER SYNTAX HIGHLIGHTING *treesitter-highlight* Syntax highlighting is specified through queries named `highlights.scm`, -which match a |tsnode| in the parsed |tstree| to a `capture` that can be -assigned a highlight group. For example, the query > +which match a |TSNode| in the parsed |TSTree| to a `capture` that can be +assigned a highlight group. For example, the query >query (parameters (identifier) @parameter) < matches any `identifier` node inside a function `parameter` node (e.g., the `bar` in `foo(bar)`) to the capture named `@parameter`. It is also possible to -match literal expressions (provided the parser returns them): > +match literal expressions (provided the parser returns them): >query "return" @keyword.return < @@ -428,7 +448,7 @@ The following captures are linked by default to standard |group-name|s: *treesitter-highlight-spell* The special `@spell` capture can be used to indicate that a node should be spell checked by Nvim's builtin |spell| checker. For example, the following -capture marks comments as to be checked: > +capture marks comments as to be checked: >query (comment) @spell < @@ -439,14 +459,14 @@ There is also `@nospell` which disables spellchecking regions with `@spell`. Treesitter highlighting supports |conceal| via the `conceal` metadata. By convention, nodes to be concealed are captured as `@conceal`, but any capture can be used. For example, the following query can be used to hide code block -delimiters in Markdown: > +delimiters in Markdown: >query - (fenced_code_block_delimiter) @conceal (#set! conceal "") + (fenced_code_block_delimiter @conceal (#set! conceal "")) < It is also possible to replace a node with a single character, which (unlike legacy syntax) can be given a custom highlight. For example, the following (ill-advised) query replaces the `!=` operator by a Unicode glyph, which is -still highlighted the same as other operators: > +still highlighted the same as other operators: >query "!=" @operator (#set! conceal "≠") < @@ -457,10 +477,61 @@ Treesitter uses |nvim_buf_set_extmark()| to set highlights with a default priority of 100. This enables plugins to set a highlighting priority lower or higher than tree-sitter. It is also possible to change the priority of an individual query pattern manually by setting its `"priority"` metadata -attribute: > +attribute: >query + + ((super_important_node) @superimportant (#set! "priority" 105)) +< - (super_important_node) @ImportantHighlight (#set! "priority" 105) +============================================================================== +TREESITTER LANGUAGE INJECTIONS *treesitter-language-injections* < + +Note the following information is adapted from: + https://tree-sitter.github.io/tree-sitter/syntax-highlighting#language-injection + +Some source files contain code written in multiple different languages. +Examples include: + + • HTML files, which can contain JavaScript inside of `<script>` tags and + CSS inside of `<style>` tags + • ERB files, which contain Ruby inside of `<%` `%>` tags, and HTML outside of + those tags + • PHP files, which can contain HTML between the `<php` tags + • JavaScript files, which contain regular expression syntax within regex + literals + • Ruby, which can contain snippets of code inside of heredoc literals, + where the heredoc delimiter often indicates the language + • Lua, which can contain snippets of Vimscript inside |vim.cmd()| calls. + • Vimscript, which can contain snippets of Lua inside |:lua-heredoc| + blocks. + +All of these examples can be modeled in terms of a parent syntax tree and one +or more injected syntax trees, which reside inside of certain nodes in the +parent tree. The language injection query allows you to specify these +“injections” using the following captures: + + • `@injection.content` - indicates that the captured node should have its + contents re-parsed using another language. + • `@injection.language` - indicates that the captured node’s text may + contain the name of a language that should be used to re-parse the + `@injection.content`. + +The language injection behavior can also be configured by some properties +associated with patterns: + + • `injection.language` - can be used to hard-code the name of a specific + language. + • `injection.combined` - indicates that all of the matching nodes in the + tree should have their content parsed as one nested document. + • `injection.include-children` - indicates that the `@injection.content` + node's entire text should be re-parsed, including the text of its child + nodes. By default, child nodes' text will be excluded from the injected + document. + • `injection.self` - indicates that the node's text should be parsed with + the same language as the node's LanguageTree. + • `injection.parent` - indicates that the captured node’s text should + be parsed with the same language as the node's parent LanguageTree. + ============================================================================== VIM.TREESITTER *lua-treesitter* @@ -481,12 +552,34 @@ library. ============================================================================== Lua module: vim.treesitter *lua-treesitter-core* +foldexpr({lnum}) *vim.treesitter.foldexpr()* + Returns the fold level for {lnum} in the current buffer. Can be set + directly to 'foldexpr': >lua + vim.wo.foldexpr = 'v:lua.vim.treesitter.foldexpr()' +< + + Parameters: ~ + • {lnum} (integer|nil) Line number to calculate fold level for + + Return: ~ + (string) + +foldtext() *vim.treesitter.foldtext()* + Returns the highlighted content of the first line of the fold or falls + back to |foldtext()| if no treesitter parser is found. Can be set directly + to 'foldtext': >lua + vim.wo.foldtext = 'v:lua.vim.treesitter.foldtext()' +< + + Return: ~ + `{ [1]: string, [2]: string[] }[]` | string + *vim.treesitter.get_captures_at_cursor()* get_captures_at_cursor({winnr}) Returns a list of highlight capture names under the cursor Parameters: ~ - • {winnr} (number|nil) Window handle or 0 for current window (default) + • {winnr} (integer|nil) Window handle or 0 for current window (default) Return: ~ string[] List of capture names @@ -500,63 +593,90 @@ get_captures_at_pos({bufnr}, {row}, {col}) if none are defined). Parameters: ~ - • {bufnr} (number) Buffer number (0 for current buffer) - • {row} (number) Position row - • {col} (number) Position column + • {bufnr} (integer) Buffer number (0 for current buffer) + • {row} (integer) Position row + • {col} (integer) Position column Return: ~ - table[] List of captures `{ capture = "capture name", metadata = { ... - } }` + table[] List of captures `{ capture = "name", metadata = { ... } }` + +get_node({opts}) *vim.treesitter.get_node()* + Returns the smallest named node at the given position -get_node_at_cursor({winnr}) *vim.treesitter.get_node_at_cursor()* - Returns the smallest named node under the cursor + NOTE: Calling this on an unparsed tree can yield an invalid node. If the + tree is not known to be parsed by, e.g., an active highlighter, parse the + tree first via >lua + vim.treesitter.get_parser(bufnr):parse(range) +< Parameters: ~ - • {winnr} (number|nil) Window handle or 0 for current window (default) + • {opts} (table|nil) Optional keyword arguments: + • bufnr integer|nil Buffer number (nil or 0 for current + buffer) + • pos table|nil 0-indexed (row, col) tuple. Defaults to cursor + position in the current window. Required if {bufnr} is not + the current buffer + • ignore_injections boolean Ignore injected languages (default + true) Return: ~ - (string) Name of node under the cursor + |TSNode| | nil Node at the given position - *vim.treesitter.get_node_at_pos()* -get_node_at_pos({bufnr}, {row}, {col}, {opts}) - Returns the smallest named node at the given position +get_node_range({node_or_range}) *vim.treesitter.get_node_range()* + Returns the node's range or an unpacked range table Parameters: ~ - • {bufnr} (number) Buffer number (0 for current buffer) - • {row} (number) Position row - • {col} (number) Position column - • {opts} (table) Optional keyword arguments: - • lang string|nil Parser language - • ignore_injections boolean Ignore injected languages - (default true) + • {node_or_range} (|TSNode| | table) Node or table of positions - Return: ~ - userdata|nil |tsnode| under the cursor + Return (multiple): ~ + (integer) start_row + (integer) start_col + (integer) end_row + (integer) end_col -get_node_range({node_or_range}) *vim.treesitter.get_node_range()* - Returns the node's range or an unpacked range table + *vim.treesitter.get_node_text()* +get_node_text({node}, {source}, {opts}) + Gets the text corresponding to a given node Parameters: ~ - • {node_or_range} (userdata|table) |tsnode| or table of positions + • {node} |TSNode| + • {source} (integer|string) Buffer or string from which the {node} is + extracted + • {opts} (table|nil) Optional parameters. + • metadata (table) Metadata of a specific capture. This + would be set to `metadata[capture_id]` when using + |vim.treesitter.query.add_directive()|. Return: ~ - (table) `{ start_row, start_col, end_row, end_col }` + (string) get_parser({bufnr}, {lang}, {opts}) *vim.treesitter.get_parser()* - Returns the parser for a specific buffer and filetype and attaches it to - the buffer + Returns the parser for a specific buffer and attaches it to the buffer If needed, this will create the parser. Parameters: ~ - • {bufnr} (number|nil) Buffer the parser should be tied to (default: + • {bufnr} (integer|nil) Buffer the parser should be tied to (default: current buffer) • {lang} (string|nil) Filetype of this parser (default: buffer filetype) • {opts} (table|nil) Options to pass to the created language tree Return: ~ - LanguageTree |LanguageTree| object to use for parsing + |LanguageTree| object to use for parsing + +get_range({node}, {source}, {metadata}) *vim.treesitter.get_range()* + Get the range of a |TSNode|. Can also supply {source} and {metadata} to + get the range with directives applied. + + Parameters: ~ + • {node} |TSNode| + • {source} integer|string|nil Buffer or string from which the {node} + is extracted + • {metadata} TSMetadata|nil + + Return: ~ + (table) *vim.treesitter.get_string_parser()* get_string_parser({str}, {lang}, {opts}) @@ -568,14 +688,42 @@ get_string_parser({str}, {lang}, {opts}) • {opts} (table|nil) Options to pass to the created language tree Return: ~ - LanguageTree |LanguageTree| object to use for parsing + |LanguageTree| object to use for parsing + +inspect_tree({opts}) *vim.treesitter.inspect_tree()* + Open a window that displays a textual representation of the nodes in the + language tree. + + While in the window, press "a" to toggle display of anonymous nodes, "I" + to toggle the display of the source language of each node, "o" to toggle + the query editor, and press <Enter> to jump to the node under the cursor + in the source buffer. + + Can also be shown with `:InspectTree`. *:InspectTree* + + Parameters: ~ + • {opts} (table|nil) Optional options table with the following possible + keys: + • lang (string|nil): The language of the source buffer. If + omitted, the filetype of the source buffer is used. + • bufnr (integer|nil): Buffer to draw the tree into. If + omitted, a new buffer is created. + • winid (integer|nil): Window id to display the tree buffer + in. If omitted, a new window is created with {command}. + • command (string|nil): Vimscript command to create the + window. Default value is "60vnew". Only used when {winid} is + nil. + • title (string|fun(bufnr:integer):string|nil): Title of the + window. If a function, it accepts the buffer number of the + source buffer as its only argument and should return a + string. is_ancestor({dest}, {source}) *vim.treesitter.is_ancestor()* Determines whether a node is the ancestor of another Parameters: ~ - • {dest} userdata Possible ancestor |tsnode| - • {source} userdata Possible descendant |tsnode| + • {dest} |TSNode| Possible ancestor + • {source} |TSNode| Possible descendant Return: ~ (boolean) True if {dest} is an ancestor of {source} @@ -585,9 +733,9 @@ is_in_node_range({node}, {line}, {col}) Determines whether (line, col) position is in node range Parameters: ~ - • {node} userdata |tsnode| defining the range - • {line} (number) Line (0-based) - • {col} (number) Column (0-based) + • {node} |TSNode| defining the range + • {line} (integer) Line (0-based) + • {col} (integer) Column (0-based) Return: ~ (boolean) True if the position is in node range @@ -596,37 +744,12 @@ node_contains({node}, {range}) *vim.treesitter.node_contains()* Determines if a node contains a range Parameters: ~ - • {node} userdata |tsnode| + • {node} |TSNode| • {range} (table) Return: ~ (boolean) True if the {node} contains the {range} -show_tree({opts}) *vim.treesitter.show_tree()* - Open a window that displays a textual representation of the nodes in the - language tree. - - While in the window, press "a" to toggle display of anonymous nodes, "I" - to toggle the display of the source language of each node, and press - <Enter> to jump to the node under the cursor in the source buffer. - - Parameters: ~ - • {opts} (table|nil) Optional options table with the following possible - keys: - • lang (string|nil): The language of the source buffer. If - omitted, the filetype of the source buffer is used. - • bufnr (number|nil): Buffer to draw the tree into. If - omitted, a new buffer is created. - • winid (number|nil): Window id to display the tree buffer in. - If omitted, a new window is created with {command}. - • command (string|nil): Vimscript command to create the - window. Default value is "topleft 60vnew". Only used when - {winid} is nil. - • title (string|fun(bufnr:number):string|nil): Title of the - window. If a function, it accepts the buffer number of the - source buffer as its only argument and should return a - string. - start({bufnr}, {lang}) *vim.treesitter.start()* Starts treesitter highlighting for a buffer @@ -637,17 +760,16 @@ start({bufnr}, {lang}) *vim.treesitter.start()* the call to `start`. Example: >lua - - vim.api.nvim_create_autocmd( 'FileType', { pattern = 'tex', - callback = function(args) - vim.treesitter.start(args.buf, 'latex') - vim.bo[args.buf].syntax = 'on' -- only if additional legacy syntax is needed - end - }) + vim.api.nvim_create_autocmd( 'FileType', { pattern = 'tex', + callback = function(args) + vim.treesitter.start(args.buf, 'latex') + vim.bo[args.buf].syntax = 'on' -- only if additional legacy syntax is needed + end + }) < Parameters: ~ - • {bufnr} (number|nil) Buffer to be highlighted (default: current + • {bufnr} (integer|nil) Buffer to be highlighted (default: current buffer) • {lang} (string|nil) Language of the parser (default: buffer filetype) @@ -656,14 +778,45 @@ stop({bufnr}) *vim.treesitter.stop()* Stops treesitter highlighting for a buffer Parameters: ~ - • {bufnr} (number|nil) Buffer to stop highlighting (default: current + • {bufnr} (integer|nil) Buffer to stop highlighting (default: current buffer) ============================================================================== Lua module: vim.treesitter.language *lua-treesitter-language* -inspect_language({lang}) *vim.treesitter.language.inspect_language()* +add({lang}, {opts}) *vim.treesitter.language.add()* + Load parser with name {lang} + + Parsers are searched in the `parser` runtime directory, or the provided + {path} + + Parameters: ~ + • {lang} (string) Name of the parser (alphanumerical and `_` only) + • {opts} (table|nil) Options: + • filetype (string|string[]) Default filetype the parser + should be associated with. Defaults to {lang}. + • path (string|nil) Optional path the parser is located at + • symbol_name (string|nil) Internal symbol name for the + language to load + +get_filetypes({lang}) *vim.treesitter.language.get_filetypes()* + Get the filetypes associated with the parser named {lang}. + + Parameters: ~ + • {lang} (string) Name of parser + + Return: ~ + string[] filetypes + +get_lang({filetype}) *vim.treesitter.language.get_lang()* + Parameters: ~ + • {filetype} (string) + + Return: ~ + (string|nil) + +inspect({lang}) *vim.treesitter.language.inspect()* Inspects the provided language. Inspecting provides some useful information on the language like node @@ -675,23 +828,12 @@ inspect_language({lang}) *vim.treesitter.language.inspect_language()* Return: ~ (table) - *vim.treesitter.language.require_language()* -require_language({lang}, {path}, {silent}, {symbol_name}) - Asserts that a parser for the language {lang} is installed. - - Parsers are searched in the `parser` runtime directory, or the provided - {path} +register({lang}, {filetype}) *vim.treesitter.language.register()* + Register a parser named {lang} to be used for {filetype}(s). Parameters: ~ - • {lang} (string) Language the parser should parse - • {path} (string|nil) Optional path the parser is located at - • {silent} (boolean|nil) Don't throw an error if language not - found - • {symbol_name} (string|nil) Internal symbol name for the language to - load - - Return: ~ - (boolean) If the specified language is installed + • {lang} (string) Name of parser + • {filetype} string|string[] Filetype(s) to associate with lang ============================================================================== @@ -708,8 +850,8 @@ add_directive({name}, {handler}, {force}) Parameters: ~ • {name} (string) Name of the directive, without leading # - • {handler} function(match:table, pattern:string, bufnr:number, - predicate:string[], metadata:table) + • {handler} function(match:table<string,|TSNode|>, pattern:string, + bufnr:integer, predicate:string[], metadata:table) • match: see |treesitter-query| • node-level data are accessible via `match[capture_id]` @@ -717,6 +859,7 @@ add_directive({name}, {handler}, {force}) • predicate: list of strings containing the full directive being called, e.g. `(node (#set! conceal "-"))` would get the predicate `{ "#set!", "conceal", "-" }` + • {force} (boolean|nil) *vim.treesitter.query.add_predicate()* add_predicate({name}, {handler}, {force}) @@ -724,27 +867,27 @@ add_predicate({name}, {handler}, {force}) Parameters: ~ • {name} (string) Name of the predicate, without leading # - • {handler} function(match:table, pattern:string, bufnr:number, - predicate:string[]) + • {handler} function(match:table<string,|TSNode|>, pattern:string, + bufnr:integer, predicate:string[]) • see |vim.treesitter.query.add_directive()| for argument meanings + • {force} (boolean|nil) - *vim.treesitter.query.get_node_text()* -get_node_text({node}, {source}, {opts}) - Gets the text corresponding to a given node +edit({lang}) *vim.treesitter.query.edit()* + Opens a live editor to query the buffer you started from. - Parameters: ~ - • {node} userdata |tsnode| - • {source} (number|string) Buffer or string from which the {node} is - extracted - • {opts} (table|nil) Optional parameters. - • concat: (boolean) Concatenate result in a string (default - true) + Can also be shown with *:EditQuery*. - Return: ~ - (string[]|string) + If you move the cursor to a capture name ("@foo"), text matching the + capture is highlighted in the source buffer. The query editor is a scratch + buffer, use `:write` to save it. You can find example queries at + `$VIMRUNTIME/queries/`. + + Parameters: ~ + • {lang} (string|nil) language to open the query editor for. If + omitted, inferred from the current buffer's filetype. -get_query({lang}, {query_name}) *vim.treesitter.query.get_query()* +get({lang}, {query_name}) *vim.treesitter.query.get()* Returns the runtime query {query_name} for {lang}. Parameters: ~ @@ -752,10 +895,10 @@ get_query({lang}, {query_name}) *vim.treesitter.query.get_query()* • {query_name} (string) Name of the query (e.g. "highlights") Return: ~ - Query Parsed query + Query|nil Parsed query - *vim.treesitter.query.get_query_files()* -get_query_files({lang}, {query_name}, {is_included}) + *vim.treesitter.query.get_files()* +get_files({lang}, {query_name}, {is_included}) Gets the list of files used to make up a query Parameters: ~ @@ -768,6 +911,28 @@ get_query_files({lang}, {query_name}, {is_included}) string[] query_files List of files to load for given query and language +lint({buf}, {opts}) *vim.treesitter.query.lint()* + Lint treesitter queries using installed parser, or clear lint errors. + + Use |treesitter-parsers| in runtimepath to check the query file in {buf} + for errors: + + • verify that used nodes are valid identifiers in the grammar. + • verify that predicates and directives are valid. + • verify that top-level s-expressions are valid. + + The found diagnostics are reported using |diagnostic-api|. By default, the + parser used for verification is determined by the containing folder of the + query file, e.g., if the path ends in `/lua/highlights.scm` , the parser for the `lua` language will be used. + + Parameters: ~ + • {buf} (integer) Buffer handle + • {opts} (QueryLinterOpts|nil) Optional keyword arguments: + • langs (string|string[]|nil) Language(s) to use for checking + the query. If multiple languages are specified, queries are + validated for all of them + • clear (boolean) if `true`, just clear current lint errors + list_directives() *vim.treesitter.query.list_directives()* Lists the currently available directives to use in queries. @@ -780,7 +945,14 @@ list_predicates() *vim.treesitter.query.list_predicates()* Return: ~ string[] List of supported predicates. -parse_query({lang}, {query}) *vim.treesitter.query.parse_query()* +omnifunc({findstart}, {base}) *vim.treesitter.query.omnifunc()* + Omnifunc for completing node names and predicates in treesitter queries. + + Use via >lua + vim.bo.omnifunc = 'v:lua.vim.treesitter.query.omnifunc' +< + +parse({lang}, {query}) *vim.treesitter.query.parse()* Parse {query} as a string. (If the query is in a file, the caller should read the contents into a string before calling). @@ -800,44 +972,41 @@ parse_query({lang}, {query}) *vim.treesitter.query.parse_query()* Query Parsed query *Query:iter_captures()* -Query:iter_captures({self}, {node}, {source}, {start}, {stop}) +Query:iter_captures({node}, {source}, {start}, {stop}) Iterate over all captures from all matches inside {node} {source} is needed if the query contains predicates; then the caller must ensure to use a freshly parsed tree consistent with the current text of - the buffer (if relevant). {start_row} and {end_row} can be used to limit - matches inside a row range (this is typically used with root node as the - {node}, i.e., to get syntax highlight matches in the current viewport). - When omitted, the {start} and {end} row values are used from the given - node. + the buffer (if relevant). {start} and {stop} can be used to limit matches + inside a row range (this is typically used with root node as the {node}, + i.e., to get syntax highlight matches in the current viewport). When + omitted, the {start} and {stop} row values are used from the given node. The iterator returns three values: a numeric id identifying the capture, the captured node, and metadata from any directives processing the match. The following example shows how to get captures by name: >lua - - for id, node, metadata in query:iter_captures(tree:root(), bufnr, first, last) do - local name = query.captures[id] -- name of the capture in the query - -- typically useful info about the node: - local type = node:type() -- type of the captured node - local row1, col1, row2, col2 = node:range() -- range of the capture - ... use the info here ... - end + for id, node, metadata in query:iter_captures(tree:root(), bufnr, first, last) do + local name = query.captures[id] -- name of the capture in the query + -- typically useful info about the node: + local type = node:type() -- type of the captured node + local row1, col1, row2, col2 = node:range() -- range of the capture + -- ... use the info here ... + end < Parameters: ~ - • {node} userdata |tsnode| under which the search will occur - • {source} (number|string) Source buffer or string to extract text from - • {start} (number) Starting line for the search - • {stop} (number) Stopping line for the search (end-exclusive) - • {self} + • {node} |TSNode| under which the search will occur + • {source} (integer|string) Source buffer or string to extract text + from + • {start} (integer) Starting line for the search + • {stop} (integer) Stopping line for the search (end-exclusive) Return: ~ - (number) capture Matching capture id - (table) capture_node Capture for {node} - (table) metadata for the {capture} + (fun(end_line: integer|nil): integer, TSNode, TSMetadata): capture id, + capture node, metadata *Query:iter_matches()* -Query:iter_matches({self}, {node}, {source}, {start}, {stop}) +Query:iter_matches({node}, {source}, {start}, {stop}, {opts}) Iterates the matches of self on a given range. Iterate over all matches within a {node}. The arguments are the same as @@ -845,34 +1014,36 @@ Query:iter_matches({self}, {node}, {source}, {start}, {stop}) (1-based) index of the pattern in the query, a table mapping capture indices to nodes, and metadata from any directives processing the match. If the query has more than one pattern, the capture table might be sparse - and e.g. `pairs()` method should be used over `ipairs` . Here is an example iterating over all captures in every match: >lua - - for pattern, match, metadata in cquery:iter_matches(tree:root(), bufnr, first, last) do - for id, node in pairs(match) do - local name = query.captures[id] - -- `node` was captured by the `name` capture in the match - - local node_data = metadata[id] -- Node level metadata - - ... use the info here ... - end - end + and e.g. `pairs()` method should be used over `ipairs`. Here is an example + iterating over all captures in every match: >lua + for pattern, match, metadata in cquery:iter_matches(tree:root(), bufnr, first, last) do + for id, node in pairs(match) do + local name = query.captures[id] + -- `node` was captured by the `name` capture in the match + + local node_data = metadata[id] -- Node level metadata + + -- ... use the info here ... + end + end < Parameters: ~ - • {node} userdata |tsnode| under which the search will occur - • {source} (number|string) Source buffer or string to search - • {start} (number) Starting line for the search - • {stop} (number) Stopping line for the search (end-exclusive) - • {self} + • {node} |TSNode| under which the search will occur + • {source} (integer|string) Source buffer or string to search + • {start} (integer) Starting line for the search + • {stop} (integer) Stopping line for the search (end-exclusive) + • {opts} (table|nil) Options: + • 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. Requires treesitter >= + 0.20.9. Return: ~ - (number) pattern id - (table) match - (table) metadata + (fun(): integer, table<integer,TSNode>, table): pattern id, match, + metadata - *vim.treesitter.query.set_query()* -set_query({lang}, {query_name}, {text}) +set({lang}, {query_name}, {text}) *vim.treesitter.query.set()* Sets the runtime query named {query_name} for {lang} This allows users to override any runtime files and/or configuration set @@ -885,111 +1056,112 @@ set_query({lang}, {query_name}, {text}) ============================================================================== -Lua module: vim.treesitter.highlighter *lua-treesitter-highlighter* +Lua module: vim.treesitter.languagetree *lua-treesitter-languagetree* -new({tree}, {opts}) *vim.treesitter.highlighter.new()* - Creates a new highlighter using - Parameters: ~ - • {tree} LanguageTree |LanguageTree| parser object to use for highlighting - • {opts} (table|nil) Configuration of the highlighter: - • queries table overwrite queries used by the highlighter +A *LanguageTree* contains a tree of parsers: the root treesitter parser +for {lang} and any "injected" language parsers, which themselves may +inject other languages, recursively. For example a Lua buffer containing +some Vimscript commands needs multiple parsers to fully understand its +contents. - Return: ~ - TSHighlighter Created highlighter object +To create a LanguageTree (parser object) for a given buffer and language, use: >lua + local parser = vim.treesitter.get_parser(bufnr, lang) -TSHighlighter:destroy({self}) *TSHighlighter:destroy()* - Removes all internal references to the highlighter +< - Parameters: ~ - • {self} +(where `bufnr=0` means current buffer). `lang` defaults to 'filetype'. +Note: currently the parser is retained for the lifetime of a buffer but +this may change; a plugin should keep a reference to the parser object if +it wants incremental updates. +Whenever you need to access the current syntax tree, parse the buffer: >lua + local tree = parser:parse({ start_row, end_row }) -============================================================================== -Lua module: vim.treesitter.languagetree *lua-treesitter-languagetree* +< -LanguageTree:children({self}) *LanguageTree:children()* +This returns a table of immutable |treesitter-tree| objects representing +the current state of the buffer. When the plugin wants to access the state +after a (possible) edit it must call `parse()` again. If the buffer wasn't +edited, the same tree will be returned again without extra work. If the +buffer was parsed before, incremental parsing will be done of the changed +parts. + +Note: To use the parser directly inside a |nvim_buf_attach()| Lua +callback, you must call |vim.treesitter.get_parser()| before you register +your callback. But preferably parsing shouldn't be done directly in the +change callback anyway as they will be very frequent. Rather a plugin that +does any kind of analysis on a tree should use a timer to throttle too +frequent updates. + +LanguageTree:children() *LanguageTree:children()* Returns a map of language to child tree. - Parameters: ~ - • {self} - -LanguageTree:contains({self}, {range}) *LanguageTree:contains()* +LanguageTree:contains({range}) *LanguageTree:contains()* Determines whether {range} is contained in the |LanguageTree|. Parameters: ~ • {range} (table) `{ start_line, start_col, end_line, end_col }` - • {self} Return: ~ (boolean) -LanguageTree:destroy({self}) *LanguageTree:destroy()* +LanguageTree:destroy() *LanguageTree:destroy()* Destroys this |LanguageTree| and all its children. Any cleanup logic should be performed here. - Note: This DOES NOT remove this tree from a parent. Instead, `remove_child` must be called on the parent to remove it. - - Parameters: ~ - • {self} - - *LanguageTree:for_each_child()* -LanguageTree:for_each_child({self}, {fn}, {include_self}) - Invokes the callback for each |LanguageTree| and its children recursively - - Parameters: ~ - • {fn} function(tree: LanguageTree, lang: string) - • {include_self} (boolean) Whether to include the invoking tree in the - results - • {self} + Note: This DOES NOT remove this tree from a parent. Instead, + `remove_child` must be called on the parent to remove it. -LanguageTree:for_each_tree({self}, {fn}) *LanguageTree:for_each_tree()* +LanguageTree:for_each_tree({fn}) *LanguageTree:for_each_tree()* Invokes the callback for each |LanguageTree| recursively. Note: This includes the invoking tree's child trees as well. Parameters: ~ - • {fn} function(tree: TSTree, languageTree: LanguageTree) - • {self} + • {fn} fun(tree: TSTree, ltree: LanguageTree) -LanguageTree:included_regions({self}) *LanguageTree:included_regions()* - Gets the set of included regions +LanguageTree:included_regions() *LanguageTree:included_regions()* + Gets the set of included regions managed by this LanguageTree . This can be different from the regions set by injection query, because a + partial |LanguageTree:parse()| drops the regions outside the requested + range. - Parameters: ~ - • {self} + Return: ~ + table<integer, Range6[]> -LanguageTree:invalidate({self}, {reload}) *LanguageTree:invalidate()* +LanguageTree:invalidate({reload}) *LanguageTree:invalidate()* Invalidates this parser and all its children Parameters: ~ - • {self} + • {reload} (boolean|nil) -LanguageTree:is_valid({self}) *LanguageTree:is_valid()* - Determines whether this tree is valid. If the tree is invalid, call `parse()` . This will return the updated tree. +LanguageTree:is_valid({exclude_children}) *LanguageTree:is_valid()* + Returns whether this LanguageTree is valid, i.e., |LanguageTree:trees()| reflects the latest state of the + source. If invalid, user should call |LanguageTree:parse()|. Parameters: ~ - • {self} + • {exclude_children} (boolean|nil) whether to ignore the validity of + children (default `false`) -LanguageTree:lang({self}) *LanguageTree:lang()* - Gets the language of this tree node. + Return: ~ + (boolean) - Parameters: ~ - • {self} +LanguageTree:lang() *LanguageTree:lang()* + Gets the language of this tree node. *LanguageTree:language_for_range()* -LanguageTree:language_for_range({self}, {range}) +LanguageTree:language_for_range({range}) Gets the appropriate language that contains {range}. Parameters: ~ • {range} (table) `{ start_line, start_col, end_line, end_col }` - • {self} Return: ~ - LanguageTree Managing {range} + |LanguageTree| Managing {range} *LanguageTree:named_node_for_range()* -LanguageTree:named_node_for_range({self}, {range}, {opts}) +LanguageTree:named_node_for_range({range}, {opts}) Gets the smallest named node that contains {range}. Parameters: ~ @@ -997,48 +1169,58 @@ LanguageTree:named_node_for_range({self}, {range}, {opts}) • {opts} (table|nil) Optional keyword arguments: • ignore_injections boolean Ignore injected languages (default true) - • {self} Return: ~ - userdata|nil Found |tsnode| + |TSNode| | nil Found node + +LanguageTree:parse({range}) *LanguageTree:parse()* + Recursively parse all regions in the language tree using + |treesitter-parsers| for the corresponding languages and run injection + queries on the parsed trees to determine whether child trees should be + created and parsed. -LanguageTree:parse({self}) *LanguageTree:parse()* - Parses all defined regions using a treesitter parser for the language this - tree represents. This will run the injection query for this language to - determine if any child languages should be created. + Any region with empty range (`{}`, typically only the root tree) is always + parsed; otherwise (typically injections) only if it intersects {range} (or + if {range} is `true`). Parameters: ~ - • {self} + • {range} boolean|Range|nil: Parse this range in the parser's source. + Set to `true` to run a complete parse of the source (Note: + Can be slow!) Set to `false|nil` to only parse regions with + empty ranges (typically only the root tree without + injections). Return: ~ - userdata[] Table of parsed |tstree| - (table) Change list + table<integer, TSTree> -LanguageTree:register_cbs({self}, {cbs}) *LanguageTree:register_cbs()* + *LanguageTree:register_cbs()* +LanguageTree:register_cbs({cbs}, {recursive}) Registers callbacks for the |LanguageTree|. Parameters: ~ - • {cbs} (table) An |nvim_buf_attach()|-like table argument with the - following handlers: - • `on_bytes` : see |nvim_buf_attach()|, but this will be called after the parsers callback. - • `on_changedtree` : a callback that will be called every time - the tree has syntactical changes. It will only be passed one - argument, which is a table of the ranges (as node ranges) - that changed. - • `on_child_added` : emitted when a child is added to the - tree. - • `on_child_removed` : emitted when a child is removed from - the tree. - • {self} - -LanguageTree:source({self}) *LanguageTree:source()* + • {cbs} (table) An |nvim_buf_attach()|-like table argument with + the following handlers: + • `on_bytes` : see |nvim_buf_attach()|, but this will be called after the parsers callback. + • `on_changedtree` : a callback that will be called every + time the tree has syntactical changes. It will be + passed two arguments: a table of the ranges (as node + ranges) that changed and the changed tree. + • `on_child_added` : emitted when a child is added to the + tree. + • `on_child_removed` : emitted when a child is removed + from the tree. + • `on_detach` : emitted when the buffer is detached, see + |nvim_buf_detach_event|. Takes one argument, the number + of the buffer. + • {recursive} (boolean|nil) Apply callbacks recursively for all + children. Any new children will also inherit the + callbacks. + +LanguageTree:source() *LanguageTree:source()* Returns the source content of the language tree (bufnr or string). - Parameters: ~ - • {self} - *LanguageTree:tree_for_range()* -LanguageTree:tree_for_range({self}, {range}, {opts}) +LanguageTree:tree_for_range({range}, {opts}) Gets the tree that contains {range}. Parameters: ~ @@ -1046,33 +1228,17 @@ LanguageTree:tree_for_range({self}, {range}, {opts}) • {opts} (table|nil) Optional keyword arguments: • ignore_injections boolean Ignore injected languages (default true) - • {self} Return: ~ - userdata|nil Contained |tstree| + TSTree|nil -LanguageTree:trees({self}) *LanguageTree:trees()* - Returns all trees this language tree contains. Does not include child - languages. - - Parameters: ~ - • {self} - -new({source}, {lang}, {opts}) *vim.treesitter.languagetree.new()* - A |LanguageTree| holds the treesitter parser for a given language {lang} - used to parse a buffer. As the buffer may contain injected languages, the LanguageTree needs to store parsers for these child languages as well (which in turn - may contain child languages themselves, hence the name). - - Parameters: ~ - • {source} (number|string) Buffer or a string of text to parse - • {lang} (string) Root language this tree represents - • {opts} (table|nil) Optional keyword arguments: - • injections table Mapping language to injection query - strings. This is useful for overriding the built-in - runtime file searching for the injection language query - per language. +LanguageTree:trees() *LanguageTree:trees()* + Returns all trees of the regions parsed by this parser. Does not include + child languages. The result is list-like if + • this LanguageTree is the root, in which case the result is empty or a singleton list; or + • the root LanguageTree is fully parsed. Return: ~ - LanguageTree |LanguageTree| parser object + table<integer, TSTree> vim:tw=78:ts=8:sw=4:sts=4:et:ft=help:norl: |