Commit graph

6238 commits

Author SHA1 Message Date
Christian Clason d97971e245 release v0.26.13 2026-08-23 10:48:19 +02:00
Will Lillis d2436dc57c fix(rust): remove must_use attribute from Tree::changed_ranges
`ExactSizeIterator` implements `std::iter::Iterator`, which is already
`must_use`.

(cherry picked from commit 54a46eb49b)
2026-08-23 10:05:49 +02:00
Christian Clason e323709b8d build(deps): bump wasmtime-c-api to v36.0.14 2026-08-21 10:11:35 +02:00
Will Lillis c7a65b67d1 fix(ci): run all workspace tests
Without `--workspace`, all generate tests were silently skipped.
2026-08-20 02:36:20 -04:00
Tim Vermeulen 9d1f31602c fix(parser): nest error children during recovery
(cherry picked from commit f30ee2b300)
2026-08-14 09:47:37 +02:00
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 15adfa9e51 fix(generate): fold case-insensitive patterns at the AST leaves
A previous fix moved case folding for `/i` patterns out of `regex_syntax` and
into `expand_regex`, so folding could drop the two non-ASCII code points
Unicode simple folding maps onto ASCII letters: the long s `ſ` (U+017F)
onto `s`, and the Kelvin sign `K` (U+212A) onto `k`. Left in, they leak
into otherwise-ASCII tokens and stop those tokens from being extracted as
keywords.

By that point, though, the HIR has already turned a negated class into a
complement, so folding it applies the fold on the wrong side of the
negation. `(?i)[^a-z]` folds a set that contains `A-Z`, which re-admits
`a-z` and leaves a class matching very nearly everything.

`regex_syntax` folds each leaf of a class expression before applying that
leaf's negation and the set algebra above it. Keep that order and change
only the fold: walk the AST, replace each leaf with its fold, and translate
with `case_insensitive(false)`.
2026-08-14 01:16:45 -04: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
Sjoerd Langkemper 4b7e2c956c fix(generate): honor right associativity despite a lower-precedence shift
A SHIFT/REDUCE conflict can bundle several shift interpretations with
different precedences against a single reduce. `handle_conflict` weighed them
with only `shift_is_less` and `shift_is_more`, so a lone lower-precedence
shift set `shift_is_less` and the REDUCE won outright, even when another
interpretation tied the REDUCE in precedence and the REDUCE was declared
right-associative. That tie's associativity should have won by shifting, so a
right-associative rule silently became left-associative as soon as an
unrelated lower-precedence rule was added to the grammar.

Track the equal-precedence case explicitly, and in the reduce-wins branch
shift instead when a tying interpretation exists and the reduce actions are
purely right-associative.

