37.3 Retrieving Nodes

Here are some terms and conventions we use when documenting tree-sitter functions.

A node in a syntax tree spans some portion of the program text in the buffer. We say that a node is “smaller” or “larger” than another if it spans, respectively, a smaller or larger portion of buffer text than the other node. Since nodes that are deeper (“lower”) in the tree are children of the nodes that are “higher” in the tree, it follows that a lower node will always be smaller than a node that is higher in the node hierarchy. A node that is higher up in the syntax tree contains one or more smaller nodes as its children, and therefore spans a larger portion of buffer text.

When a function cannot find a node, it returns nil. For convenience, all functions that take a node as argument and return a node, also accept the node argument of nil and in that case just return nil.

Nodes are not automatically updated when the associated buffer is modified, and there is no way to update a node once it is retrieved. Using an outdated node signals the treesit-node-outdated error.

Retrieving nodes from syntax tree

Function: treesit-node-at pos &optional parser-or-lang named

This function returns a leaf node at buffer position pos. A leaf node is a node that doesn’t have any child nodes.

This function tries to return a node whose span covers pos: the node’s beginning position is less than or equal to pos, and the node’s end position is greater than or equal to pos.

If no leaf node’s span covers pos (e.g., pos is in the whitespace between two leaf nodes), this function returns the first leaf node after pos.

Finally, if there is no leaf node after pos, return the first leaf node before pos.

If parser-or-lang is a parser object, this function uses that parser; if parser-or-lang is a language, this function uses the first parser for that language in the current buffer, or creates one if none exists; if parser-or-lang is nil, this function tries to guess the language at pos by calling treesit-language-at (see Parsing Text in Multiple Languages).

If this function cannot find a suitable node to return, it returns nil.

If named is non-nil, this function looks only for named nodes (see named node).

Example:

