summaryrefslogtreecommitdiffstatshomepage
path: root/src/nvim/lua/treesitter.c
AgeCommit message (Collapse)AuthorFiles
2026-04-16fix(treesitter): restore highlighting on 32 bit systems #39091Barrett Ruth1
Problem: Treesitter highlighting regressed on 32-bit builds because ranges that should cover the whole buffer were corrupted when passed into Lua. Solution: Round-trip those range values through Lua and validate them so treesitter sees the same ranges on 32 and 64-bit builds.
2026-04-02refactor(treesitter): add nts_parser_parse_bufLewis Russell1
This PR creates a C function `nts_parser_parse_buf()` which is like `ts_parser_parse_string()` but instead can be passed an nvim buffer number to parse.
2025-12-15Revert "refactor(treesitter): use scratch buffer for string parser" #36964Riley Bruins1
This reverts commit 2a7cb32959b4c616bd2c76ae1933f8e068e391ad.
2025-10-02refactor(treesitter): use scratch buffer for string parser #35988Riley Bruins1
This commit changes `languagetree.lua` so that it creates a scratch buffer under the hood when dealing with string parsers. This will make it much easier to just use extmarks whenever we need to track injection trees in `languagetree.lua`. This also allows us to remove the `treesitter.c` code for parsing a string directly. Note that the string parser's scratch buffer has `set noeol nofixeol` so that the parsed source exactly matches the passed in string.
2025-10-01fix(treesitter): don't add final newline if not present #35970Riley Bruins1
**Problem(?):** Buffers that (for whatever reason) aren't meant to have a final newline are still parsed with a final newline in `treesitter.c`. **Solution:** Don't add the newline to the last buffer line if it shouldn't be there. (This more closely matches the approach of `read_buffer_into()`.) This allows us to, say, use a scratch buffer with `noeol` and `nofixeol` behind the scenes in `get_string_parser()`. ...which would allow us to track injection trees with extmarks in that case. ...which would allow us to not drop previous trees after reparsing a different range with `get_parser():parse()`. ...which would prevent flickering when editing a buffer that has 2+ windows to it in view at a time. ...which would allow us to keep our sanity!!! (one step at a time...)
2025-08-28perf: add on_range in treesitter highlightingvanaigr1
2025-08-14refactor(build): remove INCLUDE_GENERATED_DECLARATIONS guardsbfredl1
These are not needed after #35129 but making uncrustify still play nice with them was a bit tricky. Unfortunately `uncrustify --update-config-with-doc` breaks strings with backslashes. This issue has been reported upstream, and in the meanwhile auto-update on every single run has been disabled.
2025-07-02fix(treesitter): ensure TSLuaTree is always immutableRodrigodd1
Problem: The previous fix in #34314 relies on copying the tree in `tree_root` to ensure the `TSNode`'s tree cannot be mutated. But that causes the problem where two calls to `tree_root` return nodes from different copies of a tree, which do not compare as equal. This has broken at least one plugin. Solution: Make all `TSTree`s on the Lua side always immutable, avoiding the need to copy the tree in `tree_root`, and make the only mutation point, `tree_edit`, copy the tree instead.
2025-06-06fix(treesitter): ensure TSNode's tree is immutableRodrigodd1
Problem: TSNode contains a `const TSTree*` and a `const void *id`. The `id` points to Tree-sitter's internal type `Subtree`, which resides inside the `TSTree` but may be deallocated if the `TSTree` is mutated (which is likely why it is `const`). The Lua method `TSTree:edit()` mutates the tree, which can deallocate `id`. See #25254 and #31758. Solution: To avoid this, we now make a copy of the tree before pushing its root to the Lua stack. This also removes the fenv from TSLuaTree, as it was only used when pushing the tree root to the Lua stack. We also copy the tree in `node_tree`. `ts_tree_copy()` just increments a couple of reference counters, so it's relatively cheap to call.
2025-05-13refactor(treesitter): move functions from executor.c to treesitter.cLewis Russell1
2025-05-11refactor(treesitter): remove empty parse callbackRiley Bruins1
Now that we have bumped to tree-sitter 0.25.4, we no longer need to do this since upstream does it for us when calling the regular parse method.
2025-05-04feat(messages): cleanup Lua error messagesJustin M. Keyes1
"Error" in error messages is redundant. Just provide the context, don't say "Error ...".
2025-04-12fix(treesitter): clear parse options state #33437Riley Bruins1
Apparently after parsing with options in tree-sitter, the options data persists in the parser object, and thus successive calls to `ts_parser_parse()` will act like `ts_parser_parse_with_options()`. This is problematic because `languagetree.lua` makes coroutine-environment assumptions based on if a nullptr has been returned by the parser function. This commit makes it so that the parse options state is reset upon a regular parse (would be nice if this was done upstream). Fixes #33277
2025-03-29refactor(treesitter): migrate to ts parser callback API #33141Riley Bruins1
Remove the `set_timeout` functions for `TSParser` and instead add a timeout parameter to the regular parse function. Remove these deprecated tree-sitter API functions and replace them with the preferred `TSParseOptions` style.
2025-03-11feat(treesitter): allow disabling captures and patterns on TSQuery (#32790)Ian Chamberlain1
Problem: Cannot disable individual captures and patterns in treesitter queries. Solution: * Expose the corresponding tree-sitter API functions for `TSQuery` object. * Add documentation for `TSQuery`. * Return the pattern ID from `get_captures_at_pos()` (and hence `:Inspect!`).
2025-03-01feat(treesitter): add more metadata to `language.inspect()` (#32657)Lewis Russell1
Problem: No way to check the version of a treesitter parser. Solution: Add version metadata (ABI 15 parsers only) as well as parser state count and supertype information (ABI 15) in `vim.treesitter.language.inspect()`. Also graduate the `abi_version` field, as this is now the official upstream name. --------- Co-authored-by: Christian Clason <c.clason@uni-graz.at>
2025-02-21fix(treesitter): `TSNode:field()` returns all children with the given fieldRiley Bruins1
2025-02-02refactor(treesitter): always return valid range from parse() #32273Riley Bruins1
Problem: When running an initial parse, parse() returns an empty table rather than an actual range. In `languagetree.lua`, we manually check if a parse was incremental to determine the changed parse region. Solution: - Always return a range (in the C side) from parse(). - Simplify the language tree code a bit. - Logger no longer shows empty ranges on the initial parse.
2025-01-27build(deps)!: bump tree-sitter to HEAD, wasmtime to v29.0.1 (#32200)Christian Clason1
Breaking change: `ts_node_child_containing_descendant()` was removed Breaking change: tree-sitter 0.25 (HEAD) required
2025-01-14fix(treesitter): uv_dlclose after uv_dlerrorHorror Proton1
2025-01-12feat(treesitter): async parsingRiley Bruins1
**Problem:** Parsing can be slow for large files, and it is a blocking operation which can be disruptive and annoying. **Solution:** Provide a function for asynchronous parsing, which accepts a callback to be run after parsing completes. Co-authored-by: Lewis Russell <lewis6991@gmail.com> Co-authored-by: Luuk van Baal <luukvbaal@gmail.com> Co-authored-by: VanaIgr <vanaigranov@gmail.com>
2024-12-23fix: fix broken wasmtime builddundargoc1
Regression from 2a7d0ed6145bf3f8b139c2694563f460f829813a, which removed header that is only needed if wasmtime support is enabled. Prevent this from happening again by wrapping the include in a `HAVE_WASMTIME` check.
2024-12-23refactor: iwyu #31637Justin M. Keyes1
Result of `make iwyu` (after some "fixups").
2024-11-13fix(treesitter): show proper node name error messagesRiley Bruins1
**Problem:** Currently node names with non-alphanumeric, non underscore/hyphen characters (only possible with anonymous nodes) are not given a proper error message. See tree-sitter issue 3892 for more details. **Solution:** Apply a different scanning logic to anonymous nodes to correctly identify the entire node name (i.e., up until the final double quote)
2024-10-27fix(treesitter): correct condition in `__has_ancestor`Amaan Qureshi1
2024-10-12fix(treesitter): mark supertype nodes as namedRiley Bruins1
**Problem:** Tree-sitter 0.24.0 introduced a new symbol type to denote supertype nodes (`TSSymbolTypeSupertype`). Now, `language.inspect()` (and the query `omnifunc`) return supertype symbols, but with double quotes around them. **Solution:** Mark a symbol as "named" based on it *not* being an anonymous node, rather than checking that it is a regular node (which a supertype also is not).
2024-10-11fix(treesitter): remove duplicate symbol names in language.inspect()Riley Bruins1
**Problems:** - `vim.treesitter.language.inspect()` returns duplicate symbol names, sometimes up to 6 of one kind in the case of `markdown` - The list-like `symbols` table can have holes and is thus not even a valid msgpack table anyway, mentioned in a test **Solution:** Return symbols as a map, rather than a list, where field names are the names of the symbol. The boolean value associated with the field encodes whether or not the symbol is named. Note that anonymous nodes are surrounded with double quotes (`"`) to prevent potential collisions with named counterparts that have the same identifier.
2024-10-11feat(treesitter): introduce child_with_descendant()Riley Bruins1
This commit also marks `child_containing_descendant()` as deprecated (per upstream's documentation), and uses `child_with_descendant()` in its place. Minimum required tree-sitter version will now be `0.24`.
2024-10-03perf(treesitter): do not use tree cursors with a small lifetimeLewis Russell1
Problem: Tree cursors can only be efficient when they are re-used. Short-lived cursors are very slow. Solution: Reimplement functions that use short-lived cursors.
2024-08-26feat(treesitter): add support for wasm parsersLewis Russell1
Problem: Installing treesitter parser is hard (harder than climbing to heaven). Solution: Add optional support for wasm parsers with `wasmtime`. Notes: * Needs to be enabled by setting `ENABLE_WASMTIME` for tree-sitter and Neovim. Build with `make CMAKE_EXTRA_FLAGS=-DENABLE_WASMTIME=ON DEPS_CMAKE_FLAGS=-DENABLE_WASMTIME=ON` * Adds optional Rust (obviously) and C11 dependencies. * Wasmtime comes with a lot of features that can negatively affect Neovim performance due to library and symbol table size. Make sure to build with minimal features and full LTO. * To reduce re-compilation times, install `sccache` and build with `RUSTC_WRAPPER=<path/to/sccache> make ...`
2024-06-04fixup: apply the change on more filesJames Tirta Halim1
2024-05-16perf(treesitter): use child_containing_descendant() in has-ancestor? (#28512)vanaigr1
Problem: `has-ancestor?` is O(n²) for the depth of the tree since it iterates over each of the node's ancestors (bottom-up), and each ancestor takes O(n) time. This happens because tree-sitter's nodes don't store their parent nodes, and the tree is searched (top-down) each time a new parent is requested. Solution: Make use of new `ts_node_child_containing_descendant()` in tree-sitter v0.22.6 (which is now the minimum required version) to rewrite the `has-ancestor?` predicate in C to become O(n). For a sample file, decreases the time taken by `has-ancestor?` from 360ms to 6ms.
2024-04-29fix(treesitter): make tests for memoize more robustbfredl1
Instead of painfully messing with timing to determine if queries were reparsed, we can simply keep a counter next to the call to ts_query_new Also memoization had a hidden dependency on the garbage collection of the the key, a hash value which never is kept around in memory. this was done intentionally as the hash does not capture all relevant state for the query (external included files) even if actual query objects still would be reachable in memory. To make the test fully deterministic in CI, we explicitly control GC.
2024-04-21refactor(treesitter): language loadingLewis Russell1
2024-03-20refactor(treesitter): handle coverity warnings betterLewis Russell1
2024-03-20fix(treesitter): treecursor regressionLewis Russell1
- Also address some coverity warnings Fixes #27942
2024-03-19refactor(treesitter): reorder functionsLewis Russell1
2024-03-19refactor(treesitter): simplify argument checks for userdataLewis Russell1
2024-03-19refactor(treesitter): redesign query iteratingLewis Russell1
Problem: `TSNode:_rawquery()` is complicated, has known issues and the Lua and C code is awkwardly coupled (see logic with `active`). Solution: - Add `TSQueryCursor` and `TSQueryMatch` bindings. - Replace `TSNode:_rawquery()` with `TSQueryCursor:next_capture()` and `TSQueryCursor:next_match()` - Do more stuff in Lua - API for `Query:iter_captures()` and `Query:iter_matches()` remains the same. - `treesitter.c` no longer contains any logic related to predicates. - Add `match_limit` option to `iter_matches()`. Default is still 256.
2024-03-12refactor: use ml_get_buf_len() in API code (#27825)zeertzjq1
2024-02-16fix(treesitter): correctly handle query quantifiers (#24738)Thomas Vigouroux1
Query patterns can contain quantifiers (e.g. (foo)+ @bar), so a single capture can map to multiple nodes. The iter_matches API can not handle this situation because the match table incorrectly maps capture indices to a single node instead of to an array of nodes. The match table should be updated to map capture indices to an array of nodes. However, this is a massively breaking change, so must be done with a proper deprecation period. `iter_matches`, `add_predicate` and `add_directive` must opt-in to the correct behavior for backward compatibility. This is done with a new "all" option. This option will become the default and removed after the 0.10 release. Co-authored-by: Christian Clason <c.clason@uni-graz.at> Co-authored-by: MDeiml <matthias@deiml.net> Co-authored-by: Gregory Anders <greg@gpanders.com>
2024-02-08refactor(treesitter): typing for Query, TSQuery, and TSQueryInfoJongwook Choi1
- `TSQuery`: userdata object for parsed query. - `vim.treesitter.Query`: renamed from `Query`. - Add a new field `lang`. - `TSQueryInfo`: - Move to `vim/treesitter/_meta.lua`, because C code owns it. - Correct typing for `patterns`, should be a map from `integer` (pattern_id) to `(integer|string)[][]` (list of predicates or directives). - `vim.treesitter.QueryInfo` is added. - This currently has the same structure as `TSQueryInfo` (exported from C code). - Document the fields (see `TSQuery:inspect`). - Add typing for `vim._ts_parse_query()`.
2024-01-28docs: enforce "treesitter" spelling #27110Jongwook Choi1
It's the "tree-sitter" project, but "treesitter" in our code and docs.
2024-01-25fixup: raise TS min versionChristian Clason1
2023-11-28refactor: fix headers with IWYUdundargoc1
2023-11-27refactor: rename types.h to types_defs.hdundargoc1
2023-11-27build(IWYU): fix includes for undo_defs.hdundargoc1
2023-11-27refactor: move Arena and ArenaMem to memory_defs.h (#26240)zeertzjq1
2023-11-12build: remove PVSdundargoc1
We already have an extensive suite of static analysis tools we use, which causes a fair bit of redundancy as we get duplicate warnings. PVS is also prone to give false warnings which creates a lot of work to identify and disable.
2023-10-23build(lint): remove unnecessary clint.py rulesdundargoc1
Uncrustify is the source of truth where possible. Remove any redundant checks from clint.py.