Co-authored-by: Will Lillis <will.lillis24@gmail.com>
(cherry picked from commit 0900f84eab)
2026-07-27 08:30:48 +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
Alex Le Blanc fd0ccd65a5 fix(highlight): use std::sync::OnceCell for various loader fields
`std::unsync::OnceCell` allows for data races and requires an (incorrect) manual impl of the `Sync` trait.
2026-07-23 20:14:53 -04:00
Will Lillis 8df22e6f0e fix(init): don't lowercase repository url
(cherry picked from commit 78481a8dfc)
2026-07-18 22:58:47 +02:00
Will Lillis c02f32485a fix(cli): init --update should not update setup.py after replacing it (#5760)
Co-authored-by: Philipp <philipp.zander@tweag.io>
2026-07-17 21:32:18 -04:00
Will Lillis f9b9b39075 fix(templates): replace deprecated method in Package.swift
Co-authored-by: ObserverOfTime <chronobserver@disroot.org>
2026-07-17 21:32:18 -04:00
Will Lillis 09384230b4 fix(templates): add C source files to Python sdist
Co-authored-by: ObserverOfTime <chronobserver@disroot.org>
2026-07-17 21:32:18 -04: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
Will Lillis b6243a5234 fix(generate): fold case-insensitive patterns ourselves
Unicode simple case folding maps two non-ASCII code points onto ASCII
letters: the long s `ſ` (U+017F) onto `s`, and the Kelvin sign `K` (U+212A)
onto `k`. So `regex_syntax` pulls them into any case-insensitive pattern,
which is virtually never intended and has two bad effects:

  * such tokens can no longer be extracted as keywords, because they are not
    a subset of an ASCII `word` token (#5607)
  * a broad class like `[^"]` or `\p{L}` carrying `/i` loses `ſ`/`K`, even
    though it legitimately contains them (#5755)

Rather than let `regex_syntax` fold, parse patterns unfolded and fold them
ourselves in `case_fold_ascii_safe`: fold via `regex_syntax`, then drop
`ſ`/`K` only when folding introduced them (they were not already in the
base set). A class that already contains them keeps them.
2026-07-16 23:53:31 -04:00
Christian Clason 64402de285 release v0.26.11 2026-07-12 12:05:46 +02:00
Will Lillis 2194ac1a9c fix(ci): re-set executable permission on release artifacts before zipping 2026-07-11 10:44:46 +02:00
Will Lillis a2b8369c4a fix(generate): strip non-ASCII case folds
Regexes with the case-insensitive 'i' flag caused unicode simple case folding,
which maps two non-ASCII code points onto ASCII letters:

- `ſ` (U+017F) onto `s`
- the Kelvin sign `K` (U+212A) onto `k`

This pushed such tokens outside an ASCII `word` token, so they failed to
extract as keywords.

(cherry picked from commit 07c4ed220e)
2026-07-11 10:25:59 +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 fa6222a0d3 docs(queries): clarify behavior of first child anchor example
(cherry picked from commit b53a0fe622)
2026-07-01 20:04:13 -04:00
Will Lillis 77b741bb83 docs(queries): specify anchor behavior with quantifiers and groups
- An anchor between two patterns is vacuous when an adjacent quantifier
matches zero

- A leading or trailing anchor on a node applies to the nearest matched node
when an adjacent optional is skipped

- An anchor at the edge of a group or alternation is not allowed.

(cherry picked from commit 133d549b70)
2026-07-01 20:04:13 -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 074b6eb05b fix(xtask): eliminate silent errors in zig fetch 2026-06-30 20:06:29 -04:00
Christian Clason 4ac1514d94 fix(deps): zig manifest for wasmtime is missing windows hashes
Problem: `zig fetch` on 0.16 can't download zip archives, which wasmtime
uses for Windows. This makes `cargo xtask upgrade-wastime` fail silently
with empty hashes for these platforms.

Solution: Re-run xtask with Zig 0.17 nightly.
(cherry picked from commit ae2081989e)
2026-06-29 23:30:59 +02:00
Will Lillis 3fc4cd21bc release v0.26.10 2026-06-28 11:47:27 -04:00
Will Lillis 568aee0b7e test(query): regression test for anchored siblings inside a parent
(cherry picked from commit 41d3e16eac)
2026-06-28 14:09:05 +02: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
Will Lillis fbf3049dc0 fix(dsl): forbid invalid field names 2026-06-27 00:22:57 -04: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
jannschu be8f380ad4 fix(cli): highlight test did not properly check for spans on later rows
The early exit condition to skip remaining highlights was incorrectly
checking the lexicographical order, which could lead to false
passes if a highlight was on a later row with smaller column number.
2026-06-08 18:09:21 -04:00
jannschu d4e89a4881 fix(cli): infinite loop in highlight test 2026-06-08 18:09:21 -04:00
Will Lillis e502c6c18e fix: add DESCRIPTION to grammar Makefile template 2026-06-07 18:03:19 -04:00
Will Lillis 2fddf5a1b4 fix(cli): display warning to user if parser test corpus dir isn't found
(cherry picked from commit d9acc99734)
2026-06-06 00:18:10 +02: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
Will Lillis 323d99ede3 fix(cli): improve soundness of cst range calculation 2026-05-31 23:05:37 +02:00