Commit graph

1292 commits

Author SHA1 Message Date
Tim Vermeulen f837fc9813 fix(lib): accumulate error costs through hidden error nodes
(cherry picked from commit 869638f6cf)
2026-08-14 09:47:37 +02:00
Will Lillis 063f8f886b fix(query): correctly set a state's skipped_quantifier flag when a
zero quantifier skip is performed.

The zero-skip branch currently sets skipped_quantifier unconditionally.
That flag is correct only when the quantified step and its skip target
are _siblings_ at the same query depth. Otherwise, setting it allows for
a "leak" and disables unrelated, "outer" anchors.

(cherry picked from commit 42f33fe2f8)
2026-08-11 00:26:25 -05:00
Will Lillis 6320165515 fix(query): correctly identify MISSING nodes in queries
(cherry picked from commit 5fae914f8f)
2026-08-09 23:07:51 +02:00
Christian Clason 808e4b1fc0 release v0.26.12 2026-08-08 15:04:48 +02:00
Newosko 7566ffacb7 fix(lib): continue search for later named siblings in
`ts_tree_cursor_current_status`

By terminating early on `has_later_siblings`, `has_later_named_siblings`
was incorrectly reported as `false` in some cases. This led to the
execution of some queries to terminate early.

Also remove some dead branches inside `ts_tree_cursor_current_status`.

Co-authored-by: Will Lillis <will.lillis24@gmail.com>
(cherry picked from commit 308aee0c90)
2026-08-08 00:20:18 +02:00
Will Lillis 3ee7c639de fix(parser): restart recovery for invalid tokens in the error state
The early `ts_parser__recover` dispatch for `ERROR_STATE` in
`ts_parser__advance` was dropped in `201b41cf1`. Without it, tokens
with no valid action re-enter `ts_parser__handle_error` per token
and fragment the tree instead of extending one ERROR node. Restore
it to recover the old (pre-0.25) error recovery behavior.

(cherry picked from commit 15ea3328e1)
2026-07-25 18:11:25 +02:00
Will Lillis 5ccdbb6b84 fix(query): transfer a leading boundary anchor across a zero-matched quantifier
`(P . Q* Y)` with zero `Q` dropped the leading `.`, so `Y` matched at any
position instead of being pinned to the parent's first named child. On a `?`/`*`
zero-skip, when the skipped step is the parent's first child and carries a
leading anchor, transfer that first-child requirement to the skip target.

(cherry picked from commit 1ffd612be5)
2026-07-17 19:47:19 -04:00
Will Lillis fcb38e9dcf fix(query): keep the trailing anchor when a zero-matched quantifier is anchored
on both sides

In `A . Q* . B`, a zero-matched `Q` made both anchors vacuous, so `A` and `B`
were no longer required to be immediate siblings. Only relax the following
anchor on a `?`/`*` zero-skip when the skipped step has no leading anchor of
its own; otherwise the adjacency transfers through the empty run.

(cherry picked from commit dfcf73921c)
2026-07-17 19:47:19 -04:00
Christian Clason 64402de285 release v0.26.11 2026-07-12 12:05:46 +02:00
Will Lillis 1ae3cc5753 fix(rust): address new clippy lints 2026-07-11 00:46:19 -04:00
Julia Hansbrough 90dd1a0cfb fix(templates): generated array macros do not compile with C++
Problem: A set of `array_*` macros (`array_push`, `array_extend`, etc) implicitly convert a `void*` into a different pointer type.  In environments that compile these headers as C++, this implicit conversion is an error.

Solution: This commit adds an `_array_cast` macro that uses `decltype` to cast the `void*` to the proper type when compiling as C++.
(cherry picked from commit cc7be1fd47)
2026-07-08 17:34:45 -04:00
Will Lillis 1c21ff33d6 fix(query): apply a trailing anchor when its optional node is skipped
A trailing `.` after an optional node, e.g. `(p (a)+ @a . (b)? @b .)`, sets
`is_last_child` on the `(b)?` step. When `(b)?` matched zero, the zero-skip
jumped past that step to completion, so the last-child requirement was never
enforced.

When a zero-skip would bypass a step carrying `is_last_child`, require that
the last matched node really is the last named child. Gated on the
`alternative_is_skip` edge marker.

