Compare commits

...
Sign in to create a new pull request.

540 commits

Author SHA1 Message Date
dependabot[bot]
6739742fb6 build(deps): bump cc from 1.2.52 to 1.2.53 in the cargo group
Bumps the cargo group with 1 update: [cc](https://github.com/rust-lang/cc-rs).


Updates `cc` from 1.2.52 to 1.2.53
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.52...cc-v1.2.53)

---
updated-dependencies:
- dependency-name: cc
  dependency-version: 1.2.53
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-20 10:34:48 +01:00
dependabot[bot]
d251226a3c ci: bump actions/github-script from 7 to 8 in the actions group
Bumps the actions group with 1 update: [actions/github-script](https://github.com/actions/github-script).


Updates `actions/github-script` from 7 to 8
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](https://github.com/actions/github-script/compare/v7...v8)

---
updated-dependencies:
- dependency-name: actions/github-script
  dependency-version: '8'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-20 10:34:40 +01:00
Tam1SH
ae8184b8b9 docs(playground): highlight full row for highlighted nodes 2026-01-18 23:48:58 -05:00
Will Lillis
470ecf8996 feat(ci): ensure wasm-stdlib.h is regenerated when wasm stdlib source
files are modified.
2026-01-18 22:19:52 -05:00
Will Lillis
0cdb6bef7b fix(cli): warn user when nm can't be run to verify the symbols inside
the parser being built
2026-01-18 22:19:19 -05:00
theanarkh
cd603fa981
feat: free memory automatically (#5225) 2026-01-18 14:39:52 -08:00
DanikVitek
b12009a746 fix: Clarify/fix lifetimes
- One has to think about lifetimes if a type has one:
  - `<&'a Node<'tree>>::language` now returns `LanguageRef<'tree>` instead of
    `LanguageRef<'a>`, as it should;
- Remove explicit "outlives" requirements from `QueryMatches`, `QueryCaptures`,
  and their impl blocks, because they're inferred
- Removed unnecessary `&mut` from `cst_render_node`'s `cursor` parameter
2026-01-17 00:14:21 -05:00
DanikVitek
9f9a0bc410 fix: Renamed TreeCursor<'cursor> into TreeCursor<'tree>,
to be consistant with the usages and reduse confusion
2026-01-17 00:14:21 -05:00
Christian Clason
5d290a2a75 fix(wasm): regenerate stdlib with wasm-opt
Problem: Output of `cargo xtask build-wasm-stdlib` depends on whether
`wasm-opt` is installed (since `clang` will use it by default if it
finds it).

Solution: Install it and rerun the xtask.
2026-01-15 15:33:37 +01:00
Will Lillis
5808350bfe fix(docs): appease clippy regarding spacing in README 2026-01-15 10:38:57 +01:00
Will Lillis
e64e74d5ed docs: adhere to 120 new word column limit for docs 2026-01-14 18:11:42 -05:00
Will Lillis
1a88b26a10 docs: note requirement to rebuild wasm stdlib 2026-01-14 18:11:42 -05:00
dependabot[bot]
6c05cdfb0c build(deps): bump the cargo group with 3 updates
Bumps the cargo group with 3 updates: [cc](https://github.com/rust-lang/cc-rs), [clap_complete](https://github.com/clap-rs/clap) and [serde_json](https://github.com/serde-rs/json).


Updates `cc` from 1.2.51 to 1.2.52
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.51...cc-v1.2.52)

Updates `clap_complete` from 4.5.64 to 4.5.65
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.64...clap_complete-v4.5.65)

Updates `serde_json` from 1.0.148 to 1.0.149
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.148...v1.0.149)

---
updated-dependencies:
- dependency-name: cc
  dependency-version: 1.2.52
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: clap_complete
  dependency-version: 4.5.65
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: serde_json
  dependency-version: 1.0.149
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-13 10:13:03 +01:00
Will Lillis
aefae11c0d fix(build): define _BSD_SOURCE
System endian conversion macros are gated behind this feature flag for
older versions of GLIBC. `_BSD_SOURCE` and `_SVID_SOURCE` were
deprecated and replaced with `_DEFAULT_SOURCE` starting with GLIBC 2.19.
2026-01-12 19:41:58 -05:00
Kevin Wang
630fa52717 fix(templates): fix python free-threading compatibility 2026-01-09 11:44:41 +02:00
dependabot[bot]
eea85f4eff build(deps): bump clap from 4.5.53 to 4.5.54 in the cargo group
Bumps the cargo group with 1 update: [clap](https://github.com/clap-rs/clap).


Updates `clap` from 4.5.53 to 4.5.54
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.53...clap_complete-v4.5.54)

---
updated-dependencies:
- dependency-name: clap
  dependency-version: 4.5.54
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-07 16:42:00 +00:00
Christian Clason
cd6672701b fix(wasm): update wasm-stdlib.h 2026-01-06 17:28:39 +01:00
Trim21
f4ca3d95ca
fix(wasm) add common definitions to stdlib (#5199)
Also expose `strlen` through `string.h` instead of `stdio.h`.
2026-01-06 12:01:37 +01:00
skewb1k
17e3c7a5c5 fix(cli): restore test summary output for tree-sitter test
Problem:
After commit f02d7e7e33
the `tree-sitter test` command no longer printed the final test summary,
leaving empty line. The `Stats` struct was embedded into `TestSummary`,
and the explicit call to print it was removed.

Solution:
Print `parse_stats` from `TestSummary.fmt()` implementation.
2026-01-04 21:31:11 -08:00
WillLillis
dd60d5cff0 feat(cli): fill in missing fields to tree-sitter.json when running
`tree-sitter init -u`
2025-12-31 14:08:09 -05:00
WillLillis
f1288ea5c9 fix(cli): increase verbosity of tree-sitter init -u updates
Also, use `info` logs rather than `warn`
2025-12-31 14:08:09 -05:00
Christian Clason
47ae060966 feat(quickjs): add console support for Array 2025-12-31 13:32:09 +01:00
Christian Clason
a1893b4420 build(deps): update rquickjs to 0.11.0 2025-12-31 13:32:09 +01:00
skewb1k
999e041d49 docs: add tip about using test --update flag 2025-12-31 01:43:48 -05:00
skewb1k
0d4d854809 feat(cli): make test --update rewrite all corpus files 2025-12-31 01:43:48 -05:00
WillLillis
93d793d249 fix(cli): canonicalize build --output path
This fixes a potential issue with the new lock file hashing mechanism,
in which two different path literals pointing to the same location would
hash to separate lock files, allowing a race condition.
2025-12-30 17:07:04 +01:00
dependabot[bot]
82486d4b0a build(deps): bump the cargo group with 2 updates
Bumps the cargo group with 2 updates: [cc](https://github.com/rust-lang/cc-rs) and [serde_json](https://github.com/serde-rs/json).


Updates `cc` from 1.2.50 to 1.2.51
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.50...cc-v1.2.51)

Updates `serde_json` from 1.0.145 to 1.0.147
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.145...v1.0.147)

---
updated-dependencies:
- dependency-name: cc
  dependency-version: 1.2.51
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: serde_json
  dependency-version: 1.0.147
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-30 17:06:34 +01:00
Firas al-Khalil
5d9605a91e feat(cli): concurrent build of same grammar on different paths 2025-12-29 00:20:05 -05:00
Firas al-Khalil
5293dd683e fix(cli): report library load failure
Instead of panicking somehere else.

This happens on concurrent builds of the the same grammar.
2025-12-29 00:20:05 -05:00
Firas al-Khalil
62effdf128 fix(cli): report context on compile fail 2025-12-29 00:20:05 -05:00
WillLillis
8e4f21aba0 fix(rust): address nightly clippy lint 2025-12-27 17:05:53 -05:00
WillLillis
5208299bbb fix(cli): set language in cwd for all usages of highlight command 2025-12-27 17:05:53 -05:00
Christian Clason
ba7350c7ee docs(cli): better description of files generated by init 2025-12-25 13:16:57 +01:00
skewb1k
f96d518ebf fix(cli): remove extra newline with --cst
Makes CST output consistent with other formats.
2025-12-24 15:06:48 +01:00
skewb1k
d5b82fbbab fix(cli): remove extra indentation with --cst --no-ranges 2025-12-24 15:06:48 +01:00
kevin-hua-kraken
a7d8c0cbb2
fix(playground): update query API 2025-12-23 10:36:40 +02:00
dependabot[bot]
24007727d4 build(deps): bump the cargo group with 2 updates
Bumps the cargo group with 2 updates: [cc](https://github.com/rust-lang/cc-rs) and [clap_complete](https://github.com/clap-rs/clap).


Updates `cc` from 1.2.49 to 1.2.50
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.49...cc-v1.2.50)

Updates `clap_complete` from 4.5.61 to 4.5.62
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.61...clap_complete-v4.5.62)

---
updated-dependencies:
- dependency-name: cc
  dependency-version: 1.2.50
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: clap_complete
  dependency-version: 4.5.62
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-22 22:18:42 +01:00
dependabot[bot]
6aa63a7213 ci: bump korthout/backport-action from 3 to 4 in the actions group
Bumps the actions group with 1 update: [korthout/backport-action](https://github.com/korthout/backport-action).


Updates `korthout/backport-action` from 3 to 4
- [Release notes](https://github.com/korthout/backport-action/releases)
- [Commits](https://github.com/korthout/backport-action/compare/v3...v4)

---
updated-dependencies:
- dependency-name: korthout/backport-action
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-22 22:18:09 +01:00
Will Lillis
eacb95c85d fix(cli): correct discrepancy with cst for --no-ranges 2025-12-16 21:34:03 -05:00
dependabot[bot]
6967640571 ci: bump the actions group with 2 updates
Bumps the actions group with 2 updates: [actions/upload-artifact](https://github.com/actions/upload-artifact) and [actions/download-artifact](https://github.com/actions/download-artifact).


Updates `actions/upload-artifact` from 5 to 6
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v5...v6)

Updates `actions/download-artifact` from 6 to 7
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: actions/download-artifact
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-15 22:26:50 +01:00
skewb1k
4ac2d5d276 fix(cli): trailing whitespace after multiline text nodes in CST
Problem:
The CST printer emits trailing whitespace after multiline text nodes.
With 1704c604bf and `:cst` corpus tests
this causes trailing spaces to appear on `test --update`.
These spaces cannot be removed afterward, as the test runner
expects an exact character-for-character match for CST tests.

Solution:
Print whitespace only if node is not multiline.
2025-12-14 21:34:50 -05:00
skewb1k
642b56d9af fix(docs): remove conflicting --release cargo flag in contributing.md
The argument '--release' cannot be used with '--profile <PROFILE-NAME>'
2025-12-14 20:35:13 +01:00
Christian Clason
0574fcf256 docs(cli): include information on generated files 2025-12-14 14:26:49 +01:00
Christian Clason
98de2bc1a8 feat: start working on v0.27
* bump tree-sitter crates to 0.27.0
* bump tree-sitter-language to 0.1.7
2025-12-13 14:14:33 +01:00
Christian Clason
cd4b6e2ef9 0.26.3 2025-12-13 13:41:03 +01:00
Christian Clason
8caecbc13f build(deps): cargo update 2025-12-13 12:58:59 +01:00
ObserverOfTime
1b654ae35d ci(release): use node 24 2025-12-13 06:28:18 -05:00
Marcono1234
3bd44afcaa docs(cli): fix wrong file path for Java bindings test
The test is currently generated in the default (= unnamed) package.
2025-12-10 20:54:07 +02:00
Will Lillis
8b8199775f 0.26.x
Also bump the tree-sitter-language crate to 0.1.6
2025-12-09 17:19:25 -05:00
dependabot[bot]
744e556f7e build(deps): bump esbuild
Bumps the npm group with 1 update in the /lib/binding_web directory: [esbuild](https://github.com/evanw/esbuild).


Updates `esbuild` from 0.27.0 to 0.27.1
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.27.0...v0.27.1)

---
updated-dependencies:
- dependency-name: esbuild
  dependency-version: 0.27.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-08 23:43:47 +01:00
Will Lillis
8a3dcc6155 release 0.26.1 2025-12-08 17:05:03 -05:00
dependabot[bot]
b0afbf3762 build(deps): bump wasmparser from 0.242.0 to 0.243.0 in the cargo group
Bumps the cargo group with 1 update: [wasmparser](https://github.com/bytecodealliance/wasm-tools).


Updates `wasmparser` from 0.242.0 to 0.243.0
- [Release notes](https://github.com/bytecodealliance/wasm-tools/releases)
- [Commits](https://github.com/bytecodealliance/wasm-tools/commits)

---
updated-dependencies:
- dependency-name: wasmparser
  dependency-version: 0.243.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: cargo
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-08 22:38:09 +01:00
Will Lillis
974be3bb30 fix(rust): specify workspace dependency of tree-sitter-language crate
as "0.1"

If a rust project depends on both the tree-sitter lib bindings and the
language crate, cargo needs to be able to resolve a common version of
the tree-sitter-language crate. Specifying exactly "0.1.5" for the lib
bindings is overly restrictive, and could lead to future headaches. By
specifying "0.1", any "0.1.x" version should be available to resolve to.
2025-12-08 16:00:57 -05:00
ObserverOfTime
d861e2bcd9 docs(cli): list Java & Zig binding files 2025-12-08 15:47:15 -05:00
ObserverOfTime
b9c2d1dc89 feat(bindings): add Java bindings 2025-12-08 15:47:15 -05:00
ObserverOfTime
8ca17d1bb1 ci(release): enable trusted publishing & attestations 2025-12-08 15:38:21 -05:00
ObserverOfTime
3182efeccc feat(bindings): add byproducts to cmake 2025-12-08 04:35:09 -05:00
Will Lillis
bec7c3272b fix(loader)!: correct arguments passed to select_language 2025-12-07 17:11:28 -05:00
dependabot[bot]
e6bfed33ee build(deps): bump the npm group across 1 directory with 7 updates
Bumps the npm group with 7 updates in the /lib/binding_web directory:

| Package | From | To |
| --- | --- | --- |
| [@eslint/js](https://github.com/eslint/eslint/tree/HEAD/packages/js) | `9.36.0` | `9.39.1` |
| [@types/emscripten](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/emscripten) | `1.41.2` | `1.41.5` |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `24.5.2` | `24.10.1` |
| [esbuild](https://github.com/evanw/esbuild) | `0.25.10` | `0.27.0` |
| [eslint](https://github.com/eslint/eslint) | `9.36.0` | `9.39.1` |
| [tsx](https://github.com/privatenumber/tsx) | `4.20.5` | `4.21.0` |
| [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) | `8.44.1` | `8.48.1` |



Updates `@eslint/js` from 9.36.0 to 9.39.1
- [Release notes](https://github.com/eslint/eslint/releases)
- [Commits](https://github.com/eslint/eslint/commits/v9.39.1/packages/js)

Updates `@types/emscripten` from 1.41.2 to 1.41.5
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/emscripten)

Updates `@types/node` from 24.5.2 to 24.10.1
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `esbuild` from 0.25.10 to 0.27.0
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.25.10...v0.27.0)

Updates `eslint` from 9.36.0 to 9.39.1
- [Release notes](https://github.com/eslint/eslint/releases)
- [Commits](https://github.com/eslint/eslint/compare/v9.36.0...v9.39.1)

Updates `tsx` from 4.20.5 to 4.21.0
- [Release notes](https://github.com/privatenumber/tsx/releases)
- [Changelog](https://github.com/privatenumber/tsx/blob/master/release.config.cjs)
- [Commits](https://github.com/privatenumber/tsx/compare/v4.20.5...v4.21.0)

Updates `typescript-eslint` from 8.44.1 to 8.48.1
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.48.1/packages/typescript-eslint)

---
updated-dependencies:
- dependency-name: "@eslint/js"
  dependency-version: 9.39.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm
- dependency-name: "@types/emscripten"
  dependency-version: 1.41.5
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: "@types/node"
  dependency-version: 24.10.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm
- dependency-name: esbuild
  dependency-version: 0.27.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm
- dependency-name: eslint
  dependency-version: 9.39.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm
- dependency-name: tsx
  dependency-version: 4.21.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm
- dependency-name: typescript-eslint
  dependency-version: 8.48.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-06 13:05:02 +01:00
Christian Clason
053b264502 build(deps): cargo update 2025-12-06 12:53:10 +01:00
dependabot[bot]
a8f25fa441 build(deps): bump glob from 10.4.5 to 10.5.0 in /lib/binding_web
Bumps [glob](https://github.com/isaacs/node-glob) from 10.4.5 to 10.5.0.
- [Changelog](https://github.com/isaacs/node-glob/blob/main/changelog.md)
- [Commits](https://github.com/isaacs/node-glob/compare/v10.4.5...v10.5.0)

---
updated-dependencies:
- dependency-name: glob
  dependency-version: 10.5.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-06 12:21:22 +01:00
dependabot[bot]
f450ce4f6e build(deps): bump vite from 7.1.5 to 7.1.11 in /lib/binding_web
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 7.1.5 to 7.1.11.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v7.1.11/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 7.1.11
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-05 23:59:37 -05:00
dependabot[bot]
3ff8edf9e8 build(deps): bump js-yaml from 4.1.0 to 4.1.1 in /crates/cli/eslint
Bumps [js-yaml](https://github.com/nodeca/js-yaml) from 4.1.0 to 4.1.1.
- [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nodeca/js-yaml/compare/4.1.0...4.1.1)

---
updated-dependencies:
- dependency-name: js-yaml
  dependency-version: 4.1.1
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-05 22:25:23 -05:00
dependabot[bot]
6b6040961c build(deps): bump js-yaml from 4.1.0 to 4.1.1 in /lib/binding_web
Bumps [js-yaml](https://github.com/nodeca/js-yaml) from 4.1.0 to 4.1.1.
- [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nodeca/js-yaml/compare/4.1.0...4.1.1)

---
updated-dependencies:
- dependency-name: js-yaml
  dependency-version: 4.1.1
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-05 22:24:47 -05:00
Will Lillis
888f57657d fix(cli): improve error reporting for invalid range arguments to query
command
2025-12-03 18:06:16 -05:00
Max Brunsfeld
be8fe690d8 Clean up node range tracking in query_cursor__advance 2025-12-03 18:06:16 -05:00
Piotr Osiewicz
c0b1710f8a Add containing range APIs to query cursor
Co-authored-by: Kirill Bulatov <mail4score@gmail.com>
Co-authored-by: Max Brunsfeld <maxbrunsfeld@gmail.com>
Co-authored-by: dino <dinojoaocosta@gmail.com>
Co-authored-by: John Tur <john-tur@outlook.com>
Co-authored-by: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com>
Co-authored-by: dino <dinojoaocosta@gmail.com>
Co-authored-by: Will Lillis <will.lillis24@gmail.com>
2025-12-03 18:06:16 -05:00
Piotr Osiewicz
7d3feeae9a cli: Do not validate UTF-8 boundaries when query results are not being
tested

Co-authored-by: Kirill Bulatov <mail4score@gmail.com>
Co-authored-by: dino <dinojoaocosta@gmail.com>
Co-authored-by: Max Brunsfeld <maxbrunsfeld@gmail.com>
Co-authored-by: John Tur <john-tur@outlook.com>
2025-12-03 18:06:16 -05:00
dependabot[bot]
3f85f65e3f build(deps): bump the cargo group with 2 updates
Bumps the cargo group with 2 updates: [cc](https://github.com/rust-lang/cc-rs) and [wasmparser](https://github.com/bytecodealliance/wasm-tools).


Updates `cc` from 1.2.47 to 1.2.48
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.47...cc-v1.2.48)

Updates `wasmparser` from 0.241.2 to 0.242.0
- [Release notes](https://github.com/bytecodealliance/wasm-tools/releases)
- [Commits](https://github.com/bytecodealliance/wasm-tools/commits)

---
updated-dependencies:
- dependency-name: cc
  dependency-version: 1.2.48
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: wasmparser
  dependency-version: 0.242.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: cargo
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-02 08:10:34 +01:00
WillLillis
df8b62fc50 feat(xtask): bring wasi-sdk treatment up to par with the loader
The loader package's `ensure_wasi_sdk_exists` private method checks for
the wasi-sdk, fetching it if it can't be found. This logic was
re-implemented in xtask for `build-wasm-stdlib`, but without the
fetching functionality. We can have nice things in xtask too! Rather
than make this function a public member of `tree-sitter-loader`, we
just re-implement and leave a nice comment asking people to keep the
two in sync.
2025-11-27 16:06:25 -05:00
ObserverOfTime
14b4708018 fix(loader): write Wasm lib directly to lib dir
Problem: `fs::rename` fails if the parser directory and the Tree-sitter
library directory are on different file systems.

Solution: Write the library file directly to the final directory.
2025-11-25 17:23:44 +01:00
WillLillis
dcef0cc0ee fix(cli): correct query match limit warning condition 2025-11-25 17:23:19 +01:00
WillLillis
c1a0f48781 fix(cli): return error if --wasm flag is passed when the wasm feature
is disabled

This applies to the `parse` and `test` commands, but not `build` as it
doesn't require the wasm feature. Also, hide the `--wasm` options if
from the `--help` output if the feature is disabled.
2025-11-25 17:23:19 +01:00
Antonin Delpeuch
f6d17fdb04 fix(node): bump tree-sitter dep to 0.25 in bindings
Sets the dependency `tree-sitter` to version 0.25 in
the NodeJS bindings generated by default, so that
`npm run test` passes.
2025-11-25 03:32:31 -05:00
Riley Bruins
829733a35e fix(query): prevent infinite loop with + and ? quantifiers
**Problem:** A query with a `?` quantifier followed by a `+` quantifier
would hang at 100% CPU usage while iterating through a tree, regardless
of the source content.

**Solution:** Collect all quantifiers in one step, and then add the
required repeat/optional step logic *after* we have determined the
composite quantifier we need to use for the current step.
2025-11-25 03:21:13 -05:00
Christian Clason
d64b863030 build(deps): bump wasi-sdk to v29 2025-11-25 07:41:04 +01:00
skewb1k
882aa867eb docs: remove manual bindings update steps for scanner
Since 66dab20462, bindings automatically
detect external scanner, making the instructions for manual updating
outdated. Avoids confusion about missing commented lines in Rust
bindings.
2025-11-24 23:00:40 +01:00
dependabot[bot]
de92a9b4c9 build(deps): bump the cargo group with 4 updates
Bumps the cargo group with 4 updates: [cc](https://github.com/rust-lang/cc-rs), [clap](https://github.com/clap-rs/clap), [clap_complete](https://github.com/clap-rs/clap) and [indexmap](https://github.com/indexmap-rs/indexmap).


Updates `cc` from 1.2.46 to 1.2.47
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.46...cc-v1.2.47)

Updates `clap` from 4.5.51 to 4.5.53
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.51...clap_complete-v4.5.53)

Updates `clap_complete` from 4.5.60 to 4.5.61
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.60...clap_complete-v4.5.61)

Updates `indexmap` from 2.12.0 to 2.12.1
- [Changelog](https://github.com/indexmap-rs/indexmap/blob/main/RELEASES.md)
- [Commits](https://github.com/indexmap-rs/indexmap/compare/2.12.0...2.12.1)

---
updated-dependencies:
- dependency-name: cc
  dependency-version: 1.2.47
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: clap
  dependency-version: 4.5.53
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: clap_complete
  dependency-version: 4.5.61
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: indexmap
  dependency-version: 2.12.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-24 22:42:26 +01:00
dependabot[bot]
5880df47e2 ci: bump actions/checkout from 5 to 6 in the actions group
Bumps the actions group with 1 update: [actions/checkout](https://github.com/actions/checkout).


Updates `actions/checkout` from 5 to 6
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-24 22:41:27 +01:00
Will Lillis
e92a7803eb fix(docs): final updates before 0.26.1
- Indicate where xtask looks for wasi-sdk
- Indicate where `build --wasm` looks for and downloads wasi-sdk binary
  to
- Mark native runtime as experimental, describe limitations
- Note ABI 13 support limitations
- Mention that `test --wasm` and `parse --wasm` require
  `--features=wasm` build
2025-11-24 15:18:12 +01:00
Will Lillis
0d656de98b feat(cli): update zig bindings with version command 2025-11-21 19:40:14 -05:00
Amaan Qureshi
b095968dff refactor(cli): clean up version updating code
This commit adds proper error types when updating the version across
files
2025-11-21 19:40:14 -05:00
Will Lillis
d592b16ac0 fix(docs): list dependencies on external tooling for version command 2025-11-21 19:40:14 -05:00
Will Lillis
320c0865e9 feat(cli): don't bail after first version update fails 2025-11-21 19:40:14 -05:00
ObserverOfTime
60635e0729 fix(generate): add node_modules to quickjs resolver 2025-11-21 19:39:53 -05:00
Antonin Delpeuch
120f74723e docs: fix typo in the page about ABI version
Of course I only catch that once they are already published…
2025-11-20 09:58:07 +01:00
Antonin Delpeuch
02508d5570 Apply suggestions from code review
Co-authored-by: Christian Clason <ch.clason+github@icloud.com>
2025-11-20 01:07:58 -05:00
Antonin Delpeuch
42e7e9c3e7 Integrate rewording suggestions 2025-11-20 01:07:58 -05:00
Antonin Delpeuch
55b9a25c84 docs: New page about ABI versions for parser users
Closes #374.

The statement about the intended backwards compatibility is purely
speculative and provided as a "straw man" to help reviewers come up with
a better description of the intended backwards compatibility.
2025-11-20 01:07:58 -05:00
Will Lillis
877782a8a4 fix(docs): update cli docs to reflect changes to various subcommand
arguments
2025-11-19 04:30:01 -05:00
Antonin Delpeuch
0e1f715ef1 Move PathsJSON method, reformat 2025-11-19 03:57:13 -05:00
Antonin Delpeuch
f3012a999d feat(bindings): expose the queries dynamically
Available in the Rust, Python, and Node bindings

Co-authored-by: ObserverOfTime <chronobserver@disroot.org>
2025-11-19 03:57:13 -05:00
dependabot[bot]
3072d35ed5 build(deps): bump the cargo group with 2 updates
Bumps the cargo group with 2 updates: [cc](https://github.com/rust-lang/cc-rs) and [wasmparser](https://github.com/bytecodealliance/wasm-tools).


Updates `cc` from 1.2.45 to 1.2.46
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.45...cc-v1.2.46)

Updates `wasmparser` from 0.240.0 to 0.241.2
- [Release notes](https://github.com/bytecodealliance/wasm-tools/releases)
- [Commits](https://github.com/bytecodealliance/wasm-tools/commits)

---
updated-dependencies:
- dependency-name: cc
  dependency-version: 1.2.46
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: wasmparser
  dependency-version: 0.241.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: cargo
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-17 22:29:19 +01:00
Valeriy Kosikhin
57e3a7b2ca fix(loader): set correct runtime host for cc while cross-compiling
Pass the BUILD_TARGET variable from the build environment as 'host' for
the cc crate. Otherwise, when cross-compiled, cc will keep looking for a
cross-compiler instead of the native one on the target system.

Signed-off-by: Valeriy Kosikhin <vkosikhin@gmail.com>
2025-11-17 18:19:34 +01:00
Christian Clason
0df2916920 bulild(deps): cargo update 2025-11-14 11:28:00 +01:00
WillLillis
61c21aa408 refactor(generate)!: include path when available in IO errors 2025-11-14 11:28:00 +01:00
WillLillis
7eb23d9f3c refactor(config)!: transition from anyhow to thiserror 2025-11-14 11:28:00 +01:00
WillLillis
db2d221ae9 fix(generate): remove leftover imports of anyhow 2025-11-14 11:28:00 +01:00
WillLillis
67cb3cb881 refactor(loader)!: transition from anyhow to thiserror 2025-11-14 11:28:00 +01:00
Marcono1234
12a31536e1 fix(docs): don't show mdbook help popup when using query editor 2025-11-12 23:43:03 -05:00
Will Lillis
7657cc9d35 fix(dsl): add ReservedRule to Rule type definition 2025-11-12 07:27:05 +01:00
dependabot[bot]
13ff3935ac build(deps): bump the cargo group with 3 updates
Bumps the cargo group with 3 updates: [cc](https://github.com/rust-lang/cc-rs), [libloading](https://github.com/nagisa/rust_libloading) and [schemars](https://github.com/GREsau/schemars).


Updates `cc` from 1.2.44 to 1.2.45
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.44...cc-v1.2.45)

Updates `libloading` from 0.8.9 to 0.9.0
- [Commits](https://github.com/nagisa/rust_libloading/compare/0.8.9...0.9.0)

Updates `schemars` from 1.0.4 to 1.0.5
- [Release notes](https://github.com/GREsau/schemars/releases)
- [Changelog](https://github.com/GREsau/schemars/blob/master/CHANGELOG.md)
- [Commits](https://github.com/GREsau/schemars/compare/v1.0.4...v1.0.5)

---
updated-dependencies:
- dependency-name: cc
  dependency-version: 1.2.45
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: libloading
  dependency-version: 0.9.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: cargo
- dependency-name: schemars
  dependency-version: 1.0.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-10 23:04:54 +01:00
Will Lillis
361287fb56 fix(cli)!: deprecate --build flag for generate command 2025-11-07 08:51:24 +01:00
dependabot[bot]
13d4db8bb4 build(deps): bump the cargo group across 1 directory with 6 updates
Bumps the cargo group with 6 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [cc](https://github.com/rust-lang/cc-rs) | `1.2.43` | `1.2.44` |
| [clap](https://github.com/clap-rs/clap) | `4.5.50` | `4.5.51` |
| [clap_complete](https://github.com/clap-rs/clap) | `4.5.59` | `4.5.60` |
| [clap_complete_nushell](https://github.com/clap-rs/clap) | `4.5.9` | `4.5.10` |
| [etcetera](https://github.com/lunacookies/etcetera) | `0.10.0` | `0.11.0` |
| [wasmparser](https://github.com/bytecodealliance/wasm-tools) | `0.229.0` | `0.240.0` |



Updates `cc` from 1.2.43 to 1.2.44
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.43...cc-v1.2.44)

Updates `clap` from 4.5.50 to 4.5.51
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.50...clap_complete-v4.5.51)

Updates `clap_complete` from 4.5.59 to 4.5.60
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.59...clap_complete-v4.5.60)

Updates `clap_complete_nushell` from 4.5.9 to 4.5.10
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete_nushell-v4.5.9...clap_complete_nushell-v4.5.10)

Updates `etcetera` from 0.10.0 to 0.11.0
- [Release notes](https://github.com/lunacookies/etcetera/releases)
- [Commits](https://github.com/lunacookies/etcetera/compare/v0.10.0...v0.11.0)

Updates `wasmparser` from 0.229.0 to 0.240.0
- [Release notes](https://github.com/bytecodealliance/wasm-tools/releases)
- [Commits](https://github.com/bytecodealliance/wasm-tools/commits)

---
updated-dependencies:
- dependency-name: cc
  dependency-version: 1.2.44
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: clap
  dependency-version: 4.5.51
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: clap_complete
  dependency-version: 4.5.60
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: clap_complete_nushell
  dependency-version: 4.5.10
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: etcetera
  dependency-version: 0.11.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: cargo
- dependency-name: wasmparser
  dependency-version: 0.240.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: cargo
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-04 16:08:54 +01:00
Will Lillis
419a5a7305 fix(generate): don't short-circuit within extend_sorted 2025-11-03 01:22:29 -05:00
Will Lillis
c7b5f89392 feat(xtask): generate JSON schema for cli TestSummary 2025-11-02 21:08:55 -05:00
Will Lillis
d546e28abf fix(cli): mark report_states_for_rule and json/json_summary flags
for `generate` command as conflicting
2025-11-02 21:08:55 -05:00
WillLillis
86e2fd2337 fix(cli): correct behavior of parse --stat and --json-summary flags 2025-11-02 21:08:55 -05:00
WillLillis
ff255a2354 test: add coverage for new test aggregation method 2025-11-02 21:08:55 -05:00
WillLillis
fe67521b3d refactor(cli)!: deprecate json flags in favor of json-summary 2025-11-02 21:08:55 -05:00
WillLillis
f02d7e7e33 feat(test): display test results in JSON format 2025-11-02 21:08:55 -05:00
WillLillis
6a8676f335 refactor(test): generalize printing of test diff keys and diffs 2025-11-02 21:08:55 -05:00
WillLillis
944386d25f refactor(test): clean up test filtering logic
Also, only update the expected output of a case when it is skipped if
the `update` flag has been passed
2025-11-02 21:08:55 -05:00
Will Lillis
ef03a3f8fe fix(ci): correct mdbook release url 2025-11-02 18:37:09 -05:00
Christian Clason
18a5243933 ci(docs): pin mdbook to latest release 2025-11-02 18:07:47 -05:00
Christian Clason
8444cc3deb fix(docs): remove multilingual config field
Problem: "deploy docs" always pulls in the `latest` release of `mdbook`,
which now is a v0.5.0 prerelease with breaking changes -- including
removing an (apparently unused) `multilingual` config field in the TOML
that is now an error (another breaking change).

Solution: Delete the line. Add `workflow_dispatch` to the docs workflow
in case follow-up changes are needed; see
https://github.com/rust-lang/mdBook/blob/master/CHANGELOG.md#05-migration-guide
2025-11-02 18:07:47 -05:00
Will Lillis
097c2d4f05 fix(cli): remove --emit=lib generate option
This also replaces the `--emit` option with an `--no-parser` flag. The
default value is false, meaning a parser is still generated by default.
2025-11-02 10:26:28 +01:00
WillLillis
b8f52210f9 perf: reduce needless allocations 2025-10-30 18:24:42 +01:00
WillLillis
ecc787e221 fix(test): correct language typo in test name 2025-10-30 18:24:42 +01:00
Christian Clason
6188010f53 build(deps): bump rquickjs to v0.10.0 2025-10-29 18:30:25 -04:00
Christian Clason
70cde4a110 ci(dependabot): only update patch releases for cargo 2025-10-29 18:30:25 -04:00
Christian Clason
77363a65c2 build(deps): cargo update 2025-10-29 18:30:25 -04:00
dependabot[bot]
605e580063 ci: bump the actions group across 1 directory with 3 updates
Bumps the actions group with 3 updates in the / directory: [actions/upload-artifact](https://github.com/actions/upload-artifact), [actions/download-artifact](https://github.com/actions/download-artifact) and [actions/setup-node](https://github.com/actions/setup-node).


Updates `actions/upload-artifact` from 4 to 5
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4...v5)

Updates `actions/download-artifact` from 5 to 6
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v5...v6)

Updates `actions/setup-node` from 5 to 6
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: actions/download-artifact
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: actions/setup-node
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-28 09:23:50 +01:00
WillLillis
a2f2b16acb fix(xtask): require version argument for bump-version command 2025-10-24 18:13:59 -04:00
Will Lillis
87d778a1c6 fix(rust): apply Self usage in struct definition lint 2025-10-24 17:50:28 -04:00
Will Lillis
e344837e35 fix(rust): minor cleanup in generate code 2025-10-24 17:50:28 -04:00
ObserverOfTime
bdee2c2dd3 ci: use macos-15-intel runner
The macos-13 runner will soon be removed.
2025-10-24 10:14:52 +02:00
dependabot[bot]
da5926d6f5 build(deps): bump the cargo group across 1 directory with 4 updates
Bumps the cargo group with 4 updates in the / directory: [anstyle](https://github.com/rust-cli/anstyle), [cc](https://github.com/rust-lang/cc-rs), [thiserror](https://github.com/dtolnay/thiserror) and [widestring](https://github.com/VoidStarKat/widestring-rs).


Updates `anstyle` from 1.0.11 to 1.0.13
- [Commits](https://github.com/rust-cli/anstyle/compare/v1.0.11...v1.0.13)

Updates `cc` from 1.2.39 to 1.2.41
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.39...cc-v1.2.41)

Updates `thiserror` from 2.0.16 to 2.0.17
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/2.0.16...2.0.17)

Updates `widestring` from 1.2.0 to 1.2.1
- [Release notes](https://github.com/VoidStarKat/widestring-rs/releases)
- [Changelog](https://github.com/VoidStarKat/widestring-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/VoidStarKat/widestring-rs/compare/v1.2.0...v1.2.1)

---
updated-dependencies:
- dependency-name: anstyle
  dependency-version: 1.0.13
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: cc
  dependency-version: 1.2.41
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: thiserror
  dependency-version: 2.0.17
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: widestring
  dependency-version: 1.2.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-14 11:00:03 +02:00
Will Lillis
b3bc7701cd refactor(generate): make AliasMap use BTreeMap over HashMap 2025-10-12 15:56:30 -04:00
Will Lillis
262f1782cc fix(generate): ensure deterministic iteration order for symbol aliases
while constructing node-types.json
2025-10-12 15:56:30 -04:00
WillLillis
00d172bf9f fix(generate): correct display of precedence for
`--report-states-for-rule`
2025-10-12 15:56:12 -04:00
Will Lillis
ae54350c76 fix(generate): Add missing fields to NodeInfoJson sorting
This ensures a deterministic ordering for node-types.json
2025-10-11 14:25:52 -04:00
Will Lillis
3355825a68 fix(cli): don't load languages for build command 2025-10-07 17:21:09 -04:00
ObserverOfTime
7d0e029e37 chore: add schema for node-types.json 2025-10-05 09:57:23 +03:00
Mihai-Daniel Potirniche
0f5ccc4aba Fix typo 2025-10-04 12:12:39 -04:00
ObserverOfTime
0cf6e7c507 fix(cli): prevent crash when parsing stdin
When we are parsing stdin via a pipe or heredoc, the source count is 0
(unsigned) so the XML output crashes while trying to subtract from it.
2025-10-03 19:24:58 +03:00
dependabot[bot]
1dc4804b6e build(deps): bump the cargo group with 2 updates
Bumps the cargo group with 2 updates: [memchr](https://github.com/BurntSushi/memchr) and [regex](https://github.com/rust-lang/regex).


Updates `memchr` from 2.7.5 to 2.7.6
- [Commits](https://github.com/BurntSushi/memchr/compare/2.7.5...2.7.6)

Updates `regex` from 1.11.2 to 1.11.3
- [Release notes](https://github.com/rust-lang/regex/releases)
- [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/regex/compare/1.11.2...1.11.3)

---
updated-dependencies:
- dependency-name: memchr
  dependency-version: 2.7.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: regex
  dependency-version: 1.11.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-01 02:57:21 -04:00
Amaan Qureshi
c5b22a1dc6 ci: split cross compilation and emscripten tag read 2025-10-01 02:57:04 -04:00
Amaan Qureshi
92efd26380 fix(loader): allow parallel compilation on windows 2025-10-01 02:57:04 -04:00
Amaan Qureshi
24c8feba3e fix(bindings): fix root detection on windows 2025-09-28 08:40:02 -04:00
Amaan Qureshi
122493b717 style(cli): appease clippy 2025-09-28 05:54:28 -04:00
Amaan Qureshi
4edcca9850 style(loader): appease clippy 2025-09-28 05:54:28 -04:00
dependabot[bot]
be0c44f871 build(deps): bump the cargo group with 7 updates
Bumps the cargo group with 7 updates:

| Package | From | To |
| --- | --- | --- |
| [anyhow](https://github.com/dtolnay/anyhow) | `1.0.99` | `1.0.100` |
| [cc](https://github.com/rust-lang/cc-rs) | `1.2.37` | `1.2.39` |
| [clap](https://github.com/clap-rs/clap) | `4.5.47` | `4.5.48` |
| [clap_complete](https://github.com/clap-rs/clap) | `4.5.57` | `4.5.58` |
| [indexmap](https://github.com/indexmap-rs/indexmap) | `2.11.1` | `2.11.4` |
| [libloading](https://github.com/nagisa/rust_libloading) | `0.8.8` | `0.8.9` |
| [tempfile](https://github.com/Stebalien/tempfile) | `3.22.0` | `3.23.0` |


Updates `anyhow` from 1.0.99 to 1.0.100
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.99...1.0.100)

Updates `cc` from 1.2.37 to 1.2.39
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.37...cc-v1.2.39)

Updates `clap` from 4.5.47 to 4.5.48
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.47...clap_complete-v4.5.48)

Updates `clap_complete` from 4.5.57 to 4.5.58
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.57...clap_complete-v4.5.58)

Updates `indexmap` from 2.11.1 to 2.11.4
- [Changelog](https://github.com/indexmap-rs/indexmap/blob/main/RELEASES.md)
- [Commits](https://github.com/indexmap-rs/indexmap/compare/2.11.1...2.11.4)

Updates `libloading` from 0.8.8 to 0.8.9
- [Commits](https://github.com/nagisa/rust_libloading/compare/0.8.8...0.8.9)

Updates `tempfile` from 3.22.0 to 3.23.0
- [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stebalien/tempfile/compare/v3.22.0...v3.23.0)

---
updated-dependencies:
- dependency-name: anyhow
  dependency-version: 1.0.100
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: cc
  dependency-version: 1.2.39
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: clap
  dependency-version: 4.5.48
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: clap_complete
  dependency-version: 4.5.58
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: indexmap
  dependency-version: 2.11.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: libloading
  dependency-version: 0.8.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: tempfile
  dependency-version: 3.23.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: cargo
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-28 05:54:28 -04:00
ObserverOfTime
35b1356e96 ci(dependabot): update package.json as well 2025-09-28 04:15:36 -04:00
ObserverOfTime
443acf080a ci(dependabot): enable cooldown period
This setting will delay package updates by 3 days which generally
should be enough time for supply chain attacks to be discovered
2025-09-28 03:58:23 -04:00
Amaan Qureshi
00e394f0f1 feat(lib)!: disallow whitespace in supertype syntax 2025-09-28 00:56:30 -04:00
Amaan Qureshi
341665824c fix(lib): validate subtypes in supertype queries 2025-09-28 00:56:30 -04:00
Amaan Qureshi
bd02be25d5 fix(lib): allow anonymous nodes in the supertype query syntax 2025-09-28 00:56:30 -04:00
WillLillis
12a6400c63 fix(test): trim trailing carriage return unconditionally in test
contents
2025-09-27 19:28:03 -04:00
ObserverOfTime
d86e1b4f5e feat(bindings): generate zig fingerprint 2025-09-26 18:02:35 -04:00
WillLillis
422866a437 fix(docs): update more broken links 2025-09-26 16:10:29 -05:00
Amaan Qureshi
5f7806f99e feat: add option to disable parse state optimizations 2025-09-26 02:40:53 -04:00
WillLillis
a9bce7c18a fix(generate): return error when generated grammar's state count exceeds
the maximum allowed value.

Co-authored-by: Amaan Qureshi <git@amaanq.com>
2025-09-25 22:29:04 -05:00
WillLillis
335bfabc60 feat(cli): include filenames in parsing xml output 2025-09-25 22:28:31 -05:00
Amaan Qureshi
e1b424c191 Revert "0.26.0" 2025-09-24 16:42:01 -04:00
Amaan Qureshi
ea9c318afb docs: update highlight crate link 2025-09-24 16:29:08 -04:00
ObserverOfTime
9d66dbc28f chore: remove CARGO_WORKSPACE_DIR var 2025-09-24 16:14:08 -04:00
Riley Bruins
8c22426223
feat(rust): add new_raw to create a raw, unchecked query pointer 2025-09-23 19:06:22 -04:00
Amaan Qureshi
90ee433c9b fix(lib): account for unreachable patterns with children
Co-authored-by: Will Lillis <will.lillis24@gmail.com>
2025-09-23 17:17:45 -04:00
Amaan Qureshi
f26bd44a43 flake: remove cross, add llvm-cov support 2025-09-23 01:19:14 -04:00
Amaan Qureshi
021d9c447d test: clean up async boundary test 2025-09-23 01:19:14 -04:00
Amaan Qureshi
ce56465197 test(rust): prefer asserts to panics 2025-09-23 01:19:14 -04:00
Amaan Qureshi
b0cdab85fe refactor(rust): avoid panics where possible 2025-09-23 01:19:14 -04:00
Amaan Qureshi
47c9256976 test: clean up parser hang test 2025-09-23 01:19:14 -04:00
dependabot[bot]
cf89840460 build(deps): bump the npm group across 1 directory with 6 updates
Bumps the npm group with 6 updates in the /lib/binding_web directory:

| Package | From | To |
| --- | --- | --- |
| [@eslint/js](https://github.com/eslint/eslint/tree/HEAD/packages/js) | `9.35.0` | `9.36.0` |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `24.5.0` | `24.5.2` |
| [esbuild](https://github.com/evanw/esbuild) | `0.25.9` | `0.25.10` |
| [eslint](https://github.com/eslint/eslint) | `9.35.0` | `9.36.0` |
| [typescript](https://github.com/microsoft/TypeScript) | `5.8.3` | `5.9.2` |
| [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) | `8.44.0` | `8.44.1` |



Updates `@eslint/js` from 9.35.0 to 9.36.0
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/commits/v9.36.0/packages/js)

Updates `@types/node` from 24.5.0 to 24.5.2
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `esbuild` from 0.25.9 to 0.25.10
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.25.9...v0.25.10)

Updates `eslint` from 9.35.0 to 9.36.0
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v9.35.0...v9.36.0)

Updates `typescript` from 5.8.3 to 5.9.2
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release-publish.yml)
- [Commits](https://github.com/microsoft/TypeScript/compare/v5.8.3...v5.9.2)

Updates `typescript-eslint` from 8.44.0 to 8.44.1
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.44.1/packages/typescript-eslint)

---
updated-dependencies:
- dependency-name: "@eslint/js"
  dependency-version: 9.36.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm
- dependency-name: "@types/node"
  dependency-version: 24.5.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: esbuild
  dependency-version: 0.25.10
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: eslint
  dependency-version: 9.36.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm
- dependency-name: typescript
  dependency-version: 5.9.2
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm
- dependency-name: typescript-eslint
  dependency-version: 8.44.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-22 21:49:46 -04:00
Max Brunsfeld
e3294c3faf
build: bump tree-sitter-language to 0.1.5 2025-09-22 15:54:15 -04:00
Amaan Qureshi
95ab17e444 build: define _DARWIN_C_SOURCE 2025-09-22 19:50:43 +03:00
Max Brunsfeld
9b914885f1
Fix issues preventing releases from successfully publishing (#4867)
* Correct the path to the CLI npm package in release job

* Specify a version for tree-sitter-language

* Fix path to README in doc include
2025-09-22 09:24:30 -07:00
WillLillis
92678f0fc5 fix(rust): pass correct fd to C lib's ts_tree_print_dot_graph
Co-authored-by: Amaan Qureshi <git@amaanq.com>
2025-09-21 18:21:57 -04:00
ObserverOfTime
a1640e4fe4 chore: rebuild wasm stdlib 2025-09-21 16:28:08 -04:00
ObserverOfTime
1be51c2129 chore: upgrade emscripten to 4.0.15 2025-09-21 16:28:08 -04:00
Will Lillis
6214f95e7e
docs: correct new generate flag: "stage"->"emit" 2025-09-21 15:22:11 -04:00
Amaan Qureshi
c89e40f008 fix(generate): fix builds outside of crate workspace 2025-09-21 02:34:10 -04:00
Antonin Delpeuch
8873c1aeff docs: update options for generate command 2025-09-21 01:53:40 -04:00
Amaan Qureshi
d543e2e50b refactor(loader): use the logger 2025-09-21 01:53:22 -04:00
Amaan Qureshi
e5c11d9efc refactor(config): use the logger 2025-09-21 01:53:22 -04:00
ObserverOfTime
d13657c40c refactor(generate): use the logger
Co-authored-by: Amaan Qureshi <git@amaanq.com>
2025-09-21 01:53:22 -04:00
ObserverOfTime
804ef22075 refactor(cli): use the logger
Co-authored-by: Amaan Qureshi <git@amaanq.com>
2025-09-21 01:53:22 -04:00
Amaan Qureshi
fa28b430af feat(bindings): update Zig bindings to use Language.fromRaw 2025-09-21 01:42:26 -04:00
Amaan Qureshi
311585d304 refactor!: rename stage flag to emit 2025-09-20 22:35:23 -04:00
ObserverOfTime
60c3bed6a4 fix(loader): install arm64 wasi-sdk on arm64 windows 2025-09-20 18:11:48 -04:00
ObserverOfTime
6dfa79013f feat(loader): respect NM env var 2025-09-20 18:08:07 -04:00
ObserverOfTime
79ef484392 ci: cross-compile without cross-rs 2025-09-20 18:08:07 -04:00
Amaan Qureshi
0ca8fe8c12 feat(playground): add export flag 2025-09-19 17:55:28 -04:00
John-Philip Taylor
552ab537e8
docs(cli): add docs on new version features 2025-09-19 17:52:08 -04:00
Amaan Qureshi
0cf217179c feat(rust): add reborrow method to ParseOptions 2025-09-19 17:40:35 -04:00
Amaan Qureshi
48a5077035 feat(web)!: add API for editing points and ranges 2025-09-19 17:40:26 -04:00
Amaan Qureshi
a69367f739 feat: add API for editing points and ranges 2025-09-19 17:40:26 -04:00
Will Lillis
1a0868c487 build: add static and shared targets to Makefile 2025-09-19 17:06:27 -04:00
Max Brunsfeld
9be3e2bdd8 0.26.0 2025-09-19 08:14:00 -07:00
Amaan Qureshi
074e991280 refactor: deduplicate allocation code in tests 2025-09-18 20:29:54 -04:00
Nia
f09dc3cf46
fix(wasm): fix alias map size computation
This fixes a crash where parsing with certain languages can lead to a crash due to how the alias map was allocated and laid out in wasm memory
2025-09-18 18:34:27 -04:00
ObserverOfTime
f222db57ce fix(bindings): fix ESM errors in Node bindings
1. The module tries to call the native binary as a function.

Only `node-gyp-build` returns a function, so the call is moved there.

2. `node-types.json` is imported with outdated syntax.

Use import attributes which require Node 18.

3. The test does not properly catch import errors.

This is solved by moving the import inside the assertion.
2025-09-18 16:59:34 -04:00
Amaan Qureshi
d29132512b ci: build wasm32 2025-09-17 04:57:49 -04:00
Amaan Qureshi
22553b3372 feat: support compiling to wasm32-unknown-unknown 2025-09-17 04:57:49 -04:00
Will Lillis
46ea65c89b refactor: remove url dependency 2025-09-17 04:31:53 -04:00
Will Lillis
6a28a62369 test: add safety checks to ensure langauge version constants are kept in
sync

The generate crate defines the `LANGUAGE_VERSION` constant separately
from the TREE_SITTER_LANGUAGE_VERSION definition in `api.h`.
2025-09-17 02:58:31 -04:00
Amaan Qureshi
db0d05fab3 ci: fix cache paths 2025-09-17 02:19:29 -04:00
Amaan Qureshi
317e2e74c2 Revert "feat(generate): allow more characters for keywords"
This reverts commit 0269357c5a.
2025-09-17 02:19:29 -04:00
Amaan Qureshi
04cfee5664 build(rust): remove unused dependencies 2025-09-16 18:57:06 -04:00
Amaan Qureshi
57c6105897 fix(generate): remove warning message for CJS grammars 2025-09-16 16:42:17 -04:00
Christian Clason
339bad2de4 feat(generate): don't embed tree-sitter CLI version in parser
Problem: embedding the CLI version used to generate a parser triggers CI
failures on all grammars for every (patch) release of tree-sitter, even
if there are no actual parser changes.

Solution: do not embed the version; instead rely on whether the update
introduces actual (presumably desirable) changes in the parser to
indicate regeneration is necessary.
2025-09-16 19:21:34 +02:00
Will Lillis
31ff62445b fix(generate): assert there is a Nfa last state before retrieving it
Prevents unsigned subtraction wrapping antics in release builds
2025-09-16 03:51:13 -04:00
Will Lillis
c54bc441ba fix(test): include failing test's path in error message
This helps when an empty folder was left behind in the corpus directory
2025-09-16 03:51:13 -04:00
Will Lillis
070b91628f fix(rust): appease clippy 2025-09-16 03:51:13 -04:00
bbb651
9593737871 build(generate): remove tree-sitter dependency
It was only used to share two constants, and balloons its dependencies.

This also makes `generate_parser_for_grammar` work in wasm.
(Tested in `wasm32-wasip2` in wasmtime with the json grammar,
`wasm32-unknown-unknown` running in the same setup exited successfully
so I'm pretty confident it works as well)

Co-authored-by: Amaan Qureshi <contact@amaanq.com>
2025-09-16 03:48:30 -04:00
Amaan Qureshi
0269357c5a feat(generate): allow more characters for keywords 2025-09-16 03:01:56 -04:00
Amaan Qureshi
fd68c02072 fix(init): add missing quote in replacement 2025-09-16 02:24:11 -04:00
Amaan Qureshi
39a67eec61 feat: migrate to ESM 2025-09-16 02:24:11 -04:00
Amaan Qureshi
67f50b85f5 docs: document the native js runtime 2025-09-16 02:24:11 -04:00
Amaan Qureshi
eedbec8f24 feat: remove the need of an external JS runtime for processing grammars 2025-09-16 02:24:11 -04:00
dependabot[bot]
7ba7c4a8ce build(deps): bump the cargo group with 7 updates
Bumps the cargo group with 7 updates:

| Package | From | To |
| --- | --- | --- |
| [cc](https://github.com/rust-lang/cc-rs) | `1.2.36` | `1.2.37` |
| [indexmap](https://github.com/indexmap-rs/indexmap) | `2.11.0` | `2.11.1` |
| [semver](https://github.com/dtolnay/semver) | `1.0.26` | `1.0.27` |
| [serde](https://github.com/serde-rs/serde) | `1.0.219` | `1.0.224` |
| [serde_derive](https://github.com/serde-rs/serde) | `1.0.219` | `1.0.224` |
| [serde_json](https://github.com/serde-rs/json) | `1.0.143` | `1.0.145` |
| [tempfile](https://github.com/Stebalien/tempfile) | `3.21.0` | `3.22.0` |


Updates `cc` from 1.2.36 to 1.2.37
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.36...cc-v1.2.37)

Updates `indexmap` from 2.11.0 to 2.11.1
- [Changelog](https://github.com/indexmap-rs/indexmap/blob/main/RELEASES.md)
- [Commits](https://github.com/indexmap-rs/indexmap/compare/2.11.0...2.11.1)

Updates `semver` from 1.0.26 to 1.0.27
- [Release notes](https://github.com/dtolnay/semver/releases)
- [Commits](https://github.com/dtolnay/semver/compare/1.0.26...1.0.27)

Updates `serde` from 1.0.219 to 1.0.224
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.219...v1.0.224)

Updates `serde_derive` from 1.0.219 to 1.0.224
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.219...v1.0.224)

Updates `serde_json` from 1.0.143 to 1.0.145
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.143...v1.0.145)

Updates `tempfile` from 3.21.0 to 3.22.0
- [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stebalien/tempfile/compare/v3.21.0...v3.22.0)

---
updated-dependencies:
- dependency-name: cc
  dependency-version: 1.2.37
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: indexmap
  dependency-version: 2.11.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: semver
  dependency-version: 1.0.27
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: serde
  dependency-version: 1.0.224
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: serde_derive
  dependency-version: 1.0.224
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: serde_json
  dependency-version: 1.0.145
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: tempfile
  dependency-version: 3.22.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: cargo
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-15 19:32:27 -04:00
dependabot[bot]
b6f45b0a2e build(deps): bump the npm group across 1 directory with 4 updates
Bumps the npm group with 4 updates in the /lib/binding_web directory: [@types/emscripten](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/emscripten), [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node), [typescript](https://github.com/microsoft/TypeScript) and [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint).


Updates `@types/emscripten` from 1.41.1 to 1.41.2
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/emscripten)

Updates `@types/node` from 24.3.1 to 24.5.0
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `typescript` from 5.8.3 to 5.9.2
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release-publish.yml)
- [Commits](https://github.com/microsoft/TypeScript/compare/v5.8.3...v5.9.2)

Updates `typescript-eslint` from 8.43.0 to 8.44.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.44.0/packages/typescript-eslint)

---
updated-dependencies:
- dependency-name: "@types/emscripten"
  dependency-version: 1.41.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: "@types/node"
  dependency-version: 24.5.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm
- dependency-name: typescript
  dependency-version: 5.9.2
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm
- dependency-name: typescript-eslint
  dependency-version: 8.44.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-15 19:32:20 -04:00
ObserverOfTime
3d26b8e500 feat(bindings): use CapsuleType in Python stub 2025-09-14 19:00:25 -04:00
Amaan Qureshi
46f7f860e6 docs: correct explanation about @ignore capture 2025-09-14 16:45:39 -04:00
Amaan Qureshi
2ae677162f docs: clarify that only the whitespace character class is simplfied 2025-09-14 16:45:39 -04:00
Amaan Qureshi
4dbfb5b49a docs: document the @ignore capture in tags 2025-09-14 06:27:27 -04:00
Amaan Qureshi
3a911d578c docs: add more information on supertype nodes for grammars and queries 2025-09-14 06:25:35 -04:00
Amaan Qureshi
63f48afaeb docs: explain extras in a bit more detail 2025-09-14 06:02:00 -04:00
Will Lillis
ac39aed7c5 fix(lib/wasm): return NULL for 0-sized allocations
Co-authored-by: Amaan Qureshi <contact@amaanq.com>
2025-09-13 22:29:47 -04:00
Amaan Qureshi
c4d02a5254 build(lib): regenerate wasm stdlib
Co-authored-by: Will Lillis <will.lillis24@gmail.com>
2025-09-13 22:29:47 -04:00
Amaan Qureshi
69c42450c3 fix(lib/wasm): keep track of freed blocks that are not the last allocated pointer
This fixes issues where the scanner allocates and frees a lot of data
during a single parse.

Co-authored-by: Will Lillis <will.lillis24@gmail.com>
2025-09-13 22:29:47 -04:00
Amaan Qureshi
b863b16454 fix(xtask): make building the wasm stdlib work again
Co-authored-by: Will Lillis <will.lillis24@gmail.com>
2025-09-13 22:29:47 -04:00
Will Lillis
0c35511aea fix(lib): improve wasm scanner serialization error handling
Co-authored-by: Amaan Qureshi <contact@amaanq.com>
2025-09-13 22:29:47 -04:00
Amaan Qureshi
06741d0d5d fix(playground): check that languageVersion exists for compat 2025-09-13 22:12:11 -04:00
RedCMD
ca8b944b53
build(web): fix cjs build 2025-09-13 05:51:42 -04:00
Amaan Qureshi
580cd9541a feat(web)!: remove deprecated functions 2025-09-12 02:50:30 -04:00
Amaan Qureshi
d60ef9ad0a feat(rust)!: remove deprecated functions 2025-09-12 02:50:30 -04:00
Amaan Qureshi
821cf797f2 feat(lib)!: remove deprecated functions 2025-09-12 02:50:30 -04:00
Amaan Qureshi
917895e6a3 build(nix): build cli with all features 2025-09-11 19:33:52 -04:00
Antonin Delpeuch
6e53dcc8e1
fix(playground): add missing <html> tag 2025-09-11 17:06:34 -04:00
ObserverOfTime
56325d2a3b chore: copy license to all packages 2025-09-11 03:12:35 -04:00
kilo52
d1160cb820 build(cmake)!: move CMakeLists.txt to the source root 2025-09-11 01:59:37 -04:00
kilo52
5528cfee17 build(cmake): change include directory scope to public
When a project adds tree-sitter as a dependency via the CMake
FetchContent machinery, the project fails to build because the
tree-sitter header cannot be found. This is because the include
directory is specified with the private scope instead of public.
2025-09-11 01:59:37 -04:00
Daniel Müller
937dcf5fd1 feat(rust)!: use ops::ControlFlow as parse and query progress return value
Instead of returning an undocumented boolean flag, use a
core::ops::ControlFlow object. At the expense of being a bit more
verbose, this is a type that should be self-explanatory in the context
of a callback, as an indication of whether to continue processing or
stop.
2025-09-11 01:59:21 -04:00
dependabot[bot]
57e2f41f42 build(deps): bump vite from 7.1.3 to 7.1.5 in /lib/binding_web
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 7.1.3 to 7.1.5.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v7.1.5/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 7.1.5
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-10 23:27:36 -04:00
Amaan Qureshi
3c1f02a7f9 docs(playground): show toast when tree is copied 2025-09-09 03:13:35 -04:00
Amaan Qureshi
907c7bc80b docs(playground): add version information in playground
Co-authored-by: Will Lillis <will.lillis24@gmail.com>
2025-09-09 03:13:35 -04:00
Amaan Qureshi
40a8678989 refactor(xtask): don't use docker to run wasi-sdk's clang
This now relies on TREE_SITTER_WASI_SDK_PATH being set
2025-09-09 03:13:35 -04:00
Amaan Qureshi
6451d2f65d fix(web): correct metadata function 2025-09-09 03:13:35 -04:00
faukah
e4e643086b
refactor: rework nix flake
Co-authored-by: Amaan Qureshi <amaanq12@gmail.com>
2025-09-09 03:03:35 -04:00
Amaan Qureshi
e9e4316569 feat(xtask): update nix 2025-09-09 04:45:57 +02:00
Amaan Qureshi
0719bd6ffb feat(xtask): bump versions in package-lock.json 2025-09-09 04:45:57 +02:00
Amaan Qureshi
8d6d19de1b build: add package-lock.json for npm cli package 2025-09-09 04:45:57 +02:00
dependabot[bot]
16502e19dd build(deps): bump the npm group across 1 directory with 6 updates
Bumps the npm group with 6 updates in the /lib/binding_web directory:

| Package | From | To |
| --- | --- | --- |
| [@eslint/js](https://github.com/eslint/eslint/tree/HEAD/packages/js) | `9.34.0` | `9.35.0` |
| [@types/emscripten](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/emscripten) | `1.40.0` | `1.41.1` |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `24.3.0` | `24.3.1` |
| [eslint](https://github.com/eslint/eslint) | `9.34.0` | `9.35.0` |
| [typescript](https://github.com/microsoft/TypeScript) | `5.8.3` | `5.9.2` |
| [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) | `8.41.0` | `8.43.0` |



Updates `@eslint/js` from 9.34.0 to 9.35.0
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/commits/v9.35.0/packages/js)

Updates `@types/emscripten` from 1.40.0 to 1.41.1
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/emscripten)

Updates `@types/node` from 24.3.0 to 24.3.1
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `eslint` from 9.34.0 to 9.35.0
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v9.34.0...v9.35.0)

Updates `typescript` from 5.8.3 to 5.9.2
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release-publish.yml)
- [Commits](https://github.com/microsoft/TypeScript/compare/v5.8.3...v5.9.2)

Updates `typescript-eslint` from 8.41.0 to 8.43.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.43.0/packages/typescript-eslint)

---
updated-dependencies:
- dependency-name: "@eslint/js"
  dependency-version: 9.35.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm
- dependency-name: "@types/emscripten"
  dependency-version: 1.41.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm
- dependency-name: "@types/node"
  dependency-version: 24.3.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: eslint
  dependency-version: 9.35.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm
- dependency-name: typescript
  dependency-version: 5.9.2
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm
- dependency-name: typescript-eslint
  dependency-version: 8.43.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-09 04:33:49 +02:00
dependabot[bot]
6b2ed39df6 ci: bump the actions group with 2 updates
Bumps the actions group with 2 updates: [actions/setup-node](https://github.com/actions/setup-node) and [actions/github-script](https://github.com/actions/github-script).


Updates `actions/setup-node` from 4 to 5
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v4...v5)

Updates `actions/github-script` from 7 to 8
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](https://github.com/actions/github-script/compare/v7...v8)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: actions/github-script
  dependency-version: '8'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-09 04:33:22 +02:00
dependabot[bot]
d517af4c1a build(deps): bump the cargo group with 3 updates
Bumps the cargo group with 3 updates: [cc](https://github.com/rust-lang/cc-rs), [ctrlc](https://github.com/Detegr/rust-ctrlc) and [log](https://github.com/rust-lang/log).


Updates `cc` from 1.2.35 to 1.2.36
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.35...cc-v1.2.36)

Updates `ctrlc` from 3.4.7 to 3.5.0
- [Release notes](https://github.com/Detegr/rust-ctrlc/releases)
- [Commits](https://github.com/Detegr/rust-ctrlc/commits)

Updates `log` from 0.4.27 to 0.4.28
- [Release notes](https://github.com/rust-lang/log/releases)
- [Changelog](https://github.com/rust-lang/log/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/log/compare/0.4.27...0.4.28)

---
updated-dependencies:
- dependency-name: cc
  dependency-version: 1.2.36
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: ctrlc
  dependency-version: 3.5.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: cargo
- dependency-name: log
  dependency-version: 0.4.28
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-09 04:33:02 +02:00
Shadaj Laddad
27e5147a5f feat(generate): place file APIs behind a feature flag 2025-09-07 11:44:09 +03:00
Amaan Qureshi
e659dddad1 build(nix): add cross and typescript to dev shell 2025-09-04 05:00:14 -04:00
Amaan Qureshi
643f532a70 chore: update flake 2025-09-04 05:00:14 -04:00
Amaan Qureshi
86d86628cb build(nix): use fenix for rust toolchain
This plays more nicely with cross for local testing
2025-09-04 05:00:14 -04:00
Amaan Qureshi
17854168d9 feat(nix): add cross compilation support 2025-09-04 05:00:14 -04:00
Amaan Qureshi
d287acfcc0 refactor(nix): remove openssl dependency 2025-09-04 05:00:14 -04:00
Amaan Qureshi
595299a3c2 ci: remove separate step for generate fixtures 2025-09-04 04:22:32 -04:00
Amaan Qureshi
3eabba637c fix(xtask): run all tests with the --all flag 2025-09-04 04:22:32 -04:00
Amaan Qureshi
cd12e66e67 fix(lib): don't run code snippet as a doctest 2025-09-04 04:22:32 -04:00
Amaan Qureshi
1d0ebd1065 fix(rust): do not interpret readme doc comments as doc tests 2025-09-04 04:22:32 -04:00
Will Lillis
5fd818babe fix(generate): use correct state id when adding terminal states to
non terminal extras
2025-09-04 04:15:51 -04:00
Amaan Qureshi
968d39328d ci: switch to arm runner 2025-09-04 01:47:26 -04:00
Will Lillis
310c0b86a7 fix(generate): return error when single state transitions have
indirectly recursive cycles.

This can cause infinite loops in the parser near EOF.

Co-authored-by: Amaan Qureshi <amaanq12@gmail.com>
2025-09-04 00:59:44 -04:00
Will Lillis
cc5463ad44 fix(test): improve readability of corpus error message mismatch 2025-09-04 00:59:44 -04:00
Amaan Qureshi
f95a52df4a fix(xtask): reset fixtures when checking out new version 2025-09-04 00:59:01 -04:00
Amaan Qureshi
3b0273fc61 build: bump emscripten to 4.0.12 2025-09-04 00:59:01 -04:00
Amaan Qureshi
6cb9486b28 test(fixtures): bump javascript grammar to 0.25.0 2025-09-04 00:59:01 -04:00
Amaan Qureshi
f44cbd407f perf(xtask); check out the tag directly for fixtures 2025-09-03 02:43:32 -04:00
Amaan Qureshi
0b836b2de0 ci: use armv7hf 2025-09-02 16:07:37 -04:00
Amaan Qureshi
151130a5df ci: pass in matrix target to xtask commands 2025-09-02 16:07:37 -04:00
Amaan Qureshi
4559ec51f7 fix(loader): correct logic when downloading wasi-sdk 2025-09-02 16:07:37 -04:00
Amaan Qureshi
5cd6e747a0 refactor(xtask): use the git binary to perform git operations 2025-09-02 16:07:37 -04:00
Amaan Qureshi
5263cd0706 refactor(loader): use the tar binary to extract the wasi sdk 2025-09-02 16:07:37 -04:00
Amaan Qureshi
4535ea6aaa refactor(loader): use the curl binary instead of ureq to download wasi-sdk 2025-09-02 16:07:37 -04:00
ObserverOfTime
6e8ad7e5cc fix(xtask): update paths in bump-version
and remove the toml dependency
2025-09-02 14:22:01 -04:00
Amaan Qureshi
22d658518b feat(loader): allow specifying the wasi sdk path 2025-09-01 23:14:20 -04:00
Amaan Qureshi
f0cfaffd5e build(web): mark @types/emscripten as a dev dep 2025-09-01 23:14:20 -04:00
Amaan Qureshi
94996b26e5 refactor(web): clean up preserving sourcemap logic, don't copy lib files 2025-09-01 23:14:20 -04:00
Amaan Qureshi
f2e71ec95c fix(xtask): restore stripped sourcesContent when building the wasm module 2025-09-01 23:14:20 -04:00
Amaan Qureshi
da61d7cac5 feat: add nix flake 2025-09-01 22:48:37 -04:00
Boris Verkhovskiy
9b23cd5394
feat: use compileStreaming when loading wasm parsers 2025-09-01 22:08:20 -04:00
ObserverOfTime
b75196bb81 feat(c): rename DecodeFunction to TSDecodeFunction
Keep a typedef for backwards compatibility until ABI 16.
2025-09-01 03:17:44 -04:00
ObserverOfTime
dbe88f8bbb fixup: remove permission check 2025-09-01 07:35:40 +03:00
ObserverOfTime
f9a331a505 ci(spam): fix permission check 2025-09-01 07:35:40 +03:00
ObserverOfTime
47beafb836 fix(playground): account for missing button 2025-08-31 14:08:06 -04:00
Will Lillis
a12a79b366 fix(cli): canonicalize --lib-path arguments
This fixes an issue where "./foo.so" would would work but "foo.so" would not.
2025-08-31 01:10:43 -04:00
Will Lillis
62f93e221d feat(test): pin fixture grammars to specific commits 2025-08-31 01:05:42 -04:00
ObserverOfTime
07986471b3 feat(xtask): automate edits to emscripten generated d.ts 2025-08-30 18:14:42 -04:00
ObserverOfTime
dba8446d9e feat(web)!: use bigint for timeouts 2025-08-30 18:14:42 -04:00
ObserverOfTime
0c5cdcb161 fix(xtask): add heap symbols to emscripten exported methods 2025-08-30 18:14:42 -04:00
ObserverOfTime
8b3e023ef0 chore(web): remove source files from package
and generated files from version control
2025-08-30 18:14:42 -04:00
dependabot[bot]
a0fd1ded97 build(deps): bump wasmparser from 0.224.1 to 0.229.0 in the cargo group
Bumps the cargo group with 1 update: [wasmparser](https://github.com/bytecodealliance/wasm-tools).


Updates `wasmparser` from 0.224.1 to 0.229.0
- [Release notes](https://github.com/bytecodealliance/wasm-tools/releases)
- [Commits](https://github.com/bytecodealliance/wasm-tools/commits)

---
updated-dependencies:
- dependency-name: wasmparser
  dependency-version: 0.229.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: cargo
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-30 18:13:55 -04:00
ObserverOfTime
5272b6b908 refactor(web): use nullish coalescing operator 2025-08-30 18:13:39 -04:00
dependabot[bot]
a866eb5dd0 build(deps): bump the npm group across 1 directory with 9 updates
Bumps the npm group with 8 updates in the /lib/binding_web directory:

| Package | From | To |
| --- | --- | --- |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `22.13.1` | `24.3.0` |
| [@vitest/coverage-v8](https://github.com/vitest-dev/vitest/tree/HEAD/packages/coverage-v8) | `3.0.5` | `3.2.4` |
| [dts-buddy](https://github.com/Rich-Harris/dts-buddy) | `0.5.4` | `0.6.2` |
| [esbuild](https://github.com/evanw/esbuild) | `0.25.0` | `0.25.9` |
| [source-map](https://github.com/mozilla/source-map) | `0.7.4` | `0.7.6` |
| [tsx](https://github.com/privatenumber/tsx) | `4.20.3` | `4.20.5` |
| [typescript](https://github.com/microsoft/TypeScript) | `5.7.3` | `5.9.2` |
| [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) | `8.23.0` | `8.41.0` |



Updates `@types/node` from 22.13.1 to 24.3.0
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `@vitest/coverage-v8` from 3.0.5 to 3.2.4
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Commits](https://github.com/vitest-dev/vitest/commits/v3.2.4/packages/coverage-v8)

Updates `dts-buddy` from 0.5.4 to 0.6.2
- [Release notes](https://github.com/Rich-Harris/dts-buddy/releases)
- [Changelog](https://github.com/sveltejs/dts-buddy/blob/main/CHANGELOG.md)
- [Commits](https://github.com/Rich-Harris/dts-buddy/compare/v0.5.4...v0.6.2)

Updates `esbuild` from 0.25.0 to 0.25.9
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.25.0...v0.25.9)

Updates `source-map` from 0.7.4 to 0.7.6
- [Release notes](https://github.com/mozilla/source-map/releases)
- [Changelog](https://github.com/mozilla/source-map/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mozilla/source-map/compare/v0.7.4...0.7.6)

Updates `tsx` from 4.20.3 to 4.20.5
- [Release notes](https://github.com/privatenumber/tsx/releases)
- [Changelog](https://github.com/privatenumber/tsx/blob/master/release.config.cjs)
- [Commits](https://github.com/privatenumber/tsx/compare/v4.20.3...v4.20.5)

Updates `typescript` from 5.7.3 to 5.9.2
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release-publish.yml)
- [Commits](https://github.com/microsoft/TypeScript/compare/v5.7.3...v5.9.2)

Updates `typescript-eslint` from 8.23.0 to 8.41.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.41.0/packages/typescript-eslint)

Updates `vitest` from 3.0.5 to 3.2.4
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Commits](https://github.com/vitest-dev/vitest/commits/v3.2.4/packages/vitest)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 24.3.0
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: npm
- dependency-name: "@vitest/coverage-v8"
  dependency-version: 3.2.4
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm
- dependency-name: dts-buddy
  dependency-version: 0.6.2
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm
- dependency-name: esbuild
  dependency-version: 0.25.9
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: source-map
  dependency-version: 0.7.6
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: tsx
  dependency-version: 4.20.5
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: typescript
  dependency-version: 5.9.2
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm
- dependency-name: typescript-eslint
  dependency-version: 8.41.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm
- dependency-name: vitest
  dependency-version: 3.2.4
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-30 18:13:39 -04:00
ObserverOfTime
90bdd63a71 fix(npm): add directory to repository fields
and remove non-existent "main" entry point
2025-08-30 17:16:25 -04:00
ObserverOfTime
ed2abf8609 ci(dependabot): update npm dependencies 2025-08-30 17:08:46 -04:00
ObserverOfTime
d188bf6352 chore: remove emscripten xtask & workflow 2025-08-30 16:52:22 -04:00
vemoo
4db3edadf4
fix(web): correct type errors, improve build 2025-08-30 16:51:41 -04:00
ObserverOfTime
ca27fb5d43 fix(cli): fix DSL type declarations 2025-08-30 16:47:47 -04:00
ObserverOfTime
e6fe91e2e7 build(zig): support wasmtime in more archs 2025-08-30 16:47:47 +03:00
ObserverOfTime
b57b7213a9 fix(rust): make some methods const
Addresses clippy::missing-const-for-fn
2025-08-30 16:47:47 +03:00
ObserverOfTime
ed91767663 build(rust)!: bump MSRV to 1.84.0
Required by wasmtime
2025-08-30 16:47:47 +03:00
ObserverOfTime
489ad07e8b build(deps): bump wasmtime-c-api to v33.0.2 2025-08-30 16:47:47 +03:00
ObserverOfTime
88e323ca43 fix(xtask): commit Cargo.lock in upgrade_wasmtime
And add missing zig dependency update
2025-08-30 16:47:47 +03:00
RedCMD
721b0e8b11
fix(web): update .d.ts files 2025-08-29 21:39:53 -04:00
Will Lillis
ac171eb280 fix(generate): warn users when extra rule can lead to parser hang
When a *named* rule in the extras is able to match the empty string,
parsing can hang in certain situations (i.e. near EOF).
2025-08-29 21:38:41 -04:00
Boris Verkhovskiy
a1211d3fbd
feat(web): inline C source code in source map 2025-08-29 14:26:27 -04:00
ObserverOfTime
0be215e152 fix(bindings): properly detect MSVC compiler 2025-08-29 13:32:55 +03:00
ObserverOfTime
c12b4a1565 ci: add a spam closing workflow 2025-08-29 13:26:53 +03:00
WillLillis
34ef1157a6 feat(ci): build libraries on windows x64 with mingw 2025-08-28 21:28:48 -04:00
ObserverOfTime
e0edfe1cb3 build(zig): support wasmtime for ARM64 Windows (MSVC) 2025-08-29 01:12:46 +03:00
Amaan Qureshi
8387101a61 fix(lib): allow error nodes to match when they are child nodes 2025-08-28 18:02:47 -04:00
dependabot[bot]
9fdf7213d4 ci: bump actions/upload-pages-artifact from 3 to 4 in the actions group
Bumps the actions group with 1 update: [actions/upload-pages-artifact](https://github.com/actions/upload-pages-artifact).


Updates `actions/upload-pages-artifact` from 3 to 4
- [Release notes](https://github.com/actions/upload-pages-artifact/releases)
- [Commits](https://github.com/actions/upload-pages-artifact/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/upload-pages-artifact
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-28 17:15:24 -04:00
Amaan Qureshi
b7f36a13ba fix(lib): check if an ERROR node is named before assuming it's the builtin error node 2025-08-28 17:13:57 -04:00
ObserverOfTime
66ea1a6dda style(zig): reformat files 2025-08-28 20:54:25 +03:00
ObserverOfTime
298b6775c6 build(zig): use ArrayListUnmanaged
This is supported in 0.14 and 0.15
2025-08-28 20:54:25 +03:00
ObserverOfTime
2e4b7d26b1 build(zig): don't link wasmtime in static build 2025-08-28 20:54:25 +03:00
ObserverOfTime
dab84a1b10 build(zig): expose wasmtimeDep function
This allows consumers to reuse the dependency.
2025-08-28 20:54:25 +03:00
Will Lillis
340df02655
docs: clarify definition of newline 2025-08-28 13:31:25 -04:00
Amaan Qureshi
99d8b58868 docs: clarify that a reserved rule must exist in the grammar 2025-08-28 13:28:37 -04:00
Amaan Qureshi
1152bf4c9d fix(cli): show rule names for rules with metadata 2025-08-28 13:28:37 -04:00
ObserverOfTime
107bd800b0 fix(bindings): improve zig dependency fetching logic
Currently, including a tree-sitter parser as a dependency in a zig
project and running `zig build test` on the project will fetch the
zig-tree-sitter dependency declared by the parser. This is a problem
because (a) consumers may not want this dependency for whatever reason
and (b) due to how often Zig breaks everything and how scarcely most
tree-sitter parsers are updated, the zig-tree-sitter version pinned
by the parser module will often be outdated and broken.

The workaround I used was taken from https://ziggit.dev/t/11234
2025-08-28 10:31:24 +03:00
ObserverOfTime
e67f9f8f7a fix(bindings): add tree-sitter as npm dev dependency
npm is supposed to automatically install peer dependencies since v7
but sometimes it's not doing it and we need this dependency for tests
2025-08-27 19:34:09 +03:00
Quentin LE DILAVREC
79177a1cd5
fix(rust): EqCapture accepted cases where number of captured nodes differed by one
Problem: When using alternations, the `#eq?` predicate does not always use the same capture name.

Solution: Iterate the left and right captured nodes more independently.
2025-08-27 10:25:29 +02:00
dependabot[bot]
0a7274678a build(deps): bump the cargo group with 8 updates
Bumps the cargo group with 8 updates:

| Package | From | To |
| --- | --- | --- |
| [cc](https://github.com/rust-lang/cc-rs) | `1.2.33` | `1.2.34` |
| [filetime](https://github.com/alexcrichton/filetime) | `0.2.25` | `0.2.26` |
| [indexmap](https://github.com/indexmap-rs/indexmap) | `2.10.0` | `2.11.0` |
| [regex](https://github.com/rust-lang/regex) | `1.11.1` | `1.11.2` |
| [regex-syntax](https://github.com/rust-lang/regex) | `0.8.5` | `0.8.6` |
| [serde_json](https://github.com/serde-rs/json) | `1.0.142` | `1.0.143` |
| [tempfile](https://github.com/Stebalien/tempfile) | `3.20.0` | `3.21.0` |
| [thiserror](https://github.com/dtolnay/thiserror) | `2.0.15` | `2.0.16` |


Updates `cc` from 1.2.33 to 1.2.34
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.33...cc-v1.2.34)

Updates `filetime` from 0.2.25 to 0.2.26
- [Commits](https://github.com/alexcrichton/filetime/commits)

Updates `indexmap` from 2.10.0 to 2.11.0
- [Changelog](https://github.com/indexmap-rs/indexmap/blob/main/RELEASES.md)
- [Commits](https://github.com/indexmap-rs/indexmap/compare/2.10.0...2.11.0)

Updates `regex` from 1.11.1 to 1.11.2
- [Release notes](https://github.com/rust-lang/regex/releases)
- [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/regex/compare/1.11.1...1.11.2)

Updates `regex-syntax` from 0.8.5 to 0.8.6
- [Release notes](https://github.com/rust-lang/regex/releases)
- [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/regex/compare/regex-syntax-0.8.5...regex-syntax-0.8.6)

Updates `serde_json` from 1.0.142 to 1.0.143
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.142...v1.0.143)

Updates `tempfile` from 3.20.0 to 3.21.0
- [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stebalien/tempfile/commits)

Updates `thiserror` from 2.0.15 to 2.0.16
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/2.0.15...2.0.16)

---
updated-dependencies:
- dependency-name: cc
  dependency-version: 1.2.34
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: filetime
  dependency-version: 0.2.26
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: indexmap
  dependency-version: 2.11.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: cargo
- dependency-name: regex
  dependency-version: 1.11.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: regex-syntax
  dependency-version: 0.8.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: serde_json
  dependency-version: 1.0.143
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: tempfile
  dependency-version: 3.21.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: cargo
- dependency-name: thiserror
  dependency-version: 2.0.16
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-26 16:11:45 +02:00
WillLillis
0d914c860a fix(wasm): delete var_i32_type after initializing global stack
pointer value
2025-08-25 17:16:02 -04:00
ObserverOfTime
eb5ad7eb26 feat(playground): add a button to copy the tree
Co-Authored-By: Firas al-Khalil <firasalkhalil@gmail.com>
2025-08-25 10:21:48 +03:00
ObserverOfTime
4602e60c1b refactor(playground): move style to head 2025-08-25 10:21:48 +03:00
ObserverOfTime
1c640ac2c3 fix(cli): correct resource paths 2025-08-25 10:21:48 +03:00
John-Philip Taylor
10f5a42fd7 feat(cli): Version updates (#4179)
- `version` on its own displays the current version
- `version --bump patch` bumps the patch version
- `version --bump minor` bumps the minor version
- `version --bump major` bumps the major version
- `version 1.2.3` bumps the version directly (existing behaviour)

All flavours of version bump displays a string in the form:
`Bumping version 1.2.3 to 4.5.6`
2025-08-24 00:53:41 -04:00
Will Lillis
fee50ad0ce feat(lib): add lldb pretty-printers for some C lib types 2025-08-22 20:10:03 -04:00
Alexander von Gluck
be888a5fef
fix(c): add Haiku support to endian.h 2025-08-22 14:09:13 +03:00
bfredl
86b9f81ad6 build(zig)!: upgrade build.zig to zig 0.15
This no longer supports zig 0.14.
2025-08-21 11:44:02 +02:00
ObserverOfTime
88e0b4cea4 docs: change WASM/wasm to Wasm
That is the official capitalisation.
2025-08-21 09:56:32 +03:00
dependabot[bot]
7bc8f76667 build(deps): bump the cargo group with 5 updates
Bumps the cargo group with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [anyhow](https://github.com/dtolnay/anyhow) | `1.0.98` | `1.0.99` |
| [cc](https://github.com/rust-lang/cc-rs) | `1.2.32` | `1.2.33` |
| [clap](https://github.com/clap-rs/clap) | `4.5.44` | `4.5.45` |
| [thiserror](https://github.com/dtolnay/thiserror) | `2.0.12` | `2.0.15` |
| [ureq](https://github.com/algesten/ureq) | `3.0.12` | `3.1.0` |


Updates `anyhow` from 1.0.98 to 1.0.99
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.98...1.0.99)

Updates `cc` from 1.2.32 to 1.2.33
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.32...cc-v1.2.33)

Updates `clap` from 4.5.44 to 4.5.45
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.44...clap_complete-v4.5.45)

Updates `thiserror` from 2.0.12 to 2.0.15
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/2.0.12...2.0.15)

Updates `ureq` from 3.0.12 to 3.1.0
- [Changelog](https://github.com/algesten/ureq/blob/main/CHANGELOG.md)
- [Commits](https://github.com/algesten/ureq/compare/3.0.12...3.1.0)

---
updated-dependencies:
- dependency-name: anyhow
  dependency-version: 1.0.99
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: cc
  dependency-version: 1.2.33
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: clap
  dependency-version: 4.5.45
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: thiserror
  dependency-version: 2.0.15
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: ureq
  dependency-version: 3.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: cargo
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-19 10:26:40 +02:00
ObserverOfTime
0bb43f7afb fix(playground): scroll with vanilla JS
jQuery must burn in fire.
2025-08-14 11:03:52 +03:00
Soheil Salmani
99c121bfe8
docs: replace TSInput by TSInputEdit in "Advanced Parsing" 2025-08-13 22:58:17 +03:00
Carlos Scheidegger
c60264b87f
docs(web): fix deno import example 2025-08-13 22:56:21 +03:00
Andrey L.
f9f7ae0850
fix(bindings): make npm repository field an object 2025-08-13 22:54:37 +03:00
ObserverOfTime
d45642c345 fix(bindings): don't ignore lockfiles 2025-08-13 22:51:12 +03:00
dependabot[bot]
790dcc115f ci: bump the actions group with 2 updates
Bumps the actions group with 2 updates: [actions/checkout](https://github.com/actions/checkout) and [actions/download-artifact](https://github.com/actions/download-artifact).


Updates `actions/checkout` from 4 to 5
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v5)

Updates `actions/download-artifact` from 4 to 5
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: actions/download-artifact
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-13 12:35:25 +02:00
dependabot[bot]
79a5e6a671 build(deps): bump the cargo group with 4 updates
Bumps the cargo group with 4 updates: [cc](https://github.com/rust-lang/cc-rs), [clap](https://github.com/clap-rs/clap), [clap_complete](https://github.com/clap-rs/clap) and [glob](https://github.com/rust-lang/glob).


Updates `cc` from 1.2.31 to 1.2.32
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.31...cc-v1.2.32)

Updates `clap` from 4.5.42 to 4.5.44
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.42...clap_complete-v4.5.44)

Updates `clap_complete` from 4.5.55 to 4.5.57
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.55...clap_complete-v4.5.57)

Updates `glob` from 0.3.2 to 0.3.3
- [Release notes](https://github.com/rust-lang/glob/releases)
- [Changelog](https://github.com/rust-lang/glob/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/glob/compare/v0.3.2...v0.3.3)

---
updated-dependencies:
- dependency-name: cc
  dependency-version: 1.2.32
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: clap
  dependency-version: 4.5.44
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: clap_complete
  dependency-version: 4.5.57
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: glob
  dependency-version: 0.3.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-12 10:26:29 +02:00
Will Lillis
3a47bc4435 fix(cli): escape delimiters '"' and '`' in cst node text 2025-08-11 22:39:12 -04:00
Will Lillis
3294b04436 fix(cli): remove trailing whitespace in cst print 2025-08-10 14:52:25 -04:00
Will Lillis
2c02f0767b fix(docs): correct awkward wording in fail-fast listing 2025-08-10 14:52:25 -04:00
Will Lillis
6f7f9a3869 refactor(test): replace long tuples with structs 2025-08-10 14:52:25 -04:00
Will Lillis
1704c604bf feat(test): allow cst as expected output of test case 2025-08-10 14:52:25 -04:00
Will Lillis
21b38004da fix(rust): adapt to new nightly iterator lints 2025-08-10 13:28:52 -04:00
Will Lillis
aed8b8b32c feat(cli): rebuild parsers by default when --grammar-path is passed. 2025-08-10 13:28:52 -04:00
Will Lillis
1562b719d2 feat(cli): add --rebuild flag to query, highlight, and tags commands 2025-08-10 13:28:52 -04:00
Will Lillis
e749a97f9f fix(rust): make String clones more explicit 2025-08-09 16:02:28 -04:00
Will Lillis
3d9f4d1bd3 fix(rust): remove redundant String clones 2025-08-09 16:02:28 -04:00
ObserverOfTime
9f2dd2f377 fix(bindings): fix clean makefile target 2025-08-09 14:41:22 +03:00
Ronald T. Casili
d87921bb9c
fix(bindings): update zig template files (#4637) 2025-08-09 10:18:07 +03:00
ObserverOfTime
f7838748df fix(cli): drop homepage link from config
We don't actually use this currently and the vast majority of grammars
don't have a homepage other than the repository itself.
2025-08-09 10:14:17 +03:00
ObserverOfTime
7e7e376046 refactor(cli): conditional assignment consistency 2025-08-08 10:53:57 +03:00
ObserverOfTime
bbec252c51 refactor(cli): drop unused function 2025-08-08 10:53:57 +03:00
ObserverOfTime
9d619d6fdc fix(bindings): use custom class name 2025-08-08 10:53:57 +03:00
Will Lillis
49ae48f7fe fix(ci): ignore mismatched_lifetime_syntaxes lint when building wasmtime 2025-08-08 09:44:09 +02:00
Will Lillis
46a0e94de7 fix(rust): ignore new mismatched-lifetime-syntaxes lint 2025-08-08 09:44:09 +02:00
dependabot[bot]
2368af52ea build(deps): bump the cargo group with 5 updates
Bumps the cargo group with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [cc](https://github.com/rust-lang/cc-rs) | `1.2.30` | `1.2.31` |
| [clap](https://github.com/clap-rs/clap) | `4.5.41` | `4.5.42` |
| [serde_json](https://github.com/serde-rs/json) | `1.0.141` | `1.0.142` |
| [notify](https://github.com/notify-rs/notify) | `8.1.0` | `8.2.0` |
| [notify-debouncer-full](https://github.com/notify-rs/notify) | `0.5.0` | `0.6.0` |


Updates `cc` from 1.2.30 to 1.2.31
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.30...cc-v1.2.31)

Updates `clap` from 4.5.41 to 4.5.42
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.41...clap_complete-v4.5.42)

Updates `serde_json` from 1.0.141 to 1.0.142
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.141...v1.0.142)

Updates `notify` from 8.1.0 to 8.2.0
- [Release notes](https://github.com/notify-rs/notify/releases)
- [Changelog](https://github.com/notify-rs/notify/blob/main/CHANGELOG.md)
- [Commits](https://github.com/notify-rs/notify/compare/notify-8.1.0...notify-8.2.0)

Updates `notify-debouncer-full` from 0.5.0 to 0.6.0
- [Release notes](https://github.com/notify-rs/notify/releases)
- [Changelog](https://github.com/notify-rs/notify/blob/main/CHANGELOG.md)
- [Commits](https://github.com/notify-rs/notify/compare/debouncer-full-0.5.0...debouncer-full-0.6.0)

---
updated-dependencies:
- dependency-name: cc
  dependency-version: 1.2.31
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: clap
  dependency-version: 4.5.42
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: serde_json
  dependency-version: 1.0.142
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: notify
  dependency-version: 8.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: cargo
- dependency-name: notify-debouncer-full
  dependency-version: 0.6.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: cargo
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-05 09:27:17 +02:00
Will Lillis
d000698847 fix(docs): add information on missing cli command options 2025-08-03 14:34:04 -04:00
Will Lillis
d641249f85 feat(cli): include language name in dump-languages output 2025-08-03 14:34:04 -04:00
Will Lillis
346080aad2 refactor(loader): replace replace_dashes_with_underscores with rust std lib 2025-08-03 14:34:04 -04:00
Will Lillis
acfeed006a feat(cli): allow users to specify dynamic libraries directly for
parse, query, test, and fuzz subcommands
2025-08-03 14:34:04 -04:00
Will Lillis
5e1daf0c41 fix(rust)!: take u32 for index parameter to Node::{child, named_child}
Co-authored-by: Ye Sijun <junnplus@gmail.com>
2025-08-03 12:58:53 -04:00
Will Lillis
7d0b94c008 fix(docs): indicate CJS env var export is different on Windows platforms 2025-08-03 12:58:34 -04:00
Will Lillis
d3c2fed4b3 fix(rust): correct indices for Node::utf16_text 2025-08-02 16:03:55 -04:00
dependabot[bot]
32c88194f5 build(deps): bump the cargo group with 2 updates
Bumps the cargo group with 2 updates: [cc](https://github.com/rust-lang/cc-rs) and [serde_json](https://github.com/serde-rs/json).


Updates `cc` from 1.2.29 to 1.2.30
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.29...cc-v1.2.30)

Updates `serde_json` from 1.0.140 to 1.0.141
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.140...v1.0.141)

---
updated-dependencies:
- dependency-name: cc
  dependency-version: 1.2.30
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: serde_json
  dependency-version: 1.0.141
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-02 11:59:23 +02:00
Will Lillis
9ced6172de
fix(cli): improve error message when language in list can't be found (#4643)
Problem: When multiple input paths are provided to the `parse` command (a la `tree-sitter parse --paths [...]`), if a language can't be found for one of the paths, it can be a little unclear *which* path caused the failure. The loader *can* fail with `Failed to load language for file name <foo.bar>`, but this isn't guaranteed. 

Solution: Attach some additional context in the case where multiple paths can be provided, displaying the problematic path on failure.
2025-08-02 11:52:54 +02:00
Pieter Goetschalckx
07b4c8d05d
fix(cli): add reserved type declarations and schema
- Use `globalThis` for `reserved` function export
- Add `reserved` field and function to DSL declarations
- Add `reserved` rule to grammar schema
2025-08-02 12:01:41 +03:00
Antonin Delpeuch
b787f31481
feat(bindings): generate in 2 steps via make/cmake (#4646)
This makes it possible to run `make` or `cmake --build` in grammar
repos where `grammar.json` hasn't been included, and still get the parser
compilation to work.
2025-08-02 11:57:29 +03:00
Riley Bruins
6850df969d fix(query): prevent cycles when analyzing hidden children
**Problem:** `query.c` compares the current analysis state with the
previous analysis state to see if they are equal, so that it can return
early if so. This prevents redundant work. However, the comparison
function here differs from the one used for sorted insertion/lookup in
that it does not check any state data other than the child index. This
is problematic because it leads to infinite analysis when hidden nodes
have cycles.

**Solution:** Remove the custom comparison function, and apply the
insertion/lookup comparison function in place of it.

**NOTE:** This commit also changes the comparison function slightly, so
that some comparisons are reordered. Namely, for performance, it returns
early if the lhs depth is less than the rhs depth. Is this acceptable?
Tests still pass and nothing hangs in my testing, but it still seems
sketchy. Returning early if the lhs depth is greater than the rhs depth
does seem to make query analysis hang, weirdly enough... Keeping the
depth checks at the end of the loop also works, but it introduces a
noticeable performance regression (for queries that otherwise wouldn't
have had analysis cycles, of course).
2025-07-30 00:41:01 -04:00
Will Lillis
62c53197c4 fix(cli): eliminate leak of version string 2025-07-29 20:44:48 -04:00
Will Lillis
cd2cb661a4 fix(docs): update cli path for install commands 2025-07-29 02:42:43 -04:00
Antonin Delpeuch
8e90799e27 feat(generate): Support for --stage=json/parser/lib 2025-07-26 22:48:00 -04:00
Antonin Delpeuch
d810217e63 refactor: Expose node_types_json without generating C code 2025-07-26 22:48:00 -04:00
Antonin Delpeuch
8676eda663 feat: Only evaluate grammar.js to grammar.json
This adds an `--evaluate-only` option to `tree-sitter generate`
so that it only does the evaluation of `grammar.js` to
`src/grammar.json`, without continuing on with the generation of
`src/parser.c` and related files.

It's a follow-up to #4580.
2025-07-26 22:48:00 -04:00
Robert Muir
8c61bbdb73 feat(bindings): improve python binding test
Previously, the test would not detect ABI incompatibilities.
2025-07-25 13:22:49 +03:00
ObserverOfTime
99988b7081 fix(bindings): improve python platform detection 2025-07-25 13:21:36 +03:00
ObserverOfTime
436162ae7c fix(bindings): only include top level LICENSE file
Ref: tree-sitter/workflows#33
2025-07-25 13:21:14 +03:00
ObserverOfTime
c3012a7d8a fix(bindings): use parser title in lib.rs description 2025-07-25 13:19:03 +03:00
Daniel Müller
f0165dee92 feat(rust): Add direct links to documentation
Make the URL to the documentation of the various crates known so that it
will be easier to click through to it from a crates.io search [0].

[0] https://doc.rust-lang.org/cargo/reference/manifest.html#the-documentation-field
2025-07-22 18:36:08 -04:00
Riley Bruins
dff828cdbe fix(rust): prevent overflow in error message calculation
**Problem:** When encountering an invalid symbol at the beginning of the
file, the rust bindings attempt to index the character at position -1 of
the query source, which leads to an overflow and thus invalid character
index which causes a panic.

**Solution:** Bounds check the offset before performing the subtraction.
2025-07-22 09:51:28 +02:00
Christian Clason
c18d019db0 Revert "feat(generate): warn about unreachable variables (#4567)"
This reverts commit 25c601bd2f.

Reason: Too many false positives.
2025-07-22 09:49:26 +02:00
Antonin Delpeuch
25c601bd2f
feat(generate): warn about unreachable variables (#4567) 2025-07-21 11:39:18 +02:00
Will Lillis
85ab2929e9 docs(license): update year 2025-07-20 21:14:47 -04:00
Will Lillis
86b2c939c7 fix(rust): address nightly clippy lint useless_if_let_seq 2025-07-20 21:14:47 -04:00
Benjamin A. Beasley
e3b85fd0d5 feat(cargo): update etcetera to 0.10
allows dropping a number of windows-targets crates
2025-07-20 12:47:17 +02:00
Will Lillis
0f79c61188 perf(generate): reserve more Vec capacities 2025-07-17 01:51:56 -04:00
Ronald T. Casili
618b9dd66e
fix(build.zig): remove deprecated addStaticLibrary() 2025-07-16 11:08:07 +02:00
dependabot[bot]
ccc707152a build(deps): bump the cargo group with 3 updates
---
updated-dependencies:
- dependency-name: clap
  dependency-version: 4.5.41
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: clap_complete
  dependency-version: 4.5.55
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: clap_complete_nushell
  dependency-version: 4.5.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-15 07:17:05 +00:00
Alex Aron
aeab755033
fix(lib): add wasm32 support to portable/endian.h (#4607) 2025-07-14 17:47:40 +02:00
RedCMD
912167a9cd
chore(web): fix indentation in type files 2025-07-14 12:50:04 +02:00
ObserverOfTime
42e2bba8d6 build(bindings): update Makefile
Similar to the changes made to the core Makefile.
2025-07-14 11:02:19 +03:00
Antonin Décimo
56c2fe59cb build(make): cleanup include dir on uninstall 2025-07-14 11:02:19 +03:00
Antonin Décimo
c7f877de96 build(make): invoke ln in the link directory 2025-07-14 11:02:19 +03:00
Antonin Décimo
aa11c198af ci: don't build the C library with MinGW
Only the C compiler is currently installed, without its binutils.
2025-07-14 11:02:19 +03:00
Antonin Décimo
f8f93c1ec1 build(make): fix MinGW builds
Rename libtree-sitter.lib target to libtree-sitter.dll.a which is
what MinGW actually uses, move the target after libtree-sitter.dll,
and make sure it is installed to the correct location.

Also avoid invoking `cc -dumpmachine` multiple times.
2025-07-14 11:02:19 +03:00
ObserverOfTime
f04fab9b7a docs: update bindings list 2025-07-14 10:24:17 +03:00
Will Lillis
854f527f6e perf: reorder conditional operands 2025-07-13 19:42:30 +02:00
Will Lillis
c740f244ba fix(generate): propagate node types error 2025-07-13 19:42:30 +02:00
Will Lillis
5ed2c77b59 perf: reorder expensive conditional operand 2025-07-12 13:51:54 -04:00
Will Lillis
ad0f953c21 chore(rust): remove empty grammar_files file 2025-07-10 23:44:10 -04:00
Will Lillis
3c56f53105 fix(test): unwrap result of get_node_types in
`test_node_types_deeper_extras` test
2025-07-10 17:42:52 -04:00
WillLillis
d2e06bf130 fix(generate): use topological sort for subtype map 2025-07-10 08:57:55 -04:00
Antonin Delpeuch
36d93aeff3 perf: More efficient computation of used symbols
As the call to `symbol_is_used` does not depend
on the production, it is more efficient to call it
only once outside the loop over productions.

I'm not sure if `rustc` is able to do this optimization
on its own (it would need to know that the function
is pure, which sounds difficult in general).
2025-07-09 22:34:53 -04:00
Will Lillis
1e7d77c517 perf: reserve Vec capacities where appropriate 2025-07-09 21:46:25 -04:00
liangmulu
81849352fc chore: remove redundant words in comment
Signed-off-by: liangmulu <liangmulu@outlook.com>
2025-07-09 18:38:37 +02:00
dependabot[bot]
01d8a39c0b build(deps): bump the cargo group across 1 directory with 3 updates
Bumps the cargo group with 3 updates in the / directory: [cc](https://github.com/rust-lang/cc-rs), [indexmap](https://github.com/indexmap-rs/indexmap) and [notify](https://github.com/notify-rs/notify).


Updates `cc` from 1.2.27 to 1.2.29
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.27...cc-v1.2.29)

Updates `indexmap` from 2.9.0 to 2.10.0
- [Changelog](https://github.com/indexmap-rs/indexmap/blob/main/RELEASES.md)
- [Commits](https://github.com/indexmap-rs/indexmap/compare/2.9.0...2.10.0)

Updates `notify` from 8.0.0 to 8.1.0
- [Release notes](https://github.com/notify-rs/notify/releases)
- [Changelog](https://github.com/notify-rs/notify/blob/main/CHANGELOG.md)
- [Commits](https://github.com/notify-rs/notify/compare/notify-8.0.0...notify-8.1.0)

---
updated-dependencies:
- dependency-name: cc
  dependency-version: 1.2.29
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: indexmap
  dependency-version: 2.10.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: cargo
- dependency-name: notify
  dependency-version: 8.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: cargo
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-08 11:19:24 +00:00
Antonin Delpeuch
1a3b0375fa Fix 'extra' field generation for node-types.json 2025-07-07 21:15:09 -04:00
Antonin Delpeuch
59bcffe83b Add test demonstrating failure to populate 'extra'
The test is currently failing, will be fixed by the next commit.
2025-07-07 21:15:09 -04:00
Will Lillis
45318922d8 fix(xtask): run generate crate unit tests 2025-07-06 17:05:21 -04:00
Will Lillis
1a2167b155 fix(ci): run generate crate unit tests 2025-07-06 17:05:21 -04:00
WillLillis
8938309f4b fix(rust): ignore new nightly lint, correct order of lint list 2025-07-06 12:45:15 -04:00
WillLillis
51a800b7df fix(docs): don't show mdbook help popup when using code editor 2025-07-01 18:23:38 -04:00
Christian Clason
a6cd6abcfb ci(nvim-ts): update paths to refactor
Problem: After https://github.com/tree-sitter/tree-sitter/pull/4496, the
crater tests from nvim-treesitter no longer run on PRs with relevant changes.

Solution: Update the paths in the workflows to the new structure.

Also throttle the build step to 10 parallel tasks (reduces flakiness on
Windows).

Also raise the timeout limit to 30 minutes (it's more expensive to have
to restart flaky tests than to let them run).
2025-06-27 16:34:17 +02:00
Veesh Goldman
b09a15eb54 fix(cli): require correct setuptools version 2025-06-27 14:10:30 +02:00
Will Lillis
a9818e4b17 fix(generate): only display conflicting symbol name in non-terminal
word token error message if available
2025-06-26 00:55:03 -04:00
Will Lillis
be8b3e282a fix(rust): remove unused Command import 2025-06-26 00:54:44 -04:00
dependabot[bot]
259e34435f build(deps): bump brace-expansion in /crates/cli/eslint
Bumps [brace-expansion](https://github.com/juliangruber/brace-expansion) from 1.1.11 to 1.1.12.
- [Release notes](https://github.com/juliangruber/brace-expansion/releases)
- [Commits](https://github.com/juliangruber/brace-expansion/compare/1.1.11...v1.1.12)

---
updated-dependencies:
- dependency-name: brace-expansion
  dependency-version: 1.1.12
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-23 09:30:13 +02:00
dependabot[bot]
eaa10b279f build(deps): bump the cargo group with 4 updates
Bumps the cargo group with 4 updates: [cc](https://github.com/rust-lang/cc-rs), [memchr](https://github.com/BurntSushi/memchr), [webbrowser](https://github.com/amodm/webbrowser-rs) and [ureq](https://github.com/algesten/ureq).


Updates `cc` from 1.2.26 to 1.2.27
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.26...cc-v1.2.27)

Updates `memchr` from 2.7.4 to 2.7.5
- [Commits](https://github.com/BurntSushi/memchr/compare/2.7.4...2.7.5)

Updates `webbrowser` from 1.0.4 to 1.0.5
- [Release notes](https://github.com/amodm/webbrowser-rs/releases)
- [Changelog](https://github.com/amodm/webbrowser-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/amodm/webbrowser-rs/compare/v1.0.4...v1.0.5)

Updates `ureq` from 3.0.11 to 3.0.12
- [Changelog](https://github.com/algesten/ureq/blob/main/CHANGELOG.md)
- [Commits](https://github.com/algesten/ureq/compare/3.0.11...3.0.12)

---
updated-dependencies:
- dependency-name: cc
  dependency-version: 1.2.27
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: memchr
  dependency-version: 2.7.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: webbrowser
  dependency-version: 1.0.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: ureq
  dependency-version: 3.0.12
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-17 08:18:16 +00:00
dependabot[bot]
8a15b881fd build(deps): bump esbuild and tsx in /lib/binding_web
Bumps [esbuild](https://github.com/evanw/esbuild) to 0.25.0 and updates ancestor dependency [tsx](https://github.com/privatenumber/tsx). These dependencies need to be updated together.


Updates `esbuild` from 0.23.1 to 0.25.0
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG-2024.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.23.1...v0.25.0)

Updates `tsx` from 4.19.2 to 4.19.3
- [Release notes](https://github.com/privatenumber/tsx/releases)
- [Changelog](https://github.com/privatenumber/tsx/blob/master/release.config.cjs)
- [Commits](https://github.com/privatenumber/tsx/compare/v4.19.2...v4.19.3)

---
updated-dependencies:
- dependency-name: esbuild
  dependency-version: 0.25.0
  dependency-type: indirect
- dependency-name: tsx
  dependency-version: 4.19.3
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-15 12:48:55 +03:00
Brian Schwind
f475182c7d
fix(playground): initialize tree nodes with a 'plain' class 2025-06-15 12:45:55 +03:00
sammyne
4c51f27b0a feat(cli): support selecting bindings in init cmd 2025-06-15 12:43:03 +03:00
Tamir Bahar
64760ffa76
fix(web): fix typing for Parser.init
Since we're usually only providing `locateFile`, we need the type to be
`Partial<>` to allow it.

This also matches the typing in `@types/emscripten`'s
`EmscriptenModuleFactory` type signature.
2025-06-15 12:41:21 +03:00
Andrew Dupont
02fff92b91 Fix type definitions in exports
…and generate `.d.cts` files for CommonJS exports.
2025-06-15 09:46:05 +03:00
ObserverOfTime
876d5a96bf chore: use issue types in templates 2025-06-14 11:27:29 +03:00
laur89
e8d3d01598
docs: fix CLI link in readme (#4514) 2025-06-13 11:11:44 -07:00
James McCoy
889015f03b
build(rust): use $CARGO_PKG_RUST_VERSION when generating bindings (#4512)
Since cargo 1.63, $CARGO_PKG_RUST_VERSION is set in the build
environment to the value of the rust-version Cargo.toml field.

This removes the need to manually invoke cargo from build.rs during a
build of the tree-sitter crate with the bindgen feature enabled.

Removing the cargo invocation also ensures the build doesn't write to
the current directory when the target directory has been redirected
elsewhere. "cargo metadata" will attempt to update Cargo.lock, which
will fail if the source tree is read-only.
2025-06-13 11:11:22 -07:00
ObserverOfTime
a2c98b4b5f
fix(loader): fix no-default-features build (#4505) 2025-06-11 09:00:54 -07:00
dependabot[bot]
46309a1f95 build(deps): bump the cargo group with 8 updates
Bumps the cargo group with 8 updates:

| Package | From | To |
| --- | --- | --- |
| [anstyle](https://github.com/rust-cli/anstyle) | `1.0.10` | `1.0.11` |
| [cc](https://github.com/rust-lang/cc-rs) | `1.2.25` | `1.2.26` |
| [clap](https://github.com/clap-rs/clap) | `4.5.39` | `4.5.40` |
| [clap_complete](https://github.com/clap-rs/clap) | `4.5.52` | `4.5.54` |
| [clap_complete_nushell](https://github.com/clap-rs/clap) | `4.5.6` | `4.5.7` |
| [flate2](https://github.com/rust-lang/flate2-rs) | `1.1.1` | `1.1.2` |
| [toml](https://github.com/toml-rs/toml) | `0.8.22` | `0.8.23` |
| [bindgen](https://github.com/rust-lang/rust-bindgen) | `0.71.1` | `0.72.0` |


Updates `anstyle` from 1.0.10 to 1.0.11
- [Commits](https://github.com/rust-cli/anstyle/compare/v1.0.10...v1.0.11)

Updates `cc` from 1.2.25 to 1.2.26
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.25...cc-v1.2.26)

Updates `clap` from 4.5.39 to 4.5.40
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.39...clap_complete-v4.5.40)

Updates `clap_complete` from 4.5.52 to 4.5.54
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.52...clap_complete-v4.5.54)

Updates `clap_complete_nushell` from 4.5.6 to 4.5.7
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete_nushell-v4.5.6...clap_complete_nushell-v4.5.7)

Updates `flate2` from 1.1.1 to 1.1.2
- [Release notes](https://github.com/rust-lang/flate2-rs/releases)
- [Commits](https://github.com/rust-lang/flate2-rs/compare/1.1.1...1.1.2)

Updates `toml` from 0.8.22 to 0.8.23
- [Commits](https://github.com/toml-rs/toml/compare/toml-v0.8.22...toml-v0.8.23)

Updates `bindgen` from 0.71.1 to 0.72.0
- [Release notes](https://github.com/rust-lang/rust-bindgen/releases)
- [Changelog](https://github.com/rust-lang/rust-bindgen/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/rust-bindgen/compare/v0.71.1...v0.72.0)

---
updated-dependencies:
- dependency-name: anstyle
  dependency-version: 1.0.11
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: cc
  dependency-version: 1.2.26
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: clap
  dependency-version: 4.5.40
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: clap_complete
  dependency-version: 4.5.54
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: clap_complete_nushell
  dependency-version: 4.5.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: flate2
  dependency-version: 1.1.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: toml
  dependency-version: 0.8.23
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: bindgen
  dependency-version: 0.72.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: cargo
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-10 09:10:17 +02:00
Will Lillis
e1f6e38b57
fix(xtask): limit test command to a single thread on windows (#4489) 2025-06-08 09:39:55 -07:00
ObserverOfTime
9772270868
fix(bindings): update swift & node dependencies (#4432)
* fix(bindings): update swift & node dependencies

also add the dependency name to Package.swift

* chore: update config schema
2025-06-07 11:41:07 -07:00
Max Brunsfeld
0fdf569571
Reorganize rust crates into a flat crates directory, simplify some CI steps (#4496)
* Move all rust crates (except lib) into crates dir, w/o nesting

* Remove stale path from .gitattributes

* Rename lib.rs files for easier navigation

* Rename mod.rs file for easier navigation

* Fix emscripten-version path

* Fix fixtures dir paths

* Use the default rustfmt settings

* Don't use nightly on CI
2025-06-06 14:25:37 -07:00
James McCoy
a6e530b33d fix(test): remove period in test_flatten_grammar_with_recursive_inline_variable
The period was dropped in the `thiserror` refactor
(79444e07f9), which caused the
`test_flatten_grammar_with_recursive_inline_variable` test to fail.

Signed-off-by: James McCoy <jamessan@jamessan.com>
2025-06-06 10:35:02 +02:00
Riley Bruins
6cabd9e67f fix(query)!: assert that predicates end in ! or ?
Predicates/directives are documented to end in either `!` or `?`.
However, `query.c` allows them to be any valid identifier, and also
allows `?` or `!` characters anywhere inside an identifier.

This commit removes `?` and `!` from the list of valid identifier
characters, and asserts that predicates/directives only *end* in `?` or
`!`, respectively.

This commit is breaking because you can no longer do something like
`(#eq? @capture foo!bar)` (`foo!bar` must now be quoted).
2025-06-06 10:34:00 +02:00
Will Lillis
ac13c86675 fix(cli): use a generic Into<Path> over single type for path arguments
Co-authored-by: Amaan Qureshi <amaanq12@gmail.com>
2025-06-05 02:41:18 -04:00
Will Lillis
50eaf5befd fix(query): correct expected and actual capture names in query assertions error message 2025-06-05 02:41:18 -04:00
Will Lillis
0220d9d93d feat(cli): add grammar-path to init, test, version, fuzz,
`query`, `highlight` and `tags` subcommands

Allows users to run various commands on a grammar without
being inside the directory for said grammar.
2025-06-05 02:41:18 -04:00
Antonin Delpeuch
88ac3abaa1
docs(highlight): update README with the new way to load languages 2025-06-05 02:41:00 -04:00
Dan Jacka
ad133ecb38
docs: fix indentation & formatting 2025-06-05 01:53:35 -04:00
Thalia Archibald
6ba73fd888
fix(highlight): account for carriage return at EOF and chunk ends 2025-06-05 01:48:01 -04:00
Will Lillis
8bd923ab9e fix(lib): replace raw array accesses with array_get 2025-06-05 00:53:11 -04:00
Olive Easton
50622f71f8 fix(generate): re-enable default url features 2025-06-04 10:29:59 +02:00
Max Brunsfeld
2ab9c9b590
Fully fix field underflow in go_to_previous_sibling (#4483)
Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
2025-06-02 15:34:25 -07:00
dependabot[bot]
52b719f8fb build(deps): bump the cargo group with 5 updates
Bumps the cargo group with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [cc](https://github.com/rust-lang/cc-rs) | `1.2.23` | `1.2.25` |
| [clap](https://github.com/clap-rs/clap) | `4.5.38` | `4.5.39` |
| [clap_complete](https://github.com/clap-rs/clap) | `4.5.50` | `4.5.52` |
| [clap_complete_nushell](https://github.com/clap-rs/clap) | `4.5.5` | `4.5.6` |
| [libloading](https://github.com/nagisa/rust_libloading) | `0.8.7` | `0.8.8` |


Updates `cc` from 1.2.23 to 1.2.25
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.23...cc-v1.2.25)

Updates `clap` from 4.5.38 to 4.5.39
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.38...clap_complete-v4.5.39)

Updates `clap_complete` from 4.5.50 to 4.5.52
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.50...clap_complete-v4.5.52)

Updates `clap_complete_nushell` from 4.5.5 to 4.5.6
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete_nushell-v4.5.5...clap_complete_nushell-v4.5.6)

Updates `libloading` from 0.8.7 to 0.8.8
- [Commits](https://github.com/nagisa/rust_libloading/commits)

---
updated-dependencies:
- dependency-name: cc
  dependency-version: 1.2.25
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: clap
  dependency-version: 4.5.39
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: clap_complete
  dependency-version: 4.5.52
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: clap_complete_nushell
  dependency-version: 4.5.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: libloading
  dependency-version: 0.8.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-02 23:56:03 +02:00
zyoshoka
135eeded02 docs: update broken link in the playground page 2025-05-31 21:19:20 -04:00
Kai Pastor
0bdf698673
fix(build): pkgconfig and use of GNUInstallDirs (#4319)
* Fix pkgconfig

Init CMAKE_INSTALL_INCLUDEDIR before pc file generation.
Install pc file to CMAKE_INSTALL_LIBDIR/pkgconfig -
it accompanies the architecture-dependent library.

* Include GNUInstallDirs early

The CMake module initializes variables which are used for
exported information (CMake and pkgconfig).

* Change pc file install destination
2025-05-31 11:45:35 +02:00
Christian Clason
e7f9160867
Revert "feat: add build sha to parser.c header comment" (#4475)
This reverts commit dc4e232e6e.

Reason: The sha in the generated output (which most distro builds of
tree-sitter, including `cargo install`, strip) produces too many
conflicts when verifying via CI that parsers are regenerated on every
grammar change.
2025-05-29 11:47:06 -07:00
Max Brunsfeld
ca64399f9f Ignore lock files in grammar repos
It is very common practice to ignore
these lock files for libraries, since they do not apply to applications
that use the libraries. The lock files are especially not useful in
tree-sitter grammar repos, since tree-sitter grammars should not have
dependencies. The lock files are just a source of merge conflicts and
spurious CI failures.
2025-05-28 10:58:45 -07:00
sogaiu
19148eaa0d docs: mention ~ and $HOME for parser-directories 2025-05-28 11:21:09 +02:00
Max Brunsfeld
b8ba76b1ae Fix hang in npm install script 2025-05-27 17:35:23 -07:00
Max Brunsfeld
f91255a201
Fix crash w/ goto_previous_sibling when parent node has leading extra child (#4472)
* Fix crash w/ goto_previous_sibling when parent node has leading extra
child Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>

Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>

* Fix lint

Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>

---------

Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
2025-05-27 16:56:33 -07:00
Haoxiang Fei
06537fda83 fix: wasi has endian.h 2025-05-24 12:27:13 +02:00
dependabot[bot]
299f8a9fb9 build(deps): bump cc from 1.2.22 to 1.2.23 in the cargo group
Bumps the cargo group with 1 update: [cc](https://github.com/rust-lang/cc-rs).


Updates `cc` from 1.2.22 to 1.2.23
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.22...cc-v1.2.23)

---
updated-dependencies:
- dependency-name: cc
  dependency-version: 1.2.23
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-20 08:07:08 +02:00
Mike Zeller
4339b0fe05 illumos has endian.h 2025-05-15 09:53:45 +02:00
dependabot[bot]
08bb6f44a4 build(deps): bump the cargo group with 6 updates
Bumps the cargo group with 6 updates:

| Package | From | To |
| --- | --- | --- |
| [cc](https://github.com/rust-lang/cc-rs) | `1.2.21` | `1.2.22` |
| [clap](https://github.com/clap-rs/clap) | `4.5.37` | `4.5.38` |
| [clap_complete](https://github.com/clap-rs/clap) | `4.5.48` | `4.5.50` |
| [ctrlc](https://github.com/Detegr/rust-ctrlc) | `3.4.6` | `3.4.7` |
| [libloading](https://github.com/nagisa/rust_libloading) | `0.8.6` | `0.8.7` |
| [tempfile](https://github.com/Stebalien/tempfile) | `3.19.1` | `3.20.0` |


Updates `cc` from 1.2.21 to 1.2.22
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.21...cc-v1.2.22)

Updates `clap` from 4.5.37 to 4.5.38
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.37...clap_complete-v4.5.38)

Updates `clap_complete` from 4.5.48 to 4.5.50
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.48...clap_complete-v4.5.50)

Updates `ctrlc` from 3.4.6 to 3.4.7
- [Release notes](https://github.com/Detegr/rust-ctrlc/releases)
- [Commits](https://github.com/Detegr/rust-ctrlc/compare/3.4.6...3.4.7)

Updates `libloading` from 0.8.6 to 0.8.7
- [Commits](https://github.com/nagisa/rust_libloading/compare/0.8.6...0.8.7)

Updates `tempfile` from 3.19.1 to 3.20.0
- [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stebalien/tempfile/compare/v3.19.1...v3.20.0)

---
updated-dependencies:
- dependency-name: cc
  dependency-version: 1.2.22
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: clap
  dependency-version: 4.5.38
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: clap_complete
  dependency-version: 4.5.50
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: ctrlc
  dependency-version: 3.4.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: libloading
  dependency-version: 0.8.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: tempfile
  dependency-version: 3.20.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: cargo
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-13 08:12:35 +02:00
Will Lillis
31b9717ca3 fix(lib): return early for empty predicate step slice 2025-05-11 08:57:30 -04:00
dependabot[bot]
52a792384f build(deps): bump the cargo group with 2 updates
Bumps the cargo group with 2 updates: [cc](https://github.com/rust-lang/cc-rs) and [git2](https://github.com/rust-lang/git2-rs).


Updates `cc` from 1.2.20 to 1.2.21
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.20...cc-v1.2.21)

Updates `git2` from 0.20.1 to 0.20.2
- [Changelog](https://github.com/rust-lang/git2-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/git2-rs/compare/git2-0.20.1...git2-0.20.2)

---
updated-dependencies:
- dependency-name: cc
  dependency-version: 1.2.21
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: git2
  dependency-version: 0.20.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-06 08:57:38 +00:00
Will Lillis
b1d2b7cfb8 fix(query): correct last_child_step_index in cases where a new step
wasn't created.

This fixes an OOB access to `self.steps` when a last child anchor
immediately follows a predicate.
2025-05-03 17:27:37 -04:00
Will Lillis
cc634236b1 fix(rust): address new clippy lint 2025-05-03 19:57:11 +02:00
Will Lillis
91274f47e4 fix(rust): ignore obfuscated_if_else lint 2025-05-03 19:57:11 +02:00
dependabot[bot]
bfc5d1180c build(deps): bump vite from 6.3.2 to 6.3.4 in /lib/binding_web
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 6.3.2 to 6.3.4.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v6.3.4/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 6.3.4
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-01 09:18:47 +02:00
Amaan Qureshi
21c658a12c fix(lib): do not access the alias sequence for the end subtree in ts_subtree_summarize_children 2025-04-28 23:13:13 -04:00
dependabot[bot]
e057299b0d build(deps): bump the cargo group with 3 updates
Bumps the cargo group with 3 updates: [cc](https://github.com/rust-lang/cc-rs), [clap_complete](https://github.com/clap-rs/clap) and [toml](https://github.com/toml-rs/toml).


Updates `cc` from 1.2.19 to 1.2.20
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.19...cc-v1.2.20)

Updates `clap_complete` from 4.5.47 to 4.5.48
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.47...clap_complete-v4.5.48)

Updates `toml` from 0.8.20 to 0.8.22
- [Commits](https://github.com/toml-rs/toml/compare/toml-v0.8.20...toml-v0.8.22)

---
updated-dependencies:
- dependency-name: cc
  dependency-version: 1.2.20
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: clap_complete
  dependency-version: 4.5.48
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: toml
  dependency-version: 0.8.22
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-28 19:43:22 -04:00
Amaan Qureshi
3056dc5be4 fix(generate): mark url as a Windows-only dependency 2025-04-28 18:31:09 -04:00
Amaan Qureshi
0191e94226 docs(rust): remove adding cc as a build dependency for consumers 2025-04-28 18:30:45 -04:00
Will Lillis
dcdd5bc372
fix(parse): explicitly move temporaries in the logger callback
This fixes problems where these stack-local temporaries are used after their scope ends.
2025-04-28 03:30:05 -04:00
Will Lillis
d0e0e0322c
fix(xtask): properly trim emscripten version at the source (#4402)
* fix(xtask): properly trim emscripten version at the source

* fix(loader): trim emscripten version in `cargo:rustc-env=` print
2025-04-27 20:59:04 -07:00
Max Brunsfeld
ca7ff033db
Fix wasm build issues introduced by switching to wasi-sdk (#4407)
* Don't shell out for extracting tar.gz files

* Avoid wasi-sdk adding dependency on libc.so

* Clippy

* Fix -nostdlib flag
2025-04-27 19:42:34 -07:00
Max Brunsfeld
d4d8ed32b3
cli: Compile parsers to wasm using wasi-sdk, not emscripten (#4393)
* Build wasm modules using wasi-sdk, not emscripten

* Log a warning if --docker is passed
2025-04-24 16:00:09 -07:00
Max Brunsfeld
635c49909c Add zed config file (enable all cargo features for rust-analyzer) 2025-04-23 16:32:21 -07:00
Tamchuk
70cf2a7a22
docs: fix typo 2025-04-23 08:26:51 -04:00
dependabot[bot]
74e6641afc build(deps): bump the cargo group with 2 updates
Bumps the cargo group with 2 updates: [clap](https://github.com/clap-rs/clap) and [ureq](https://github.com/algesten/ureq).


Updates `clap` from 4.5.36 to 4.5.37
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.36...clap_complete-v4.5.37)

Updates `ureq` from 3.0.10 to 3.0.11
- [Changelog](https://github.com/algesten/ureq/blob/main/CHANGELOG.md)
- [Commits](https://github.com/algesten/ureq/compare/3.0.10...3.0.11)

---
updated-dependencies:
- dependency-name: clap
  dependency-version: 4.5.37
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: ureq
  dependency-version: 3.0.11
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-22 10:13:43 +02:00
Will Lillis
c7475e4bf3 perf(highlight): use BTreeMap over IndexMap for highlight configs 2025-04-20 05:55:37 -04:00
WillLillis
eee41925aa fix(ci): increase timeouts for flaky tests 2025-04-19 10:59:09 +02:00
Amaan Qureshi
69d553c82a style(cli): formatting 2025-04-19 01:15:53 -04:00
dependabot[bot]
043e0c65ec build(deps): bump vite from 6.1.0 to 6.2.6 in /lib/binding_web
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 6.1.0 to 6.2.6.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v6.2.6/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v6.2.6/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 6.2.6
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-18 23:57:56 -04:00
vemoo
4dffb818e2
feat(web): export wasm files to better support bundling use cases 2025-04-18 23:47:27 -04:00
Daniel Jalkut
4514751803
docs(cli): improve documentation for the edits argument when parsing code 2025-04-18 23:45:52 -04:00
Tamir Bahar
27fa1088b9
fix(web): replace dynamic require with import 2025-04-18 23:40:40 -04:00
MichiRecRoom
853ca46899
docs(rust): improve bindings' crate doc 2025-04-18 22:55:59 -04:00
Riley Bruins
21390af2dd fix(web): correct childWithDescendant() functionality
This fix allows for more granular address control when marshalling nodes
across WASM. This is necessary for node methods which accept another
node as a parameter (i.e., `childWithDescendant()`)
2025-04-18 18:11:42 -04:00
Will Lillis
45a281c962 fix(ci): trigger build_wasm workflow when xtask is modified 2025-04-16 18:06:48 -04:00
Will Lillis
c7c1614278 fix(xtask): trim EMSCRIPTEN_TAG arg to docker command in build-wasm
command
2025-04-16 18:06:48 -04:00
dependabot[bot]
c085a772cf build(deps): bump the cargo group with 4 updates
Bumps the cargo group with 4 updates: [anyhow](https://github.com/dtolnay/anyhow), [bstr](https://github.com/BurntSushi/bstr), [cc](https://github.com/rust-lang/cc-rs) and [clap](https://github.com/clap-rs/clap).


Updates `anyhow` from 1.0.97 to 1.0.98
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.97...1.0.98)

Updates `bstr` from 1.11.3 to 1.12.0
- [Commits](https://github.com/BurntSushi/bstr/compare/1.11.3...1.12.0)

Updates `cc` from 1.2.18 to 1.2.19
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.18...cc-v1.2.19)

Updates `clap` from 4.5.35 to 4.5.36
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.35...clap_complete-v4.5.36)

---
updated-dependencies:
- dependency-name: anyhow
  dependency-version: 1.0.98
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: bstr
  dependency-version: 1.12.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: cargo
- dependency-name: cc
  dependency-version: 1.2.19
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: clap
  dependency-version: 4.5.36
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-15 11:38:47 +02:00
Will Lillis
9fdf685dd5 fix(bindings): report wasm store error in rust bindings set_language 2025-04-14 22:15:40 -04:00
Riley Bruins
733d7513af fix(lib): reset parser options after use
**Problem:** After `ts_parser_parse_with_options()`, the parser options
are still stored in the parser object, meaning that a successive call to
`ts_parser_parse()` will actually behave like
`ts_parser_parse_with_options()`, which is not obvious and can have
unintended consequences.

**Solution:** Reset to empty options state after
`ts_parser_parse_with_options()`.
2025-04-14 21:35:40 -04:00
Paul Gey
b341073192 Make highlighting more deterministic when themes are ambiguous 2025-04-10 23:04:00 -04:00
Jon Shea
92c5d3b8e2 fix(rust): clarify error message for non-token reserved words
Improve the `NonTokenReservedWord` error message by including the
specific reserved word that was not used as a token.
2025-04-09 18:15:48 -04:00
Jason Boatman
abc5c6bc50
Fix WASI build by not calling a non-existent function. (#4343) 2025-04-08 09:33:48 -07:00
Edgar Onghena
52d2865365
chore(generate): add @generated to parser.c header (#4338)
This makes `parser.c` follow the https://generated.at/ convention for generated files. This potentially allows any compatible IDE to discourage editing it directly.
2025-04-08 10:52:37 +02:00
dependabot[bot]
89b04babfb ci: bump actions/create-github-app-token in the actions group
Bumps the actions group with 1 update: [actions/create-github-app-token](https://github.com/actions/create-github-app-token).


Updates `actions/create-github-app-token` from 1 to 2
- [Release notes](https://github.com/actions/create-github-app-token/releases)
- [Commits](https://github.com/actions/create-github-app-token/compare/v1...v2)

---
updated-dependencies:
- dependency-name: actions/create-github-app-token
  dependency-version: '2'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-08 10:18:03 +02:00
dependabot[bot]
755f77231c build(deps): bump the cargo group across 1 directory with 5 updates
Bumps the cargo group with 5 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [cc](https://github.com/rust-lang/cc-rs) | `1.2.17` | `1.2.18` |
| [clap](https://github.com/clap-rs/clap) | `4.5.32` | `4.5.35` |
| [ctrlc](https://github.com/Detegr/rust-ctrlc) | `3.4.5` | `3.4.6` |
| [indexmap](https://github.com/indexmap-rs/indexmap) | `2.8.0` | `2.9.0` |
| [once_cell](https://github.com/matklad/once_cell) | `1.21.1` | `1.21.3` |



Updates `cc` from 1.2.17 to 1.2.18
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.17...cc-v1.2.18)

Updates `clap` from 4.5.32 to 4.5.35
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.32...clap_complete-v4.5.35)

Updates `ctrlc` from 3.4.5 to 3.4.6
- [Release notes](https://github.com/Detegr/rust-ctrlc/releases)
- [Commits](https://github.com/Detegr/rust-ctrlc/compare/3.4.5...3.4.6)

Updates `indexmap` from 2.8.0 to 2.9.0
- [Changelog](https://github.com/indexmap-rs/indexmap/blob/main/RELEASES.md)
- [Commits](https://github.com/indexmap-rs/indexmap/compare/2.8.0...2.9.0)

Updates `once_cell` from 1.21.1 to 1.21.3
- [Changelog](https://github.com/matklad/once_cell/blob/master/CHANGELOG.md)
- [Commits](https://github.com/matklad/once_cell/compare/v1.21.1...v1.21.3)

---
updated-dependencies:
- dependency-name: cc
  dependency-version: 1.2.18
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: clap
  dependency-version: 4.5.35
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: ctrlc
  dependency-version: 3.4.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: indexmap
  dependency-version: 2.9.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: cargo
- dependency-name: once_cell
  dependency-version: 1.21.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-08 10:17:45 +02:00
Bernardo Sulzbach
3d4d13ea1e Fix typo of "corresponds" 2025-04-07 18:34:12 -04:00
Peter Hill
4ec8aacaec docs: Fix link to named-vs-anonymous-nodes section 2025-04-06 10:58:42 -04:00
Will Lillis
0f949168ef fix(cli): display "N/A" in parse stats where appropriate when no parsing
took place
2025-04-06 09:45:50 -04:00
Will Lillis
71941d8bda fix(highlight): account for multiple rows in highlight testing assertions 2025-04-06 09:45:50 -04:00
WillLillis
521da2b0a7 fix(rust): address new nightly lint for pointer comparisons 2025-03-26 08:58:50 +01:00
Christian Clason
37a9ecd5b7 build(deps): update emscripten to v4.0.5 2025-03-25 15:18:44 +01:00
Simon Willshire
ee8d529552
fix(rust): use core crates for no_std
also add `no_std` build to CI
2025-03-25 14:30:32 +01:00
WillLillis
dac6300558 fix(rust): address new clippy lint for pointer comparisons 2025-03-25 13:44:42 +01:00
dependabot[bot]
d05e4ae7ff build(deps): bump the cargo group across 1 directory with 8 updates
Bumps the cargo group with 8 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [cc](https://github.com/rust-lang/cc-rs) | `1.2.16` | `1.2.17` |
| [clap_complete](https://github.com/clap-rs/clap) | `4.5.46` | `4.5.47` |
| [git2](https://github.com/rust-lang/git2-rs) | `0.20.0` | `0.20.1` |
| [log](https://github.com/rust-lang/log) | `0.4.26` | `0.4.27` |
| [once_cell](https://github.com/matklad/once_cell) | `1.21.0` | `1.21.1` |
| [tempfile](https://github.com/Stebalien/tempfile) | `3.18.0` | `3.19.1` |
| [widestring](https://github.com/starkat99/widestring-rs) | `1.1.0` | `1.2.0` |
| [ureq](https://github.com/algesten/ureq) | `3.0.8` | `3.0.10` |



Updates `cc` from 1.2.16 to 1.2.17
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.16...cc-v1.2.17)

Updates `clap_complete` from 4.5.46 to 4.5.47
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.46...clap_complete-v4.5.47)

Updates `git2` from 0.20.0 to 0.20.1
- [Changelog](https://github.com/rust-lang/git2-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/git2-rs/compare/git2-0.20.0...git2-0.20.1)

Updates `log` from 0.4.26 to 0.4.27
- [Release notes](https://github.com/rust-lang/log/releases)
- [Changelog](https://github.com/rust-lang/log/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/log/compare/0.4.26...0.4.27)

Updates `once_cell` from 1.21.0 to 1.21.1
- [Changelog](https://github.com/matklad/once_cell/blob/master/CHANGELOG.md)
- [Commits](https://github.com/matklad/once_cell/compare/v1.21.0...v1.21.1)

Updates `tempfile` from 3.18.0 to 3.19.1
- [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stebalien/tempfile/compare/v3.18.0...v3.19.1)

Updates `widestring` from 1.1.0 to 1.2.0
- [Release notes](https://github.com/starkat99/widestring-rs/releases)
- [Changelog](https://github.com/VoidStarKat/widestring-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/starkat99/widestring-rs/compare/v1.1.0...v1.2.0)

Updates `ureq` from 3.0.8 to 3.0.10
- [Changelog](https://github.com/algesten/ureq/blob/main/CHANGELOG.md)
- [Commits](https://github.com/algesten/ureq/compare/3.0.8...3.0.10)

---
updated-dependencies:
- dependency-name: cc
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: clap_complete
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: git2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: log
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: once_cell
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: tempfile
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: cargo
- dependency-name: widestring
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: cargo
- dependency-name: ureq
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-25 12:24:08 +01:00
JacobCrabill
e3db212b0b build.zig.zon: Fix package hashes for Zig 0.14
Zig 0.14 changed how package hashes are computed and used, and if the
old package hashes are left, every call to `zig build` will re-download
every package every time.  Updating to the new hash format solves this.
2025-03-21 17:33:38 +01:00
WillLillis
f0e7ac2f18 chore(cli): remove deprecated --no-bindings flag from generate command 2025-03-16 11:04:29 +01:00
dependabot[bot]
e08fe3b993 build(deps): bump the cargo group across 1 directory with 21 updates
Bumps the cargo group with 20 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [anyhow](https://github.com/dtolnay/anyhow) | `1.0.95` | `1.0.97` |
| [cc](https://github.com/rust-lang/cc-rs) | `1.2.10` | `1.2.16` |
| [clap](https://github.com/clap-rs/clap) | `4.5.27` | `4.5.32` |
| [clap_complete](https://github.com/clap-rs/clap) | `4.5.42` | `4.5.46` |
| [indexmap](https://github.com/indexmap-rs/indexmap) | `2.7.1` | `2.8.0` |
| [indoc](https://github.com/dtolnay/indoc) | `2.0.5` | `2.0.6` |
| [log](https://github.com/rust-lang/log) | `0.4.25` | `0.4.26` |
| [once_cell](https://github.com/matklad/once_cell) | `1.20.2` | `1.21.0` |
| [rustc-hash](https://github.com/rust-lang/rustc-hash) | `2.1.0` | `2.1.1` |
| [semver](https://github.com/dtolnay/semver) | `1.0.25` | `1.0.26` |
| [serde](https://github.com/serde-rs/serde) | `1.0.217` | `1.0.219` |
| [serde_json](https://github.com/serde-rs/json) | `1.0.137` | `1.0.140` |
| [smallbitvec](https://github.com/servo/smallbitvec) | `2.5.3` | `2.6.0` |
| [tempfile](https://github.com/Stebalien/tempfile) | `3.15.0` | `3.18.0` |
| [thiserror](https://github.com/dtolnay/thiserror) | `2.0.11` | `2.0.12` |
| [toml](https://github.com/toml-rs/toml) | `0.8.19` | `0.8.20` |
| [unindent](https://github.com/dtolnay/indoc) | `0.2.3` | `0.2.4` |
| [wasmparser](https://github.com/bytecodealliance/wasm-tools) | `0.224.0` | `0.224.1` |
| [webbrowser](https://github.com/amodm/webbrowser-rs) | `1.0.3` | `1.0.4` |
| [ureq](https://github.com/algesten/ureq) | `3.0.0` | `3.0.8` |



Updates `anyhow` from 1.0.95 to 1.0.97
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.95...1.0.97)

Updates `cc` from 1.2.10 to 1.2.16
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.10...cc-v1.2.16)

Updates `clap` from 4.5.27 to 4.5.32
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.27...clap_complete-v4.5.32)

Updates `clap_complete` from 4.5.42 to 4.5.46
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.42...clap_complete-v4.5.46)

Updates `indexmap` from 2.7.1 to 2.8.0
- [Changelog](https://github.com/indexmap-rs/indexmap/blob/main/RELEASES.md)
- [Commits](https://github.com/indexmap-rs/indexmap/compare/2.7.1...2.8.0)

Updates `indoc` from 2.0.5 to 2.0.6
- [Release notes](https://github.com/dtolnay/indoc/releases)
- [Commits](https://github.com/dtolnay/indoc/compare/2.0.5...2.0.6)

Updates `log` from 0.4.25 to 0.4.26
- [Release notes](https://github.com/rust-lang/log/releases)
- [Changelog](https://github.com/rust-lang/log/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/log/compare/0.4.25...0.4.26)

Updates `once_cell` from 1.20.2 to 1.21.0
- [Changelog](https://github.com/matklad/once_cell/blob/master/CHANGELOG.md)
- [Commits](https://github.com/matklad/once_cell/compare/v1.20.2...v1.21.0)

Updates `rustc-hash` from 2.1.0 to 2.1.1
- [Changelog](https://github.com/rust-lang/rustc-hash/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/rustc-hash/compare/v2.1.0...v2.1.1)

Updates `semver` from 1.0.25 to 1.0.26
- [Release notes](https://github.com/dtolnay/semver/releases)
- [Commits](https://github.com/dtolnay/semver/compare/1.0.25...1.0.26)

Updates `serde` from 1.0.217 to 1.0.219
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.217...v1.0.219)

Updates `serde_derive` from 1.0.217 to 1.0.219
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.217...v1.0.219)

Updates `serde_json` from 1.0.137 to 1.0.140
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.137...v1.0.140)

Updates `smallbitvec` from 2.5.3 to 2.6.0
- [Release notes](https://github.com/servo/smallbitvec/releases)
- [Commits](https://github.com/servo/smallbitvec/compare/v2.5.3...v2.6.0)

Updates `tempfile` from 3.15.0 to 3.18.0
- [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stebalien/tempfile/compare/v3.15.0...v3.18.0)

Updates `thiserror` from 2.0.11 to 2.0.12
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/2.0.11...2.0.12)

Updates `toml` from 0.8.19 to 0.8.20
- [Commits](https://github.com/toml-rs/toml/compare/toml-v0.8.19...toml-v0.8.20)

Updates `unindent` from 0.2.3 to 0.2.4
- [Release notes](https://github.com/dtolnay/indoc/releases)
- [Commits](https://github.com/dtolnay/indoc/compare/0.2.3...0.2.4)

Updates `wasmparser` from 0.224.0 to 0.224.1
- [Release notes](https://github.com/bytecodealliance/wasm-tools/releases)
- [Commits](https://github.com/bytecodealliance/wasm-tools/commits)

Updates `webbrowser` from 1.0.3 to 1.0.4
- [Release notes](https://github.com/amodm/webbrowser-rs/releases)
- [Changelog](https://github.com/amodm/webbrowser-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/amodm/webbrowser-rs/compare/v1.0.3...v1.0.4)

Updates `ureq` from 3.0.0 to 3.0.8
- [Changelog](https://github.com/algesten/ureq/blob/main/CHANGELOG.md)
- [Commits](https://github.com/algesten/ureq/compare/3.0.0...3.0.8)

---
updated-dependencies:
- dependency-name: anyhow
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: cc
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: clap
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: clap_complete
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: indexmap
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: cargo
- dependency-name: indoc
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: log
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: once_cell
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: cargo
- dependency-name: rustc-hash
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: semver
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: serde_derive
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: smallbitvec
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: cargo
- dependency-name: tempfile
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: cargo
- dependency-name: thiserror
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: toml
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: unindent
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: wasmparser
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: webbrowser
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
- dependency-name: ureq
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-15 16:43:49 +01:00
Tamir Bahar
a380e1a259
refactor(web): change return types to Node[] in child-related methods 2025-03-15 09:09:31 -04:00
Peter Oliver
17471bdfcc
fix(build): make install shouldn’t fail when a parser bundles no queries (#4284) 2025-03-14 09:37:51 +01:00
WillLillis
5985690d45 fix(xtask): error if new version supplied to bump-version is less than
or equal to current version
2025-03-14 09:37:25 +01:00
Christian Clason
07a1b7fc00 fix(build): bump version to 0.26.0
After a release, `master` branch should be bumped to the next _minor_ version.
2025-03-12 14:52:09 +01:00
dependabot[bot]
12aff698b9 build(deps): bump emscripten to 4.0.4 2025-03-12 09:30:11 +00:00
dependabot[bot]
276accc210 build(deps): bump ring from 0.17.8 to 0.17.13
Bumps [ring](https://github.com/briansmith/ring) from 0.17.8 to 0.17.13.
- [Changelog](https://github.com/briansmith/ring/blob/main/RELEASES.md)
- [Commits](https://github.com/briansmith/ring/commits)

---
updated-dependencies:
- dependency-name: ring
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-12 09:30:11 +00:00
Riley Bruins
cc3994928c feat(lib): quote invalid nodes, fields, and captures 2025-03-12 10:28:57 +01:00
WillLillis
efd212ee46 fix(cli): properly escape invisible characters in parse error output 2025-03-11 17:27:12 -04:00
Jon Shea
ec3a889758 fix(docs): update test command flag from -f to -i
The `-f` flag on `tree-sitter test` seems to have been removed or
replaced with a `-i, --include` flag. This PR updates the "Writing Tests"
page to reflect this change.
2025-03-10 11:18:59 -04:00
Niklas Koll
1850762118
feat(build): update build.zig.zon for zig 0.14 2025-03-10 15:56:41 +01:00
June Gschwantner
0b28226615
docs(bindings): Add "Using WASM Grammar files" section to binding_rust (#4235) 2025-03-06 14:15:21 -08:00
NOT XVilka
a00fab7dc4
fix(lib): remove duplicate TSLanguageMetadata typedef (#4268) 2025-03-06 14:14:25 -08:00
WillLillis
11071ed682 fix(rust): adapt to new nightly lint 2025-03-06 09:32:21 +01:00
Max Brunsfeld
066fd77d39
Fix cases where error recovery could infinite loop (#4257)
* Rename corpus test functions to allow easy filtering by language

* Use usize for seed argument

* Avoid retaining useless stack versions when reductions merge

We found this problem when debugging an infinite loop that happened
during error recovery when using the Zig grammar. The large number of
unnecessary paused stack versions were preventing the correct recovery
strategy from being tried.

* Fix leaked lookahead token when reduction results in a merged stack

* Enable running PHP tests in CI

* Fix possible infinite loop during error recovery at EOF

* Account for external scanner state changes when detecting changed ranges in subtrees
2025-03-04 13:50:56 -08:00
polazarus
8138dba800
fix(generate): mark TSCharacterRange as static (#4255)
Problem: Linking different parsers into one executable fails due to duplicate symbols.

Solution: Mark `TSCharacterRange` as `static` when generating parsers.

fixes #4209
2025-03-04 15:26:13 +01:00
Yuri Astrakhan
b749c02eb5 Mark all format-like macros for Clippy
See https://doc.rust-lang.org/nightly/clippy/attribs.html#clippyformat_args

Ensure that usage of the macros with `format!`-like parameters will be validated by Clippy
2025-03-03 02:16:23 -05:00
WillLillis
1fdd1d250c ci: separate nightly lints to separate job 2025-03-02 16:37:03 -05:00
WillLillis
998fb34d15 fix(test): update expected tree-sitter-rust supertypes 2025-03-02 16:37:03 -05:00
WillLillis
cb30ec5b17 fix(rust): adapt to some new nightly lints 2025-03-02 16:37:03 -05:00
Andrew Dunbar
ab7eb70a3c
typo: but is only works → but it only works (#4242) 2025-02-26 09:29:27 -08:00
Will Lillis
3b67861def
fix(wasm): restore passing in ERROR to descendantsOfType (#4226) 2025-02-19 14:47:10 -08:00
Max Brunsfeld
b26b7f8d62
Decrease the MSRV for the tree-sitter-language crate (#4221) 2025-02-17 18:52:57 -08:00
Max Brunsfeld
2bd400dcee
Reset result_symbol field of lexer in wasm memory in between invocations (#4218) 2025-02-17 17:36:46 -08:00
Max Brunsfeld
dedcc5255a
Ignore external tokens that are zero-length and extra (#4213)
Co-authored-by: Anthony <anthony@zed.dev>
2025-02-17 15:07:44 -08:00
Max Brunsfeld
14b8ead412
Fix crash when loading languages w/ old ABI via wasm (#4210) 2025-02-17 13:56:53 -08:00
Antonin Décimo
f0571b1e33
feat: Windows support using MinGW-w64 (#4201)
Building tree-sitter on Windows within a Cygwin or MSYS2 environment
for MinGW-w64 targets should work. As there's no configure-like step,
the tools have to be specified with:

    make CC=x86_64-w64-mingw32-gcc \
         AR=x86_64-w64-mingw32-ar \
         STRIP=x86_64-w64-mingw32-strip

Useful reference:
[How to build and use DLLs on Windows](https://nullprogram.com/blog/2021/05/31/)

This commit doesn't tag public functions with dllexport or
dllimport. This results in exporting non-static functions visible
between translation units, and generating slightly less efficient code
for calling exported functions from the DLL.

This commit doesn't include support to build libtree-sitter with MSVC or
clang-cl, but generates a libtree-sitter.lib file for MSVC/clang-cl
consumers.
2025-02-12 16:31:06 -08:00
Amaan Qureshi
8e79929cb8 ci: remove benchmark step
We don't actually use this data, it runs without a purpose
2025-02-11 22:56:50 -05:00
Amaan Qureshi
0a33135483 ci: rename web files, and upload a tarball for web-tree-sitter assets 2025-02-11 22:56:50 -05:00
Amaan Qureshi
a40265cbeb refactor(web): rename tree-sitter.js to web-tree-sitter.js
This is not breaking for consumers of the web bindings, nor the
playground as both filenames will be kept in the .github.io repo
2025-02-11 22:56:50 -05:00
Amaan Qureshi
74d7ca8582 fix(rust): adapt to new clippy lints 2025-02-08 13:15:56 -05:00
Amaan Qureshi
1a80a1f413 fix: add generate crate to workspace members 2025-02-08 13:15:56 -05:00
Roberto Huertas
f95e0e3a56 fix(web): provide type in the exports
When using TypeScript projects using other module settings than CommonJs, the types were not correctly exposed, and the compilation failed.

This adds the types path to the exports so compilation works for `module: NodeNext` and other variants.
2025-02-08 12:47:17 -05:00
Thomas Klausner
14647b2a38 build: add a comment explaining why we undef _POSIX_C_SOURCE 2025-02-02 17:14:28 -05:00
Thomas Klausner
5311904619 build: fix compilation on NetBSD a different way 2025-02-02 17:14:28 -05:00
Thomas Klausner
60b76c7834 Revert "build: do not define _POSIX_C_SOURCE on NetBSD"
This reverts commit 54921453da.
2025-02-02 17:14:28 -05:00
Thomas Klausner
2bf04d1f04 build: do not define _POSIX_C_SOURCE on NetBSD
It leads to missing symbols, see #4180.
2025-02-02 17:14:28 -05:00
422 changed files with 21219 additions and 13790 deletions

View file

@ -10,6 +10,9 @@ insert_final_newline = true
[*.rs] [*.rs]
indent_size = 4 indent_size = 4
[*.{zig,zon}]
indent_size = 4
[Makefile] [Makefile]
indent_style = tab indent_style = tab
indent_size = 8 indent_size = 8

1
.envrc Normal file
View file

@ -0,0 +1 @@
use flake

1
.gitattributes vendored
View file

@ -3,5 +3,4 @@
/lib/src/unicode/*.h linguist-vendored /lib/src/unicode/*.h linguist-vendored
/lib/src/unicode/LICENSE linguist-vendored /lib/src/unicode/LICENSE linguist-vendored
/cli/src/generate/prepare_grammar/*.json -diff
Cargo.lock -diff Cargo.lock -diff

View file

@ -1,6 +1,6 @@
name: Bug Report name: Bug Report
description: Report a problem description: Report a problem
labels: [bug] type: Bug
body: body:
- type: textarea - type: textarea
attributes: attributes:

View file

@ -1,6 +1,6 @@
name: Feature request name: Feature request
description: Request an enhancement description: Request an enhancement
labels: [enhancement] type: Feature
body: body:
- type: markdown - type: markdown
attributes: attributes:

View file

@ -17,10 +17,9 @@ runs:
test/fixtures/grammars test/fixtures/grammars
target/release/tree-sitter-*.wasm target/release/tree-sitter-*.wasm
key: fixtures-${{ join(matrix.*, '_') }}-${{ hashFiles( key: fixtures-${{ join(matrix.*, '_') }}-${{ hashFiles(
'cli/generate/src/**', 'crates/generate/src/**',
'lib/src/parser.h', 'lib/src/parser.h',
'lib/src/array.h', 'lib/src/array.h',
'lib/src/alloc.h', 'lib/src/alloc.h',
'xtask/src/*',
'test/fixtures/grammars/*/**/src/*.c', 'test/fixtures/grammars/*/**/src/*.c',
'.github/actions/cache/action.yml') }} '.github/actions/cache/action.yml') }}

View file

@ -4,6 +4,8 @@ updates:
directory: "/" directory: "/"
schedule: schedule:
interval: "weekly" interval: "weekly"
cooldown:
default-days: 3
commit-message: commit-message:
prefix: "build(deps)" prefix: "build(deps)"
labels: labels:
@ -12,10 +14,16 @@ updates:
groups: groups:
cargo: cargo:
patterns: ["*"] patterns: ["*"]
ignore:
- dependency-name: "*"
update-types: ["version-update:semver-major", "version-update:semver-minor"]
- package-ecosystem: "github-actions" - package-ecosystem: "github-actions"
directory: "/" directory: "/"
schedule: schedule:
interval: "weekly" interval: "weekly"
cooldown:
default-days: 3
commit-message: commit-message:
prefix: "ci" prefix: "ci"
labels: labels:
@ -24,3 +32,22 @@ updates:
groups: groups:
actions: actions:
patterns: ["*"] patterns: ["*"]
- package-ecosystem: "npm"
versioning-strategy: increase
directories:
- "/crates/npm"
- "/crates/eslint"
- "/lib/binding_web"
schedule:
interval: "weekly"
cooldown:
default-days: 3
commit-message:
prefix: "build(deps)"
labels:
- "dependencies"
- "npm"
groups:
npm:
patterns: ["*"]

29
.github/scripts/close_spam.js vendored Normal file
View file

@ -0,0 +1,29 @@
module.exports = async ({ github, context }) => {
let target = context.payload.issue;
if (target) {
await github.rest.issues.update({
...context.repo,
issue_number: target.number,
state: "closed",
state_reason: "not_planned",
title: "[spam]",
body: "",
type: null,
});
} else {
target = context.payload.pull_request;
await github.rest.pulls.update({
...context.repo,
pull_number: target.number,
state: "closed",
title: "[spam]",
body: "",
});
}
await github.rest.issues.lock({
...context.repo,
issue_number: target.number,
lock_reason: "spam",
});
};

View file

@ -1,3 +0,0 @@
#!/bin/bash -eu
exec docker run --rm -v /home/runner:/home/runner -w "$PWD" "$CROSS_IMAGE" "$@"

View file

@ -1,9 +0,0 @@
#!/bin/bash -eu
tree_sitter="$ROOT"/target/"$TARGET"/release/tree-sitter
if [[ $BUILD_CMD == cross ]]; then
cross.sh make CC="$CC" AR="$AR" "$@"
else
exec make "$@"
fi

View file

@ -1,9 +0,0 @@
#!/bin/bash -eu
tree_sitter="$ROOT"/target/"$TARGET"/release/tree-sitter
if [[ $BUILD_CMD == cross ]]; then
cross.sh "$CROSS_RUNNER" "$tree_sitter" "$@"
else
exec "$tree_sitter" "$@"
fi

25
.github/scripts/wasm_stdlib.js vendored Normal file
View file

@ -0,0 +1,25 @@
module.exports = async ({ github, context, core }) => {
if (context.eventName !== 'pull_request') return;
const prNumber = context.payload.pull_request.number;
const owner = context.repo.owner;
const repo = context.repo.repo;
const { data: files } = await github.rest.pulls.listFiles({
owner,
repo,
pull_number: prNumber
});
const changedFiles = files.map(file => file.filename);
const wasmStdLibSrc = 'crates/language/wasm/';
const dirChanged = changedFiles.some(file => file.startsWith(wasmStdLibSrc));
if (!dirChanged) return;
const wasmStdLibHeader = 'lib/src/wasm/wasm-stdlib.h';
const requiredChanged = changedFiles.includes(wasmStdLibHeader);
if (!requiredChanged) core.setFailed(`Changes detected in ${wasmStdLibSrc} but ${wasmStdLibHeader} was not modified.`);
};

View file

@ -14,17 +14,17 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v6
- name: Create app token - name: Create app token
uses: actions/create-github-app-token@v1 uses: actions/create-github-app-token@v2
id: app-token id: app-token
with: with:
app-id: ${{ vars.BACKPORT_APP }} app-id: ${{ vars.BACKPORT_APP }}
private-key: ${{ secrets.BACKPORT_KEY }} private-key: ${{ secrets.BACKPORT_KEY }}
- name: Create backport PR - name: Create backport PR
uses: korthout/backport-action@v3 uses: korthout/backport-action@v4
with: with:
pull_title: "${pull_title}" pull_title: "${pull_title}"
label_pattern: "^ci:backport ([^ ]+)$" label_pattern: "^ci:backport ([^ ]+)$"

View file

@ -16,7 +16,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v6
- name: Set up stable Rust toolchain - name: Set up stable Rust toolchain
uses: actions-rust-lang/setup-rust-toolchain@v1 uses: actions-rust-lang/setup-rust-toolchain@v1

View file

@ -1,10 +1,5 @@
name: Build & Test name: Build & Test
env:
CARGO_TERM_COLOR: always
RUSTFLAGS: "-D warnings"
CROSS_DEBUG: 1
on: on:
workflow_call: workflow_call:
inputs: inputs:
@ -31,38 +26,41 @@ jobs:
- windows-x86 - windows-x86
- macos-arm64 - macos-arm64
- macos-x64 - macos-x64
- wasm32
include: include:
# When adding a new `target`: # When adding a new `target`:
# 1. Define a new platform alias above # 1. Define a new platform alias above
# 2. Add a new record to the matrix map in `cli/npm/install.js` # 2. Add a new record to the matrix map in `crates/cli/npm/install.js`
- { platform: linux-arm64 , target: aarch64-unknown-linux-gnu , os: ubuntu-latest , use-cross: true } - { platform: linux-arm64 , target: aarch64-unknown-linux-gnu , os: ubuntu-24.04-arm }
- { platform: linux-arm , target: arm-unknown-linux-gnueabi , os: ubuntu-latest , use-cross: true } - { platform: linux-arm , target: armv7-unknown-linux-gnueabihf , os: ubuntu-24.04-arm }
- { platform: linux-x64 , target: x86_64-unknown-linux-gnu , os: ubuntu-22.04 , features: wasm } - { platform: linux-x64 , target: x86_64-unknown-linux-gnu , os: ubuntu-24.04 }
- { platform: linux-x86 , target: i686-unknown-linux-gnu , os: ubuntu-latest , use-cross: true } - { platform: linux-x86 , target: i686-unknown-linux-gnu , os: ubuntu-24.04 }
- { platform: linux-powerpc64 , target: powerpc64-unknown-linux-gnu , os: ubuntu-latest , use-cross: true } - { platform: linux-powerpc64 , target: powerpc64-unknown-linux-gnu , os: ubuntu-24.04 }
- { platform: windows-arm64 , target: aarch64-pc-windows-msvc , os: windows-latest } - { platform: windows-arm64 , target: aarch64-pc-windows-msvc , os: windows-11-arm }
- { platform: windows-x64 , target: x86_64-pc-windows-msvc , os: windows-latest , features: wasm } - { platform: windows-x64 , target: x86_64-pc-windows-msvc , os: windows-2025 }
- { platform: windows-x86 , target: i686-pc-windows-msvc , os: windows-latest } - { platform: windows-x86 , target: i686-pc-windows-msvc , os: windows-2025 }
- { platform: macos-arm64 , target: aarch64-apple-darwin , os: macos-latest , features: wasm } - { platform: macos-arm64 , target: aarch64-apple-darwin , os: macos-15 }
- { platform: macos-x64 , target: x86_64-apple-darwin , os: macos-13 , features: wasm } - { platform: macos-x64 , target: x86_64-apple-darwin , os: macos-15-intel }
- { platform: wasm32 , target: wasm32-unknown-unknown , os: ubuntu-24.04 }
# Cross compilers for C library # Extra features
- { platform: linux-arm64 , cc: aarch64-linux-gnu-gcc , ar: aarch64-linux-gnu-ar } - { platform: linux-arm64 , features: wasm }
- { platform: linux-arm , cc: arm-linux-gnueabi-gcc , ar: arm-linux-gnueabi-ar } - { platform: linux-x64 , features: wasm }
- { platform: linux-x86 , cc: i686-linux-gnu-gcc , ar: i686-linux-gnu-ar } - { platform: macos-arm64 , features: wasm }
- { platform: linux-powerpc64 , cc: powerpc64-linux-gnu-gcc , ar: powerpc64-linux-gnu-ar } - { platform: macos-x64 , features: wasm }
# Prevent race condition (see #2041) # Cross-compilation
- { platform: windows-x64 , rust-test-threads: 1 } - { platform: linux-arm , cross: true }
- { platform: windows-x86 , rust-test-threads: 1 } - { platform: linux-x86 , cross: true }
- { platform: linux-powerpc64 , cross: true }
# Can't natively run CLI on Github runner's host # Compile-only
- { platform: windows-arm64 , no-run: true } - { platform: wasm32 , no-run: true }
env: env:
BUILD_CMD: cargo CARGO_TERM_COLOR: always
SUFFIX: ${{ contains(matrix.target, 'windows') && '.exe' || '' }} RUSTFLAGS: -D warnings
defaults: defaults:
run: run:
@ -70,13 +68,28 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v6
- name: Read Emscripten version - name: Set up cross-compilation
run: printf 'EMSCRIPTEN_VERSION=%s\n' "$(<cli/loader/emscripten-version)" >> $GITHUB_ENV if: matrix.cross
run: |
for target in armv7-unknown-linux-gnueabihf i686-unknown-linux-gnu powerpc64-unknown-linux-gnu; do
camel_target=${target//-/_}; target_cc=${target/-unknown/}
printf 'CC_%s=%s\n' "$camel_target" "${target_cc/v7/}-gcc"
printf 'AR_%s=%s\n' "$camel_target" "${target_cc/v7/}-ar"
printf 'CARGO_TARGET_%s_LINKER=%s\n' "${camel_target^^}" "${target_cc/v7/}-gcc"
done >> $GITHUB_ENV
{
printf 'CARGO_TARGET_ARMV7_UNKNOWN_LINUX_GNUEABIHF_RUNNER=qemu-arm -L /usr/arm-linux-gnueabihf\n'
printf 'CARGO_TARGET_POWERPC64_UNKNOWN_LINUX_GNU_RUNNER=qemu-ppc64 -L /usr/powerpc64-linux-gnu\n'
} >> $GITHUB_ENV
- name: Get emscripten version
if: contains(matrix.features, 'wasm')
run: printf 'EMSCRIPTEN_VERSION=%s\n' "$(<crates/loader/emscripten-version)" >> $GITHUB_ENV
- name: Install Emscripten - name: Install Emscripten
if: ${{ !matrix.no-run && !matrix.use-cross }} if: contains(matrix.features, 'wasm')
uses: mymindstorm/setup-emsdk@v14 uses: mymindstorm/setup-emsdk@v14
with: with:
version: ${{ env.EMSCRIPTEN_VERSION }} version: ${{ env.EMSCRIPTEN_VERSION }}
@ -86,61 +99,82 @@ jobs:
with: with:
target: ${{ matrix.target }} target: ${{ matrix.target }}
- name: Install cross - name: Install cross-compilation toolchain
if: ${{ matrix.use-cross }} if: matrix.cross
run: | run: |
if [ ! -x "$(command -v cross)" ]; then sudo apt-get update -qy
# TODO: Remove 'RUSTFLAGS=""' once https://github.com/cross-rs/cross/issues/1561 is resolved if [[ $PLATFORM == linux-arm ]]; then
RUSTFLAGS="" cargo install cross --git https://github.com/cross-rs/cross sudo apt-get install -qy {binutils,gcc}-arm-linux-gnueabihf qemu-user
elif [[ $PLATFORM == linux-x86 ]]; then
sudo apt-get install -qy {binutils,gcc}-i686-linux-gnu
elif [[ $PLATFORM == linux-powerpc64 ]]; then
sudo apt-get install -qy {binutils,gcc}-powerpc64-linux-gnu qemu-user
fi fi
- name: Configure cross
if: ${{ matrix.use-cross }}
run: |
printf '%s\n' > Cross.toml \
'[target.${{ matrix.target }}]' \
'image = "ghcr.io/cross-rs/${{ matrix.target }}:edge"' \
'[build]' \
'pre-build = [' \
' "dpkg --add-architecture $CROSS_DEB_ARCH",' \
' "curl -fsSL https://deb.nodesource.com/setup_22.x | bash -",' \
' "apt-get update && apt-get -y install libssl-dev nodejs"' \
']'
cat - Cross.toml <<< 'Cross.toml:'
printf '%s\n' >> $GITHUB_ENV \
"CROSS_CONFIG=$PWD/Cross.toml" \
"CROSS_IMAGE=ghcr.io/cross-rs/${{ matrix.target }}:edge"
- name: Set up environment
env: env:
RUST_TEST_THREADS: ${{ matrix.rust-test-threads }} PLATFORM: ${{ matrix.platform }}
USE_CROSS: ${{ matrix.use-cross }}
TARGET: ${{ matrix.target }} - name: Install MinGW and Clang (Windows x64 MSYS2)
CC: ${{ matrix.cc }} if: matrix.platform == 'windows-x64'
AR: ${{ matrix.ar }} uses: msys2/setup-msys2@v2
with:
update: true
install: |
mingw-w64-x86_64-toolchain
mingw-w64-x86_64-clang
mingw-w64-x86_64-make
mingw-w64-x86_64-cmake
# TODO: Remove RUSTFLAGS="--cap-lints allow" once we use a wasmtime release that addresses
# the `mismatched-lifetime-syntaxes` lint
- name: Build wasmtime library (Windows x64 MSYS2)
if: contains(matrix.features, 'wasm') && matrix.platform == 'windows-x64'
run: | run: |
PATH="$PWD/.github/scripts:$PATH" mkdir -p target
printf '%s/.github/scripts\n' "$PWD" >> $GITHUB_PATH WASMTIME_VERSION=$(cargo metadata --format-version=1 --locked --features wasm | \
jq -r '.packages[] | select(.name == "wasmtime-c-api-impl") | .version')
curl -LSs "$WASMTIME_REPO/archive/refs/tags/v${WASMTIME_VERSION}.tar.gz" | tar xzf - -C target
cd target/wasmtime-${WASMTIME_VERSION}
cmake -S crates/c-api -B target/c-api \
-DCMAKE_INSTALL_PREFIX="$PWD/artifacts" \
-DWASMTIME_DISABLE_ALL_FEATURES=ON \
-DWASMTIME_FEATURE_CRANELIFT=ON \
-DWASMTIME_TARGET='x86_64-pc-windows-gnu'
cmake --build target/c-api && cmake --install target/c-api
printf 'CMAKE_PREFIX_PATH=%s\n' "$PWD/artifacts" >> $GITHUB_ENV
env:
WASMTIME_REPO: https://github.com/bytecodealliance/wasmtime
RUSTFLAGS: ${{ env.RUSTFLAGS }} --cap-lints allow
printf '%s\n' >> $GITHUB_ENV \ - name: Build C library (Windows x64 MSYS2 CMake)
'TREE_SITTER=tree-sitter.sh' \ if: matrix.platform == 'windows-x64'
"TARGET=$TARGET" \ shell: msys2 {0}
"ROOT=$PWD" run: |
cmake -G Ninja -S . -B build/static \
-DBUILD_SHARED_LIBS=OFF \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_COMPILE_WARNING_AS_ERROR=ON \
-DTREE_SITTER_FEATURE_WASM=$WASM \
-DCMAKE_C_COMPILER=clang
cmake --build build/static
[[ -n $RUST_TEST_THREADS ]] && \ cmake -G Ninja -S . -B build/shared \
printf 'RUST_TEST_THREADS=%s\n' "$RUST_TEST_THREADS" >> $GITHUB_ENV -DBUILD_SHARED_LIBS=ON \
-DCMAKE_BUILD_TYPE=Debug \
[[ -n $CC ]] && printf 'CC=%s\n' "$CC" >> $GITHUB_ENV -DCMAKE_COMPILE_WARNING_AS_ERROR=ON \
[[ -n $AR ]] && printf 'AR=%s\n' "$AR" >> $GITHUB_ENV -DTREE_SITTER_FEATURE_WASM=$WASM \
-DCMAKE_C_COMPILER=clang
if [[ $USE_CROSS == true ]]; then cmake --build build/shared
printf 'BUILD_CMD=cross\n' >> $GITHUB_ENV rm -rf \
runner=$(cross.sh bash -c "env | sed -n 's/^CARGO_TARGET_.*_RUNNER=//p'") build/{static,shared} \
[[ -n $runner ]] && printf 'CROSS_RUNNER=%s\n' "$runner" >> $GITHUB_ENV "${CMAKE_PREFIX_PATH}/artifacts" \
fi target/wasmtime-${WASMTIME_VERSION}
env:
WASM: ${{ contains(matrix.features, 'wasm') && 'ON' || 'OFF' }}
# TODO: Remove RUSTFLAGS="--cap-lints allow" once we use a wasmtime release that addresses
# the `mismatched-lifetime-syntaxes` lint
- name: Build wasmtime library - name: Build wasmtime library
if: ${{ !matrix.use-cross && contains(matrix.features, 'wasm') }} if: contains(matrix.features, 'wasm')
run: | run: |
mkdir -p target mkdir -p target
WASMTIME_VERSION=$(cargo metadata --format-version=1 --locked --features wasm | \ WASMTIME_VERSION=$(cargo metadata --format-version=1 --locked --features wasm | \
@ -156,36 +190,47 @@ jobs:
printf 'CMAKE_PREFIX_PATH=%s\n' "$PWD/artifacts" >> $GITHUB_ENV printf 'CMAKE_PREFIX_PATH=%s\n' "$PWD/artifacts" >> $GITHUB_ENV
env: env:
WASMTIME_REPO: https://github.com/bytecodealliance/wasmtime WASMTIME_REPO: https://github.com/bytecodealliance/wasmtime
RUSTFLAGS: ${{ env.RUSTFLAGS }} --cap-lints allow
- name: Build C library (make) - name: Build C library (make)
if: ${{ runner.os != 'Windows' }} if: runner.os != 'Windows'
run: make.sh -j CFLAGS="$CFLAGS" run: |
if [[ $PLATFORM == linux-arm ]]; then
CC=arm-linux-gnueabihf-gcc; AR=arm-linux-gnueabihf-ar
elif [[ $PLATFORM == linux-x86 ]]; then
CC=i686-linux-gnu-gcc; AR=i686-linux-gnu-ar
elif [[ $PLATFORM == linux-powerpc64 ]]; then
CC=powerpc64-linux-gnu-gcc; AR=powerpc64-linux-gnu-ar
else
CC=gcc; AR=ar
fi
make -j CFLAGS="$CFLAGS" CC=$CC AR=$AR
env: env:
PLATFORM: ${{ matrix.platform }}
CFLAGS: -g -Werror -Wall -Wextra -Wshadow -Wpedantic -Werror=incompatible-pointer-types CFLAGS: -g -Werror -Wall -Wextra -Wshadow -Wpedantic -Werror=incompatible-pointer-types
- name: Build C library (CMake) - name: Build C library (CMake)
if: ${{ !matrix.use-cross }} if: "!matrix.cross"
run: | run: |
cmake -S lib -B build/static \ cmake -S . -B build/static \
-DBUILD_SHARED_LIBS=OFF \ -DBUILD_SHARED_LIBS=OFF \
-DCMAKE_BUILD_TYPE=Debug \ -DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_COMPILE_WARNING_AS_ERROR=ON \ -DCMAKE_COMPILE_WARNING_AS_ERROR=ON \
-DTREE_SITTER_FEATURE_WASM=$WASM -DTREE_SITTER_FEATURE_WASM=$WASM
cmake --build build/static --verbose cmake --build build/static --verbose
cmake -S lib -B build/shared \ cmake -S . -B build/shared \
-DBUILD_SHARED_LIBS=ON \ -DBUILD_SHARED_LIBS=ON \
-DCMAKE_BUILD_TYPE=Debug \ -DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_COMPILE_WARNING_AS_ERROR=ON \ -DCMAKE_COMPILE_WARNING_AS_ERROR=ON \
-DTREE_SITTER_FEATURE_WASM=$WASM -DTREE_SITTER_FEATURE_WASM=$WASM
cmake --build build/shared --verbose cmake --build build/shared --verbose
env: env:
CC: ${{ contains(matrix.target, 'linux') && 'clang' || '' }} CC: ${{ contains(matrix.platform, 'linux') && 'clang' || '' }}
WASM: ${{ contains(matrix.features, 'wasm') && 'ON' || 'OFF' }} WASM: ${{ contains(matrix.features, 'wasm') && 'ON' || 'OFF' }}
- name: Build wasm library - name: Build Wasm library
# No reason to build on the same Github runner hosts many times if: contains(matrix.features, 'wasm')
if: ${{ !matrix.no-run && !matrix.use-cross }}
shell: bash shell: bash
run: | run: |
cd lib/binding_web cd lib/binding_web
@ -195,64 +240,72 @@ jobs:
npm run build npm run build
npm run build:debug npm run build:debug
- name: Check no_std builds
if: inputs.run-test && !matrix.no-run
working-directory: lib
shell: bash
run: cargo check --no-default-features --target='${{ matrix.target }}'
- name: Build target - name: Build target
run: $BUILD_CMD build --release --target=${{ matrix.target }} --features=${{ matrix.features }} run: cargo build --release --target='${{ matrix.target }}' --features='${{ matrix.features }}' $PACKAGE
env:
PACKAGE: ${{ matrix.platform == 'wasm32' && '-p tree-sitter' || '' }}
- name: Cache fixtures - name: Cache fixtures
id: cache id: cache
if: ${{ !matrix.no-run && inputs.run-test }} if: inputs.run-test && !matrix.no-run
uses: ./.github/actions/cache uses: ./.github/actions/cache
- name: Fetch fixtures - name: Fetch fixtures
if: ${{ !matrix.no-run && inputs.run-test }} if: inputs.run-test && !matrix.no-run
run: $BUILD_CMD run -p xtask -- fetch-fixtures run: cargo run -p xtask --target='${{ matrix.target }}' -- fetch-fixtures
- name: Generate fixtures - name: Generate fixtures
if: ${{ !matrix.no-run && inputs.run-test && steps.cache.outputs.cache-hit != 'true' }} if: inputs.run-test && !matrix.no-run && steps.cache.outputs.cache-hit != 'true'
run: $BUILD_CMD run -p xtask -- generate-fixtures run: cargo run -p xtask --target='${{ matrix.target }}' -- generate-fixtures
- name: Generate Wasm fixtures - name: Generate Wasm fixtures
if: ${{ !matrix.no-run && !matrix.use-cross && inputs.run-test && steps.cache.outputs.cache-hit != 'true' }} if: inputs.run-test && !matrix.no-run && contains(matrix.features, 'wasm') && steps.cache.outputs.cache-hit != 'true'
run: $BUILD_CMD run -p xtask -- generate-fixtures --wasm run: cargo run -p xtask --target='${{ matrix.target }}' -- generate-fixtures --wasm
- name: Run main tests - name: Run main tests
if: ${{ !matrix.no-run && inputs.run-test }} if: inputs.run-test && !matrix.no-run
run: $BUILD_CMD test --target=${{ matrix.target }} --features=${{ matrix.features }} run: cargo test --target='${{ matrix.target }}' --features='${{ matrix.features }}'
- name: Run wasm tests - name: Run Wasm tests
if: ${{ !matrix.no-run && !matrix.use-cross && inputs.run-test }} if: inputs.run-test && !matrix.no-run && contains(matrix.features, 'wasm')
run: $BUILD_CMD run -p xtask -- test-wasm run: cargo run -p xtask --target='${{ matrix.target }}' -- test-wasm
- name: Run benchmarks
# Cross-compiled benchmarks are pointless
if: ${{ !matrix.no-run && !matrix.use-cross && inputs.run-test }}
run: $BUILD_CMD bench benchmark -p tree-sitter-cli --target=${{ matrix.target }}
- name: Upload CLI artifact - name: Upload CLI artifact
uses: actions/upload-artifact@v4 if: "!matrix.no-run"
uses: actions/upload-artifact@v6
with: with:
name: tree-sitter.${{ matrix.platform }} name: tree-sitter.${{ matrix.platform }}
path: target/${{ matrix.target }}/release/tree-sitter${{ env.SUFFIX }} path: target/${{ matrix.target }}/release/tree-sitter${{ contains(matrix.target, 'windows') && '.exe' || '' }}
if-no-files-found: error if-no-files-found: error
retention-days: 7 retention-days: 7
- name: Upload Wasm artifacts - name: Upload Wasm artifacts
if: ${{ matrix.platform == 'linux-x64' }} if: matrix.platform == 'linux-x64'
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v6
with: with:
name: tree-sitter.wasm name: tree-sitter.wasm
path: | path: |
lib/binding_web/tree-sitter.js lib/binding_web/web-tree-sitter.js
lib/binding_web/tree-sitter.js.map lib/binding_web/web-tree-sitter.js.map
lib/binding_web/tree-sitter.cjs lib/binding_web/web-tree-sitter.cjs
lib/binding_web/tree-sitter.cjs.map lib/binding_web/web-tree-sitter.cjs.map
lib/binding_web/tree-sitter.wasm lib/binding_web/web-tree-sitter.wasm
lib/binding_web/tree-sitter.wasm.map lib/binding_web/web-tree-sitter.wasm.map
lib/binding_web/debug/tree-sitter.cjs lib/binding_web/debug/web-tree-sitter.cjs
lib/binding_web/debug/tree-sitter.cjs.map lib/binding_web/debug/web-tree-sitter.cjs.map
lib/binding_web/debug/tree-sitter.js lib/binding_web/debug/web-tree-sitter.js
lib/binding_web/debug/tree-sitter.js.map lib/binding_web/debug/web-tree-sitter.js.map
lib/binding_web/debug/tree-sitter.wasm lib/binding_web/debug/web-tree-sitter.wasm
lib/binding_web/debug/tree-sitter.wasm.map lib/binding_web/debug/web-tree-sitter.wasm.map
lib/binding_web/lib/*.c
lib/binding_web/lib/*.h
lib/binding_web/lib/*.ts
lib/binding_web/src/*.ts
if-no-files-found: error if-no-files-found: error
retention-days: 7 retention-days: 7

View file

@ -26,17 +26,12 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v6
- name: Set up stable Rust toolchain - name: Set up stable Rust toolchain
uses: actions-rust-lang/setup-rust-toolchain@v1 uses: actions-rust-lang/setup-rust-toolchain@v1
with: with:
toolchain: stable toolchain: stable
- name: Set up nightly Rust toolchain
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
toolchain: nightly
components: clippy, rustfmt components: clippy, rustfmt
- name: Lint files - name: Lint files
@ -49,3 +44,6 @@ jobs:
build: build:
uses: ./.github/workflows/build.yml uses: ./.github/workflows/build.yml
check-wasm-stdlib:
uses: ./.github/workflows/wasm_stdlib.yml

View file

@ -3,6 +3,7 @@ on:
push: push:
branches: [master] branches: [master]
paths: [docs/**] paths: [docs/**]
workflow_dispatch:
jobs: jobs:
deploy-docs: deploy-docs:
@ -15,7 +16,7 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v6
- name: Set up Rust - name: Set up Rust
uses: actions-rust-lang/setup-rust-toolchain@v1 uses: actions-rust-lang/setup-rust-toolchain@v1
@ -25,7 +26,7 @@ jobs:
GH_TOKEN: ${{ github.token }} GH_TOKEN: ${{ github.token }}
run: | run: |
jq_expr='.assets[] | select(.name | contains("x86_64-unknown-linux-gnu")) | .browser_download_url' jq_expr='.assets[] | select(.name | contains("x86_64-unknown-linux-gnu")) | .browser_download_url'
url=$(gh api repos/rust-lang/mdbook/releases/latest --jq "$jq_expr") url=$(gh api repos/rust-lang/mdbook/releases/tags/v0.4.52 --jq "$jq_expr")
mkdir mdbook mkdir mdbook
curl -sSL "$url" | tar -xz -C mdbook curl -sSL "$url" | tar -xz -C mdbook
printf '%s/mdbook\n' "$PWD" >> "$GITHUB_PATH" printf '%s/mdbook\n' "$PWD" >> "$GITHUB_PATH"
@ -40,7 +41,7 @@ jobs:
uses: actions/configure-pages@v5 uses: actions/configure-pages@v5
- name: Upload artifact - name: Upload artifact
uses: actions/upload-pages-artifact@v3 uses: actions/upload-pages-artifact@v4
with: with:
path: docs/book path: docs/book

View file

@ -1,30 +0,0 @@
name: Update Emscripten
on:
pull_request:
types: [opened, synchronize]
permissions:
contents: write
pull-requests: read
jobs:
update-emscripten:
if: github.actor == 'dependabot[bot]'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Set up stable Rust toolchain
uses: actions-rust-lang/setup-rust-toolchain@v1
- name: Run emscripten update xtask
run: |
git config --global user.name "dependabot[bot]"
git config --global user.email "49699333+dependabot[bot]@users.noreply.github.com"
cargo xtask upgrade-emscripten
- name: Push updated version
run: git push origin HEAD:$GITHUB_HEAD_REF

View file

@ -3,7 +3,10 @@ name: nvim-treesitter parser tests
on: on:
pull_request: pull_request:
paths: paths:
- 'cli/**' - 'crates/cli/**'
- 'crates/config/**'
- 'crates/generate/**'
- 'crates/loader/**'
- '.github/workflows/nvim_ts.yml' - '.github/workflows/nvim_ts.yml'
workflow_dispatch: workflow_dispatch:
@ -13,7 +16,7 @@ concurrency:
jobs: jobs:
check_compilation: check_compilation:
timeout-minutes: 20 timeout-minutes: 30
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
@ -25,9 +28,9 @@ jobs:
NVIM: ${{ matrix.os == 'windows-latest' && 'nvim-win64\\bin\\nvim.exe' || 'nvim' }} NVIM: ${{ matrix.os == 'windows-latest' && 'nvim-win64\\bin\\nvim.exe' || 'nvim' }}
NVIM_TS_DIR: nvim-treesitter NVIM_TS_DIR: nvim-treesitter
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v6
- uses: actions/checkout@v4 - uses: actions/checkout@v6
with: with:
repository: nvim-treesitter/nvim-treesitter repository: nvim-treesitter/nvim-treesitter
path: ${{ env.NVIM_TS_DIR }} path: ${{ env.NVIM_TS_DIR }}
@ -55,7 +58,7 @@ jobs:
- if: matrix.type == 'build' - if: matrix.type == 'build'
name: Compile parsers name: Compile parsers
run: $NVIM -l ./scripts/install-parsers.lua run: $NVIM -l ./scripts/install-parsers.lua --max-jobs=10
working-directory: ${{ env.NVIM_TS_DIR }} working-directory: ${{ env.NVIM_TS_DIR }}
shell: bash shell: bash

View file

@ -17,13 +17,15 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: build needs: build
permissions: permissions:
id-token: write
attestations: write
contents: write contents: write
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v6
- name: Download build artifacts - name: Download build artifacts
uses: actions/download-artifact@v4 uses: actions/download-artifact@v7
with: with:
path: artifacts path: artifacts
@ -33,26 +35,13 @@ jobs:
- name: Prepare release artifacts - name: Prepare release artifacts
run: | run: |
mkdir -p target mkdir -p target web
mv artifacts/tree-sitter.wasm/* target/ mv artifacts/tree-sitter.wasm/* web/
# Rename files tar -czf target/web-tree-sitter.tar.gz -C web .
mv target/tree-sitter.js target/web-tree-sitter.js
mv target/tree-sitter.js.map target/web-tree-sitter.js.map
mv target/tree-sitter.cjs target/web-tree-sitter.cjs
mv target/tree-sitter.cjs.map target/web-tree-sitter.cjs.map
mv target/tree-sitter.wasm target/web-tree-sitter.wasm
mv target/tree-sitter.wasm.map target/web-tree-sitter.wasm.map
mv target/debug/tree-sitter.js target/web-tree-sitter-debug.js
mv target/debug/tree-sitter.js.map target/web-tree-sitter-debug.js.map
mv target/debug/tree-sitter.cjs target/web-tree-sitter-debug.cjs
mv target/debug/tree-sitter.cjs.map target/web-tree-sitter-debug.cjs.map
mv target/debug/tree-sitter.wasm target/web-tree-sitter-debug.wasm
mv target/debug/tree-sitter.wasm.map target/web-tree-sitter-debug.wasm.map
rm -rf target/debug
rm -r artifacts/tree-sitter.wasm rm -r artifacts/tree-sitter.wasm
for platform in $(cd artifacts; ls | sed 's/^tree-sitter\.//'); do for platform in $(cd artifacts; ls | sed 's/^tree-sitter\.//'); do
exe=$(ls artifacts/tree-sitter.$platform/tree-sitter*) exe=$(ls artifacts/tree-sitter.$platform/tree-sitter*)
gzip --stdout --name $exe > target/tree-sitter-$platform.gz gzip --stdout --name $exe > target/tree-sitter-$platform.gz
@ -60,57 +49,65 @@ jobs:
rm -rf artifacts rm -rf artifacts
ls -l target/ ls -l target/
- name: Generate attestations
uses: actions/attest-build-provenance@v3
with:
subject-path: |
target/tree-sitter-*.gz
target/web-tree-sitter.tar.gz
- name: Create release - name: Create release
run: |- run: |-
gh release create ${{ github.ref_name }} \ gh release create $GITHUB_REF_NAME \
target/tree-sitter-*.gz \ target/tree-sitter-*.gz \
target/web-tree-sitter.js \ target/web-tree-sitter.tar.gz
target/web-tree-sitter.js.map \
target/web-tree-sitter.cjs \
target/web-tree-sitter.cjs.map \
target/web-tree-sitter.wasm \
target/web-tree-sitter.wasm.map \
target/web-tree-sitter-debug.js \
target/web-tree-sitter-debug.js.map \
target/web-tree-sitter-debug.cjs \
target/web-tree-sitter-debug.cjs.map \
target/web-tree-sitter-debug.wasm \
target/web-tree-sitter-debug.wasm.map
env: env:
GH_TOKEN: ${{ github.token }} GH_TOKEN: ${{ github.token }}
crates_io: crates_io:
name: Publish packages to Crates.io name: Publish packages to Crates.io
runs-on: ubuntu-latest runs-on: ubuntu-latest
environment: crates
permissions:
id-token: write
contents: read
needs: release needs: release
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v6
- name: Set up Rust - name: Set up Rust
uses: actions-rust-lang/setup-rust-toolchain@v1 uses: actions-rust-lang/setup-rust-toolchain@v1
- name: Set up registry token
id: auth
uses: rust-lang/crates-io-auth-action@v1
- name: Publish crates to Crates.io - name: Publish crates to Crates.io
uses: katyo/publish-crates@v2 uses: katyo/publish-crates@v2
with: with:
registry-token: ${{ secrets.CARGO_REGISTRY_TOKEN }} registry-token: ${{ steps.auth.outputs.token }}
npm: npm:
name: Publish packages to npmjs.com name: Publish packages to npmjs.com
runs-on: ubuntu-latest runs-on: ubuntu-latest
environment: npm
permissions:
id-token: write
contents: read
needs: release needs: release
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
directory: [cli/npm, lib/binding_web] directory: [crates/cli/npm, lib/binding_web]
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v6
- name: Set up Node - name: Set up Node
uses: actions/setup-node@v4 uses: actions/setup-node@v6
with: with:
node-version: 20 node-version: 24
registry-url: https://registry.npmjs.org registry-url: https://registry.npmjs.org
- name: Set up Rust - name: Set up Rust
@ -125,9 +122,8 @@ jobs:
npm run build:debug npm run build:debug
CJS=true npm run build CJS=true npm run build
CJS=true npm run build:debug CJS=true npm run build:debug
npm run build:dts
- name: Publish to npmjs.com - name: Publish to npmjs.com
working-directory: ${{ matrix.directory }} working-directory: ${{ matrix.directory }}
run: npm publish run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

View file

@ -17,13 +17,13 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout script - name: Checkout script
uses: actions/checkout@v4 uses: actions/checkout@v6
with: with:
sparse-checkout: .github/scripts/close_unresponsive.js sparse-checkout: .github/scripts/close_unresponsive.js
sparse-checkout-cone-mode: false sparse-checkout-cone-mode: false
- name: Run script - name: Run script
uses: actions/github-script@v7 uses: actions/github-script@v8
with: with:
script: | script: |
const script = require('./.github/scripts/close_unresponsive.js') const script = require('./.github/scripts/close_unresponsive.js')
@ -35,13 +35,13 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout script - name: Checkout script
uses: actions/checkout@v4 uses: actions/checkout@v6
with: with:
sparse-checkout: .github/scripts/remove_response_label.js sparse-checkout: .github/scripts/remove_response_label.js
sparse-checkout-cone-mode: false sparse-checkout-cone-mode: false
- name: Run script - name: Run script
uses: actions/github-script@v7 uses: actions/github-script@v8
with: with:
script: | script: |
const script = require('./.github/scripts/remove_response_label.js') const script = require('./.github/scripts/remove_response_label.js')

View file

@ -12,13 +12,13 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout script - name: Checkout script
uses: actions/checkout@v4 uses: actions/checkout@v6
with: with:
sparse-checkout: .github/scripts/reviewers_remove.js sparse-checkout: .github/scripts/reviewers_remove.js
sparse-checkout-cone-mode: false sparse-checkout-cone-mode: false
- name: Run script - name: Run script
uses: actions/github-script@v7 uses: actions/github-script@v8
with: with:
script: | script: |
const script = require('./.github/scripts/reviewers_remove.js') const script = require('./.github/scripts/reviewers_remove.js')

View file

@ -15,7 +15,7 @@ jobs:
TREE_SITTER: ${{ github.workspace }}/target/release/tree-sitter TREE_SITTER: ${{ github.workspace }}/target/release/tree-sitter
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v6
- name: Install UBSAN library - name: Install UBSAN library
run: sudo apt-get update -y && sudo apt-get install -y libubsan1 run: sudo apt-get update -y && sudo apt-get install -y libubsan1

29
.github/workflows/spam.yml vendored Normal file
View file

@ -0,0 +1,29 @@
name: Close as spam
on:
issues:
types: [labeled]
pull_request_target:
types: [labeled]
permissions:
issues: write
pull-requests: write
jobs:
spam:
runs-on: ubuntu-latest
if: github.event.label.name == 'spam'
steps:
- name: Checkout script
uses: actions/checkout@v6
with:
sparse-checkout: .github/scripts/close_spam.js
sparse-checkout-cone-mode: false
- name: Run script
uses: actions/github-script@v8
with:
script: |
const script = require('./.github/scripts/close_spam.js')
await script({github, context})

View file

@ -1,23 +1,24 @@
name: Check WASM Exports name: Check Wasm Exports
on: on:
pull_request: pull_request:
paths: paths:
- lib/include/tree_sitter/api.h - lib/include/tree_sitter/api.h
- lib/binding_web/** - lib/binding_web/**
- xtask/src/**
push: push:
branches: [master] branches: [master]
paths: paths:
- lib/include/tree_sitter/api.h - lib/include/tree_sitter/api.h
- lib/binding_rust/bindings.rs - lib/binding_rust/bindings.rs
- lib/CMakeLists.txt - CMakeLists.txt
jobs: jobs:
check-wasm-exports: check-wasm-exports:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v6
- name: Set up stable Rust toolchain - name: Set up stable Rust toolchain
uses: actions-rust-lang/setup-rust-toolchain@v1 uses: actions-rust-lang/setup-rust-toolchain@v1
@ -32,9 +33,9 @@ jobs:
env: env:
CFLAGS: -g -Werror -Wall -Wextra -Wshadow -Wpedantic -Werror=incompatible-pointer-types CFLAGS: -g -Werror -Wall -Wextra -Wshadow -Wpedantic -Werror=incompatible-pointer-types
- name: Build WASM Library - name: Build Wasm Library
working-directory: lib/binding_web working-directory: lib/binding_web
run: npm ci && npm run build:debug run: npm ci && npm run build:debug
- name: Check WASM exports - name: Check Wasm exports
run: cargo xtask check-wasm-exports run: cargo xtask check-wasm-exports

19
.github/workflows/wasm_stdlib.yml vendored Normal file
View file

@ -0,0 +1,19 @@
name: Check Wasm Stdlib build
on:
workflow_call:
jobs:
check:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Check directory changes
uses: actions/github-script@v8
with:
script: |
const scriptPath = `${process.env.GITHUB_WORKSPACE}/.github/scripts/wasm_stdlib.js`;
const script = require(scriptPath);
return script({ github, context, core });

5
.gitignore vendored
View file

@ -1,10 +1,12 @@
log*.html log*.html
.direnv
.idea .idea
*.xcodeproj *.xcodeproj
.vscode .vscode
.cache .cache
.zig-cache .zig-cache
.direnv
profile* profile*
fuzz-results fuzz-results
@ -24,6 +26,7 @@ docs/assets/js/tree-sitter.js
*.dylib *.dylib
*.so *.so
*.so.[0-9]* *.so.[0-9]*
*.dll
*.o *.o
*.obj *.obj
*.exp *.exp
@ -33,3 +36,5 @@ docs/assets/js/tree-sitter.js
.build .build
build build
zig-* zig-*
/result

11
.zed/settings.json Normal file
View file

@ -0,0 +1,11 @@
{
"lsp": {
"rust-analyzer": {
"initialization_options": {
"cargo": {
"features": "all"
}
}
}
}
}

View file

@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.13) cmake_minimum_required(VERSION 3.13)
project(tree-sitter project(tree-sitter
VERSION "0.25.1" VERSION "0.27.0"
DESCRIPTION "An incremental parsing system for programming tools" DESCRIPTION "An incremental parsing system for programming tools"
HOMEPAGE_URL "https://tree-sitter.github.io/tree-sitter/" HOMEPAGE_URL "https://tree-sitter.github.io/tree-sitter/"
LANGUAGES C) LANGUAGES C)
@ -11,15 +11,15 @@ option(TREE_SITTER_FEATURE_WASM "Enable the Wasm feature" OFF)
option(AMALGAMATED "Build using an amalgamated source" OFF) option(AMALGAMATED "Build using an amalgamated source" OFF)
if(AMALGAMATED) if(AMALGAMATED)
set(TS_SOURCE_FILES "${PROJECT_SOURCE_DIR}/src/lib.c") set(TS_SOURCE_FILES "${PROJECT_SOURCE_DIR}/lib/src/lib.c")
else() else()
file(GLOB TS_SOURCE_FILES src/*.c) file(GLOB TS_SOURCE_FILES lib/src/*.c)
list(REMOVE_ITEM TS_SOURCE_FILES "${PROJECT_SOURCE_DIR}/src/lib.c") list(REMOVE_ITEM TS_SOURCE_FILES "${PROJECT_SOURCE_DIR}/lib/src/lib.c")
endif() endif()
add_library(tree-sitter ${TS_SOURCE_FILES}) add_library(tree-sitter ${TS_SOURCE_FILES})
target_include_directories(tree-sitter PRIVATE src src/wasm include) target_include_directories(tree-sitter PRIVATE lib/src lib/src/wasm PUBLIC lib/include)
if(MSVC) if(MSVC)
target_compile_options(tree-sitter PRIVATE target_compile_options(tree-sitter PRIVATE
@ -81,15 +81,15 @@ set_target_properties(tree-sitter
SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}" SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}"
DEFINE_SYMBOL "") DEFINE_SYMBOL "")
target_compile_definitions(tree-sitter PRIVATE _POSIX_C_SOURCE=200112L _DEFAULT_SOURCE) target_compile_definitions(tree-sitter PRIVATE _POSIX_C_SOURCE=200112L _DEFAULT_SOURCE _BSD_SOURCE _DARWIN_C_SOURCE)
configure_file(tree-sitter.pc.in "${CMAKE_CURRENT_BINARY_DIR}/tree-sitter.pc" @ONLY)
include(GNUInstallDirs) include(GNUInstallDirs)
install(FILES include/tree_sitter/api.h configure_file(lib/tree-sitter.pc.in "${CMAKE_CURRENT_BINARY_DIR}/tree-sitter.pc" @ONLY)
install(FILES lib/include/tree_sitter/api.h
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/tree_sitter") DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/tree_sitter")
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/tree-sitter.pc" install(FILES "${CMAKE_CURRENT_BINARY_DIR}/tree-sitter.pc"
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig") DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
install(TARGETS tree-sitter install(TARGETS tree-sitter
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}") LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}")

1939
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,25 +1,26 @@
[workspace] [workspace]
default-members = ["cli"] default-members = ["crates/cli"]
members = [ members = [
"cli", "crates/cli",
"cli/config", "crates/config",
"cli/loader", "crates/generate",
"crates/highlight",
"crates/loader",
"crates/tags",
"crates/xtask",
"crates/language",
"lib", "lib",
"lib/language",
"tags",
"highlight",
"xtask",
] ]
resolver = "2" resolver = "2"
[workspace.package] [workspace.package]
version = "0.25.1" version = "0.27.0"
authors = [ authors = [
"Max Brunsfeld <maxbrunsfeld@gmail.com>", "Max Brunsfeld <maxbrunsfeld@gmail.com>",
"Amaan Qureshi <amaanq12@gmail.com>", "Amaan Qureshi <amaanq12@gmail.com>",
] ]
edition = "2021" edition = "2021"
rust-version = "1.82" rust-version = "1.85"
homepage = "https://tree-sitter.github.io/tree-sitter" homepage = "https://tree-sitter.github.io/tree-sitter"
repository = "https://github.com/tree-sitter/tree-sitter" repository = "https://github.com/tree-sitter/tree-sitter"
license = "MIT" license = "MIT"
@ -59,6 +60,8 @@ missing_errors_doc = "allow"
missing_panics_doc = "allow" missing_panics_doc = "allow"
module_name_repetitions = "allow" module_name_repetitions = "allow"
multiple_crate_versions = "allow" multiple_crate_versions = "allow"
needless_for_each = "allow"
obfuscated_if_else = "allow"
option_if_let_else = "allow" option_if_let_else = "allow"
or_fun_call = "allow" or_fun_call = "allow"
range_plus_one = "allow" range_plus_one = "allow"
@ -75,6 +78,9 @@ unnecessary_wraps = "allow"
unused_self = "allow" unused_self = "allow"
used_underscore_items = "allow" used_underscore_items = "allow"
[workspace.lints.rust]
mismatched_lifetime_syntaxes = "allow"
[profile.optimize] [profile.optimize]
inherits = "release" inherits = "release"
strip = true # Automatically strip symbols from the binary. strip = true # Automatically strip symbols from the binary.
@ -97,61 +103,61 @@ codegen-units = 256
[workspace.dependencies] [workspace.dependencies]
ansi_colours = "1.2.3" ansi_colours = "1.2.3"
anstyle = "1.0.10" anstyle = "1.0.13"
anyhow = "1.0.95" anyhow = "1.0.100"
bstr = "1.11.3" bstr = "1.12.0"
cc = "1.2.10" cc = "1.2.53"
clap = { version = "4.5.27", features = [ clap = { version = "4.5.54", features = [
"cargo", "cargo",
"derive", "derive",
"env", "env",
"help", "help",
"string",
"unstable-styles", "unstable-styles",
] } ] }
clap_complete = "4.5.42" clap_complete = "4.5.65"
clap_complete_nushell = "4.5.5" clap_complete_nushell = "4.5.10"
crc32fast = "1.5.0"
ctor = "0.2.9" ctor = "0.2.9"
ctrlc = { version = "3.4.5", features = ["termination"] } ctrlc = { version = "3.5.0", features = ["termination"] }
dialoguer = { version = "0.11.0", features = ["fuzzy-select"] } dialoguer = { version = "0.11.0", features = ["fuzzy-select"] }
etcetera = "0.8.0" etcetera = "0.11.0"
filetime = "0.2.25"
fs4 = "0.12.0" fs4 = "0.12.0"
git2 = "0.20.0" glob = "0.3.3"
glob = "0.3.2"
heck = "0.5.0" heck = "0.5.0"
html-escape = "0.2.13" html-escape = "0.2.13"
indexmap = "2.7.1" indexmap = "2.12.1"
indoc = "2.0.5" indoc = "2.0.6"
libloading = "0.8.6" libloading = "0.9.0"
log = { version = "0.4.25", features = ["std"] } log = { version = "0.4.28", features = ["std"] }
memchr = "2.7.4" memchr = "2.7.6"
once_cell = "1.20.2" once_cell = "1.21.3"
path-slash = "0.2.1"
pretty_assertions = "1.4.1" pretty_assertions = "1.4.1"
rand = "0.8.5" rand = "0.8.5"
regex = "1.11.1" regex = "1.11.3"
regex-syntax = "0.8.5" regex-syntax = "0.8.6"
rustc-hash = "2.1.0" rustc-hash = "2.1.1"
semver = { version = "1.0.25", features = ["serde"] } schemars = "1.0.5"
serde = { version = "1.0.217", features = ["derive"] } semver = { version = "1.0.27", features = ["serde"] }
serde_derive = "1.0.217" serde = { version = "1.0.219", features = ["derive"] }
serde_json = { version = "1.0.137", features = ["preserve_order"] } serde_json = { version = "1.0.149", features = ["preserve_order"] }
similar = "2.7.0" similar = "2.7.0"
smallbitvec = "2.5.3" smallbitvec = "2.6.0"
streaming-iterator = "0.1.9" streaming-iterator = "0.1.9"
tempfile = "3.15.0" tempfile = "3.23.0"
thiserror = "2.0.11" thiserror = "2.0.17"
tiny_http = "0.12.0" tiny_http = "0.12.0"
toml = "0.8.19" topological-sort = "0.2.2"
unindent = "0.2.3" unindent = "0.2.4"
url = { version = "2.5.4", features = ["serde"] }
walkdir = "2.5.0" walkdir = "2.5.0"
wasmparser = "0.224.0" wasmparser = "0.243.0"
webbrowser = "1.0.3" webbrowser = "1.0.5"
tree-sitter = { version = "0.25.1", path = "./lib" } tree-sitter = { version = "0.27.0", path = "./lib" }
tree-sitter-generate = { version = "0.25.1", path = "./cli/generate" } tree-sitter-generate = { version = "0.27.0", path = "./crates/generate" }
tree-sitter-loader = { version = "0.25.1", path = "./cli/loader" } tree-sitter-loader = { version = "0.27.0", path = "./crates/loader" }
tree-sitter-config = { version = "0.25.1", path = "./cli/config" } tree-sitter-config = { version = "0.27.0", path = "./crates/config" }
tree-sitter-highlight = { version = "0.25.1", path = "./highlight" } tree-sitter-highlight = { version = "0.27.0", path = "./crates/highlight" }
tree-sitter-tags = { version = "0.25.1", path = "./tags" } tree-sitter-tags = { version = "0.27.0", path = "./crates/tags" }
tree-sitter-language = { version = "0.1", path = "./crates/language" }

View file

@ -1,6 +1,6 @@
The MIT License (MIT) The MIT License (MIT)
Copyright (c) 2018-2024 Max Brunsfeld Copyright (c) 2018 Max Brunsfeld
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View file

@ -1,8 +1,4 @@
ifeq ($(OS),Windows_NT) VERSION := 0.27.0
$(error Windows is not supported)
endif
VERSION := 0.25.1
DESCRIPTION := An incremental parsing system for programming tools DESCRIPTION := An incremental parsing system for programming tools
HOMEPAGE_URL := https://tree-sitter.github.io/tree-sitter/ HOMEPAGE_URL := https://tree-sitter.github.io/tree-sitter/
@ -10,6 +6,7 @@ HOMEPAGE_URL := https://tree-sitter.github.io/tree-sitter/
PREFIX ?= /usr/local PREFIX ?= /usr/local
INCLUDEDIR ?= $(PREFIX)/include INCLUDEDIR ?= $(PREFIX)/include
LIBDIR ?= $(PREFIX)/lib LIBDIR ?= $(PREFIX)/lib
BINDIR ?= $(PREFIX)/bin
PCLIBDIR ?= $(LIBDIR)/pkgconfig PCLIBDIR ?= $(LIBDIR)/pkgconfig
# collect sources # collect sources
@ -27,7 +24,7 @@ OBJ := $(SRC:.c=.o)
ARFLAGS := rcs ARFLAGS := rcs
CFLAGS ?= -O3 -Wall -Wextra -Wshadow -Wpedantic -Werror=incompatible-pointer-types CFLAGS ?= -O3 -Wall -Wextra -Wshadow -Wpedantic -Werror=incompatible-pointer-types
override CFLAGS += -std=c11 -fPIC -fvisibility=hidden override CFLAGS += -std=c11 -fPIC -fvisibility=hidden
override CFLAGS += -D_POSIX_C_SOURCE=200112L -D_DEFAULT_SOURCE override CFLAGS += -D_POSIX_C_SOURCE=200112L -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_DARWIN_C_SOURCE
override CFLAGS += -Ilib/src -Ilib/src/wasm -Ilib/include override CFLAGS += -Ilib/src -Ilib/src/wasm -Ilib/include
# ABI versioning # ABI versioning
@ -35,20 +32,25 @@ SONAME_MAJOR := $(word 1,$(subst ., ,$(VERSION)))
SONAME_MINOR := $(word 2,$(subst ., ,$(VERSION))) SONAME_MINOR := $(word 2,$(subst ., ,$(VERSION)))
# OS-specific bits # OS-specific bits
ifneq ($(findstring darwin,$(shell $(CC) -dumpmachine)),) MACHINE := $(shell $(CC) -dumpmachine)
ifneq ($(findstring darwin,$(MACHINE)),)
SOEXT = dylib SOEXT = dylib
SOEXTVER_MAJOR = $(SONAME_MAJOR).$(SOEXT) SOEXTVER_MAJOR = $(SONAME_MAJOR).$(SOEXT)
SOEXTVER = $(SONAME_MAJOR).$(SONAME_MINOR).$(SOEXT) SOEXTVER = $(SONAME_MAJOR).$(SONAME_MINOR).$(SOEXT)
LINKSHARED += -dynamiclib -Wl,-install_name,$(LIBDIR)/libtree-sitter.$(SOEXTVER) LINKSHARED += -dynamiclib -Wl,-install_name,$(LIBDIR)/libtree-sitter.$(SOEXTVER)
else ifneq ($(findstring mingw32,$(MACHINE)),)
SOEXT = dll
LINKSHARED += -s -shared -Wl,--out-implib,libtree-sitter.dll.a
else else
SOEXT = so SOEXT = so
SOEXTVER_MAJOR = $(SOEXT).$(SONAME_MAJOR) SOEXTVER_MAJOR = $(SOEXT).$(SONAME_MAJOR)
SOEXTVER = $(SOEXT).$(SONAME_MAJOR).$(SONAME_MINOR) SOEXTVER = $(SOEXT).$(SONAME_MAJOR).$(SONAME_MINOR)
LINKSHARED += -shared -Wl,-soname,libtree-sitter.$(SOEXTVER) LINKSHARED += -shared -Wl,-soname,libtree-sitter.$(SOEXTVER)
endif
ifneq ($(filter $(shell uname),FreeBSD NetBSD DragonFly),) ifneq ($(filter $(shell uname),FreeBSD NetBSD DragonFly),)
PCLIBDIR := $(PREFIX)/libdata/pkgconfig PCLIBDIR := $(PREFIX)/libdata/pkgconfig
endif endif
endif
all: libtree-sitter.a libtree-sitter.$(SOEXT) tree-sitter.pc all: libtree-sitter.a libtree-sitter.$(SOEXT) tree-sitter.pc
@ -61,6 +63,10 @@ ifneq ($(STRIP),)
$(STRIP) $@ $(STRIP) $@
endif endif
ifneq ($(findstring mingw32,$(MACHINE)),)
libtree-sitter.dll.a: libtree-sitter.$(SOEXT)
endif
tree-sitter.pc: lib/tree-sitter.pc.in tree-sitter.pc: lib/tree-sitter.pc.in
sed -e 's|@PROJECT_VERSION@|$(VERSION)|' \ sed -e 's|@PROJECT_VERSION@|$(VERSION)|' \
-e 's|@CMAKE_INSTALL_LIBDIR@|$(LIBDIR:$(PREFIX)/%=%)|' \ -e 's|@CMAKE_INSTALL_LIBDIR@|$(LIBDIR:$(PREFIX)/%=%)|' \
@ -69,17 +75,27 @@ tree-sitter.pc: lib/tree-sitter.pc.in
-e 's|@PROJECT_HOMEPAGE_URL@|$(HOMEPAGE_URL)|' \ -e 's|@PROJECT_HOMEPAGE_URL@|$(HOMEPAGE_URL)|' \
-e 's|@CMAKE_INSTALL_PREFIX@|$(PREFIX)|' $< > $@ -e 's|@CMAKE_INSTALL_PREFIX@|$(PREFIX)|' $< > $@
shared: libtree-sitter.$(SOEXT)
static: libtree-sitter.a
clean: clean:
$(RM) $(OBJ) tree-sitter.pc libtree-sitter.a libtree-sitter.$(SOEXT) $(RM) $(OBJ) tree-sitter.pc libtree-sitter.a libtree-sitter.$(SOEXT) libtree-stitter.dll.a
install: all install: all
install -d '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter '$(DESTDIR)$(PCLIBDIR)' '$(DESTDIR)$(LIBDIR)' install -d '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter '$(DESTDIR)$(PCLIBDIR)' '$(DESTDIR)$(LIBDIR)'
install -m644 lib/include/tree_sitter/api.h '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter/api.h install -m644 lib/include/tree_sitter/api.h '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter/api.h
install -m644 tree-sitter.pc '$(DESTDIR)$(PCLIBDIR)'/tree-sitter.pc install -m644 tree-sitter.pc '$(DESTDIR)$(PCLIBDIR)'/tree-sitter.pc
install -m644 libtree-sitter.a '$(DESTDIR)$(LIBDIR)'/libtree-sitter.a install -m644 libtree-sitter.a '$(DESTDIR)$(LIBDIR)'/libtree-sitter.a
ifneq ($(findstring mingw32,$(MACHINE)),)
install -d '$(DESTDIR)$(BINDIR)'
install -m755 libtree-sitter.dll '$(DESTDIR)$(BINDIR)'/libtree-sitter.dll
install -m755 libtree-sitter.dll.a '$(DESTDIR)$(LIBDIR)'/libtree-sitter.dll.a
else
install -m755 libtree-sitter.$(SOEXT) '$(DESTDIR)$(LIBDIR)'/libtree-sitter.$(SOEXTVER) install -m755 libtree-sitter.$(SOEXT) '$(DESTDIR)$(LIBDIR)'/libtree-sitter.$(SOEXTVER)
ln -sf libtree-sitter.$(SOEXTVER) '$(DESTDIR)$(LIBDIR)'/libtree-sitter.$(SOEXTVER_MAJOR) cd '$(DESTDIR)$(LIBDIR)' && ln -sf libtree-sitter.$(SOEXTVER) libtree-sitter.$(SOEXTVER_MAJOR)
ln -sf libtree-sitter.$(SOEXTVER_MAJOR) '$(DESTDIR)$(LIBDIR)'/libtree-sitter.$(SOEXT) cd '$(DESTDIR)$(LIBDIR)' && ln -sf libtree-sitter.$(SOEXTVER_MAJOR) libtree-sitter.$(SOEXT)
endif
uninstall: uninstall:
$(RM) '$(DESTDIR)$(LIBDIR)'/libtree-sitter.a \ $(RM) '$(DESTDIR)$(LIBDIR)'/libtree-sitter.a \
@ -88,8 +104,9 @@ uninstall:
'$(DESTDIR)$(LIBDIR)'/libtree-sitter.$(SOEXT) \ '$(DESTDIR)$(LIBDIR)'/libtree-sitter.$(SOEXT) \
'$(DESTDIR)$(INCLUDEDIR)'/tree_sitter/api.h \ '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter/api.h \
'$(DESTDIR)$(PCLIBDIR)'/tree-sitter.pc '$(DESTDIR)$(PCLIBDIR)'/tree-sitter.pc
rmdir '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter
.PHONY: all install uninstall clean .PHONY: all shared static install uninstall clean
##### Dev targets ##### ##### Dev targets #####
@ -106,15 +123,15 @@ test-wasm:
lint: lint:
cargo update --workspace --locked --quiet cargo update --workspace --locked --quiet
cargo check --workspace --all-targets cargo check --workspace --all-targets
cargo +nightly fmt --all --check cargo fmt --all --check
cargo +nightly clippy --workspace --all-targets -- -D warnings cargo clippy --workspace --all-targets -- -D warnings
lint-web: lint-web:
npm --prefix lib/binding_web ci npm --prefix lib/binding_web ci
npm --prefix lib/binding_web run lint npm --prefix lib/binding_web run lint
format: format:
cargo +nightly fmt --all cargo fmt --all
changelog: changelog:
@git-cliff --config .github/cliff.toml --prepend CHANGELOG.md --latest --github-token $(shell gh auth token) @git-cliff --config .github/cliff.toml --prepend CHANGELOG.md --latest --github-token $(shell gh auth token)

View file

@ -27,6 +27,8 @@ let package = Package(
.headerSearchPath("src"), .headerSearchPath("src"),
.define("_POSIX_C_SOURCE", to: "200112L"), .define("_POSIX_C_SOURCE", to: "200112L"),
.define("_DEFAULT_SOURCE"), .define("_DEFAULT_SOURCE"),
.define("_BSD_SOURCE"),
.define("_DARWIN_C_SOURCE"),
]), ]),
], ],
cLanguageStandard: .c11 cLanguageStandard: .c11

View file

@ -14,8 +14,8 @@ Tree-sitter is a parser generator tool and an incremental parsing library. It ca
## Links ## Links
- [Documentation](https://tree-sitter.github.io) - [Documentation](https://tree-sitter.github.io)
- [Rust binding](lib/binding_rust/README.md) - [Rust binding](lib/binding_rust/README.md)
- [WASM binding](lib/binding_web/README.md) - [Wasm binding](lib/binding_web/README.md)
- [Command-line interface](cli/README.md) - [Command-line interface](crates/cli/README.md)
[discord]: https://img.shields.io/discord/1063097320771698699?logo=discord&label=discord [discord]: https://img.shields.io/discord/1063097320771698699?logo=discord&label=discord
[matrix]: https://img.shields.io/matrix/tree-sitter-chat%3Amatrix.org?logo=matrix&label=matrix [matrix]: https://img.shields.io/matrix/tree-sitter-chat%3Amatrix.org?logo=matrix&label=matrix

218
build.zig
View file

@ -1,116 +1,142 @@
const std = @import("std"); const std = @import("std");
pub fn build(b: *std.Build) !void { pub fn build(b: *std.Build) !void {
const target = b.standardTargetOptions(.{}); const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{}); const optimize = b.standardOptimizeOption(.{});
const wasm = b.option(bool, "enable-wasm", "Enable Wasm support") orelse false; const wasm = b.option(bool, "enable-wasm", "Enable Wasm support") orelse false;
const shared = b.option(bool, "build-shared", "Build a shared library") orelse false; const shared = b.option(bool, "build-shared", "Build a shared library") orelse false;
const amalgamated = b.option(bool, "amalgamated", "Build using an amalgamated source") orelse false; const amalgamated = b.option(bool, "amalgamated", "Build using an amalgamated source") orelse false;
const lib: *std.Build.Step.Compile = if (!shared) b.addStaticLibrary(.{ const lib: *std.Build.Step.Compile = b.addLibrary(.{
.name = "tree-sitter", .name = "tree-sitter",
.target = target, .linkage = if (shared) .dynamic else .static,
.optimize = optimize, .root_module = b.createModule(.{
.link_libc = true, .target = target,
}) else b.addSharedLibrary(.{ .optimize = optimize,
.name = "tree-sitter", .link_libc = true,
.pic = true, .pic = if (shared) true else null,
.target = target, }),
.optimize = optimize,
.link_libc = true,
});
if (amalgamated) {
lib.addCSourceFile(.{
.file = b.path("lib/src/lib.c"),
.flags = &.{"-std=c11"},
}); });
} else {
lib.addCSourceFiles(.{
.root = b.path("lib/src"),
.files = try findSourceFiles(b),
.flags = &.{"-std=c11"},
});
}
lib.addIncludePath(b.path("lib/include")); if (amalgamated) {
lib.addIncludePath(b.path("lib/src")); lib.addCSourceFile(.{
lib.addIncludePath(b.path("lib/src/wasm")); .file = b.path("lib/src/lib.c"),
.flags = &.{"-std=c11"},
lib.root_module.addCMacro("_POSIX_C_SOURCE", "200112L"); });
lib.root_module.addCMacro("_DEFAULT_SOURCE", ""); } else {
const files = try findSourceFiles(b);
if (wasm) { defer b.allocator.free(files);
if (b.lazyDependency(wasmtimeDep(target.result), .{})) |wasmtime| { lib.addCSourceFiles(.{
lib.root_module.addCMacro("TREE_SITTER_FEATURE_WASM", ""); .root = b.path("lib/src"),
lib.addSystemIncludePath(wasmtime.path("include")); .files = files,
lib.addLibraryPath(wasmtime.path("lib")); .flags = &.{"-std=c11"},
lib.linkSystemLibrary("wasmtime"); });
} }
}
lib.installHeadersDirectory(b.path("lib/include"), ".", .{}); lib.addIncludePath(b.path("lib/include"));
lib.addIncludePath(b.path("lib/src"));
lib.addIncludePath(b.path("lib/src/wasm"));
b.installArtifact(lib); lib.root_module.addCMacro("_POSIX_C_SOURCE", "200112L");
lib.root_module.addCMacro("_DEFAULT_SOURCE", "");
lib.root_module.addCMacro("_BSD_SOURCE", "");
lib.root_module.addCMacro("_DARWIN_C_SOURCE", "");
if (wasm) {
if (b.lazyDependency(wasmtimeDep(target.result), .{})) |wasmtime| {
lib.root_module.addCMacro("TREE_SITTER_FEATURE_WASM", "");
lib.addSystemIncludePath(wasmtime.path("include"));
lib.addLibraryPath(wasmtime.path("lib"));
if (shared) lib.linkSystemLibrary("wasmtime");
}
}
lib.installHeadersDirectory(b.path("lib/include"), ".", .{});
b.installArtifact(lib);
} }
fn wasmtimeDep(target: std.Target) []const u8 { /// Get the name of the wasmtime dependency for this target.
const arch = target.cpu.arch; pub fn wasmtimeDep(target: std.Target) []const u8 {
const os = target.os.tag; const arch = target.cpu.arch;
const abi = target.abi; const os = target.os.tag;
return switch (os) { const abi = target.abi;
.linux => switch (arch) { return @as(?[]const u8, switch (os) {
.x86_64 => switch (abi) { .linux => switch (arch) {
.gnu => "wasmtime_c_api_x86_64_linux", .x86_64 => switch (abi) {
.musl => "wasmtime_c_api_x86_64_musl", .gnu => "wasmtime_c_api_x86_64_linux",
.android => "wasmtime_c_api_x86_64_android", .musl => "wasmtime_c_api_x86_64_musl",
else => null .android => "wasmtime_c_api_x86_64_android",
}, else => null,
.aarch64 => switch (abi) { },
.gnu => "wasmtime_c_api_aarch64_linux", .aarch64 => switch (abi) {
.android => "wasmtime_c_api_aarch64_android", .gnu => "wasmtime_c_api_aarch64_linux",
else => null .musl => "wasmtime_c_api_aarch64_musl",
}, .android => "wasmtime_c_api_aarch64_android",
.s390x => "wasmtime_c_api_s390x_linux", else => null,
.riscv64 => "wasmtime_c_api_riscv64gc_linux", },
else => null .x86 => switch (abi) {
}, .gnu => "wasmtime_c_api_i686_linux",
.windows => switch (arch) { else => null,
.x86_64 => switch (abi) { },
.gnu => "wasmtime_c_api_x86_64_mingw", .arm => switch (abi) {
.msvc => "wasmtime_c_api_x86_64_windows", .gnueabi => "wasmtime_c_api_armv7_linux",
else => null else => null,
}, },
else => null .s390x => switch (abi) {
}, .gnu => "wasmtime_c_api_s390x_linux",
.macos => switch (arch) { else => null,
.x86_64 => "wasmtime_c_api_x86_64_macos", },
.aarch64 => "wasmtime_c_api_aarch64_macos", .riscv64 => switch (abi) {
else => null .gnu => "wasmtime_c_api_riscv64gc_linux",
}, else => null,
else => null },
} orelse std.debug.panic( else => null,
"Unsupported target for wasmtime: {s}-{s}-{s}", },
.{ @tagName(arch), @tagName(os), @tagName(abi) } .windows => switch (arch) {
); .x86_64 => switch (abi) {
.gnu => "wasmtime_c_api_x86_64_mingw",
.msvc => "wasmtime_c_api_x86_64_windows",
else => null,
},
.aarch64 => switch (abi) {
.msvc => "wasmtime_c_api_aarch64_windows",
else => null,
},
.x86 => switch (abi) {
.msvc => "wasmtime_c_api_i686_windows",
else => null,
},
else => null,
},
.macos => switch (arch) {
.x86_64 => "wasmtime_c_api_x86_64_macos",
.aarch64 => "wasmtime_c_api_aarch64_macos",
else => null,
},
else => null,
}) orelse std.debug.panic(
"Unsupported target for wasmtime: {s}-{s}-{s}",
.{ @tagName(arch), @tagName(os), @tagName(abi) },
);
} }
fn findSourceFiles(b: *std.Build) ![]const []const u8 { fn findSourceFiles(b: *std.Build) ![]const []const u8 {
var sources = std.ArrayList([]const u8).init(b.allocator); var sources: std.ArrayListUnmanaged([]const u8) = .empty;
var dir = try b.build_root.handle.openDir("lib/src", .{ .iterate = true }); var dir = try b.build_root.handle.openDir("lib/src", .{ .iterate = true });
var iter = dir.iterate(); var iter = dir.iterate();
defer dir.close(); defer dir.close();
while (try iter.next()) |entry| { while (try iter.next()) |entry| {
if (entry.kind != .file) continue; if (entry.kind != .file) continue;
const file = entry.name; const file = entry.name;
const ext = std.fs.path.extension(file); const ext = std.fs.path.extension(file);
if (std.mem.eql(u8, ext, ".c") and !std.mem.eql(u8, file, "lib.c")) { if (std.mem.eql(u8, ext, ".c") and !std.mem.eql(u8, file, "lib.c")) {
try sources.append(b.dupe(file)); try sources.append(b.allocator, b.dupe(file));
}
} }
}
return sources.items; return sources.toOwnedSlice(b.allocator);
} }

View file

@ -1,69 +1,96 @@
.{ .{
.name = "tree-sitter", .name = .tree_sitter,
.version = "0.25.1", .fingerprint = 0x841224b447ac0d4f,
.paths = .{ .version = "0.27.0",
"build.zig", .minimum_zig_version = "0.14.1",
"build.zig.zon", .paths = .{
"lib/src", "build.zig",
"lib/include", "build.zig.zon",
"README.md", "lib/src",
"LICENSE", "lib/include",
}, "README.md",
.dependencies = .{ "LICENSE",
.wasmtime_c_api_aarch64_android = .{
.url = "https://github.com/bytecodealliance/wasmtime/releases/download/v29.0.1/wasmtime-v29.0.1-aarch64-android-c-api.tar.xz",
.hash = "12204c77979ad8291c6e395d695a824fb053ffdfeb2cc21de95fffb09f77d77188d1",
.lazy = true,
}, },
.wasmtime_c_api_aarch64_linux = .{ .dependencies = .{
.url = "https://github.com/bytecodealliance/wasmtime/releases/download/v29.0.1/wasmtime-v29.0.1-aarch64-linux-c-api.tar.xz", .wasmtime_c_api_aarch64_android = .{
.hash = "12203a8e3d823490186fb1e230d54f575148713088e914926305ee5678790b731bba", .url = "https://github.com/bytecodealliance/wasmtime/releases/download/v33.0.2/wasmtime-v33.0.2-aarch64-android-c-api.tar.xz",
.lazy = true, .hash = "N-V-__8AAIfPIgdw2YnV3QyiFQ2NHdrxrXzzCdjYJyxJDOta",
.lazy = true,
},
.wasmtime_c_api_aarch64_linux = .{
.url = "https://github.com/bytecodealliance/wasmtime/releases/download/v33.0.2/wasmtime-v33.0.2-aarch64-linux-c-api.tar.xz",
.hash = "N-V-__8AAIt97QZi7Pf7nNJ2mVY6uxA80Klyuvvtop3pLMRK",
.lazy = true,
},
.wasmtime_c_api_aarch64_macos = .{
.url = "https://github.com/bytecodealliance/wasmtime/releases/download/v33.0.2/wasmtime-v33.0.2-aarch64-macos-c-api.tar.xz",
.hash = "N-V-__8AAAO48QQf91w9RmmUDHTja8DrXZA1n6Bmc8waW3qe",
.lazy = true,
},
.wasmtime_c_api_aarch64_musl = .{
.url = "https://github.com/bytecodealliance/wasmtime/releases/download/v33.0.2/wasmtime-v33.0.2-aarch64-musl-c-api.tar.xz",
.hash = "N-V-__8AAI196wa9pwADoA2RbCDp5F7bKQg1iOPq6gIh8-FH",
.lazy = true,
},
.wasmtime_c_api_aarch64_windows = .{
.url = "https://github.com/bytecodealliance/wasmtime/releases/download/v33.0.2/wasmtime-v33.0.2-aarch64-windows-c-api.zip",
.hash = "N-V-__8AAC9u4wXfqd1Q6XyQaC8_DbQZClXux60Vu5743N05",
.lazy = true,
},
.wasmtime_c_api_armv7_linux = .{
.url = "https://github.com/bytecodealliance/wasmtime/releases/download/v33.0.2/wasmtime-v33.0.2-armv7-linux-c-api.tar.xz",
.hash = "N-V-__8AAHXe8gWs3s83Cc5G6SIq0_jWxj8fGTT5xG4vb6-x",
.lazy = true,
},
.wasmtime_c_api_i686_linux = .{
.url = "https://github.com/bytecodealliance/wasmtime/releases/download/v33.0.2/wasmtime-v33.0.2-i686-linux-c-api.tar.xz",
.hash = "N-V-__8AAN2pzgUUfulRCYnipSfis9IIYHoTHVlieLRmKuct",
.lazy = true,
},
.wasmtime_c_api_i686_windows = .{
.url = "https://github.com/bytecodealliance/wasmtime/releases/download/v33.0.2/wasmtime-v33.0.2-i686-windows-c-api.zip",
.hash = "N-V-__8AAJu0YAUUTFBLxFIOi-MSQVezA6MMkpoFtuaf2Quf",
.lazy = true,
},
.wasmtime_c_api_riscv64gc_linux = .{
.url = "https://github.com/bytecodealliance/wasmtime/releases/download/v33.0.2/wasmtime-v33.0.2-riscv64gc-linux-c-api.tar.xz",
.hash = "N-V-__8AAG8m-gc3E3AIImtTZ3l1c7HC6HUWazQ9OH5KACX4",
.lazy = true,
},
.wasmtime_c_api_s390x_linux = .{
.url = "https://github.com/bytecodealliance/wasmtime/releases/download/v33.0.2/wasmtime-v33.0.2-s390x-linux-c-api.tar.xz",
.hash = "N-V-__8AAH314gd-gE4IBp2uvAL3gHeuW1uUZjMiLLeUdXL_",
.lazy = true,
},
.wasmtime_c_api_x86_64_android = .{
.url = "https://github.com/bytecodealliance/wasmtime/releases/download/v33.0.2/wasmtime-v33.0.2-x86_64-android-c-api.tar.xz",
.hash = "N-V-__8AAIPNRwfNkznebrcGb0IKUe7f35bkuZEYOjcx6q3f",
.lazy = true,
},
.wasmtime_c_api_x86_64_linux = .{
.url = "https://github.com/bytecodealliance/wasmtime/releases/download/v33.0.2/wasmtime-v33.0.2-x86_64-linux-c-api.tar.xz",
.hash = "N-V-__8AAI8EDwcyTtk_Afhk47SEaqfpoRqGkJeZpGs69ChF",
.lazy = true,
},
.wasmtime_c_api_x86_64_macos = .{
.url = "https://github.com/bytecodealliance/wasmtime/releases/download/v33.0.2/wasmtime-v33.0.2-x86_64-macos-c-api.tar.xz",
.hash = "N-V-__8AAGtGNgVaOpHSxC22IjrampbRIy6lLwscdcAE8nG1",
.lazy = true,
},
.wasmtime_c_api_x86_64_mingw = .{
.url = "https://github.com/bytecodealliance/wasmtime/releases/download/v33.0.2/wasmtime-v33.0.2-x86_64-mingw-c-api.zip",
.hash = "N-V-__8AAPS2PAbVix50L6lnddlgazCPTz3whLUFk1qnRtnZ",
.lazy = true,
},
.wasmtime_c_api_x86_64_musl = .{
.url = "https://github.com/bytecodealliance/wasmtime/releases/download/v33.0.2/wasmtime-v33.0.2-x86_64-musl-c-api.tar.xz",
.hash = "N-V-__8AAF-WEQe0nzvi09PgusM5i46FIuCKJmIDWUleWgQ3",
.lazy = true,
},
.wasmtime_c_api_x86_64_windows = .{
.url = "https://github.com/bytecodealliance/wasmtime/releases/download/v33.0.2/wasmtime-v33.0.2-x86_64-windows-c-api.zip",
.hash = "N-V-__8AAKGNXwbpJQsn0_6kwSIVDDWifSg8cBzf7T2RzsC9",
.lazy = true,
},
}, },
.wasmtime_c_api_aarch64_macos = .{
.url = "https://github.com/bytecodealliance/wasmtime/releases/download/v29.0.1/wasmtime-v29.0.1-aarch64-macos-c-api.tar.xz",
.hash = "122043e8b19079b855b12674b9e3d4a28dc5c399c43b62fbeb8bdf0fdb4ef2d1d38c",
.lazy = true,
},
.wasmtime_c_api_riscv64gc_linux = .{
.url = "https://github.com/bytecodealliance/wasmtime/releases/download/v29.0.1/wasmtime-v29.0.1-riscv64gc-linux-c-api.tar.xz",
.hash = "12209d07031cf33271bf4b0c63df407b535cd5d65c6402bd6f80d99de439d6feb89b",
.lazy = true,
},
.wasmtime_c_api_s390x_linux = .{
.url = "https://github.com/bytecodealliance/wasmtime/releases/download/v29.0.1/wasmtime-v29.0.1-s390x-linux-c-api.tar.xz",
.hash = "122033f7d9b04f429063d9b2d9ac75a7a00fce02c425e578208f54ddc40edaa1e355",
.lazy = true,
},
.wasmtime_c_api_x86_64_android = .{
.url = "https://github.com/bytecodealliance/wasmtime/releases/download/v29.0.1/wasmtime-v29.0.1-x86_64-android-c-api.tar.xz",
.hash = "122093cb33df8e09e70b2d1dc09897a0388915b942918389b10bf23f9684bdb6f047",
.lazy = true,
},
.wasmtime_c_api_x86_64_linux = .{
.url = "https://github.com/bytecodealliance/wasmtime/releases/download/v29.0.1/wasmtime-v29.0.1-x86_64-linux-c-api.tar.xz",
.hash = "12209210346e94bf6ef8e249fa5d3f1a84f95050ed19665ac8422a15b5f2246d83af",
.lazy = true,
},
.wasmtime_c_api_x86_64_macos = .{
.url = "https://github.com/bytecodealliance/wasmtime/releases/download/v29.0.1/wasmtime-v29.0.1-x86_64-macos-c-api.tar.xz",
.hash = "12208f875dd3a89092485762f3b184707b3cccae85a84e2ffd38c138cc3a3fd90447",
.lazy = true,
},
.wasmtime_c_api_x86_64_mingw = .{
.url = "https://github.com/bytecodealliance/wasmtime/releases/download/v29.0.1/wasmtime-v29.0.1-x86_64-mingw-c-api.zip",
.hash = "1220bea757df3a777b6ec6322fc498e4ece20d466eedc5e2a3610b338849553cd94d",
.lazy = true,
},
.wasmtime_c_api_x86_64_musl = .{
.url = "https://github.com/bytecodealliance/wasmtime/releases/download/v29.0.1/wasmtime-v29.0.1-x86_64-musl-c-api.tar.xz",
.hash = "1220c9596e6a63edcc3234c0611d0cbac724bf30ac9a0fbaf402c7da649b278b1322",
.lazy = true,
},
.wasmtime_c_api_x86_64_windows = .{
.url = "https://github.com/bytecodealliance/wasmtime/releases/download/v29.0.1/wasmtime-v29.0.1-x86_64-windows-c-api.zip",
.hash = "1220440ccb01d72989cf1a47728897a35fc8dd31673cce598f2d62c58e2c3228b0ed",
.lazy = true,
},
}
} }

View file

@ -1,32 +0,0 @@
use std::{env, path::PathBuf, process::Command};
fn main() {
if let Some(git_sha) = read_git_sha() {
println!("cargo:rustc-env=BUILD_SHA={git_sha}");
}
}
// This is copied from the build.rs in parent directory. This should be updated if the
// parent build.rs gets fixes.
fn read_git_sha() -> Option<String> {
let crate_path = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
if !crate_path
.parent()?
.parent()
.is_some_and(|p| p.join(".git").exists())
{
return None;
}
Command::new("git")
.args(["rev-parse", "HEAD"])
.current_dir(crate_path)
.output()
.map_or(None, |output| {
if !output.status.success() {
return None;
}
Some(String::from_utf8_lossy(&output.stdout).to_string())
})
}

View file

@ -1 +0,0 @@

View file

@ -1 +0,0 @@
4.0.1

File diff suppressed because it is too large Load diff

View file

@ -1,30 +0,0 @@
use log::{LevelFilter, Log, Metadata, Record};
#[allow(dead_code)]
struct Logger {
pub filter: Option<String>,
}
impl Log for Logger {
fn enabled(&self, _: &Metadata) -> bool {
true
}
fn log(&self, record: &Record) {
eprintln!(
"[{}] {}",
record
.module_path()
.unwrap_or_default()
.trim_start_matches("rust_tree_sitter_cli::"),
record.args()
);
}
fn flush(&self) {}
}
pub fn init() {
log::set_boxed_logger(Box::new(Logger { filter: None })).unwrap();
log::set_max_level(LevelFilter::Info);
}

View file

@ -1,410 +0,0 @@
<head>
<meta charset="utf-8">
<title>tree-sitter THE_LANGUAGE_NAME</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/6.65.7/codemirror.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/clusterize.js/0.19.0/clusterize.min.css">
<link rel="icon" type="image/png" href="https://tree-sitter.github.io/tree-sitter/assets/images/favicon-32x32.png"
sizes="32x32" />
<link rel="icon" type="image/png" href="https://tree-sitter.github.io/tree-sitter/assets/images/favicon-16x16.png"
sizes="16x16" />
</head>
<body>
<div id="playground-container" style="visibility: hidden;">
<header>
<div class="header-item">
<span class="language-name">Language: THE_LANGUAGE_NAME</span>
</div>
<div class="header-item">
<input id="logging-checkbox" type="checkbox">
<label for="logging-checkbox">log</label>
</div>
<div class="header-item">
<input id="anonymous-nodes-checkbox" type="checkbox">
<label for="anonymous-nodes-checkbox">show anonymous nodes</label>
</div>
<div class="header-item">
<input id="query-checkbox" type="checkbox">
<label for="query-checkbox">query</label>
</div>
<div class="header-item">
<input id="accessibility-checkbox" type="checkbox">
<label for="accessibility-checkbox">accessibility</label>
</div>
<div class="header-item">
<label for="update-time">parse time: </label>
<span id="update-time"></span>
</div>
<div class="header-item">
<a href="https://tree-sitter.github.io/tree-sitter/7-playground.html#about">(?)</a>
</div>
<select id="language-select" style="display: none;">
<option value="parser">Parser</option>
</select>
<div class="header-item">
<button id="theme-toggle" class="theme-toggle" aria-label="Toggle theme">
<svg class="sun-icon" viewBox="0 0 24 24" width="16" height="16">
<path fill="currentColor"
d="M12 17.5a5.5 5.5 0 1 0 0-11 5.5 5.5 0 0 0 0 11zm0 1.5a7 7 0 1 1 0-14 7 7 0 0 1 0 14zm0-16a1 1 0 0 1 1 1v2a1 1 0 1 1-2 0V4a1 1 0 0 1 1-1zm0 15a1 1 0 0 1 1 1v2a1 1 0 1 1-2 0v-2a1 1 0 0 1 1-1zm9-9a1 1 0 0 1-1 1h-2a1 1 0 1 1 0-2h2a1 1 0 0 1 1 1zM4 12a1 1 0 0 1-1 1H1a1 1 0 1 1 0-2h2a1 1 0 0 1 1 1z" />
</svg>
<svg class="moon-icon" viewBox="0 0 24 24" width="16" height="16">
<path fill="currentColor"
d="M12.1 22c-5.5 0-10-4.5-10-10s4.5-10 10-10c.2 0 .3 0 .5.1-1.3 1.4-2 3.2-2 5.2 0 4.1 3.4 7.5 7.5 7.5 2 0 3.8-.7 5.2-2 .1.2.1.3.1.5 0 5.4-4.5 9.7-10 9.7z" />
</svg>
</button>
</div>
</header>
<main>
<div id="input-pane">
<div class="panel-header">Code</div>
<div id="code-container">
<textarea id="code-input"></textarea>
</div>
<div id="query-container" style="visibility: hidden; position: absolute;">
<div class="panel-header">Query</div>
<textarea id="query-input"></textarea>
</div>
</div>
<div id="output-container-scroll">
<div class="panel-header">Tree</div>
<pre id="output-container" class="highlight"></pre>
</div>
</main>
</div>
<script src="https://code.jquery.com/jquery-3.3.1.min.js" crossorigin="anonymous">
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/6.65.7/codemirror.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/clusterize.js/0.19.0/clusterize.min.js"></script>
<script>LANGUAGE_BASE_URL = "";</script>
<script type="module" src="playground.js"></script>
<script type="module">
import * as TreeSitter from './tree-sitter.js';
window.TreeSitter = TreeSitter;
setTimeout(() => window.initializePlayground({local: true}), 1)
</script>
<style>
/* Base Variables */
:root {
--light-bg: #f9f9f9;
--light-border: #e0e0e0;
--light-text: #333;
--light-hover-border: #c1c1c1;
--light-scrollbar-track: #f1f1f1;
--light-scrollbar-thumb: #c1c1c1;
--light-scrollbar-thumb-hover: #a8a8a8;
--dark-bg: #1d1f21;
--dark-border: #2d2d2d;
--dark-text: #c5c8c6;
--dark-panel-bg: #252526;
--dark-code-bg: #1e1e1e;
--dark-scrollbar-track: #25282c;
--dark-scrollbar-thumb: #4a4d51;
--dark-scrollbar-thumb-hover: #5a5d61;
--primary-color: #0550ae;
--primary-color-alpha: rgba(5, 80, 174, 0.1);
--primary-color-alpha-dark: rgba(121, 192, 255, 0.1);
--selection-color: rgba(39, 95, 255, 0.3);
}
/* Theme Colors */
[data-theme="dark"] {
--bg-color: var(--dark-bg);
--border-color: var(--dark-border);
--text-color: var(--dark-text);
--panel-bg: var(--dark-panel-bg);
--code-bg: var(--dark-code-bg);
}
[data-theme="light"] {
--bg-color: var(--light-bg);
--border-color: var(--light-border);
--text-color: var(--light-text);
--panel-bg: white;
--code-bg: white;
}
/* Base Styles */
body {
margin: 0;
padding: 0;
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
background-color: var(--bg-color);
color: var(--text-color);
}
/* Layout */
#playground-container {
width: 100%;
height: 100vh;
display: flex;
flex-direction: column;
background-color: var(--bg-color);
}
header {
padding: 16px 24px;
border-bottom: 1px solid var(--border-color);
display: flex;
align-items: center;
gap: 20px;
background-color: var(--panel-bg);
font-size: 14px;
}
.header-item {
display: flex;
align-items: center;
gap: 8px;
}
.language-name {
font-weight: 600;
}
main {
flex: 1;
display: flex;
overflow: hidden;
}
#input-pane {
width: 50%;
display: flex;
flex-direction: column;
border-right: 1px solid var(--border-color);
background-color: var(--panel-bg);
overflow: hidden;
}
#code-container {
flex: 1;
min-height: 0;
position: relative;
border-bottom: 1px solid var(--border-color);
display: flex;
flex-direction: column;
}
#query-container:not([style*="visibility: hidden"]) {
flex: 1;
min-height: 0;
display: flex;
flex-direction: column;
}
#query-container .panel-header {
flex: 0 0 auto;
}
#query-container .CodeMirror {
flex: 1;
position: relative;
min-height: 0;
}
#output-container-scroll {
width: 50%;
overflow: auto;
background-color: var(--panel-bg);
padding: 0;
display: flex;
flex-direction: column;
}
#output-container {
font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
line-height: 1.5;
margin: 0;
padding: 16px;
}
.panel-header {
padding: 8px 16px;
font-weight: 600;
font-size: 14px;
border-bottom: 1px solid var(--border-color);
background-color: var(--panel-bg);
}
.CodeMirror {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
height: 100%;
font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
font-size: 14px;
line-height: 1.6;
background-color: var(--code-bg) !important;
color: var(--text-color) !important;
}
.query-error {
text-decoration: underline red dashed;
-webkit-text-decoration: underline red dashed;
}
/* Scrollbars */
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-track {
border-radius: 4px;
background: var(--light-scrollbar-track);
}
::-webkit-scrollbar-thumb {
border-radius: 4px;
background: var(--light-scrollbar-thumb);
}
::-webkit-scrollbar-thumb:hover {
background: var(--light-scrollbar-thumb-hover);
}
[data-theme="dark"] {
::-webkit-scrollbar-track {
background: var(--dark-scrollbar-track) !important;
}
::-webkit-scrollbar-thumb {
background: var(--dark-scrollbar-thumb) !important;
}
::-webkit-scrollbar-thumb:hover {
background: var(--dark-scrollbar-thumb-hover) !important;
}
}
/* Theme Toggle */
.theme-toggle {
background: none;
border: 1px solid var(--border-color);
border-radius: 4px;
padding: 6px;
cursor: pointer;
color: var(--text-color);
}
.theme-toggle:hover {
background-color: var(--primary-color-alpha);
}
[data-theme="light"] .moon-icon,
[data-theme="dark"] .sun-icon {
display: none;
}
/* Form Elements */
input[type="checkbox"] {
margin-right: 6px;
vertical-align: middle;
}
label {
font-size: 14px;
margin-right: 16px;
cursor: pointer;
}
#output-container a {
cursor: pointer;
text-decoration: none;
color: #040404;
padding: 2px;
}
#output-container a:hover {
text-decoration: underline;
}
#output-container a.node-link.named {
color: #0550ae;
}
#output-container a.node-link.anonymous {
color: #116329;
}
#output-container a.node-link.anonymous:before {
content: '"';
}
#output-container a.node-link.anonymous:after {
content: '"';
}
#output-container a.node-link.error {
color: #cf222e;
}
#output-container a.highlighted {
background-color: #d9d9d9;
color: red;
border-radius: 3px;
text-decoration: underline;
}
/* Dark Theme Node Colors */
[data-theme="dark"] {
& #output-container a {
color: #d4d4d4;
}
& #output-container a.node-link.named {
color: #79c0ff;
}
& #output-container a.node-link.anonymous {
color: #7ee787;
}
& #output-container a.node-link.error {
color: #ff7b72;
}
& #output-container a.highlighted {
background-color: #373b41;
color: red;
}
& .CodeMirror {
background-color: var(--dark-code-bg) !important;
color: var(--dark-text) !important;
}
& .CodeMirror-gutters {
background-color: var(--dark-panel-bg) !important;
border-color: var(--dark-border) !important;
}
& .CodeMirror-cursor {
border-color: var(--dark-text) !important;
}
& .CodeMirror-selected {
background-color: rgba(255, 255, 255, 0.1) !important;
}
}
</style>
</body>

View file

@ -1,42 +0,0 @@
"""PARSER_DESCRIPTION"""
from importlib.resources import files as _files
from ._binding import language
def _get_query(name, file):
query = _files(f"{__package__}.queries") / file
globals()[name] = query.read_text()
return globals()[name]
def __getattr__(name):
# NOTE: uncomment these to include any queries that this grammar contains:
# if name == "HIGHLIGHTS_QUERY":
# return _get_query("HIGHLIGHTS_QUERY", "highlights.scm")
# if name == "INJECTIONS_QUERY":
# return _get_query("INJECTIONS_QUERY", "injections.scm")
# if name == "LOCALS_QUERY":
# return _get_query("LOCALS_QUERY", "locals.scm")
# if name == "TAGS_QUERY":
# return _get_query("TAGS_QUERY", "tags.scm")
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
__all__ = [
"language",
# "HIGHLIGHTS_QUERY",
# "INJECTIONS_QUERY",
# "LOCALS_QUERY",
# "TAGS_QUERY",
]
def __dir__():
return sorted(__all__ + [
"__all__", "__builtins__", "__cached__", "__doc__", "__file__",
"__loader__", "__name__", "__package__", "__path__", "__spec__",
])

View file

@ -1,10 +0,0 @@
from typing import Final
# NOTE: uncomment these to include any queries that this grammar contains:
# HIGHLIGHTS_QUERY: Final[str]
# INJECTIONS_QUERY: Final[str]
# LOCALS_QUERY: Final[str]
# TAGS_QUERY: Final[str]
def language() -> object: ...

View file

@ -1,9 +0,0 @@
const assert = require("node:assert");
const { test } = require("node:test");
const Parser = require("tree-sitter");
test("can load grammar", () => {
const parser = new Parser();
assert.doesNotThrow(() => parser.setLanguage(require(".")));
});

View file

@ -1,21 +0,0 @@
fn main() {
let src_dir = std::path::Path::new("src");
let mut c_config = cc::Build::new();
c_config.std("c11").include(src_dir);
#[cfg(target_env = "msvc")]
c_config.flag("-utf-8");
let parser_path = src_dir.join("parser.c");
c_config.file(&parser_path);
println!("cargo:rerun-if-changed={}", parser_path.to_str().unwrap());
let scanner_path = src_dir.join("scanner.c");
if scanner_path.exists() {
c_config.file(&scanner_path);
println!("cargo:rerun-if-changed={}", scanner_path.to_str().unwrap());
}
c_config.compile("tree-sitter-KEBAB_PARSER_NAME");
}

View file

@ -1,79 +0,0 @@
const std = @import("std");
pub fn build(b: *std.Build) !void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const shared = b.option(bool, "build-shared", "Build a shared library") orelse true;
const reuse_alloc = b.option(bool, "reuse-allocator", "Reuse the library allocator") orelse false;
const lib: *std.Build.Step.Compile = if (shared) b.addSharedLibrary(.{
.name = "tree-sitter-PARSER_NAME",
.pic = true,
.target = target,
.optimize = optimize,
.link_libc = true,
}) else b.addStaticLibrary(.{
.name = "tree-sitter-PARSER_NAME",
.target = target,
.optimize = optimize,
.link_libc = true,
});
lib.addCSourceFile(.{
.file = b.path("src/parser.c"),
.flags = &.{"-std=c11"},
});
if (hasScanner(b.build_root.handle)) {
lib.addCSourceFile(.{
.file = b.path("src/scanner.c"),
.flags = &.{"-std=c11"},
});
}
if (reuse_alloc) {
lib.root_module.addCMacro("TREE_SITTER_REUSE_ALLOCATOR", "");
}
if (optimize == .Debug) {
lib.root_module.addCMacro("TREE_SITTER_DEBUG", "");
}
lib.addIncludePath(b.path("src"));
b.installArtifact(lib);
b.installFile("src/node-types.json", "node-types.json");
b.installDirectory(.{ .source_dir = b.path("queries"), .install_dir = .prefix, .install_subdir = "queries", .include_extensions = &.{"scm"} });
const module = b.addModule("tree-sitter-PARSER_NAME", .{
.root_source_file = b.path("bindings/zig/root.zig"),
.target = target,
.optimize = optimize,
});
module.linkLibrary(lib);
const ts_dep = b.dependency("tree-sitter", .{});
const ts_mod = ts_dep.module("tree-sitter");
module.addImport("tree-sitter", ts_mod);
//
// Tests
//
const tests = b.addTest(.{
.root_source_file = b.path("bindings/zig/root.zig"),
.target = target,
.optimize = optimize,
});
tests.linkLibrary(lib);
tests.root_module.addImport("tree-sitter", ts_mod);
const run_tests = b.addRunArtifact(tests);
const test_step = b.step("test", "Run unit tests");
test_step.dependOn(&run_tests.step);
}
inline fn hasScanner(dir: std.fs.Dir) bool {
dir.access("src/scanner.c", .{}) catch return false;
return true;
}

View file

@ -1,17 +0,0 @@
.{
.name = "tree-sitter-PARSER_NAME",
.version = "PARSER_VERSION",
.dependencies = .{ .@"tree-sitter" = .{
.url = "https://github.com/tree-sitter/zig-tree-sitter/archive/refs/tags/v0.25.0.tar.gz",
.hash = "12201a8d5e840678bbbf5128e605519c4024af422295d68e2ba2090e675328e5811d",
} },
.paths = .{
"build.zig",
"build.zig.zon",
"bindings/zig",
"src",
"queries",
"LICENSE",
"README.md",
},
}

View file

@ -1,27 +0,0 @@
type BaseNode = {
type: string;
named: boolean;
};
type ChildNode = {
multiple: boolean;
required: boolean;
types: BaseNode[];
};
type NodeInfo =
| (BaseNode & {
subtypes: BaseNode[];
})
| (BaseNode & {
fields: { [name: string]: ChildNode };
children: ChildNode[];
});
type Language = {
language: unknown;
nodeTypeInfo: NodeInfo[];
};
declare const language: Language;
export = language;

View file

@ -1,11 +0,0 @@
const root = require("path").join(__dirname, "..", "..");
module.exports =
typeof process.versions.bun === "string"
// Support `bun build --compile` by being statically analyzable enough to find the .node file at build-time
? require(`../../prebuilds/${process.platform}-${process.arch}/tree-sitter-KEBAB_PARSER_NAME.node`)
: require("node-gyp-build")(root);
try {
module.exports.nodeTypeInfo = require("../../src/node-types.json");
} catch (_) {}

View file

@ -1,19 +0,0 @@
const testing = @import("std").testing;
const ts = @import("tree-sitter");
const Language = ts.Language;
const Parser = ts.Parser;
pub extern fn tree_sitter_PARSER_NAME() callconv(.C) *const Language;
pub export fn language() *const Language {
return tree_sitter_PARSER_NAME();
}
test "can load grammar" {
const parser = Parser.create();
defer parser.destroy();
try testing.expectEqual(parser.setLanguage(language()), void{});
try testing.expectEqual(parser.getLanguage(), tree_sitter_PARSER_NAME());
}

File diff suppressed because it is too large Load diff

View file

@ -1,278 +0,0 @@
use std::{
future::Future,
pin::{pin, Pin},
ptr,
task::{self, Context, Poll, RawWaker, RawWakerVTable, Waker},
};
use tree_sitter::Parser;
use super::helpers::fixtures::get_language;
#[test]
fn test_node_in_fut() {
let (ret, pended) = tokio_like_spawn(async {
let mut parser = Parser::new();
let language = get_language("bash");
parser.set_language(&language).unwrap();
let tree = parser.parse("#", None).unwrap();
let root = tree.root_node();
let root_ref = &root;
let fut_val_fn = || async {
yield_now().await;
root.child(0).unwrap().kind()
};
yield_now().await;
let fut_ref_fn = || async {
yield_now().await;
root_ref.child(0).unwrap().kind()
};
let f1 = fut_val_fn().await;
let f2 = fut_ref_fn().await;
assert_eq!(f1, f2);
let fut_val = async {
yield_now().await;
root.child(0).unwrap().kind()
};
let fut_ref = async {
yield_now().await;
root_ref.child(0).unwrap().kind()
};
let f1 = fut_val.await;
let f2 = fut_ref.await;
assert_eq!(f1, f2);
f1
})
.join();
assert_eq!(ret, "comment");
assert_eq!(pended, 5);
}
#[test]
fn test_node_and_cursor_ref_in_fut() {
let ((), pended) = tokio_like_spawn(async {
let mut parser = Parser::new();
let language = get_language("c");
parser.set_language(&language).unwrap();
let tree = parser.parse("#", None).unwrap();
let root = tree.root_node();
let root_ref = &root;
let mut cursor = tree.walk();
let cursor_ref = &mut cursor;
cursor_ref.goto_first_child();
let fut_val = async {
yield_now().await;
let _ = root.to_sexp();
};
yield_now().await;
let fut_ref = async {
yield_now().await;
let _ = root_ref.to_sexp();
cursor_ref.goto_first_child();
};
fut_val.await;
fut_ref.await;
cursor_ref.goto_first_child();
})
.join();
assert_eq!(pended, 3);
}
#[test]
fn test_node_and_cursor_ref_in_fut_with_fut_fabrics() {
let ((), pended) = tokio_like_spawn(async {
let mut parser = Parser::new();
let language = get_language("javascript");
parser.set_language(&language).unwrap();
let tree = parser.parse("#", None).unwrap();
let root = tree.root_node();
let root_ref = &root;
let mut cursor = tree.walk();
let cursor_ref = &mut cursor;
cursor_ref.goto_first_child();
let fut_val = || async {
yield_now().await;
let _ = root.to_sexp();
};
yield_now().await;
let fut_ref = || async move {
yield_now().await;
let _ = root_ref.to_sexp();
cursor_ref.goto_first_child();
};
fut_val().await;
fut_val().await;
fut_ref().await;
})
.join();
assert_eq!(pended, 4);
}
#[test]
fn test_node_and_cursor_ref_in_fut_with_inner_spawns() {
let (ret, pended) = tokio_like_spawn(async {
let mut parser = Parser::new();
let language = get_language("rust");
parser.set_language(&language).unwrap();
let tree = parser.parse("#", None).unwrap();
let mut cursor = tree.walk();
let cursor_ref = &mut cursor;
cursor_ref.goto_first_child();
let fut_val = || {
let tree = tree.clone();
async move {
let root = tree.root_node();
let mut cursor = tree.walk();
let cursor_ref = &mut cursor;
yield_now().await;
let _ = root.to_sexp();
cursor_ref.goto_first_child();
}
};
yield_now().await;
let fut_ref = || {
let tree = tree.clone();
async move {
let root = tree.root_node();
let root_ref = &root;
let mut cursor = tree.walk();
let cursor_ref = &mut cursor;
yield_now().await;
let _ = root_ref.to_sexp();
cursor_ref.goto_first_child();
}
};
let ((), p1) = tokio_like_spawn(fut_val()).await.unwrap();
let ((), p2) = tokio_like_spawn(fut_ref()).await.unwrap();
cursor_ref.goto_first_child();
fut_val().await;
fut_val().await;
fut_ref().await;
cursor_ref.goto_first_child();
p1 + p2
})
.join();
assert_eq!(pended, 4);
assert_eq!(ret, 2);
}
fn tokio_like_spawn<T>(future: T) -> JoinHandle<(T::Output, usize)>
where
T: Future + Send + 'static,
T::Output: Send + 'static,
{
// No runtime, just noop waker
let waker = noop_waker();
let mut cx = task::Context::from_waker(&waker);
let mut pending = 0;
let mut future = pin!(future);
let ret = loop {
match future.as_mut().poll(&mut cx) {
Poll::Pending => pending += 1,
Poll::Ready(r) => {
break r;
}
}
};
JoinHandle::new((ret, pending))
}
async fn yield_now() {
struct SimpleYieldNow {
yielded: bool,
}
impl Future for SimpleYieldNow {
type Output = ();
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
cx.waker().wake_by_ref();
if self.yielded {
return Poll::Ready(());
}
self.yielded = true;
Poll::Pending
}
}
SimpleYieldNow { yielded: false }.await;
}
pub fn noop_waker() -> Waker {
const VTABLE: RawWakerVTable = RawWakerVTable::new(
// Cloning just returns a new no-op raw waker
|_| RAW,
// `wake` does nothing
|_| {},
// `wake_by_ref` does nothing
|_| {},
// Dropping does nothing as we don't allocate anything
|_| {},
);
const RAW: RawWaker = RawWaker::new(ptr::null(), &VTABLE);
unsafe { Waker::from_raw(RAW) }
}
struct JoinHandle<T> {
data: Option<T>,
}
impl<T> JoinHandle<T> {
#[must_use]
const fn new(data: T) -> Self {
Self { data: Some(data) }
}
fn join(&mut self) -> T {
self.data.take().unwrap()
}
}
impl<T: Unpin> Future for JoinHandle<T> {
type Output = std::result::Result<T, ()>;
fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
let data = self.get_mut().data.take().unwrap();
Poll::Ready(Ok(data))
}
}

View file

@ -1,121 +0,0 @@
use std::{
collections::HashMap,
os::raw::c_void,
sync::{
atomic::{AtomicBool, AtomicUsize, Ordering::SeqCst},
Mutex,
},
};
#[ctor::ctor]
unsafe fn initialize_allocation_recording() {
tree_sitter::set_allocator(
Some(ts_record_malloc),
Some(ts_record_calloc),
Some(ts_record_realloc),
Some(ts_record_free),
);
}
#[derive(Debug, PartialEq, Eq, Hash)]
struct Allocation(*const c_void);
unsafe impl Send for Allocation {}
unsafe impl Sync for Allocation {}
#[derive(Default)]
struct AllocationRecorder {
enabled: AtomicBool,
allocation_count: AtomicUsize,
outstanding_allocations: Mutex<HashMap<Allocation, usize>>,
}
thread_local! {
static RECORDER: AllocationRecorder = AllocationRecorder::default();
}
extern "C" {
fn malloc(size: usize) -> *mut c_void;
fn calloc(count: usize, size: usize) -> *mut c_void;
fn realloc(ptr: *mut c_void, size: usize) -> *mut c_void;
fn free(ptr: *mut c_void);
}
pub fn record<T>(f: impl FnOnce() -> T) -> T {
RECORDER.with(|recorder| {
recorder.enabled.store(true, SeqCst);
recorder.allocation_count.store(0, SeqCst);
recorder.outstanding_allocations.lock().unwrap().clear();
});
let value = f();
let outstanding_allocation_indices = RECORDER.with(|recorder| {
recorder.enabled.store(false, SeqCst);
recorder.allocation_count.store(0, SeqCst);
recorder
.outstanding_allocations
.lock()
.unwrap()
.drain()
.map(|e| e.1)
.collect::<Vec<_>>()
});
assert!(
outstanding_allocation_indices.is_empty(),
"Leaked allocation indices: {outstanding_allocation_indices:?}"
);
value
}
fn record_alloc(ptr: *mut c_void) {
RECORDER.with(|recorder| {
if recorder.enabled.load(SeqCst) {
let count = recorder.allocation_count.fetch_add(1, SeqCst);
recorder
.outstanding_allocations
.lock()
.unwrap()
.insert(Allocation(ptr), count);
}
});
}
fn record_dealloc(ptr: *mut c_void) {
RECORDER.with(|recorder| {
if recorder.enabled.load(SeqCst) {
recorder
.outstanding_allocations
.lock()
.unwrap()
.remove(&Allocation(ptr));
}
});
}
unsafe extern "C" fn ts_record_malloc(size: usize) -> *mut c_void {
let result = malloc(size);
record_alloc(result);
result
}
unsafe extern "C" fn ts_record_calloc(count: usize, size: usize) -> *mut c_void {
let result = calloc(count, size);
record_alloc(result);
result
}
unsafe extern "C" fn ts_record_realloc(ptr: *mut c_void, size: usize) -> *mut c_void {
let result = realloc(ptr, size);
if ptr.is_null() {
record_alloc(result);
} else if ptr != result {
record_dealloc(ptr);
record_alloc(result);
}
result
}
unsafe extern "C" fn ts_record_free(ptr: *mut c_void) {
record_dealloc(ptr);
free(ptr);
}

View file

@ -1,104 +0,0 @@
// For some reasons `Command::spawn` doesn't work in CI env for many exotic arches.
#![cfg(all(any(target_arch = "x86_64", target_arch = "x86"), not(sanitizing)))]
use std::{
env::VarError,
process::{Command, Stdio},
};
use tree_sitter::Parser;
use tree_sitter_generate::load_grammar_file;
use super::generate_parser;
use crate::tests::helpers::fixtures::{fixtures_dir, get_test_language};
// The `sanitizing` cfg is required to don't run tests under specific sunitizer
// because they don't work well with subprocesses _(it's an assumption)_.
//
// Below are two alternative examples of how to disable tests for some arches
// if a way with excluding the whole mod from compilation wouldn't work well.
//
// XXX: Also may be it makes sense to keep such tests as ignored by default
// to omit surprises and enable them on CI by passing an extra option explicitly:
//
// > cargo test -- --include-ignored
//
// #[cfg(all(any(target_arch = "x86_64", target_arch = "x86"), not(sanitizing)))]
// #[cfg_attr(not(all(any(target_arch = "x86_64", target_arch = "x86"), not(sanitizing))), ignore)]
//
#[test]
fn test_grammar_that_should_hang_and_not_segfault() {
let parent_sleep_millis = 1000;
let test_name = "test_grammar_that_should_hang_and_not_segfault";
let test_var = "CARGO_HANG_TEST";
eprintln!(" {test_name}");
let tests_exec_path = std::env::args()
.next()
.expect("Failed to get tests executable path");
match std::env::var(test_var) {
Ok(v) if v == test_name => {
eprintln!(" child process id {}", std::process::id());
hang_test();
}
Err(VarError::NotPresent) => {
eprintln!(" parent process id {}", std::process::id());
let mut command = Command::new(tests_exec_path);
command.arg(test_name).env(test_var, test_name);
if std::env::args().any(|x| x == "--nocapture") {
command.arg("--nocapture");
} else {
command.stdout(Stdio::null()).stderr(Stdio::null());
}
match command.spawn() {
Ok(mut child) => {
std::thread::sleep(std::time::Duration::from_millis(parent_sleep_millis));
match child.try_wait() {
Ok(Some(status)) if status.success() => {
panic!("Child didn't hang and exited successfully")
}
Ok(Some(status)) => panic!(
"Child didn't hang and exited with status code: {:?}",
status.code()
),
_ => (),
}
if let Err(e) = child.kill() {
eprintln!(
"Failed to kill hang test's process id: {}, error: {e}",
child.id()
);
}
}
Err(e) => panic!("{e}"),
}
}
Err(e) => panic!("Env var error: {e}"),
_ => unreachable!(),
}
}
fn hang_test() {
let test_grammar_dir = fixtures_dir()
.join("test_grammars")
.join("get_col_should_hang_not_crash");
let grammar_json = load_grammar_file(&test_grammar_dir.join("grammar.js"), None).unwrap();
let (parser_name, parser_code) = generate_parser(grammar_json.as_str()).unwrap();
let language = get_test_language(&parser_name, &parser_code, Some(test_grammar_dir.as_path()));
let mut parser = Parser::new();
parser.set_language(&language).unwrap();
let code_that_should_hang = "\nHello";
parser.parse(code_that_should_hang, None).unwrap();
}

View file

@ -1,264 +0,0 @@
use std::{fs, path::PathBuf, process::Command};
use anyhow::{anyhow, Context, Result};
use regex::Regex;
use tree_sitter_loader::TreeSitterJSON;
pub struct Version {
pub version: String,
pub current_dir: PathBuf,
}
impl Version {
#[must_use]
pub const fn new(version: String, current_dir: PathBuf) -> Self {
Self {
version,
current_dir,
}
}
pub fn run(self) -> Result<()> {
let tree_sitter_json = self.current_dir.join("tree-sitter.json");
let tree_sitter_json =
serde_json::from_str::<TreeSitterJSON>(&fs::read_to_string(tree_sitter_json)?)?;
let is_multigrammar = tree_sitter_json.grammars.len() > 1;
self.update_treesitter_json().with_context(|| {
format!(
"Failed to update tree-sitter.json at {}",
self.current_dir.display()
)
})?;
self.update_cargo_toml().with_context(|| {
format!(
"Failed to update Cargo.toml at {}",
self.current_dir.display()
)
})?;
self.update_package_json().with_context(|| {
format!(
"Failed to update package.json at {}",
self.current_dir.display()
)
})?;
self.update_makefile(is_multigrammar).with_context(|| {
format!(
"Failed to update Makefile at {}",
self.current_dir.display()
)
})?;
self.update_cmakelists_txt().with_context(|| {
format!(
"Failed to update CMakeLists.txt at {}",
self.current_dir.display()
)
})?;
self.update_pyproject_toml().with_context(|| {
format!(
"Failed to update pyproject.toml at {}",
self.current_dir.display()
)
})?;
Ok(())
}
fn update_treesitter_json(&self) -> Result<()> {
let tree_sitter_json = &fs::read_to_string(self.current_dir.join("tree-sitter.json"))?;
let tree_sitter_json = tree_sitter_json
.lines()
.map(|line| {
if line.contains("\"version\":") {
let prefix_index = line.find("\"version\":").unwrap() + "\"version\":".len();
let start_quote = line[prefix_index..].find('"').unwrap() + prefix_index + 1;
let end_quote = line[start_quote + 1..].find('"').unwrap() + start_quote + 1;
format!(
"{}{}{}",
&line[..start_quote],
self.version,
&line[end_quote..]
)
} else {
line.to_string()
}
})
.collect::<Vec<_>>()
.join("\n")
+ "\n";
fs::write(self.current_dir.join("tree-sitter.json"), tree_sitter_json)?;
Ok(())
}
fn update_cargo_toml(&self) -> Result<()> {
if !self.current_dir.join("Cargo.toml").exists() {
return Ok(());
}
let cargo_toml = fs::read_to_string(self.current_dir.join("Cargo.toml"))?;
let cargo_toml = cargo_toml
.lines()
.map(|line| {
if line.starts_with("version =") {
format!("version = \"{}\"", self.version)
} else {
line.to_string()
}
})
.collect::<Vec<_>>()
.join("\n")
+ "\n";
fs::write(self.current_dir.join("Cargo.toml"), cargo_toml)?;
if self.current_dir.join("Cargo.lock").exists() {
let Ok(cmd) = Command::new("cargo")
.arg("generate-lockfile")
.arg("--offline")
.current_dir(&self.current_dir)
.output()
else {
return Ok(()); // cargo is not `executable`, ignore
};
if !cmd.status.success() {
let stderr = String::from_utf8_lossy(&cmd.stderr);
return Err(anyhow!(
"Failed to run `cargo generate-lockfile`:\n{stderr}"
));
}
}
Ok(())
}
fn update_package_json(&self) -> Result<()> {
if !self.current_dir.join("package.json").exists() {
return Ok(());
}
let package_json = &fs::read_to_string(self.current_dir.join("package.json"))?;
let package_json = package_json
.lines()
.map(|line| {
if line.contains("\"version\":") {
let prefix_index = line.find("\"version\":").unwrap() + "\"version\":".len();
let start_quote = line[prefix_index..].find('"').unwrap() + prefix_index + 1;
let end_quote = line[start_quote + 1..].find('"').unwrap() + start_quote + 1;
format!(
"{}{}{}",
&line[..start_quote],
self.version,
&line[end_quote..]
)
} else {
line.to_string()
}
})
.collect::<Vec<_>>()
.join("\n")
+ "\n";
fs::write(self.current_dir.join("package.json"), package_json)?;
if self.current_dir.join("package-lock.json").exists() {
let Ok(cmd) = Command::new("npm")
.arg("install")
.arg("--package-lock-only")
.current_dir(&self.current_dir)
.output()
else {
return Ok(()); // npm is not `executable`, ignore
};
if !cmd.status.success() {
let stderr = String::from_utf8_lossy(&cmd.stderr);
return Err(anyhow!("Failed to run `npm install`:\n{stderr}"));
}
}
Ok(())
}
fn update_makefile(&self, is_multigrammar: bool) -> Result<()> {
let makefile = if is_multigrammar {
if !self.current_dir.join("common").join("common.mak").exists() {
return Ok(());
}
fs::read_to_string(self.current_dir.join("Makefile"))?
} else {
if !self.current_dir.join("Makefile").exists() {
return Ok(());
}
fs::read_to_string(self.current_dir.join("Makefile"))?
};
let makefile = makefile
.lines()
.map(|line| {
if line.starts_with("VERSION") {
format!("VERSION := {}", self.version)
} else {
line.to_string()
}
})
.collect::<Vec<_>>()
.join("\n")
+ "\n";
fs::write(self.current_dir.join("Makefile"), makefile)?;
Ok(())
}
fn update_cmakelists_txt(&self) -> Result<()> {
if !self.current_dir.join("CMakeLists.txt").exists() {
return Ok(());
}
let cmake = fs::read_to_string(self.current_dir.join("CMakeLists.txt"))?;
let re = Regex::new(r#"(\s*VERSION\s+)"[0-9]+\.[0-9]+\.[0-9]+""#)?;
let cmake = re.replace(&cmake, format!(r#"$1"{}""#, self.version));
fs::write(self.current_dir.join("CMakeLists.txt"), cmake.as_bytes())?;
Ok(())
}
fn update_pyproject_toml(&self) -> Result<()> {
if !self.current_dir.join("pyproject.toml").exists() {
return Ok(());
}
let pyproject_toml = fs::read_to_string(self.current_dir.join("pyproject.toml"))?;
let pyproject_toml = pyproject_toml
.lines()
.map(|line| {
if line.starts_with("version =") {
format!("version = \"{}\"", self.version)
} else {
line.to_string()
}
})
.collect::<Vec<_>>()
.join("\n")
+ "\n";
fs::write(self.current_dir.join("pyproject.toml"), pyproject_toml)?;
Ok(())
}
}

View file

@ -8,14 +8,18 @@ rust-version.workspace = true
readme = "README.md" readme = "README.md"
homepage.workspace = true homepage.workspace = true
repository.workspace = true repository.workspace = true
documentation = "https://docs.rs/tree-sitter-cli"
license.workspace = true license.workspace = true
keywords.workspace = true keywords.workspace = true
categories.workspace = true categories.workspace = true
include = ["build.rs", "README.md", "benches/*", "src/**"] include = ["build.rs", "README.md", "LICENSE", "benches/*", "src/**"]
[lints] [lints]
workspace = true workspace = true
[lib]
path = "src/tree_sitter_cli.rs"
[[bin]] [[bin]]
name = "tree-sitter" name = "tree-sitter"
path = "src/main.rs" path = "src/main.rs"
@ -26,7 +30,9 @@ name = "benchmark"
harness = false harness = false
[features] [features]
default = ["qjs-rt"]
wasm = ["tree-sitter/wasm", "tree-sitter-loader/wasm"] wasm = ["tree-sitter/wasm", "tree-sitter-loader/wasm"]
qjs-rt = ["tree-sitter-generate/qjs-rt"]
[dependencies] [dependencies]
ansi_colours.workspace = true ansi_colours.workspace = true
@ -36,30 +42,26 @@ bstr.workspace = true
clap.workspace = true clap.workspace = true
clap_complete.workspace = true clap_complete.workspace = true
clap_complete_nushell.workspace = true clap_complete_nushell.workspace = true
crc32fast.workspace = true
ctor.workspace = true ctor.workspace = true
ctrlc.workspace = true ctrlc.workspace = true
dialoguer.workspace = true dialoguer.workspace = true
filetime.workspace = true
glob.workspace = true glob.workspace = true
heck.workspace = true heck.workspace = true
html-escape.workspace = true html-escape.workspace = true
indexmap.workspace = true
indoc.workspace = true indoc.workspace = true
log.workspace = true log.workspace = true
memchr.workspace = true memchr.workspace = true
rand.workspace = true rand.workspace = true
regex.workspace = true regex.workspace = true
regex-syntax.workspace = true schemars.workspace = true
rustc-hash.workspace = true
semver.workspace = true semver.workspace = true
serde.workspace = true serde.workspace = true
serde_derive.workspace = true
serde_json.workspace = true serde_json.workspace = true
similar.workspace = true similar.workspace = true
smallbitvec.workspace = true
streaming-iterator.workspace = true streaming-iterator.workspace = true
thiserror.workspace = true
tiny_http.workspace = true tiny_http.workspace = true
url.workspace = true
walkdir.workspace = true walkdir.workspace = true
wasmparser.workspace = true wasmparser.workspace = true
webbrowser.workspace = true webbrowser.workspace = true
@ -73,7 +75,7 @@ tree-sitter-tags.workspace = true
[dev-dependencies] [dev-dependencies]
encoding_rs = "0.8.35" encoding_rs = "0.8.35"
widestring = "1.1.0" widestring = "1.2.1"
tree_sitter_proc_macro = { path = "src/tests/proc_macro", package = "tree-sitter-tests-proc-macro" } tree_sitter_proc_macro = { path = "src/tests/proc_macro", package = "tree-sitter-tests-proc-macro" }
tempfile.workspace = true tempfile.workspace = true

21
crates/cli/LICENSE Normal file
View file

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2018 Max Brunsfeld
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -7,7 +7,8 @@
[npmjs.com]: https://www.npmjs.org/package/tree-sitter-cli [npmjs.com]: https://www.npmjs.org/package/tree-sitter-cli
[npmjs.com badge]: https://img.shields.io/npm/v/tree-sitter-cli.svg?color=%23BF4A4A [npmjs.com badge]: https://img.shields.io/npm/v/tree-sitter-cli.svg?color=%23BF4A4A
The Tree-sitter CLI allows you to develop, test, and use Tree-sitter grammars from the command line. It works on `MacOS`, `Linux`, and `Windows`. The Tree-sitter CLI allows you to develop, test, and use Tree-sitter grammars from the command line. It works on `MacOS`,
`Linux`, and `Windows`.
### Installation ### Installation
@ -34,9 +35,11 @@ The `tree-sitter` binary itself has no dependencies, but specific commands have
### Commands ### Commands
* `generate` - The `tree-sitter generate` command will generate a Tree-sitter parser based on the grammar in the current working directory. See [the documentation] for more information. * `generate` - The `tree-sitter generate` command will generate a Tree-sitter parser based on the grammar in the current
working directory. See [the documentation] for more information.
* `test` - The `tree-sitter test` command will run the unit tests for the Tree-sitter parser in the current working directory. See [the documentation] for more information. * `test` - The `tree-sitter test` command will run the unit tests for the Tree-sitter parser in the current working directory.
See [the documentation] for more information.
* `parse` - The `tree-sitter parse` command will parse a file (or list of files) using Tree-sitter parsers. * `parse` - The `tree-sitter parse` command will parse a file (or list of files) using Tree-sitter parsers.

View file

@ -8,6 +8,7 @@ use std::{
}; };
use anyhow::Context; use anyhow::Context;
use log::info;
use tree_sitter::{Language, Parser, Query}; use tree_sitter::{Language, Parser, Query};
use tree_sitter_loader::{CompileConfig, Loader}; use tree_sitter_loader::{CompileConfig, Loader};
@ -71,6 +72,8 @@ static EXAMPLE_AND_QUERY_PATHS_BY_LANGUAGE_DIR: LazyLock<
}); });
fn main() { fn main() {
tree_sitter_cli::logger::init();
let max_path_length = EXAMPLE_AND_QUERY_PATHS_BY_LANGUAGE_DIR let max_path_length = EXAMPLE_AND_QUERY_PATHS_BY_LANGUAGE_DIR
.values() .values()
.flat_map(|(e, q)| { .flat_map(|(e, q)| {
@ -81,7 +84,7 @@ fn main() {
.max() .max()
.unwrap_or(0); .unwrap_or(0);
eprintln!("Benchmarking with {} repetitions", *REPETITION_COUNT); info!("Benchmarking with {} repetitions", *REPETITION_COUNT);
let mut parser = Parser::new(); let mut parser = Parser::new();
let mut all_normal_speeds = Vec::new(); let mut all_normal_speeds = Vec::new();
@ -98,11 +101,11 @@ fn main() {
} }
} }
eprintln!("\nLanguage: {language_name}"); info!("\nLanguage: {language_name}");
let language = get_language(language_path); let language = get_language(language_path);
parser.set_language(&language).unwrap(); parser.set_language(&language).unwrap();
eprintln!(" Constructing Queries"); info!(" Constructing Queries");
for path in query_paths { for path in query_paths {
if let Some(filter) = EXAMPLE_FILTER.as_ref() { if let Some(filter) = EXAMPLE_FILTER.as_ref() {
if !path.to_str().unwrap().contains(filter.as_str()) { if !path.to_str().unwrap().contains(filter.as_str()) {
@ -112,12 +115,12 @@ fn main() {
parse(path, max_path_length, |source| { parse(path, max_path_length, |source| {
Query::new(&language, str::from_utf8(source).unwrap()) Query::new(&language, str::from_utf8(source).unwrap())
.with_context(|| format!("Query file path: {path:?}")) .with_context(|| format!("Query file path: {}", path.display()))
.expect("Failed to parse query"); .expect("Failed to parse query");
}); });
} }
eprintln!(" Parsing Valid Code:"); info!(" Parsing Valid Code:");
let mut normal_speeds = Vec::new(); let mut normal_speeds = Vec::new();
for example_path in example_paths { for example_path in example_paths {
if let Some(filter) = EXAMPLE_FILTER.as_ref() { if let Some(filter) = EXAMPLE_FILTER.as_ref() {
@ -131,7 +134,7 @@ fn main() {
})); }));
} }
eprintln!(" Parsing Invalid Code (mismatched languages):"); info!(" Parsing Invalid Code (mismatched languages):");
let mut error_speeds = Vec::new(); let mut error_speeds = Vec::new();
for (other_language_path, (example_paths, _)) in for (other_language_path, (example_paths, _)) in
EXAMPLE_AND_QUERY_PATHS_BY_LANGUAGE_DIR.iter() EXAMPLE_AND_QUERY_PATHS_BY_LANGUAGE_DIR.iter()
@ -152,30 +155,30 @@ fn main() {
} }
if let Some((average_normal, worst_normal)) = aggregate(&normal_speeds) { if let Some((average_normal, worst_normal)) = aggregate(&normal_speeds) {
eprintln!(" Average Speed (normal): {average_normal} bytes/ms"); info!(" Average Speed (normal): {average_normal} bytes/ms");
eprintln!(" Worst Speed (normal): {worst_normal} bytes/ms"); info!(" Worst Speed (normal): {worst_normal} bytes/ms");
} }
if let Some((average_error, worst_error)) = aggregate(&error_speeds) { if let Some((average_error, worst_error)) = aggregate(&error_speeds) {
eprintln!(" Average Speed (errors): {average_error} bytes/ms"); info!(" Average Speed (errors): {average_error} bytes/ms");
eprintln!(" Worst Speed (errors): {worst_error} bytes/ms"); info!(" Worst Speed (errors): {worst_error} bytes/ms");
} }
all_normal_speeds.extend(normal_speeds); all_normal_speeds.extend(normal_speeds);
all_error_speeds.extend(error_speeds); all_error_speeds.extend(error_speeds);
} }
eprintln!("\n Overall"); info!("\n Overall");
if let Some((average_normal, worst_normal)) = aggregate(&all_normal_speeds) { if let Some((average_normal, worst_normal)) = aggregate(&all_normal_speeds) {
eprintln!(" Average Speed (normal): {average_normal} bytes/ms"); info!(" Average Speed (normal): {average_normal} bytes/ms");
eprintln!(" Worst Speed (normal): {worst_normal} bytes/ms"); info!(" Worst Speed (normal): {worst_normal} bytes/ms");
} }
if let Some((average_error, worst_error)) = aggregate(&all_error_speeds) { if let Some((average_error, worst_error)) = aggregate(&all_error_speeds) {
eprintln!(" Average Speed (errors): {average_error} bytes/ms"); info!(" Average Speed (errors): {average_error} bytes/ms");
eprintln!(" Worst Speed (errors): {worst_error} bytes/ms"); info!(" Worst Speed (errors): {worst_error} bytes/ms");
} }
eprintln!(); info!("");
} }
fn aggregate(speeds: &[usize]) -> Option<(usize, usize)> { fn aggregate(speeds: &[usize]) -> Option<(usize, usize)> {
@ -194,14 +197,8 @@ fn aggregate(speeds: &[usize]) -> Option<(usize, usize)> {
} }
fn parse(path: &Path, max_path_length: usize, mut action: impl FnMut(&[u8])) -> usize { fn parse(path: &Path, max_path_length: usize, mut action: impl FnMut(&[u8])) -> usize {
eprint!(
" {:width$}\t",
path.file_name().unwrap().to_str().unwrap(),
width = max_path_length
);
let source_code = fs::read(path) let source_code = fs::read(path)
.with_context(|| format!("Failed to read {path:?}")) .with_context(|| format!("Failed to read {}", path.display()))
.unwrap(); .unwrap();
let time = Instant::now(); let time = Instant::now();
for _ in 0..*REPETITION_COUNT { for _ in 0..*REPETITION_COUNT {
@ -210,8 +207,9 @@ fn parse(path: &Path, max_path_length: usize, mut action: impl FnMut(&[u8])) ->
let duration = time.elapsed() / (*REPETITION_COUNT as u32); let duration = time.elapsed() / (*REPETITION_COUNT as u32);
let duration_ns = duration.as_nanos(); let duration_ns = duration.as_nanos();
let speed = ((source_code.len() as u128) * 1_000_000) / duration_ns; let speed = ((source_code.len() as u128) * 1_000_000) / duration_ns;
eprintln!( info!(
"time {:>7.2} ms\t\tspeed {speed:>6} bytes/ms", " {:max_path_length$}\ttime {:>7.2} ms\t\tspeed {speed:>6} bytes/ms",
path.file_name().unwrap().to_str().unwrap(),
(duration_ns as f64) / 1e6, (duration_ns as f64) / 1e6,
); );
speed as usize speed as usize
@ -221,6 +219,6 @@ fn get_language(path: &Path) -> Language {
let src_path = GRAMMARS_DIR.join(path).join("src"); let src_path = GRAMMARS_DIR.join(path).join("src");
TEST_LOADER TEST_LOADER
.load_language_at_path(CompileConfig::new(&src_path, None, None)) .load_language_at_path(CompileConfig::new(&src_path, None, None))
.with_context(|| format!("Failed to load language at path {src_path:?}")) .with_context(|| format!("Failed to load language at path {}", src_path.display()))
.unwrap() .unwrap()
} }

View file

@ -52,16 +52,14 @@ fn main() {
fn web_playground_files_present() -> bool { fn web_playground_files_present() -> bool {
let paths = [ let paths = [
"../docs/src/assets/js/playground.js", "../../docs/src/assets/js/playground.js",
"../lib/binding_web/tree-sitter.js", "../../lib/binding_web/web-tree-sitter.js",
"../lib/binding_web/tree-sitter.wasm", "../../lib/binding_web/web-tree-sitter.wasm",
]; ];
paths.iter().all(|p| Path::new(p).exists()) paths.iter().all(|p| Path::new(p).exists())
} }
// When updating this function, don't forget to also update generate/build.rs which has a
// near-identical function.
fn read_git_sha() -> Option<String> { fn read_git_sha() -> Option<String> {
let crate_path = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()); let crate_path = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());

1
crates/cli/eslint/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
LICENSE

View file

@ -305,9 +305,9 @@
"peer": true "peer": true
}, },
"node_modules/brace-expansion": { "node_modules/brace-expansion": {
"version": "1.1.11", "version": "1.1.12",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"license": "MIT", "license": "MIT",
"peer": true, "peer": true,
"dependencies": { "dependencies": {
@ -805,9 +805,9 @@
"peer": true "peer": true
}, },
"node_modules/js-yaml": { "node_modules/js-yaml": {
"version": "4.1.0", "version": "4.1.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
"license": "MIT", "license": "MIT",
"peer": true, "peer": true,
"dependencies": { "dependencies": {

View file

@ -4,7 +4,8 @@
"description": "Eslint configuration for Tree-sitter grammar files", "description": "Eslint configuration for Tree-sitter grammar files",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://github.com/tree-sitter/tree-sitter.git" "url": "git+https://github.com/tree-sitter/tree-sitter.git",
"directory": "crates/cli/eslint"
}, },
"license": "MIT", "license": "MIT",
"author": "Amaan Qureshi <amaanq12@gmail.com>", "author": "Amaan Qureshi <amaanq12@gmail.com>",
@ -20,5 +21,9 @@
}, },
"peerDependencies": { "peerDependencies": {
"eslint": ">= 9" "eslint": ">= 9"
},
"scripts": {
"prepack": "cp ../../../LICENSE .",
"postpack": "rm LICENSE"
} }
} }

View file

@ -10,6 +10,7 @@ type PrecRightRule = { type: 'PREC_RIGHT'; content: Rule; value: number };
type PrecRule = { type: 'PREC'; content: Rule; value: number }; type PrecRule = { type: 'PREC'; content: Rule; value: number };
type Repeat1Rule = { type: 'REPEAT1'; content: Rule }; type Repeat1Rule = { type: 'REPEAT1'; content: Rule };
type RepeatRule = { type: 'REPEAT'; content: Rule }; type RepeatRule = { type: 'REPEAT'; content: Rule };
type ReservedRule = { type: 'RESERVED'; content: Rule; context_name: string };
type SeqRule = { type: 'SEQ'; members: Rule[] }; type SeqRule = { type: 'SEQ'; members: Rule[] };
type StringRule = { type: 'STRING'; value: string }; type StringRule = { type: 'STRING'; value: string };
type SymbolRule<Name extends string> = { type: 'SYMBOL'; name: Name }; type SymbolRule<Name extends string> = { type: 'SYMBOL'; name: Name };
@ -28,17 +29,16 @@ type Rule =
| PrecRule | PrecRule
| Repeat1Rule | Repeat1Rule
| RepeatRule | RepeatRule
| ReservedRule
| SeqRule | SeqRule
| StringRule | StringRule
| SymbolRule<string> | SymbolRule<string>
| TokenRule; | TokenRule;
class RustRegex { declare class RustRegex {
value: string; value: string;
constructor(pattern: string) { constructor(pattern: string);
this.value = pattern;
}
} }
type RuleOrLiteral = Rule | RegExp | RustRegex | string; type RuleOrLiteral = Rule | RegExp | RustRegex | string;
@ -167,6 +167,17 @@ interface Grammar<
* @see https://tree-sitter.github.io/tree-sitter/creating-parsers/3-writing-the-grammar#keyword-extraction * @see https://tree-sitter.github.io/tree-sitter/creating-parsers/3-writing-the-grammar#keyword-extraction
*/ */
word?: ($: GrammarSymbols<RuleName | BaseGrammarRuleName>) => RuleOrLiteral; word?: ($: GrammarSymbols<RuleName | BaseGrammarRuleName>) => RuleOrLiteral;
/**
* Mapping of names to reserved word sets. The first reserved word set is the
* global word set, meaning it applies to every rule in every parse state.
* The other word sets can be used with the `reserved` function.
*/
reserved?: Record<
string,
($: GrammarSymbols<RuleName | BaseGrammarRuleName>) => RuleOrLiteral[]
>;
} }
type GrammarSchema<RuleName extends string> = { type GrammarSchema<RuleName extends string> = {
@ -251,7 +262,7 @@ declare function optional(rule: RuleOrLiteral): ChoiceRule;
* @see https://docs.oracle.com/cd/E19504-01/802-5880/6i9k05dh3/index.html * @see https://docs.oracle.com/cd/E19504-01/802-5880/6i9k05dh3/index.html
*/ */
declare const prec: { declare const prec: {
(value: String | number, rule: RuleOrLiteral): PrecRule; (value: string | number, rule: RuleOrLiteral): PrecRule;
/** /**
* Marks the given rule as left-associative (and optionally applies a * Marks the given rule as left-associative (and optionally applies a
@ -267,7 +278,7 @@ declare const prec: {
* @see https://docs.oracle.com/cd/E19504-01/802-5880/6i9k05dh3/index.html * @see https://docs.oracle.com/cd/E19504-01/802-5880/6i9k05dh3/index.html
*/ */
left(rule: RuleOrLiteral): PrecLeftRule; left(rule: RuleOrLiteral): PrecLeftRule;
left(value: String | number, rule: RuleOrLiteral): PrecLeftRule; left(value: string | number, rule: RuleOrLiteral): PrecLeftRule;
/** /**
* Marks the given rule as right-associative (and optionally applies a * Marks the given rule as right-associative (and optionally applies a
@ -283,7 +294,7 @@ declare const prec: {
* @see https://docs.oracle.com/cd/E19504-01/802-5880/6i9k05dh3/index.html * @see https://docs.oracle.com/cd/E19504-01/802-5880/6i9k05dh3/index.html
*/ */
right(rule: RuleOrLiteral): PrecRightRule; right(rule: RuleOrLiteral): PrecRightRule;
right(value: String | number, rule: RuleOrLiteral): PrecRightRule; right(value: string | number, rule: RuleOrLiteral): PrecRightRule;
/** /**
* Marks the given rule with a numerical precedence which will be used to * Marks the given rule with a numerical precedence which will be used to
@ -300,7 +311,7 @@ declare const prec: {
* *
* @see https://www.gnu.org/software/bison/manual/html_node/Generalized-LR-Parsing.html * @see https://www.gnu.org/software/bison/manual/html_node/Generalized-LR-Parsing.html
*/ */
dynamic(value: String | number, rule: RuleOrLiteral): PrecDynamicRule; dynamic(value: string | number, rule: RuleOrLiteral): PrecDynamicRule;
}; };
/** /**
@ -320,6 +331,15 @@ declare function repeat(rule: RuleOrLiteral): RepeatRule;
*/ */
declare function repeat1(rule: RuleOrLiteral): Repeat1Rule; declare function repeat1(rule: RuleOrLiteral): Repeat1Rule;
/**
* Overrides the global reserved word set for a given rule. The word set name
* should be defined in the `reserved` field in the grammar.
*
* @param wordset name of the reserved word set
* @param rule rule that will use the reserved word set
*/
declare function reserved(wordset: string, rule: RuleOrLiteral): ReservedRule;
/** /**
* Creates a rule that matches any number of other rules, one after another. * Creates a rule that matches any number of other rules, one after another.
* It is analogous to simply writing multiple symbols next to each other * It is analogous to simply writing multiple symbols next to each other
@ -338,7 +358,7 @@ declare function sym<Name extends string>(name: Name): SymbolRule<Name>;
/** /**
* Marks the given rule as producing only a single token. Tree-sitter's * Marks the given rule as producing only a single token. Tree-sitter's
* default is to treat each String or RegExp literal in the grammar as a * default is to treat each string or RegExp literal in the grammar as a
* separate token. Each token is matched separately by the lexer and * separate token. Each token is matched separately by the lexer and
* returned as its own leaf node in the tree. The token function allows * returned as its own leaf node in the tree. The token function allows
* you to express a complex rule using the DSL functions (rather * you to express a complex rule using the DSL functions (rather

3
cli/npm/install.js → crates/cli/npm/install.js Executable file → Normal file
View file

@ -6,7 +6,8 @@ const http = require('http');
const https = require('https'); const https = require('https');
const packageJSON = require('./package.json'); const packageJSON = require('./package.json');
// Look to a results table in https://github.com/tree-sitter/tree-sitter/issues/2196 https.globalAgent.keepAlive = false;
const matrix = { const matrix = {
platform: { platform: {
'darwin': { 'darwin': {

20
crates/cli/npm/package-lock.json generated Normal file
View file

@ -0,0 +1,20 @@
{
"name": "tree-sitter-cli",
"version": "0.27.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "tree-sitter-cli",
"version": "0.27.0",
"hasInstallScript": true,
"license": "MIT",
"bin": {
"tree-sitter": "cli.js"
},
"engines": {
"node": ">=12.0.0"
}
}
}
}

View file

@ -1,6 +1,6 @@
{ {
"name": "tree-sitter-cli", "name": "tree-sitter-cli",
"version": "0.25.1", "version": "0.27.0",
"author": { "author": {
"name": "Max Brunsfeld", "name": "Max Brunsfeld",
"email": "maxbrunsfeld@gmail.com" "email": "maxbrunsfeld@gmail.com"
@ -14,20 +14,20 @@
"license": "MIT", "license": "MIT",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://github.com/tree-sitter/tree-sitter.git" "url": "git+https://github.com/tree-sitter/tree-sitter.git",
"directory": "crates/cli/npm"
}, },
"description": "CLI for generating fast incremental parsers", "description": "CLI for generating fast incremental parsers",
"keywords": [ "keywords": [
"parser", "parser",
"lexer" "lexer"
], ],
"main": "lib/api/index.js",
"engines": { "engines": {
"node": ">=12.0.0" "node": ">=12.0.0"
}, },
"scripts": { "scripts": {
"install": "node install.js", "install": "node install.js",
"prepack": "cp ../../LICENSE ../README.md .", "prepack": "cp ../../../LICENSE ../README.md .",
"postpack": "rm LICENSE README.md" "postpack": "rm LICENSE README.md"
}, },
"bin": { "bin": {

69
crates/cli/package.nix Normal file
View file

@ -0,0 +1,69 @@
{
lib,
src,
rustPlatform,
version,
clang,
libclang,
cmake,
pkg-config,
nodejs_22,
test-grammars,
stdenv,
installShellFiles,
}:
let
isCross = stdenv.targetPlatform == stdenv.buildPlatform;
in
rustPlatform.buildRustPackage {
pname = "tree-sitter-cli";
inherit src version;
cargoBuildFlags = [ "--all-features" ];
nativeBuildInputs = [
clang
cmake
pkg-config
nodejs_22
]
++ lib.optionals (!isCross) [ installShellFiles ];
cargoLock.lockFile = ../../Cargo.lock;
env.LIBCLANG_PATH = "${libclang.lib}/lib";
preBuild = ''
rm -rf test/fixtures
mkdir -p test/fixtures
cp -r ${test-grammars}/fixtures/* test/fixtures/
chmod -R u+w test/fixtures
'';
preCheck = "export HOME=$TMPDIR";
doCheck = !isCross;
postInstall = lib.optionalString (!isCross) ''
installShellCompletion --cmd tree-sitter \
--bash <($out/bin/tree-sitter complete --shell bash) \
--zsh <($out/bin/tree-sitter complete --shell zsh) \
--fish <($out/bin/tree-sitter complete --shell fish)
'';
meta = {
description = "Tree-sitter CLI - A tool for developing, testing, and using Tree-sitter parsers";
longDescription = ''
Tree-sitter is a parser generator tool and an incremental parsing library.
It can build a concrete syntax tree for a source file and efficiently update
the syntax tree as the source file is edited. This package provides the CLI
tool for developing, testing, and using Tree-sitter parsers.
'';
homepage = "https://tree-sitter.github.io/tree-sitter";
changelog = "https://github.com/tree-sitter/tree-sitter/releases/tag/v${version}";
license = lib.licenses.mit;
maintainers = with lib.maintainers; [ amaanq ];
platforms = lib.platforms.all;
mainProgram = "tree-sitter";
};
}

View file

@ -1,5 +1,11 @@
use std::{collections::HashMap, env, fs, path::Path, sync::LazyLock}; use std::{
collections::HashMap,
env, fs,
path::{Path, PathBuf},
sync::LazyLock,
};
use log::{error, info};
use rand::Rng; use rand::Rng;
use regex::Regex; use regex::Regex;
use tree_sitter::{Language, Parser}; use tree_sitter::{Language, Parser};
@ -19,7 +25,7 @@ use crate::{
random::Rand, random::Rand,
}, },
parse::perform_edit, parse::perform_edit,
test::{parse_tests, print_diff, print_diff_key, strip_sexp_fields, TestEntry}, test::{parse_tests, strip_sexp_fields, DiffKey, TestDiff, TestEntry},
}; };
pub static LOG_ENABLED: LazyLock<bool> = LazyLock::new(|| env::var("TREE_SITTER_LOG").is_ok()); pub static LOG_ENABLED: LazyLock<bool> = LazyLock::new(|| env::var("TREE_SITTER_LOG").is_ok());
@ -56,13 +62,15 @@ fn regex_env_var(name: &'static str) -> Option<Regex> {
pub fn new_seed() -> usize { pub fn new_seed() -> usize {
int_env_var("TREE_SITTER_SEED").unwrap_or_else(|| { int_env_var("TREE_SITTER_SEED").unwrap_or_else(|| {
let mut rng = rand::thread_rng(); let mut rng = rand::thread_rng();
rng.gen::<usize>() let seed = rng.gen::<usize>();
info!("Seed: {seed}");
seed
}) })
} }
pub struct FuzzOptions { pub struct FuzzOptions {
pub skipped: Option<Vec<String>>, pub skipped: Option<Vec<String>>,
pub subdir: Option<String>, pub subdir: Option<PathBuf>,
pub edits: usize, pub edits: usize,
pub iterations: usize, pub iterations: usize,
pub include: Option<Regex>, pub include: Option<Regex>,
@ -101,12 +109,12 @@ pub fn fuzz_language_corpus(
let corpus_dir = grammar_dir.join(subdir).join("test").join("corpus"); let corpus_dir = grammar_dir.join(subdir).join("test").join("corpus");
if !corpus_dir.exists() || !corpus_dir.is_dir() { if !corpus_dir.exists() || !corpus_dir.is_dir() {
eprintln!("No corpus directory found, ensure that you have a `test/corpus` directory in your grammar directory with at least one test file."); error!("No corpus directory found, ensure that you have a `test/corpus` directory in your grammar directory with at least one test file.");
return; return;
} }
if std::fs::read_dir(&corpus_dir).unwrap().count() == 0 { if std::fs::read_dir(&corpus_dir).unwrap().count() == 0 {
eprintln!("No corpus files found in `test/corpus`, ensure that you have at least one test file in your corpus directory."); error!("No corpus files found in `test/corpus`, ensure that you have at least one test file in your corpus directory.");
return; return;
} }
@ -142,7 +150,7 @@ pub fn fuzz_language_corpus(
let dump_edits = env::var("TREE_SITTER_DUMP_EDITS").is_ok(); let dump_edits = env::var("TREE_SITTER_DUMP_EDITS").is_ok();
if log_seed { if log_seed {
println!(" start seed: {start_seed}"); info!(" start seed: {start_seed}");
} }
println!(); println!();
@ -156,7 +164,7 @@ pub fn fuzz_language_corpus(
println!(" {test_index}. {test_name}"); println!(" {test_index}. {test_name}");
let passed = allocations::record(|| { let passed = allocations::record_checked(|| {
let mut log_session = None; let mut log_session = None;
let mut parser = get_parser(&mut log_session, "log.html"); let mut parser = get_parser(&mut log_session, "log.html");
parser.set_language(language).unwrap(); parser.set_language(language).unwrap();
@ -175,8 +183,8 @@ pub fn fuzz_language_corpus(
if actual_output != test.output { if actual_output != test.output {
println!("Incorrect initial parse for {test_name}"); println!("Incorrect initial parse for {test_name}");
print_diff_key(); DiffKey::print();
print_diff(&actual_output, &test.output, true); println!("{}", TestDiff::new(&actual_output, &test.output));
println!(); println!();
return false; return false;
} }
@ -184,7 +192,7 @@ pub fn fuzz_language_corpus(
true true
}) })
.unwrap_or_else(|e| { .unwrap_or_else(|e| {
eprintln!("Error: {e}"); error!("{e}");
false false
}); });
@ -200,7 +208,7 @@ pub fn fuzz_language_corpus(
for trial in 0..options.iterations { for trial in 0..options.iterations {
let seed = start_seed + trial; let seed = start_seed + trial;
let passed = allocations::record(|| { let passed = allocations::record_checked(|| {
let mut rand = Rand::new(seed); let mut rand = Rand::new(seed);
let mut log_session = None; let mut log_session = None;
let mut parser = get_parser(&mut log_session, "log.html"); let mut parser = get_parser(&mut log_session, "log.html");
@ -209,19 +217,20 @@ pub fn fuzz_language_corpus(
let mut input = test.input.clone(); let mut input = test.input.clone();
if options.log_graphs { if options.log_graphs {
eprintln!("{}\n", String::from_utf8_lossy(&input)); info!("{}\n", String::from_utf8_lossy(&input));
} }
// Perform a random series of edits and reparse. // Perform a random series of edits and reparse.
let mut undo_stack = Vec::new(); let edit_count = rand.unsigned(*EDIT_COUNT);
for _ in 0..=rand.unsigned(*EDIT_COUNT) { let mut undo_stack = Vec::with_capacity(edit_count);
for _ in 0..=edit_count {
let edit = get_random_edit(&mut rand, &input); let edit = get_random_edit(&mut rand, &input);
undo_stack.push(invert_edit(&input, &edit)); undo_stack.push(invert_edit(&input, &edit));
perform_edit(&mut tree, &mut input, &edit).unwrap(); perform_edit(&mut tree, &mut input, &edit).unwrap();
} }
if log_seed { if log_seed {
println!(" {test_index}.{trial:<2} seed: {seed}"); info!(" {test_index}.{trial:<2} seed: {seed}");
} }
if dump_edits { if dump_edits {
@ -235,7 +244,7 @@ pub fn fuzz_language_corpus(
} }
if options.log_graphs { if options.log_graphs {
eprintln!("{}\n", String::from_utf8_lossy(&input)); info!("{}\n", String::from_utf8_lossy(&input));
} }
set_included_ranges(&mut parser, &input, test.template_delimiters); set_included_ranges(&mut parser, &input, test.template_delimiters);
@ -244,7 +253,7 @@ pub fn fuzz_language_corpus(
// Check that the new tree is consistent. // Check that the new tree is consistent.
check_consistent_sizes(&tree2, &input); check_consistent_sizes(&tree2, &input);
if let Err(message) = check_changed_ranges(&tree, &tree2, &input) { if let Err(message) = check_changed_ranges(&tree, &tree2, &input) {
println!("\nUnexpected scope change in seed {seed} with start seed {start_seed}\n{message}\n\n",); error!("\nUnexpected scope change in seed {seed} with start seed {start_seed}\n{message}\n\n",);
return false; return false;
} }
@ -253,7 +262,7 @@ pub fn fuzz_language_corpus(
perform_edit(&mut tree2, &mut input, &edit).unwrap(); perform_edit(&mut tree2, &mut input, &edit).unwrap();
} }
if options.log_graphs { if options.log_graphs {
eprintln!("{}\n", String::from_utf8_lossy(&input)); info!("{}\n", String::from_utf8_lossy(&input));
} }
set_included_ranges(&mut parser, &test.input, test.template_delimiters); set_included_ranges(&mut parser, &test.input, test.template_delimiters);
@ -267,8 +276,8 @@ pub fn fuzz_language_corpus(
if actual_output != test.output && !test.error { if actual_output != test.output && !test.error {
println!("Incorrect parse for {test_name} - seed {seed}"); println!("Incorrect parse for {test_name} - seed {seed}");
print_diff_key(); DiffKey::print();
print_diff(&actual_output, &test.output, true); println!("{}", TestDiff::new(&actual_output, &test.output));
println!(); println!();
return false; return false;
} }
@ -276,13 +285,13 @@ pub fn fuzz_language_corpus(
// Check that the edited tree is consistent. // Check that the edited tree is consistent.
check_consistent_sizes(&tree3, &input); check_consistent_sizes(&tree3, &input);
if let Err(message) = check_changed_ranges(&tree2, &tree3, &input) { if let Err(message) = check_changed_ranges(&tree2, &tree3, &input) {
println!("Unexpected scope change in seed {seed} with start seed {start_seed}\n{message}\n\n"); error!("Unexpected scope change in seed {seed} with start seed {start_seed}\n{message}\n\n");
return false; return false;
} }
true true
}).unwrap_or_else(|e| { }).unwrap_or_else(|e| {
eprintln!("Error: {e}"); error!("{e}");
false false
}); });
@ -294,17 +303,17 @@ pub fn fuzz_language_corpus(
} }
if failure_count != 0 { if failure_count != 0 {
eprintln!("{failure_count} {language_name} corpus tests failed fuzzing"); info!("{failure_count} {language_name} corpus tests failed fuzzing");
} }
skipped.retain(|_, v| *v == 0); skipped.retain(|_, v| *v == 0);
if !skipped.is_empty() { if !skipped.is_empty() {
println!("Non matchable skip definitions:"); info!("Non matchable skip definitions:");
for k in skipped.keys() { for k in skipped.keys() {
println!(" {k}"); info!(" {k}");
} }
panic!("Non matchable skip definitions needs to be removed"); panic!("Non matchable skip definitions need to be removed");
} }
} }

View file

@ -40,7 +40,11 @@ extern "C" {
fn free(ptr: *mut c_void); fn free(ptr: *mut c_void);
} }
pub fn record<T>(f: impl FnOnce() -> T) -> Result<T, String> { pub fn record<T>(f: impl FnOnce() -> T) -> T {
record_checked(f).unwrap()
}
pub fn record_checked<T>(f: impl FnOnce() -> T) -> Result<T, String> {
RECORDER.with(|recorder| { RECORDER.with(|recorder| {
recorder.enabled.store(true, SeqCst); recorder.enabled.store(true, SeqCst);
recorder.allocation_count.store(0, SeqCst); recorder.allocation_count.store(0, SeqCst);
@ -93,30 +97,49 @@ fn record_dealloc(ptr: *mut c_void) {
}); });
} }
unsafe extern "C" fn ts_record_malloc(size: usize) -> *mut c_void { /// # Safety
///
/// The caller must ensure that the returned pointer is eventually
/// freed by calling `ts_record_free`.
#[must_use]
pub unsafe extern "C" fn ts_record_malloc(size: usize) -> *mut c_void {
let result = malloc(size); let result = malloc(size);
record_alloc(result); record_alloc(result);
result result
} }
unsafe extern "C" fn ts_record_calloc(count: usize, size: usize) -> *mut c_void { /// # Safety
///
/// The caller must ensure that the returned pointer is eventually
/// freed by calling `ts_record_free`.
#[must_use]
pub unsafe extern "C" fn ts_record_calloc(count: usize, size: usize) -> *mut c_void {
let result = calloc(count, size); let result = calloc(count, size);
record_alloc(result); record_alloc(result);
result result
} }
unsafe extern "C" fn ts_record_realloc(ptr: *mut c_void, size: usize) -> *mut c_void { /// # Safety
///
/// The caller must ensure that the returned pointer is eventually
/// freed by calling `ts_record_free`.
#[must_use]
pub unsafe extern "C" fn ts_record_realloc(ptr: *mut c_void, size: usize) -> *mut c_void {
let result = realloc(ptr, size); let result = realloc(ptr, size);
if ptr.is_null() { if ptr.is_null() {
record_alloc(result); record_alloc(result);
} else if ptr != result { } else if !core::ptr::eq(ptr, result) {
record_dealloc(ptr); record_dealloc(ptr);
record_alloc(result); record_alloc(result);
} }
result result
} }
unsafe extern "C" fn ts_record_free(ptr: *mut c_void) { /// # Safety
///
/// The caller must ensure that `ptr` was allocated by a previous call
/// to `ts_record_malloc`, `ts_record_calloc`, or `ts_record_realloc`.
pub unsafe extern "C" fn ts_record_free(ptr: *mut c_void) {
record_dealloc(ptr); record_dealloc(ptr);
free(ptr); free(ptr);
} }

View file

@ -23,7 +23,7 @@ pub fn check_consistent_sizes(tree: &Tree, input: &[u8]) {
let mut some_child_has_changes = false; let mut some_child_has_changes = false;
let mut actual_named_child_count = 0; let mut actual_named_child_count = 0;
for i in 0..node.child_count() { for i in 0..node.child_count() {
let child = node.child(i).unwrap(); let child = node.child(i as u32).unwrap();
assert!(child.start_byte() >= last_child_end_byte); assert!(child.start_byte() >= last_child_end_byte);
assert!(child.start_position() >= last_child_end_point); assert!(child.start_position() >= last_child_end_point);
check(child, line_offsets); check(child, line_offsets);

View file

@ -20,8 +20,8 @@ impl Rand {
} }
pub fn words(&mut self, max_count: usize) -> Vec<u8> { pub fn words(&mut self, max_count: usize) -> Vec<u8> {
let mut result = Vec::new();
let word_count = self.unsigned(max_count); let word_count = self.unsigned(max_count);
let mut result = Vec::with_capacity(2 * word_count);
for i in 0..word_count { for i in 0..word_count {
if i > 0 { if i > 0 {
if self.unsigned(5) == 0 { if self.unsigned(5) == 0 {

View file

@ -1,5 +1,5 @@
use std::{ use std::{
collections::{HashMap, HashSet}, collections::{BTreeMap, HashSet},
fmt::Write, fmt::Write,
fs, fs,
io::{self, Write as _}, io::{self, Write as _},
@ -12,6 +12,7 @@ use std::{
use ansi_colours::{ansi256_from_rgb, rgb_from_ansi256}; use ansi_colours::{ansi256_from_rgb, rgb_from_ansi256};
use anstyle::{Ansi256Color, AnsiColor, Color, Effects, RgbColor}; use anstyle::{Ansi256Color, AnsiColor, Color, Effects, RgbColor};
use anyhow::Result; use anyhow::Result;
use log::{info, warn};
use serde::{ser::SerializeMap, Deserialize, Deserializer, Serialize, Serializer}; use serde::{ser::SerializeMap, Deserialize, Deserializer, Serialize, Serializer};
use serde_json::{json, Value}; use serde_json::{json, Value};
use tree_sitter_highlight::{HighlightConfiguration, HighlightEvent, Highlighter, HtmlRenderer}; use tree_sitter_highlight::{HighlightConfiguration, HighlightEvent, Highlighter, HtmlRenderer};
@ -82,9 +83,9 @@ impl<'de> Deserialize<'de> for Theme {
{ {
let mut styles = Vec::new(); let mut styles = Vec::new();
let mut highlight_names = Vec::new(); let mut highlight_names = Vec::new();
if let Ok(colors) = HashMap::<String, Value>::deserialize(deserializer) { if let Ok(colors) = BTreeMap::<String, Value>::deserialize(deserializer) {
highlight_names.reserve(colors.len());
styles.reserve(colors.len()); styles.reserve(colors.len());
highlight_names.reserve(colors.len());
for (name, style_value) in colors { for (name, style_value) in colors {
let mut style = Style::default(); let mut style = Style::default();
parse_style(&mut style, style_value); parse_style(&mut style, style_value);
@ -127,7 +128,7 @@ impl Serialize for Theme {
|| effects.contains(Effects::ITALIC) || effects.contains(Effects::ITALIC)
|| effects.contains(Effects::UNDERLINE) || effects.contains(Effects::UNDERLINE)
{ {
let mut style_json = HashMap::new(); let mut style_json = BTreeMap::new();
if let Some(color) = color { if let Some(color) = color {
style_json.insert("color", color); style_json.insert("color", color);
} }
@ -348,19 +349,17 @@ pub fn highlight(
config.nonconformant_capture_names(&HashSet::new()) config.nonconformant_capture_names(&HashSet::new())
}; };
if names.is_empty() { if names.is_empty() {
eprintln!("All highlight captures conform to standards."); info!("All highlight captures conform to standards.");
} else { } else {
eprintln!( warn!(
"Non-standard highlight {} detected:", "Non-standard highlight {} detected:\n* {}",
if names.len() > 1 { if names.len() > 1 {
"captures" "captures"
} else { } else {
"capture" "capture"
} },
names.join("\n* ")
); );
for name in names {
eprintln!("* {name}");
}
} }
} }
@ -451,7 +450,7 @@ pub fn highlight(
} }
if opts.print_time { if opts.print_time {
eprintln!("Time: {}ms", time.elapsed().as_millis()); info!("Time: {}ms", time.elapsed().as_millis());
} }
Ok(()) Ok(())

1548
crates/cli/src/init.rs Normal file

File diff suppressed because it is too large Load diff

View file

@ -89,8 +89,8 @@ pub fn get_input(
let Some(path_str) = path.to_str() else { let Some(path_str) = path.to_str() else {
bail!("Invalid path: {}", path.display()); bail!("Invalid path: {}", path.display());
}; };
let paths = let paths = glob(path_str)
glob(path_str).with_context(|| format!("Invalid glob pattern {path:?}"))?; .with_context(|| format!("Invalid glob pattern {}", path.display()))?;
for path in paths { for path in paths {
incorporate_path(path?, positive); incorporate_path(path?, positive);
} }

55
crates/cli/src/logger.rs Normal file
View file

@ -0,0 +1,55 @@
use std::io::Write;
use anstyle::{AnsiColor, Color, Style};
use log::{Level, LevelFilter, Log, Metadata, Record};
pub fn paint(color: Option<impl Into<Color>>, text: &str) -> String {
let style = Style::new().fg_color(color.map(Into::into));
format!("{style}{text}{style:#}")
}
struct Logger;
impl Log for Logger {
fn enabled(&self, _: &Metadata) -> bool {
true
}
fn log(&self, record: &Record) {
match record.level() {
Level::Error => eprintln!(
"{} {}",
paint(Some(AnsiColor::Red), "Error:"),
record.args()
),
Level::Warn => eprintln!(
"{} {}",
paint(Some(AnsiColor::Yellow), "Warning:"),
record.args()
),
Level::Info | Level::Debug => eprintln!("{}", record.args()),
Level::Trace => eprintln!(
"[{}] {}",
record
.module_path()
.unwrap_or_default()
.trim_start_matches("rust_tree_sitter_cli::"),
record.args()
),
}
}
fn flush(&self) {
let mut stderr = std::io::stderr().lock();
let _ = stderr.flush();
}
}
pub fn init() {
log::set_boxed_logger(Box::new(Logger {})).unwrap();
log::set_max_level(LevelFilter::Info);
}
pub fn enable_debug() {
log::set_max_level(LevelFilter::Debug);
}

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,7 @@
use std::{ use std::{
fmt, fs, fmt, fs,
io::{self, StdoutLock, Write}, io::{self, Write},
ops::ControlFlow,
path::{Path, PathBuf}, path::{Path, PathBuf},
sync::atomic::{AtomicUsize, Ordering}, sync::atomic::{AtomicUsize, Ordering},
time::{Duration, Instant}, time::{Duration, Instant},
@ -9,16 +10,17 @@ use std::{
use anstyle::{AnsiColor, Color, RgbColor}; use anstyle::{AnsiColor, Color, RgbColor};
use anyhow::{anyhow, Context, Result}; use anyhow::{anyhow, Context, Result};
use clap::ValueEnum; use clap::ValueEnum;
use log::info;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::{ use tree_sitter::{
ffi, InputEdit, Language, LogType, ParseOptions, ParseState, Parser, Point, Range, Tree, ffi, InputEdit, Language, LogType, ParseOptions, ParseState, Parser, Point, Range, Tree,
TreeCursor, TreeCursor,
}; };
use super::util; use crate::{fuzz::edits::Edit, logger::paint, util};
use crate::{fuzz::edits::Edit, test::paint};
#[derive(Debug, Default, Serialize)] #[derive(Debug, Default, Serialize, JsonSchema)]
pub struct Stats { pub struct Stats {
pub successful_parses: usize, pub successful_parses: usize,
pub total_parses: usize, pub total_parses: usize,
@ -29,18 +31,28 @@ pub struct Stats {
impl fmt::Display for Stats { impl fmt::Display for Stats {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let duration_us = self.total_duration.as_micros(); let duration_us = self.total_duration.as_micros();
let success_rate = if self.total_parses > 0 {
format!(
"{:.2}%",
((self.successful_parses as f64) / (self.total_parses as f64)) * 100.0,
)
} else {
"N/A".to_string()
};
let duration_str = match (self.total_parses, duration_us) {
(0, _) => "N/A".to_string(),
(_, 0) => "0 bytes/ms".to_string(),
(_, _) => format!(
"{} bytes/ms",
((self.total_bytes as u128) * 1_000) / duration_us
),
};
writeln!( writeln!(
f, f,
"Total parses: {}; successful parses: {}; failed parses: {}; success percentage: {:.2}%; average speed: {} bytes/ms", "Total parses: {}; successful parses: {}; failed parses: {}; success percentage: {success_rate}; average speed: {duration_str}",
self.total_parses, self.total_parses,
self.successful_parses, self.successful_parses,
self.total_parses - self.successful_parses, self.total_parses - self.successful_parses,
((self.successful_parses as f64) / (self.total_parses as f64)) * 100.0,
if duration_us != 0 {
((self.total_bytes as u128) * 1_000) / duration_us
} else {
0
}
) )
} }
} }
@ -219,13 +231,24 @@ impl ParseSummary {
} }
} }
#[derive(Serialize, Debug, Default)] #[derive(Serialize, Debug)]
pub struct ParseStats { pub struct ParseStats {
pub parse_summaries: Vec<ParseSummary>, pub parse_summaries: Vec<ParseSummary>,
pub cumulative_stats: Stats, pub cumulative_stats: Stats,
pub source_count: usize,
} }
#[derive(Serialize, ValueEnum, Debug, Clone, Default, Eq, PartialEq)] impl Default for ParseStats {
fn default() -> Self {
Self {
parse_summaries: Vec::new(),
cumulative_stats: Stats::default(),
source_count: 1,
}
}
}
#[derive(Serialize, ValueEnum, Debug, Copy, Clone, Default, Eq, PartialEq)]
pub enum ParseDebugType { pub enum ParseDebugType {
#[default] #[default]
Quiet, Quiet,
@ -273,10 +296,11 @@ pub fn parse_file_at_path(
} }
// Log to stderr if `--debug` was passed // Log to stderr if `--debug` was passed
else if opts.debug != ParseDebugType::Quiet { else if opts.debug != ParseDebugType::Quiet {
let mut curr_version: usize = 0usize; let mut curr_version: usize = 0;
let use_color = std::env::var("NO_COLOR").map_or(true, |v| v != "1"); let use_color = std::env::var("NO_COLOR").map_or(true, |v| v != "1");
parser.set_logger(Some(Box::new(|log_type, message| { let debug = opts.debug;
if opts.debug == ParseDebugType::Normal { parser.set_logger(Some(Box::new(move |log_type, message| {
if debug == ParseDebugType::Normal {
if log_type == LogType::Lex { if log_type == LogType::Lex {
write!(&mut io::stderr(), " ").unwrap(); write!(&mut io::stderr(), " ").unwrap();
} }
@ -346,15 +370,15 @@ pub fn parse_file_at_path(
let progress_callback = &mut |_: &ParseState| { let progress_callback = &mut |_: &ParseState| {
if let Some(cancellation_flag) = opts.cancellation_flag { if let Some(cancellation_flag) = opts.cancellation_flag {
if cancellation_flag.load(Ordering::SeqCst) != 0 { if cancellation_flag.load(Ordering::SeqCst) != 0 {
return true; return ControlFlow::Break(());
} }
} }
if opts.timeout > 0 && start_time.elapsed().as_micros() > opts.timeout as u128 { if opts.timeout > 0 && start_time.elapsed().as_micros() > opts.timeout as u128 {
return true; return ControlFlow::Break(());
} }
false ControlFlow::Continue(())
}; };
let parse_opts = ParseOptions::new().progress_callback(progress_callback); let parse_opts = ParseOptions::new().progress_callback(progress_callback);
@ -413,7 +437,7 @@ pub fn parse_file_at_path(
if let Some(mut tree) = tree { if let Some(mut tree) = tree {
if opts.debug_graph && !opts.edits.is_empty() { if opts.debug_graph && !opts.edits.is_empty() {
println!("BEFORE:\n{}", String::from_utf8_lossy(&source_code)); info!("BEFORE:\n{}", String::from_utf8_lossy(&source_code));
} }
let edit_time = Instant::now(); let edit_time = Instant::now();
@ -423,7 +447,7 @@ pub fn parse_file_at_path(
tree = parser.parse(&source_code, Some(&tree)).unwrap(); tree = parser.parse(&source_code, Some(&tree)).unwrap();
if opts.debug_graph { if opts.debug_graph {
println!("AFTER {i}:\n{}", String::from_utf8_lossy(&source_code)); info!("AFTER {i}:\n{}", String::from_utf8_lossy(&source_code));
} }
} }
let edit_duration = edit_time.elapsed(); let edit_duration = edit_time.elapsed();
@ -490,63 +514,23 @@ pub fn parse_file_at_path(
} }
if opts.output == ParseOutput::Cst { if opts.output == ParseOutput::Cst {
let lossy_source_code = String::from_utf8_lossy(&source_code); render_cst(&source_code, &tree, &mut cursor, opts, &mut stdout)?;
let total_width = lossy_source_code
.lines()
.enumerate()
.map(|(row, col)| {
(row as f64).log10() as usize + (col.len() as f64).log10() as usize + 1
})
.max()
.unwrap_or(1);
let mut indent_level = 1;
let mut did_visit_children = false;
let mut in_error = false;
loop {
if did_visit_children {
if cursor.goto_next_sibling() {
did_visit_children = false;
} else if cursor.goto_parent() {
did_visit_children = true;
indent_level -= 1;
if !cursor.node().has_error() {
in_error = false;
}
} else {
break;
}
} else {
cst_render_node(
opts,
&mut cursor,
&source_code,
&mut stdout,
total_width,
indent_level,
in_error,
)?;
if cursor.goto_first_child() {
did_visit_children = false;
indent_level += 1;
if cursor.node().has_error() {
in_error = true;
}
} else {
did_visit_children = true;
}
}
}
cursor.reset(tree.root_node());
println!();
} }
if opts.output == ParseOutput::Xml { if opts.output == ParseOutput::Xml {
let mut needs_newline = false; let mut needs_newline = false;
let mut indent_level = 0; let mut indent_level = 2;
let mut did_visit_children = false; let mut did_visit_children = false;
let mut had_named_children = false; let mut had_named_children = false;
let mut tags = Vec::<&str>::new(); let mut tags = Vec::<&str>::new();
writeln!(&mut stdout, "<?xml version=\"1.0\"?>")?;
// If we're parsing the first file, write the header
if opts.stats.parse_summaries.is_empty() {
writeln!(&mut stdout, "<?xml version=\"1.0\"?>")?;
writeln!(&mut stdout, "<sources>")?;
}
writeln!(&mut stdout, " <source name=\"{}\">", path.display())?;
loop { loop {
let node = cursor.node(); let node = cursor.node();
let is_named = node.is_named(); let is_named = node.is_named();
@ -561,7 +545,7 @@ pub fn parse_file_at_path(
write!(&mut stdout, "</{}>", tag.expect("there is a tag"))?; write!(&mut stdout, "</{}>", tag.expect("there is a tag"))?;
// we only write a line in the case where it's the last sibling // we only write a line in the case where it's the last sibling
if let Some(parent) = node.parent() { if let Some(parent) = node.parent() {
if parent.child(parent.child_count() - 1).unwrap() == node { if parent.child(parent.child_count() as u32 - 1).unwrap() == node {
stdout.write_all(b"\n")?; stdout.write_all(b"\n")?;
} }
} }
@ -625,8 +609,14 @@ pub fn parse_file_at_path(
} }
} }
} }
writeln!(&mut stdout)?;
writeln!(&mut stdout, " </source>")?;
// If we parsed the last file, write the closing tag for the `sources` header
if opts.stats.parse_summaries.len() == opts.stats.source_count - 1 {
writeln!(&mut stdout, "</sources>")?;
}
cursor.reset(tree.root_node()); cursor.reset(tree.root_node());
println!();
} }
if opts.output == ParseOutput::Dot { if opts.output == ParseOutput::Dot {
@ -684,22 +674,28 @@ pub fn parse_file_at_path(
width = max_path_length width = max_path_length
)?; )?;
if let Some(node) = first_error { if let Some(node) = first_error {
let start = node.start_position(); let node_kind = node.kind();
let end = node.end_position(); let mut node_text = String::with_capacity(node_kind.len());
for c in node_kind.chars() {
if let Some(escaped) = escape_invisible(c) {
node_text += escaped;
} else {
node_text.push(c);
}
}
write!(&mut stdout, "\t(")?; write!(&mut stdout, "\t(")?;
if node.is_missing() { if node.is_missing() {
if node.is_named() { if node.is_named() {
write!(&mut stdout, "MISSING {}", node.kind())?; write!(&mut stdout, "MISSING {node_text}")?;
} else { } else {
write!( write!(&mut stdout, "MISSING \"{node_text}\"")?;
&mut stdout,
"MISSING \"{}\"",
node.kind().replace('\n', "\\n")
)?;
} }
} else { } else {
write!(&mut stdout, "{}", node.kind())?; write!(&mut stdout, "{node_text}")?;
} }
let start = node.start_position();
let end = node.end_position();
write!( write!(
&mut stdout, &mut stdout,
" [{}, {}] - [{}, {}])", " [{}, {}] - [{}, {}])",
@ -766,12 +762,77 @@ const fn escape_invisible(c: char) -> Option<&'static str> {
}) })
} }
const fn escape_delimiter(c: char) -> Option<&'static str> {
Some(match c {
'`' => "\\`",
'\"' => "\\\"",
_ => return None,
})
}
pub fn render_cst<'a, 'b: 'a>(
source_code: &[u8],
tree: &'b Tree,
cursor: &mut TreeCursor<'a>,
opts: &ParseFileOptions,
out: &mut impl Write,
) -> Result<()> {
let lossy_source_code = String::from_utf8_lossy(source_code);
let total_width = lossy_source_code
.lines()
.enumerate()
.map(|(row, col)| (row as f64).log10() as usize + (col.len() as f64).log10() as usize + 1)
.max()
.unwrap_or(1);
let mut indent_level = usize::from(!opts.no_ranges);
let mut did_visit_children = false;
let mut in_error = false;
loop {
if did_visit_children {
if cursor.goto_next_sibling() {
did_visit_children = false;
} else if cursor.goto_parent() {
did_visit_children = true;
indent_level -= 1;
if !cursor.node().has_error() {
in_error = false;
}
} else {
break;
}
} else {
cst_render_node(
opts,
cursor,
source_code,
out,
total_width,
indent_level,
in_error,
)?;
if cursor.goto_first_child() {
did_visit_children = false;
indent_level += 1;
if cursor.node().has_error() {
in_error = true;
}
} else {
did_visit_children = true;
}
}
}
cursor.reset(tree.root_node());
Ok(())
}
fn render_node_text(source: &str) -> String { fn render_node_text(source: &str) -> String {
source source
.chars() .chars()
.fold(String::with_capacity(source.len()), |mut acc, c| { .fold(String::with_capacity(source.len()), |mut acc, c| {
if let Some(esc) = escape_invisible(c) { if let Some(esc) = escape_invisible(c) {
acc.push_str(esc); acc.push_str(esc);
} else if let Some(esc) = escape_delimiter(c) {
acc.push_str(esc);
} else { } else {
acc.push(c); acc.push(c);
} }
@ -781,7 +842,7 @@ fn render_node_text(source: &str) -> String {
fn write_node_text( fn write_node_text(
opts: &ParseFileOptions, opts: &ParseFileOptions,
stdout: &mut StdoutLock<'static>, out: &mut impl Write,
cursor: &TreeCursor, cursor: &TreeCursor,
is_named: bool, is_named: bool,
source: &str, source: &str,
@ -797,7 +858,7 @@ fn write_node_text(
if !is_named { if !is_named {
write!( write!(
stdout, out,
"{}{}{}", "{}{}{}",
paint(quote_color, &String::from(quote)), paint(quote_color, &String::from(quote)),
paint(color, &render_node_text(source)), paint(color, &render_node_text(source)),
@ -821,35 +882,24 @@ fn write_node_text(
0 0
}; };
let formatted_line = render_line_feed(line, opts); let formatted_line = render_line_feed(line, opts);
if !opts.no_ranges { write!(
write!( out,
stdout, "{}{}{}{}{}{}",
"{}{}{}{}{}{}", if multiline { "\n" } else { " " },
if multiline { "\n" } else { "" }, if multiline && !opts.no_ranges {
if multiline { render_node_range(opts, cursor, is_named, true, total_width, node_range)
render_node_range(opts, cursor, is_named, true, total_width, node_range) } else {
} else { String::new()
String::new() },
}, if multiline {
if multiline { " ".repeat(indent_level + 1)
" ".repeat(indent_level + 1) } else {
} else { String::new()
String::new() },
}, paint(quote_color, &String::from(quote)),
paint(quote_color, &String::from(quote)), paint(color, &render_node_text(&formatted_line)),
&paint(color, &render_node_text(&formatted_line)), paint(quote_color, &String::from(quote)),
paint(quote_color, &String::from(quote)), )?;
)?;
} else {
write!(
stdout,
"\n{}{}{}{}",
" ".repeat(indent_level + 1),
paint(quote_color, &String::from(quote)),
&paint(color, &render_node_text(&formatted_line)),
paint(quote_color, &String::from(quote)),
)?;
}
} }
} }
@ -903,9 +953,9 @@ fn render_node_range(
fn cst_render_node( fn cst_render_node(
opts: &ParseFileOptions, opts: &ParseFileOptions,
cursor: &mut TreeCursor, cursor: &TreeCursor,
source_code: &[u8], source_code: &[u8],
stdout: &mut StdoutLock<'static>, out: &mut impl Write,
total_width: usize, total_width: usize,
indent_level: usize, indent_level: usize,
in_error: bool, in_error: bool,
@ -914,13 +964,13 @@ fn cst_render_node(
let is_named = node.is_named(); let is_named = node.is_named();
if !opts.no_ranges { if !opts.no_ranges {
write!( write!(
stdout, out,
"{}", "{}",
render_node_range(opts, cursor, is_named, false, total_width, node.range()) render_node_range(opts, cursor, is_named, false, total_width, node.range())
)?; )?;
} }
write!( write!(
stdout, out,
"{}{}", "{}{}",
" ".repeat(indent_level), " ".repeat(indent_level),
if in_error && !node.has_error() { if in_error && !node.has_error() {
@ -932,14 +982,14 @@ fn cst_render_node(
if is_named { if is_named {
if let Some(field_name) = cursor.field_name() { if let Some(field_name) = cursor.field_name() {
write!( write!(
stdout, out,
"{}", "{}",
paint(opts.parse_theme.field, &format!("{field_name}: ")) paint(opts.parse_theme.field, &format!("{field_name}: "))
)?; )?;
} }
if node.has_error() || node.is_error() { if node.has_error() || node.is_error() {
write!(stdout, "{}", paint(opts.parse_theme.error, ""))?; write!(out, "{}", paint(opts.parse_theme.error, ""))?;
} }
let kind_color = if node.is_error() { let kind_color = if node.is_error() {
@ -949,13 +999,13 @@ fn cst_render_node(
} else { } else {
opts.parse_theme.node_kind opts.parse_theme.node_kind
}; };
write!(stdout, "{} ", paint(kind_color, node.kind()))?; write!(out, "{}", paint(kind_color, node.kind()))?;
if node.child_count() == 0 { if node.child_count() == 0 {
// Node text from a pattern or external scanner // Node text from a pattern or external scanner
write_node_text( write_node_text(
opts, opts,
stdout, out,
cursor, cursor,
is_named, is_named,
&String::from_utf8_lossy(&source_code[node.start_byte()..node.end_byte()]), &String::from_utf8_lossy(&source_code[node.start_byte()..node.end_byte()]),
@ -964,17 +1014,13 @@ fn cst_render_node(
)?; )?;
} }
} else if node.is_missing() { } else if node.is_missing() {
write!(stdout, "{}: ", paint(opts.parse_theme.missing, "MISSING"))?; write!(out, "{}: ", paint(opts.parse_theme.missing, "MISSING"))?;
write!( write!(out, "\"{}\"", paint(opts.parse_theme.missing, node.kind()))?;
stdout,
"\"{}\"",
paint(opts.parse_theme.missing, node.kind())
)?;
} else { } else {
// Terminal literals, like "fn" // Terminal literals, like "fn"
write_node_text( write_node_text(
opts, opts,
stdout, out,
cursor, cursor,
is_named, is_named,
node.kind(), node.kind(),
@ -982,7 +1028,7 @@ fn cst_render_node(
(total_width, indent_level), (total_width, indent_level),
)?; )?;
} }
writeln!(stdout)?; writeln!(out)?;
Ok(()) Ok(())
} }

View file

@ -0,0 +1,481 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>tree-sitter THE_LANGUAGE_NAME</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/6.65.7/codemirror.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/clusterize.js/0.19.0/clusterize.min.css">
<link rel="icon" type="image/png" href="https://tree-sitter.github.io/tree-sitter/assets/images/favicon-32x32.png"
sizes="32x32" />
<link rel="icon" type="image/png" href="https://tree-sitter.github.io/tree-sitter/assets/images/favicon-16x16.png"
sizes="16x16" />
<style>
/* Base Variables */
:root {
--light-bg: #f9f9f9;
--light-border: #e0e0e0;
--light-text: #333;
--light-hover-border: #c1c1c1;
--light-scrollbar-track: #f1f1f1;
--light-scrollbar-thumb: #c1c1c1;
--light-scrollbar-thumb-hover: #a8a8a8;
--light-tree-row-bg: #e3f2fd;
--dark-bg: #1d1f21;
--dark-border: #2d2d2d;
--dark-text: #c5c8c6;
--dark-panel-bg: #252526;
--dark-code-bg: #1e1e1e;
--dark-scrollbar-track: #25282c;
--dark-scrollbar-thumb: #4a4d51;
--dark-scrollbar-thumb-hover: #5a5d61;
--dark-tree-row-bg: #373737;
--primary-color: #0550ae;
--primary-color-alpha: rgba(5, 80, 174, 0.1);
--primary-color-alpha-dark: rgba(121, 192, 255, 0.1);
--selection-color: rgba(39, 95, 255, 0.3);
}
/* Theme Colors */
[data-theme="dark"] {
--bg-color: var(--dark-bg);
--border-color: var(--dark-border);
--text-color: var(--dark-text);
--panel-bg: var(--dark-panel-bg);
--code-bg: var(--dark-code-bg);
--tree-row-bg: var(--dark-tree-row-bg);
}
[data-theme="light"] {
--bg-color: var(--light-bg);
--border-color: var(--light-border);
--text-color: var(--light-text);
--panel-bg: white;
--code-bg: white;
--tree-row-bg: var(--light-tree-row-bg);
}
/* Base Styles */
body {
margin: 0;
padding: 0;
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
background-color: var(--bg-color);
color: var(--text-color);
}
/* Layout */
#playground-container {
width: 100%;
height: 100vh;
display: flex;
flex-direction: column;
background-color: var(--bg-color);
}
header {
padding: 16px 24px;
border-bottom: 1px solid var(--border-color);
display: flex;
align-items: center;
gap: 20px;
background-color: var(--panel-bg);
font-size: 14px;
}
.header-item {
display: flex;
align-items: center;
gap: 8px;
}
.language-name,
#language-version {
font-weight: 600;
}
main {
flex: 1;
display: flex;
overflow: hidden;
}
#input-pane {
width: 50%;
display: flex;
flex-direction: column;
border-right: 1px solid var(--border-color);
background-color: var(--panel-bg);
overflow: hidden;
}
#code-container {
flex: 1;
min-height: 0;
position: relative;
border-bottom: 1px solid var(--border-color);
display: flex;
flex-direction: column;
}
#query-container:not([style*="visibility: hidden"]) {
flex: 1;
min-height: 0;
display: flex;
flex-direction: column;
}
#query-container .panel-header {
flex: 0 0 auto;
}
#query-container .CodeMirror {
flex: 1;
position: relative;
min-height: 0;
}
#output-container-scroll {
width: 50%;
overflow: auto;
background-color: var(--panel-bg);
padding: 0;
display: flex;
flex-direction: column;
}
#output-container {
font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
line-height: 1.5;
margin: 0;
padding: 16px;
}
.panel-header {
padding: 8px 16px;
font-weight: 600;
font-size: 14px;
border-bottom: 1px solid var(--border-color);
background-color: var(--panel-bg);
display: flex;
align-items: center;
gap: 8px;
}
.CodeMirror {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
height: 100%;
font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
font-size: 14px;
line-height: 1.6;
background-color: var(--code-bg) !important;
color: var(--text-color) !important;
}
.query-error {
text-decoration: underline red dashed;
-webkit-text-decoration: underline red dashed;
}
/* Scrollbars */
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-track {
border-radius: 4px;
background: var(--light-scrollbar-track);
}
::-webkit-scrollbar-thumb {
border-radius: 4px;
background: var(--light-scrollbar-thumb);
}
::-webkit-scrollbar-thumb:hover {
background: var(--light-scrollbar-thumb-hover);
}
[data-theme="dark"] {
::-webkit-scrollbar-track {
background: var(--dark-scrollbar-track) !important;
}
::-webkit-scrollbar-thumb {
background: var(--dark-scrollbar-thumb) !important;
}
::-webkit-scrollbar-thumb:hover {
background: var(--dark-scrollbar-thumb-hover) !important;
}
}
/* Theme Toggle */
.theme-toggle {
background: none;
border: 1px solid var(--border-color);
border-radius: 4px;
padding: 6px;
cursor: pointer;
color: var(--text-color);
}
.theme-toggle:hover {
background-color: var(--primary-color-alpha);
}
[data-theme="light"] .moon-icon,
[data-theme="dark"] .sun-icon {
display: none;
}
/* Form Elements */
input[type="checkbox"] {
margin-right: 6px;
vertical-align: middle;
}
label {
font-size: 14px;
margin-right: 16px;
cursor: pointer;
}
#output-container a {
cursor: pointer;
text-decoration: none;
color: #040404;
padding: 2px;
}
#output-container a:hover {
text-decoration: underline;
}
#output-container a.node-link.named {
color: #0550ae;
}
#output-container a.node-link.anonymous {
color: #116329;
}
#output-container a.node-link.anonymous:before {
content: '"';
}
#output-container a.node-link.anonymous:after {
content: '"';
}
#output-container a.node-link.error {
color: #cf222e;
}
#output-container a.highlighted {
background-color: #cae2ff;
color: red;
border-radius: 3px;
text-decoration: underline;
}
#copy-button {
background: none;
border: 1px solid var(--border-color);
border-radius: 4px;
padding: 6px;
cursor: pointer;
color: var(--text-color);
display: inline-flex;
align-items: center;
justify-content: center;
margin-left: 8px;
}
#copy-button:hover {
background-color: var(--primary-color-alpha);
}
#copy-button:focus {
outline: none;
border-color: var(--primary-color);
box-shadow: 0 0 0 2px var(--primary-color-alpha);
}
.toast {
position: fixed;
bottom: 20px;
right: 20px;
background-color: var(--light-text);
color: white;
padding: 12px 16px;
border-radius: 6px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
font-size: 14px;
font-weight: 500;
opacity: 0;
transform: translateY(20px);
transition: all 0.3s ease;
z-index: 1000;
pointer-events: none;
}
.toast.show {
opacity: 1;
transform: translateY(0);
}
/* Dark Theme Node Colors */
[data-theme="dark"] {
& #output-container a {
color: #d4d4d4;
}
& #output-container a.node-link.named {
color: #79c0ff;
}
& #output-container a.node-link.anonymous {
color: #7ee787;
}
& #output-container a.node-link.error {
color: #ff7b72;
}
& #output-container a.highlighted {
background-color: #656669;
color: red;
}
& .CodeMirror {
background-color: var(--dark-code-bg) !important;
color: var(--dark-text) !important;
}
& .CodeMirror-gutters {
background-color: var(--dark-panel-bg) !important;
border-color: var(--dark-border) !important;
}
& .CodeMirror-cursor {
border-color: var(--dark-text) !important;
}
& .CodeMirror-selected {
background-color: rgba(255, 255, 255, 0.1) !important;
}
& .toast {
background-color: var(--dark-bg);
color: var(--dark-text);
}
}
.tree-row:has(.highlighted) {
background-color: var(--tree-row-bg);
}
</style>
</head>
<body>
<div id="playground-container" style="visibility: hidden;">
<header>
<div class="header-item">
<span class="language-name">Language: THE_LANGUAGE_NAME</span>
<span id="language-version"></span>
</div>
<div class="header-item">
<input id="logging-checkbox" type="checkbox">
<label for="logging-checkbox">log</label>
</div>
<div class="header-item">
<input id="anonymous-nodes-checkbox" type="checkbox">
<label for="anonymous-nodes-checkbox">show anonymous nodes</label>
</div>
<div class="header-item">
<input id="query-checkbox" type="checkbox">
<label for="query-checkbox">query</label>
</div>
<div class="header-item">
<input id="accessibility-checkbox" type="checkbox">
<label for="accessibility-checkbox">accessibility</label>
</div>
<div class="header-item">
<label for="update-time">parse time: </label>
<span id="update-time"></span>
</div>
<div class="header-item">
<a href="https://tree-sitter.github.io/tree-sitter/7-playground.html#about">(?)</a>
</div>
<select id="language-select" style="display: none;">
<option value="parser">Parser</option>
</select>
<div class="header-item">
<button id="theme-toggle" class="theme-toggle" aria-label="Toggle theme">
<svg class="sun-icon" viewBox="0 0 24 24" width="16" height="16">
<path fill="currentColor"
d="M12 17.5a5.5 5.5 0 1 0 0-11 5.5 5.5 0 0 0 0 11zm0 1.5a7 7 0 1 1 0-14 7 7 0 0 1 0 14zm0-16a1 1 0 0 1 1 1v2a1 1 0 1 1-2 0V4a1 1 0 0 1 1-1zm0 15a1 1 0 0 1 1 1v2a1 1 0 1 1-2 0v-2a1 1 0 0 1 1-1zm9-9a1 1 0 0 1-1 1h-2a1 1 0 1 1 0-2h2a1 1 0 0 1 1 1zM4 12a1 1 0 0 1-1 1H1a1 1 0 1 1 0-2h2a1 1 0 0 1 1 1z" />
</svg>
<svg class="moon-icon" viewBox="0 0 24 24" width="16" height="16">
<path fill="currentColor"
d="M12.1 22c-5.5 0-10-4.5-10-10s4.5-10 10-10c.2 0 .3 0 .5.1-1.3 1.4-2 3.2-2 5.2 0 4.1 3.4 7.5 7.5 7.5 2 0 3.8-.7 5.2-2 .1.2.1.3.1.5 0 5.4-4.5 9.7-10 9.7z" />
</svg>
</button>
</div>
</header>
<main>
<div id="input-pane">
<div class="panel-header">Code</div>
<div id="code-container">
<textarea id="code-input"></textarea>
</div>
<div id="query-container" style="visibility: hidden; position: absolute;">
<div class="panel-header">Query</div>
<textarea id="query-input"></textarea>
</div>
</div>
<div id="output-container-scroll">
<div class="panel-header">
Tree
<button type="button" id="copy-button" class="theme-toggle" aria-label="Copy tree">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round">
<rect width="14" height="14" x="8" y="8" rx="2" ry="2" />
<path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" />
</svg>
</button>
</div>
<pre id="output-container" class="highlight"></pre>
</div>
</main>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/6.65.7/codemirror.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/clusterize.js/0.19.0/clusterize.min.js"></script>
<script>LANGUAGE_BASE_URL = "";</script>
<script type="module" src="playground.js"></script>
<script type="module">
import * as TreeSitter from './web-tree-sitter.js';
window.TreeSitter = TreeSitter;
setTimeout(() => window.initializePlayground({local: true}), 1)
</script>
</body>
</html>

View file

@ -7,6 +7,7 @@ use std::{
}; };
use anyhow::{anyhow, Context, Result}; use anyhow::{anyhow, Context, Result};
use log::{error, info};
use tiny_http::{Header, Response, Server}; use tiny_http::{Header, Response, Server};
use super::wasm; use super::wasm;
@ -18,7 +19,7 @@ macro_rules! optional_resource {
if let Some(tree_sitter_dir) = tree_sitter_dir { if let Some(tree_sitter_dir) = tree_sitter_dir {
Cow::Owned(fs::read(tree_sitter_dir.join($path)).unwrap()) Cow::Owned(fs::read(tree_sitter_dir.join($path)).unwrap())
} else { } else {
Cow::Borrowed(include_bytes!(concat!("../../", $path))) Cow::Borrowed(include_bytes!(concat!("../../../", $path)))
} }
} }
@ -34,25 +35,91 @@ macro_rules! optional_resource {
} }
optional_resource!(get_playground_js, "docs/src/assets/js/playground.js"); optional_resource!(get_playground_js, "docs/src/assets/js/playground.js");
optional_resource!(get_lib_js, "lib/binding_web/tree-sitter.js"); optional_resource!(get_lib_js, "lib/binding_web/web-tree-sitter.js");
optional_resource!(get_lib_wasm, "lib/binding_web/tree-sitter.wasm"); optional_resource!(get_lib_wasm, "lib/binding_web/web-tree-sitter.wasm");
fn get_main_html(tree_sitter_dir: Option<&Path>) -> Cow<'static, [u8]> { fn get_main_html(tree_sitter_dir: Option<&Path>) -> Cow<'static, [u8]> {
tree_sitter_dir.map_or( tree_sitter_dir.map_or(
Cow::Borrowed(include_bytes!("playground.html")), Cow::Borrowed(include_bytes!("playground.html")),
|tree_sitter_dir| { |tree_sitter_dir| {
Cow::Owned(fs::read(tree_sitter_dir.join("cli/src/playground.html")).unwrap()) Cow::Owned(fs::read(tree_sitter_dir.join("crates/cli/src/playground.html")).unwrap())
}, },
) )
} }
pub fn export(grammar_path: &Path, export_path: &Path) -> Result<()> {
let (grammar_name, language_wasm) = wasm::load_language_wasm_file(grammar_path)?;
fs::create_dir_all(export_path).with_context(|| {
format!(
"Failed to create export directory: {}",
export_path.display()
)
})?;
let tree_sitter_dir = env::var("TREE_SITTER_BASE_DIR").map(PathBuf::from).ok();
let playground_js = get_playground_js(tree_sitter_dir.as_deref());
let lib_js = get_lib_js(tree_sitter_dir.as_deref());
let lib_wasm = get_lib_wasm(tree_sitter_dir.as_deref());
let has_local_playground_js = !playground_js.is_empty();
let has_local_lib_js = !lib_js.is_empty();
let has_local_lib_wasm = !lib_wasm.is_empty();
let mut main_html = str::from_utf8(&get_main_html(tree_sitter_dir.as_deref()))
.unwrap()
.replace("THE_LANGUAGE_NAME", &grammar_name);
if !has_local_playground_js {
main_html = main_html.replace(
r#"<script type="module" src="playground.js"></script>"#,
r#"<script type="module" src="https://tree-sitter.github.io/tree-sitter/assets/js/playground.js"></script>"#
);
}
if !has_local_lib_js {
main_html = main_html.replace(
"import * as TreeSitter from './web-tree-sitter.js';",
"import * as TreeSitter from 'https://tree-sitter.github.io/web-tree-sitter.js';",
);
}
fs::write(export_path.join("index.html"), main_html.as_bytes())
.with_context(|| "Failed to write index.html")?;
fs::write(export_path.join("tree-sitter-parser.wasm"), language_wasm)
.with_context(|| "Failed to write parser wasm file")?;
if has_local_playground_js {
fs::write(export_path.join("playground.js"), playground_js)
.with_context(|| "Failed to write playground.js")?;
}
if has_local_lib_js {
fs::write(export_path.join("web-tree-sitter.js"), lib_js)
.with_context(|| "Failed to write web-tree-sitter.js")?;
}
if has_local_lib_wasm {
fs::write(export_path.join("web-tree-sitter.wasm"), lib_wasm)
.with_context(|| "Failed to write web-tree-sitter.wasm")?;
}
println!(
"Exported playground to {}",
export_path.canonicalize()?.display()
);
Ok(())
}
pub fn serve(grammar_path: &Path, open_in_browser: bool) -> Result<()> { pub fn serve(grammar_path: &Path, open_in_browser: bool) -> Result<()> {
let server = get_server()?; let server = get_server()?;
let (grammar_name, language_wasm) = wasm::load_language_wasm_file(grammar_path)?; let (grammar_name, language_wasm) = wasm::load_language_wasm_file(grammar_path)?;
let url = format!("http://{}", server.server_addr()); let url = format!("http://{}", server.server_addr());
println!("Started playground on: {url}"); info!("Started playground on: {url}");
if open_in_browser && webbrowser::open(&url).is_err() { if open_in_browser && webbrowser::open(&url).is_err() {
eprintln!("Failed to open '{url}' in a web browser"); error!("Failed to open '{url}' in a web browser");
} }
let tree_sitter_dir = env::var("TREE_SITTER_BASE_DIR").map(PathBuf::from).ok(); let tree_sitter_dir = env::var("TREE_SITTER_BASE_DIR").map(PathBuf::from).ok();
@ -79,16 +146,16 @@ pub fn serve(grammar_path: &Path, open_in_browser: bool) -> Result<()> {
response(&playground_js, &js_header) response(&playground_js, &js_header)
} }
} }
"/tree-sitter.js" => { "/web-tree-sitter.js" => {
if lib_js.is_empty() { if lib_js.is_empty() {
redirect("https://tree-sitter.github.io/tree-sitter.js") redirect("https://tree-sitter.github.io/web-tree-sitter.js")
} else { } else {
response(&lib_js, &js_header) response(&lib_js, &js_header)
} }
} }
"/tree-sitter.wasm" => { "/web-tree-sitter.wasm" => {
if lib_wasm.is_empty() { if lib_wasm.is_empty() {
redirect("https://tree-sitter.github.io/tree-sitter.wasm") redirect("https://tree-sitter.github.io/web-tree-sitter.wasm")
} else { } else {
response(&lib_wasm, &wasm_header) response(&lib_wasm, &wasm_header)
} }

View file

@ -6,65 +6,78 @@ use std::{
time::Instant, time::Instant,
}; };
use anstyle::AnsiColor;
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use log::warn;
use streaming_iterator::StreamingIterator; use streaming_iterator::StreamingIterator;
use tree_sitter::{Language, Parser, Point, Query, QueryCursor}; use tree_sitter::{Language, Parser, Point, Query, QueryCursor};
use crate::{ use crate::{
query_testing::{self, to_utf8_point}, query_testing::{self, to_utf8_point},
test::paint, test::{TestInfo, TestOutcome, TestResult, TestSummary},
}; };
#[allow(clippy::too_many_arguments)] #[derive(Default)]
pub struct QueryFileOptions {
pub ordered_captures: bool,
pub byte_range: Option<Range<usize>>,
pub point_range: Option<Range<Point>>,
pub containing_byte_range: Option<Range<usize>>,
pub containing_point_range: Option<Range<Point>>,
pub quiet: bool,
pub print_time: bool,
pub stdin: bool,
}
pub fn query_file_at_path( pub fn query_file_at_path(
language: &Language, language: &Language,
path: &Path, path: &Path,
name: &str, name: &str,
query_path: &Path, query_path: &Path,
ordered_captures: bool, opts: &QueryFileOptions,
byte_range: Option<Range<usize>>, test_summary: Option<&mut TestSummary>,
point_range: Option<Range<Point>>,
should_test: bool,
quiet: bool,
print_time: bool,
stdin: bool,
) -> Result<()> { ) -> Result<()> {
let stdout = io::stdout(); let stdout = io::stdout();
let mut stdout = stdout.lock(); let mut stdout = stdout.lock();
let query_source = fs::read_to_string(query_path) let query_source = fs::read_to_string(query_path)
.with_context(|| format!("Error reading query file {query_path:?}"))?; .with_context(|| format!("Error reading query file {}", query_path.display()))?;
let query = Query::new(language, &query_source).with_context(|| "Query compilation failed")?; let query = Query::new(language, &query_source).with_context(|| "Query compilation failed")?;
let mut query_cursor = QueryCursor::new(); let mut query_cursor = QueryCursor::new();
if let Some(range) = byte_range { if let Some(ref range) = opts.byte_range {
query_cursor.set_byte_range(range); query_cursor.set_byte_range(range.clone());
} }
if let Some(range) = point_range { if let Some(ref range) = opts.point_range {
query_cursor.set_point_range(range); query_cursor.set_point_range(range.clone());
}
if let Some(ref range) = opts.containing_byte_range {
query_cursor.set_containing_byte_range(range.clone());
}
if let Some(ref range) = opts.containing_point_range {
query_cursor.set_containing_point_range(range.clone());
} }
let mut parser = Parser::new(); let mut parser = Parser::new();
parser.set_language(language)?; parser.set_language(language)?;
let mut results = Vec::new(); let mut results = Vec::new();
let should_test = test_summary.is_some();
if !should_test && !stdin { if !should_test && !opts.stdin {
writeln!(&mut stdout, "{name}")?; writeln!(&mut stdout, "{name}")?;
} }
let source_code = let source_code =
fs::read(path).with_context(|| format!("Error reading source file {path:?}"))?; fs::read(path).with_context(|| format!("Error reading source file {}", path.display()))?;
let tree = parser.parse(&source_code, None).unwrap(); let tree = parser.parse(&source_code, None).unwrap();
let start = Instant::now(); let start = Instant::now();
if ordered_captures { if opts.ordered_captures {
let mut captures = query_cursor.captures(&query, tree.root_node(), source_code.as_slice()); let mut captures = query_cursor.captures(&query, tree.root_node(), source_code.as_slice());
while let Some((mat, capture_index)) = captures.next() { while let Some((mat, capture_index)) = captures.next() {
let capture = mat.captures[*capture_index]; let capture = mat.captures[*capture_index];
let capture_name = &query.capture_names()[capture.index as usize]; let capture_name = &query.capture_names()[capture.index as usize];
if !quiet && !should_test { if !opts.quiet && !should_test {
writeln!( writeln!(
&mut stdout, &mut stdout,
" pattern: {:>2}, capture: {} - {capture_name}, start: {}, end: {}, text: `{}`", " pattern: {:>2}, capture: {} - {capture_name}, start: {}, end: {}, text: `{}`",
@ -75,23 +88,25 @@ pub fn query_file_at_path(
capture.node.utf8_text(&source_code).unwrap_or("") capture.node.utf8_text(&source_code).unwrap_or("")
)?; )?;
} }
results.push(query_testing::CaptureInfo { if should_test {
name: (*capture_name).to_string(), results.push(query_testing::CaptureInfo {
start: to_utf8_point(capture.node.start_position(), source_code.as_slice()), name: (*capture_name).to_string(),
end: to_utf8_point(capture.node.end_position(), source_code.as_slice()), start: to_utf8_point(capture.node.start_position(), source_code.as_slice()),
}); end: to_utf8_point(capture.node.end_position(), source_code.as_slice()),
});
}
} }
} else { } else {
let mut matches = query_cursor.matches(&query, tree.root_node(), source_code.as_slice()); let mut matches = query_cursor.matches(&query, tree.root_node(), source_code.as_slice());
while let Some(m) = matches.next() { while let Some(m) = matches.next() {
if !quiet && !should_test { if !opts.quiet && !should_test {
writeln!(&mut stdout, " pattern: {}", m.pattern_index)?; writeln!(&mut stdout, " pattern: {}", m.pattern_index)?;
} }
for capture in m.captures { for capture in m.captures {
let start = capture.node.start_position(); let start = capture.node.start_position();
let end = capture.node.end_position(); let end = capture.node.end_position();
let capture_name = &query.capture_names()[capture.index as usize]; let capture_name = &query.capture_names()[capture.index as usize];
if !quiet && !should_test { if !opts.quiet && !should_test {
if end.row == start.row { if end.row == start.row {
writeln!( writeln!(
&mut stdout, &mut stdout,
@ -106,41 +121,52 @@ pub fn query_file_at_path(
)?; )?;
} }
} }
results.push(query_testing::CaptureInfo { if should_test {
name: (*capture_name).to_string(), results.push(query_testing::CaptureInfo {
start: to_utf8_point(capture.node.start_position(), source_code.as_slice()), name: (*capture_name).to_string(),
end: to_utf8_point(capture.node.end_position(), source_code.as_slice()), start: to_utf8_point(capture.node.start_position(), source_code.as_slice()),
}); end: to_utf8_point(capture.node.end_position(), source_code.as_slice()),
});
}
} }
} }
} }
if query_cursor.did_exceed_match_limit() { if query_cursor.did_exceed_match_limit() {
writeln!( warn!("Query exceeded maximum number of in-progress captures!");
&mut stdout,
" WARNING: Query exceeded maximum number of in-progress captures!"
)?;
} }
if should_test { if should_test {
let path_name = if stdin { let path_name = if opts.stdin {
"stdin" "stdin"
} else { } else {
Path::new(&path).file_name().unwrap().to_str().unwrap() Path::new(&path).file_name().unwrap().to_str().unwrap()
}; };
// Invariant: `test_summary` will always be `Some` when `should_test` is true
let test_summary = test_summary.unwrap();
match query_testing::assert_expected_captures(&results, path, &mut parser, language) { match query_testing::assert_expected_captures(&results, path, &mut parser, language) {
Ok(assertion_count) => { Ok(assertion_count) => {
println!( test_summary.query_results.add_case(TestResult {
" ✓ {} ({} assertions)", name: path_name.to_string(),
paint(Some(AnsiColor::Green), path_name), info: TestInfo::AssertionTest {
assertion_count outcome: TestOutcome::AssertionPassed { assertion_count },
); test_num: test_summary.test_num,
},
});
} }
Err(e) => { Err(e) => {
println!("{}", paint(Some(AnsiColor::Red), path_name)); test_summary.query_results.add_case(TestResult {
name: path_name.to_string(),
info: TestInfo::AssertionTest {
outcome: TestOutcome::AssertionFailed {
error: e.to_string(),
},
test_num: test_summary.test_num,
},
});
return Err(e); return Err(e);
} }
} }
} }
if print_time { if opts.print_time {
writeln!(&mut stdout, "{:?}", start.elapsed())?; writeln!(&mut stdout, "{:?}", start.elapsed())?;
} }

View file

@ -237,8 +237,8 @@ pub fn assert_expected_captures(
return Err(anyhow!( return Err(anyhow!(
"Assertion failed: at {}, found {}, expected {}", "Assertion failed: at {}, found {}, expected {}",
found.start, found.start,
found.name,
assertion.expected_capture_name, assertion.expected_capture_name,
found.name
)); ));
} }
} else { } else {

View file

@ -3,11 +3,11 @@ root = true
[*] [*]
charset = utf-8 charset = utf-8
[*.{json,toml,yml,gyp}] [*.{json,toml,yml,gyp,xml}]
indent_style = space indent_style = space
indent_size = 2 indent_size = 2
[*.js] [*.{js,ts}]
indent_style = space indent_style = space
indent_size = 2 indent_size = 2
@ -31,6 +31,10 @@ indent_size = 4
indent_style = space indent_style = space
indent_size = 4 indent_size = 4
[*.java]
indent_style = space
indent_size = 4
[*.go] [*.go]
indent_style = tab indent_style = tab
indent_size = 8 indent_size = 8

View file

@ -0,0 +1,43 @@
"""PARSER_DESCRIPTION"""
from importlib.resources import files as _files
from ._binding import language
def _get_query(name, file):
try:
query = _files(f"{__package__}") / file
globals()[name] = query.read_text()
except FileNotFoundError:
globals()[name] = None
return globals()[name]
def __getattr__(name):
if name == "HIGHLIGHTS_QUERY":
return _get_query("HIGHLIGHTS_QUERY", "HIGHLIGHTS_QUERY_PATH")
if name == "INJECTIONS_QUERY":
return _get_query("INJECTIONS_QUERY", "INJECTIONS_QUERY_PATH")
if name == "LOCALS_QUERY":
return _get_query("LOCALS_QUERY", "LOCALS_QUERY_PATH")
if name == "TAGS_QUERY":
return _get_query("TAGS_QUERY", "TAGS_QUERY_PATH")
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
__all__ = [
"language",
"HIGHLIGHTS_QUERY",
"INJECTIONS_QUERY",
"LOCALS_QUERY",
"TAGS_QUERY",
]
def __dir__():
return sorted(__all__ + [
"__all__", "__builtins__", "__cached__", "__doc__", "__file__",
"__loader__", "__name__", "__package__", "__path__", "__spec__",
])

View file

@ -0,0 +1,17 @@
from typing import Final
from typing_extensions import CapsuleType
HIGHLIGHTS_QUERY: Final[str] | None
"""The syntax highlighting query for this grammar."""
INJECTIONS_QUERY: Final[str] | None
"""The language injection query for this grammar."""
LOCALS_QUERY: Final[str] | None
"""The local variable query for this grammar."""
TAGS_QUERY: Final[str] | None
"""The symbol tagging query for this grammar."""
def language() -> CapsuleType:
"""The tree-sitter language function for this grammar."""

View file

@ -18,7 +18,7 @@ include = [
"queries/*", "queries/*",
"src/*", "src/*",
"tree-sitter.json", "tree-sitter.json",
"LICENSE", "/LICENSE",
] ]
[lib] [lib]

View file

@ -0,0 +1,65 @@
package PARSER_NS_CLEANED.jtreesitter.LOWER_PARSER_NAME;
import java.lang.foreign.*;
public final class PARSER_CLASS_NAME {
private static final ValueLayout VOID_PTR =
ValueLayout.ADDRESS.withTargetLayout(MemoryLayout.sequenceLayout(Long.MAX_VALUE, ValueLayout.JAVA_BYTE));
private static final FunctionDescriptor FUNC_DESC = FunctionDescriptor.of(VOID_PTR);
private static final Linker LINKER = Linker.nativeLinker();
private static final PARSER_CLASS_NAME INSTANCE = new PARSER_CLASS_NAME();
private final Arena arena = Arena.ofAuto();
private volatile SymbolLookup lookup = null;
private PARSER_CLASS_NAME() {}
/**
* Get the tree-sitter language for this grammar.
*/
public static MemorySegment language() {
if (INSTANCE.lookup == null)
INSTANCE.lookup = INSTANCE.findLibrary();
return language(INSTANCE.lookup);
}
/**
* Get the tree-sitter language for this grammar.
*
* <strong>The {@linkplain Arena} used in the {@code lookup}
* must not be closed while the language is being used.</strong>
*/
public static MemorySegment language(SymbolLookup lookup) {
return call(lookup, "tree_sitter_PARSER_NAME");
}
private SymbolLookup findLibrary() {
try {
var library = System.mapLibraryName("tree-sitter-KEBAB_PARSER_NAME");
return SymbolLookup.libraryLookup(library, arena);
} catch (IllegalArgumentException ex1) {
try {
System.loadLibrary("tree-sitter-KEBAB_PARSER_NAME");
return SymbolLookup.loaderLookup();
} catch (UnsatisfiedLinkError ex2) {
ex1.addSuppressed(ex2);
throw ex1;
}
}
}
private static UnsatisfiedLinkError unresolved(String name) {
return new UnsatisfiedLinkError("Unresolved symbol: %s".formatted(name));
}
@SuppressWarnings("SameParameterValue")
private static MemorySegment call(SymbolLookup lookup, String name) throws UnsatisfiedLinkError {
var address = lookup.find(name).orElseThrow(() -> unresolved(name));
try {
var function = LINKER.downcallHandle(address, FUNC_DESC);
return (MemorySegment) function.invokeExact();
} catch (Throwable e) {
throw new RuntimeException("Call to %s failed".formatted(name), e);
}
}
}

Some files were not shown because too many files have changed in this diff Show more