Skip to main content

Editing

In applications like text editors, you often need to re-parse a file after its source code has changed. Tree-sitter is designed to support this use case efficiently through incremental parsing.

The Two-Step Process

1

Edit the syntax tree

First, you must edit the syntax tree to adjust the ranges of its nodes so they stay in sync with the code.
2

Re-parse with the old tree

Then, call ts_parser_parse again, passing in the old tree. This creates a new tree that internally shares structure with the old tree.

Complete Example

Editing Stored Nodes

When you edit a syntax tree, the positions of its nodes will change. If you have stored any TSNode instances outside of the TSTree, you must update them separately:
The ts_node_edit function is only needed when you have retrieved TSNode instances before editing the tree and want to continue using those specific instances afterward. Often, you’ll just re-fetch nodes from the edited tree, in which case ts_node_edit is not needed.

Multi-language Documents

Sometimes, different parts of a file may be written in different languages. For example, templating languages like EJS and ERB allow you to generate HTML by writing a mixture of HTML and another language like JavaScript or Ruby. Tree-sitter handles these types of documents by allowing you to create a syntax tree based on the text in certain ranges of a file.

Setting Included Ranges

Example: Parsing ERB

Consider this ERB document:
Conceptually, it can be represented by three syntax trees with overlapping ranges:
  • An ERB syntax tree
  • A Ruby syntax tree (for the <% %> blocks)
  • An HTML syntax tree (for the content outside the blocks)
This API allows for great flexibility in how languages can be composed. Tree-sitter is not responsible for mediating the interactions between languages — you’re free to do that using arbitrary application-specific logic.

Concurrency

Tree-sitter supports multi-threaded use cases by making syntax trees very cheap to copy.
Internally, copying a syntax tree just entails incrementing an atomic reference count. Conceptually, it provides you a new tree which you can freely query, edit, reparse, or delete on a new thread while continuing to use the original tree on a different thread.
Individual TSTree instances are not thread safe. You must copy a tree if you want to use it on multiple threads simultaneously.

Getting Changed Ranges

When re-parsing after an edit, you can determine which parts of the tree have changed:
This function returns an array of ranges whose syntactic structure has changed between the old and new trees. The returned array is allocated using malloc and must be freed by the caller.
The returned ranges indicate areas where the hierarchical structure of syntax nodes (from root to leaf) has changed. Characters outside these ranges have identical ancestor nodes in both trees. The ranges may be slightly larger than the exact changed areas, but Tree-sitter attempts to make them as small as possible.

Next Steps

Walking Trees

Learn about efficient tree traversal with cursors

Pattern Matching

Query syntax trees with powerful patterns