(cherry picked from commit a8486ca239)
2026-07-01 20:04:13 -04:00
Will Lillis 5756ced350 fix(query): make an anchor after a zero-matched quantifier vacuous
A `.` anchor between a quantified pattern and a following node, e.g.
`(parent (comment)* @c . (decl))`, was treated as a leading anchor when the
quantifier matched zero. The zero-skip jumps a state directly onto the anchored
step, where `is_immediate` was enforced even though no sibling had matched before
it. Name that skip edge (`alternative_is_skip`) and, when a state follows it,
record that it skipped the quantifier (`skipped_quantifier`). The
immediate anchor is then supressoed for that state's next match.

(cherry picked from commit 7e7f2584d1)
2026-07-01 20:04:13 -04:00
Will Lillis eca86a7a6c fix(query): forbid an anchor at the end of a group
A `.` at the end of a group, such as `((comment)+ @c .)`, was silently dropped
during compilation. Reject rather than dropping.

(cherry picked from commit 966dc52557)
2026-07-01 20:04:13 -04:00
Will Lillis 306f868299 feat(query): enhanced step dumper
Extract the step dump into `ts_query__dump_steps` and enrich it with the control-flow
fields and analysis annotations.

(cherry picked from commit 6bfbd9d84d)
2026-07-01 20:04:13 -04:00
Will Lillis e7d6651336 fix(query): short-circuit longest-match dedup for disjoint states
An unanchored quantified sibling like `(program (comment)+ @doc (class))`
keeps one match state per matching sibling. A recent fix stopped over-pruning
them, but the per-node longest-match dedup is pairwise, so with n live states
matching became O(n^3).

Two states can only be capture subsets of one another if their captured
byte ranges overlap, so keep each group ordered by first-capture position
and stop the pairwise scan once the rest of the group is disjoint.

Refs neovim/neovim#40517

(cherry picked from commit 91fd04f96a)
2026-07-01 19:01:52 -04:00
Will Lillis 3fc4cd21bc release v0.26.10 2026-06-28 11:47:27 -04:00
Lucas M. de Jong Larrarte 2efce10fe9 fix(query): skip passthrough steps when checking for fallible step splitting
Problem: In queries matching a parent node with anchored children
(siblings) where the first sibling has a quantifier and is not
captured, the check for fallible steps skips splitting the state because
the next node is a passthrough node (and not an is_immediate one). This
prevents the query from matching beyond the first occurrence.

Solution: In the check for fallible steps, skip the next steps if they
are passthrough steps.

(cherry picked from commit 99bceec689)
2026-06-28 00:10:08 +02:00
Lucas M. de Jong Larrarte e8b9639291 fix(query): avoid overriding states not seeking immediate match with states seeking immediate match
Problem: In queries matching a parent node with anchored children
(siblings) where the first anchored sibling has a quantifier, the
deduplication logic for states is overly aggressive. The logic causes
the state split on the first capture (with the parent) to be dropped in
favor of the loopback state. This results in the query not being able to
match beyond the first occurrence.

Solution: Prevent the deduplication logic from dropping a state that is
not seeking an immediate match for one that is seeking an immediate
match, since the one not seeking for an immediate match could still
match later nodes.

(cherry picked from commit 8b43f42dca)
2026-06-28 00:10:08 +02:00
Lucas M. de Jong Larrarte 576564d25a fix(query): take anchors between siblings into account for fallible step splitting
Problem: In queries matching a parent node with anchored children
(siblings), the check for fallible steps only considers nodes with
children, which results in no state split being made for anchored
siblings (node1) . (node2). This prevents the query from matching beyond
the first occurrence.

Solution: Make the check for fallible steps consider also the case where
the next step is at the same depth and must be matched immediately
after.

(cherry picked from commit 1b110f62dd)
2026-06-28 00:10:08 +02:00
Christian Clason 99bc36b857 build(deps): bump wasmtime-c-api to v36.0.12 2026-06-26 14:25:24 +02:00
Will Lillis 1ef1048d05 fix(build): use std helper rather than passing -std=c11 flag
MSVC expects `/std:c11`
2026-06-17 00:29:06 -04:00
Will Lillis a61be4ac27 fix(lib): address strict aliasing violations in TreeCursor type
Omit the static assert from master to avoid a breaking change on the
release branch.
2026-06-17 00:29:06 -04:00
Will Lillis 70068dd487 fix(lib): Consider subtree lookahead bytes when determining whether the
parser can reuse a node.

Lookahead bytes can be used to decide what a node is parsed as, so it's
resaonable to consider this as part of a node's "range" when deciding
which edits affect it.