;; Find the node at point in a C parser's syntax tree.
(treesit-node-at (point) 'c)
  ⇒ #<treesit-node (primitive_type) in 23-27>
Function: treesit-node-on beg end &optional parser-or-lang named

This function returns the smallest node that covers the region of buffer text between beg and end. In other words, the start of the node is before or at beg, and the end of the node is at or after end.

Beware: calling this function on an empty line that is not inside any top-level construct (function definition, etc.) most probably will give you the root node, because the root node is the smallest node that covers that empty line. Most of the time, you want to use treesit-node-at instead.

If parser-or-lang is a parser object, this function uses that parser; if parser-or-lang is a language, this function uses the first parser for that language in the current buffer, or creates one if none exists; if parser-or-lang is nil, this function tries to guess the language at beg by calling treesit-language-at.

If named is non-nil, this function looks for a named node only (see named node).

Function: treesit-parser-root-node parser

This function returns the root node of the syntax tree generated by parser.

Function: treesit-buffer-root-node &optional language

This function finds the first parser for language in the current buffer, or creates one if none exists, and returns the root node generated by that parser. If language is omitted, it uses the first parser in the parser list. If it cannot find an appropriate parser, it returns nil.

Given a node, a Lisp program can retrieve other nodes starting from it, or query for information about this node.

Retrieving nodes from other nodes

By kinship

Function: treesit-node-parent node

This function returns the immediate parent of node.

If node is more than 1000 levels deep in a parse tree, the return value is undefined. Currently it returns nil, but that could change in the future.

Function: treesit-node-child node n &optional named

This function returns the n’th child of node. If named is non-nil, it counts only named nodes (see named node).

For example, in a node that represents a string "text", there are three children nodes: the opening quote ", the string text text, and the closing quote ". Among these nodes, the first child is the opening quote ", and the first named child is the string text.

This function returns nil if there is no n’th child. n could be negative, e.g., −1 represents the last child.

Function: treesit-node-children node &optional named

This function returns all of node’s children as a list. If named is non-nil, it retrieves only named nodes.

Function: treesit-node-next-sibling node &optional named

This function finds the next sibling of node. If named is non-nil, it finds the next named sibling.

Function: treesit-node-prev-sibling node &optional named

This function finds the previous sibling of node. If named is non-nil, it finds the previous named sibling.

By field name

To make the syntax tree easier to analyze, many language grammars assign field names to child nodes (see field name). For example, a function_definition node could have a declarator node and a body node.

Function: treesit-node-child-by-field-name node field-name

This function finds the child of node whose field name is field-name, a string.

;; Get the child that has "body" as its field name.
(treesit-node-child-by-field-name node "body")
  ⇒ #<treesit-node (compound_statement) in 45-89>

By position

Function: treesit-node-first-child-for-pos node pos &optional named

This function finds the first child of node that extends beyond buffer position pos. “Extends beyond” means the end of the child node is greater or equal to pos. This function only looks for immediate children of node, and doesn’t look in its grandchildren. If named is non-nil, it looks for the first named child (see named node).

Function: treesit-node-descendant-for-range node beg end &optional named

This function finds the smallest descendant node of node that spans the region of text between positions beg and end. It is similar to treesit-node-at. If named is non-nil, it looks for the smallest named child.

Searching for node

Function: treesit-search-subtree node predicate &optional backward all depth

This function traverses the subtree of node (including node itself), looking for a node for which predicate returns non-nil. predicate is a regexp that is matched against each node’s type, or a predicate function that takes a node and returns non-nil if the node matches. The function returns the first node that matches, or nil if none does.

By default, this function only traverses named nodes, but if all is non-nil, it traverses all the nodes. If backward is non-nil, it traverses backwards (i.e., it visits the last child first when traversing down the tree). If depth is non-nil, it must be a number that limits the tree traversal to that many levels down the tree. If depth is nil, it defaults to 1000.

Function: treesit-search-forward start predicate &optional backward all

Like treesit-search-subtree, this function also traverses the parse tree and matches each node with predicate (except for start), where predicate can be a regexp or a function. For a tree like the one below where start is marked ‘S’, this function traverses as numbered from 1 to 12:

              12
              |
     S--------3----------11
     |        |          |
o--o-+--o  1--+--2    6--+-----10
|  |                  |        |
o  o                +-+-+   +--+--+
                    |   |   |  |  |
                    4   5   7  8  9

Note that this function doesn’t traverse the subtree of start, and it always traverses leaf nodes first, before moving upwards.

Like treesit-search-subtree, this function only searches for named nodes by default, but if all is non-nil, it searches for all nodes. If backward is non-nil, it searches backwards.

While treesit-search-subtree traverses the subtree of a node, this function starts with node start and traverses every node that comes after it in the buffer position order, i.e., nodes with start positions greater than the end position of start.

In the tree shown above, treesit-search-subtree traverses node ‘S’ (start) and nodes marked with o, where this function traverses the nodes marked with numbers. This function is useful for answering questions like “what is the first node after start in the buffer that satisfies some condition?”

Function: treesit-search-forward-goto node predicate &optional start backward all

This function moves point to the start or end of the next node after node in the buffer that matches predicate. If start is non-nil, stop at the beginning rather than the end of a node.

This function guarantees that the matched node it returns makes progress in terms of buffer position: the start/end position of the returned node is always greater than that of node.

Arguments predicate, backward, and all are the same as in treesit-search-forward.

Function: treesit-induce-sparse-tree root predicate &optional process-fn depth

This function creates a sparse tree from root’s subtree.

It takes the subtree under root, and combs it so only the nodes that match predicate are left. Like previous functions, the predicate can be a regexp string that matches against each node’s type, or a function that takes a node and returns non-nil if it matches.

For example, given the subtree on the left that consists of both numbers and letters, if predicate is “letter only”, the returned tree is the one on the right.

    a                 a              a
    |                 |              |
+---+---+         +---+---+      +---+---+
|   |   |         |   |   |      |   |   |
b   1   2         b   |   |      b   c   d
    |   |     =>      |   |  =>      |
    c   +--+          c   +          e
    |   |  |          |   |
 +--+   d  4       +--+   d
 |  |              |
 e  5              e

If process-fn is non-nil, instead of returning the matched nodes, this function passes each node to process-fn and uses the returned value instead. If non-nil, depth limits the number of levels to go down from root. If depth is nil, it defaults to 1000.

Each node in the returned tree looks like (tree-sitter-node . (child …)). The tree-sitter-node of the root of this tree will be nil if root doesn’t match predicate. If no node matches predicate, the function returns nil.

More convenience functions

Function: treesit-filter-child node predicate &optional named

This function finds immediate children of node that satisfy predicate.

The predicate function takes a node as argument and should return non-nil to indicate that the node should be kept. If named is non-nil, this function only examines named nodes.

Function: treesit-parent-until node predicate &optional include-node

This function repeatedly finds the parents of node, and returns the parent that satisfies pred, a function that takes a node as argument and returns a boolean that indicates a match. If no parent satisfies pred, this function returns nil.

Normally this function only looks at the parents of node but not node itself. But if include-node is non-nil, this function returns node if node satisfies pred.

Function: treesit-parent-while node pred

This function goes up the tree starting from node, and keeps doing so as long as the nodes satisfy pred, a function that takes a node as argument. That is, this function returns the highest parent of node that still satisfies pred. Note that if node satisfies pred but its immediate parent doesn’t, node itself is returned.

Function: treesit-node-top-level node &optional type

This function returns the highest parent of node that has the same type as node. If no such parent exists, it returns nil. Therefore this function is also useful for testing whether node is top-level.

If type is non-nil, this function matches each parent’s type with type as a regexp, rather than using node’s type.