(cherry picked from commit 15ddfb21ed)
2026-06-01 19:12:50 -04:00
Georges Savoundararadj 3ab78c3c5b fix(lib): use correct TREE_SITTER_HIDE_SYMBOLS macro name in alloc.h
The alloc.h header checked for TREE_SITTER_HIDDEN_SYMBOLS, but the
canonical macro name used everywhere else (api.h, render.rs, setup.py)
is TREE_SITTER_HIDE_SYMBOLS. This mismatch meant that defining
TREE_SITTER_HIDE_SYMBOLS (as the Python binding build does) would not
actually hide the allocator symbols in alloc.h.

Fixes tree-sitter/tree-sitter#5625

Signed-off-by: Georges Savoundararadj <savoundg@amazon.com>
(cherry picked from commit 1da46327b3)
2026-05-30 23:00:00 -04:00
Will Lillis f4b1fe2ba7 fix(lib): update doc comment for ts_parser_parse 2026-05-30 19:15:38 -04:00
Christian Clason 7f534862c3 release v0.26.9 2026-05-19 19:51:53 +02:00
tree-sitter-ci-bot[bot] 77b96de523
fix(wasm): validate memory reads (#5569) (#5613)
Problem: Offsets such as parse_table, symbol_names, lex_modes, and the alias/supertype tables are used directly as indexes into the store's memory buffer. A malformed module can point one of those fields outside the current linear memory and make the host process read through an invalid pointer while loading the language.

Solution: Add a small checked-memory wrapper for Wasm language loading and routes descriptor reads, table copies, string reads, and the alias-map scan through it. Invalid descriptor addresses now fail loading with TSWasmErrorKindInstantiate.

(cherry picked from commit 21cfae7b56)

Co-authored-by: 𝙽!𝙻 <z_hakmi@estin.dz>
2026-05-19 19:40:15 +02:00
Christian Clason a082228e43 build(deps): bump wasmtime-c-api to v36.0.9 2026-05-19 19:07:01 +02:00
tree-sitter-ci-bot[bot] 7aea01521d
fix(wasm): load supertype tables for ABI 15 grammars (#5605) (#5606)
The wasm store gated supertype_symbols / supertype_map_slices /
supertype_map_entries copies on abi_version > LANGUAGE_VERSION_WITH_RESERVED_WORDS,
but every other consumer (language.c, query.c) treats those tables as
present when abi_version >= LANGUAGE_VERSION_WITH_RESERVED_WORDS.

A Wasm grammar built at ABI exactly 15 with supertype_count > 0 ends up
with supertype_count copied into the native TSLanguage but supertype_map_slices
left NULL. ts_query__analyze_patterns then calls ts_language_subtypes,
which dereferences self->supertype_map_slices[supertype] and crashes.

(cherry picked from commit a53c3b03a0)

Co-authored-by: Max Brunsfeld <maxbrunsfeld@gmail.com>
2026-05-18 13:58:51 -07:00
Christian Clason ec120d06f2 build(deps): bump wasmtime-c-api to v36.0.8
(cherry picked from commit 85f985a778)
2026-05-05 08:38:44 +02:00
Will Lillis 7c3d842519 docs: note zero point unbounded behavior in query functions 2026-04-30 19:19:03 -04:00
Amaan Qureshi b7964b9b19 query: fix finished state heap invariants
(cherry picked from commit 43dc8eadbe)
2026-04-27 03:37:38 -04:00
Will Lillis b0ddae770e perf(query): use min-heap for finished_states in next_capture
`ts_query_cursor_next_capture` linearly scanned all finished states to
find the one with the earliest next capture byte offset. With deeply
nested code, this O(n) scan per capture caused the highlight crate to
hang for minutes on large files.

Replace the linear scan with a min-heap over the finished_states array,
keyed by (next_capture_byte_offset, pattern_index, id). The heap is
maintained lazily: ts_query_cursor__advance uses plain array_push
(preserving FIFO insertion order), and next_capture sifts new elements
into the heap on entry via a tracked heap_size boundary. This preserves
the documented "order found" guarantee for next_match while giving
next_capture O(log n) per call.

(cherry picked from commit 123fb1c13c)
2026-04-27 03:37:38 -04:00
Will Lillis 0b9a7f87ee fix(query): widen capture list pool from uint16_t to uint32_t
Commit 1f6eac55 ("query: Use uint32_t for capture list IDs") widened
QueryState.capture_list_id to uint32_t and removed the 65536 pool cap,
but left the pool function signatures as uint16_t. This caused silent
truncation when the pool exceeded 65535 entries, leading to a segfault.

(cherry picked from commit 361f293a73)
2026-04-27 03:37:38 -04:00
Daniel Jalkut e4ac513afd lexer: pass code-unit length to U16_NEXT in UTF-16 decoders
`ts_decode_utf16_le` and `ts_decode_utf16_be` passed a byte length to
`U16_NEXT_LE` and `U16_NEXT_BE`, but those macros count `uint16_t` code
units. If a lead surrogate was the last code unit in a chunk, the decoder
could peek past the chunk and combine it with adjacent memory.

This commit passes the code-unit length to the UTF-16 macros, and fails
with `TS_DECODE_ERROR` when a chunk is too short to contain even one full
code unit. This lets the lexer retry with a fresh chunk or advance through
the invalid byte as it already does.

Co-authored-by: Will Lillis <will.lillis24@gmail.com>
Co-authored-by: Amaan Qureshi <git@amaanq.com>
(cherry picked from commit 0f6780b9a3)
2026-04-26 03:40:09 -04:00
Will Lillis 8185030b48 fix(rust): fix new clippy lints 2026-04-23 02:19:20 -04:00
Will Lillis a4bdd941d5 build(deps): bump wasmtime-c-api to v36.0.7
Co-authored-by: Christian Clason <c.clason@uni-graz.at>
2026-04-10 09:46:43 +02:00
Christian Clason cd5b087cd9 release v0.26.8 2026-03-31 19:31:10 +02:00
Max Brunsfeld 0b04fd0533 Fix wasm loading of languages w/ multiple reserved word sets (#5475)
(cherry picked from commit d3ff0ce81d)
2026-03-31 02:01:50 -04:00
Will Lillis 05cf9a161a perf(cli): minor allocation and write call reductions
- Cache tree byte range length to avoid redundant FFI calls per test
- Combine 5 separate XML attribute write! calls into one
- Pre-allocate format_sexp output buffer to avoid repeated growth

(cherry picked from commit 791d7cead4)
2026-03-31 02:01:32 -04:00
Will Lillis 3839f6fcf5 fix(lib): document invariants that must be upheld for TSInputEdit 2026-03-23 00:16:34 -04:00
Christian Clason 6f2e8a6cf4 release v0.26.7 2026-03-14 17:23:21 +01:00
Riley Bruins 8e87144b61 fix(query): don't add copies for quantifier steps outside alternations
(cherry picked from commit cf302b07d1)
2026-03-04 11:01:39 +01:00
Riley Bruins b61eabb4d2 refactor(query): remove alternative_is_immediate
This is implied by `is_pass_through`.

(cherry picked from commit a95fff5477)
2026-03-04 02:52:27 -05:00
Riley Bruins 16c7bfb48f chore(parser): return NULL, not false, for incomplete parse
Small nit; `NULL` is returned everywhere else in this function for an
incomplete parse.

(cherry picked from commit 4ae90615d1)
2026-03-01 05:13:28 -05:00
Christian Clason 534c4a074c 0.26.6 2026-02-25 17:28:48 +01:00
Christian Clason 0de6ea6edd build(deps): bump wasmtime to v36.0.6
(cherry picked from commit 4d7d35818b)
2026-02-24 22:55:55 +01:00
lucasew a226c68720 fix(lib): cast NULL in ts_subtree_children macro
Explicitly casting NULL to (Subtree *) in the ternary expression ensures
type consistency. This resolves ambiguous type inference issues encountered
by strict static analysis tools and C-to-Go transpilers (like ccgo).

Signed-off-by: lucasew <lucas59356@gmail.com>
(cherry picked from commit 4e9fededff)
2026-02-21 04:34:07 -05:00
Christian Clason d03bb288e2 build(deps): bump wasmtime to v36.0.5 LTS
Wasmtime v34 introduced breaking ABI changes to `wasmtime_func_t` and
`wasmtime_table_t` structures. The `__private` field changed from
`size_t` to `void*`, requiring code updates to store complete
`wasmtime_func_t` structures instead of raw indices.

Changes:
- `BuiltinFunctionIndices`: `uint32_t` -> `wasmtime_func_t`
- `stdlib_fn_indices`: `uint32_t*` -> `wasmtime_func_t*`
- `FunctionDefinition.storage_location`: `uint32_t*` -> `void*`
- `get_builtin_extern()`: simplified to return stored func directly
- Lexer functions: use temp array for func storage, store table index
- Zero-initialize `builtin_fn_indices` so `store_id == 0` sentinel
  reliably detects missing stdlib exports
- Free `lexer_funcs` on error paths in `ts_wasm_store_new`
- Remove stale `(uint32_t *)` casts from `lexer_definitions`

Co-Authored-By: nzinfo <li.monan@gmail.com>
(cherry picked from commit a21ee02710)
2026-02-20 10:52:27 +01:00