GitNexus/gitnexus/vendor/tree-sitter-swift
Gergő Magyar 2870aa6248
fix(grammars): load vendored tree-sitter grammars from vendor/ by absolute path (#2111) (#2144)
* fix(grammars): load vendored tree-sitter grammars from vendor/ by absolute path (#2111)

The recurring Windows `EPERM: operation not permitted, symlink` (errno -4048)
when adding the MCP server to Antigravity is NOT the #2101/#2110 module-load
crash — it is an install-time arborist failure during the `_npx` reify that the
MCP client triggers on every `npx gitnexus` launch.

Root cause: the `postinstall` materialize step copied each vendored grammar
(`vendor/tree-sitter-{c,dart,proto,swift,kotlin}`) into
`node_modules/gitnexus/node_modules/tree-sitter-*` as a real package so runtime
`require('tree-sitter-dart')` would resolve. Those packages are in no dependency
graph, so every subsequent npm/npx reify treats them as **extraneous** and
prunes/relocates them — on Windows the relocation goes through
`@npmcli/move-file`'s symlink path and throws EPERM (symlinks need Developer
Mode/admin), and on every OS the 2nd run silently deletes the grammars. This is
the same class as #1728, which the materialize step itself claimed to have
fixed.

Fix (the prebuildify + node-gyp-build ecosystem pattern): never copy grammars
into node_modules. Load each by absolute path from `vendor/<name>` via the new
`requireVendoredGrammar` helper — the grammar's own `bindings/node` runs
`node-gyp-build(<dir>)` and loads the committed `vendor/<name>/prebuilds/
<platform>-<arch>/…` directly (all 5 ship all 6 tuples). vendor/ is inside the
package but not a node_modules subtree, so arborist never sees the grammars and
the reify is idempotent — no EPERM, no silent deletion.

- new src/core/tree-sitter/vendored-grammars.ts (requireVendoredGrammar /
  vendoredGrammarDir / VENDORED_GRAMMAR_PACKAGES; VENDOR_ROOT stable in dev+dist)
- route all consumers through it: parser-loader, parse-worker, grpc proto,
  include-extractor (C), http-patterns kotlin, cli optional-grammars probe
- postinstall drops the materialize step; build-tree-sitter-grammars.cjs builds
  in-place under vendor/ (gitignored) and deletes materialize-vendor-grammars.cjs
- tests + grammar-introspection helper load grammars from vendor/ too (single
  source of truth); new vendored-grammars.test.ts guards against reintroducing a
  bare `require('tree-sitter-<vendored>')`

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(grammars): throw on a non-vendored name in requireVendoredGrammar

Drift guard (PR #2144 review, P3): validate the argument against
VENDORED_GRAMMAR_PACKAGES and fail loudly on an unknown name, so the three
grammar lists (package set / CLI probe / build registry) drifting out of sync
surfaces as a clear error instead of a confusing absolute-path require miss.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(grammars): prepack guard against stray vendor/<g>/build/ shadowing prebuilds

Publish hygiene (PR #2144 review, P2). Now that build-tree-sitter-grammars.cjs
source-builds into vendor/<name>/build/, a stray build dir would ship in the
tarball (files:["vendor"] overrides .gitignore/.npmignore) AND shadow the
committed prebuild — node-gyp-build resolves build/Release before prebuilds/.
assert-publish-grammar-coverage.cjs (prepack) now fails `npm pack` if any
vendor/*/build exists (findStrayBuildArtifacts), with a clear `rm -rf` fix hint.
Adds unit coverage for the new pure function.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test(grammars): harden the #2111 no-bare-require regression guard

PR #2144 review (P2). The guard regex missed dynamic import(), side-effect
`import 'x'`, /subpath, and backtick loads, and only scanned src/. It now covers
every node_modules-forcing form (single/double/backtick quotes, optional
subpath), scans test/ too (excluding fixtures and the guard file itself), drops
the `//`-substring false-negative (leading-comment-only heuristic), and adds a
self-test asserting every load form is caught while prose mentions and
tree-sitter-cpp are ignored.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs(grammars): correct stale vendored-grammar comments

PR #2144 review (P3). kotlin/query.ts called tree-sitter-kotlin an
"optionalDependency" — it is vendored and loaded from vendor/ by absolute path
(#2111). proto.ts now states its remaining `_require` is only for the real
`tree-sitter` dependency, not a vendored grammar (which goes through
requireVendoredGrammar). Comment-only; no behavior change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 14:20:42 +01:00
..
bindings/node feat(install): toolchain-free tree-sitter via vendored prebuilds (#2113) 2026-06-09 18:16:24 +01:00
prebuilds chore(vendor): rebuild native prebuilds (tree-sitter-c,tree-sitter-dart,tree-sitter-proto,tree-sitter-kotlin,tree-sitter-swift) (#2125) 2026-06-09 20:57:37 +01:00
src feat(install): toolchain-free tree-sitter via vendored prebuilds (#2113) 2026-06-09 18:16:24 +01:00
binding.gyp feat(install): toolchain-free tree-sitter via vendored prebuilds (#2113) 2026-06-09 18:16:24 +01:00
LICENSE fix(swift): use official prebuilt parser runtime (#1130) 2026-04-28 09:57:42 +01:00
package.json fix(grammars): load vendored tree-sitter grammars from vendor/ by absolute path (#2111) (#2144) 2026-06-10 14:20:42 +01:00
README.md feat(install): toolchain-free tree-sitter via vendored prebuilds (#2113) 2026-06-09 18:16:24 +01:00

GitNexus vendor notice

This directory is a GitNexus-managed vendored copy of the official tree-sitter-swift@0.7.1 npm runtime package. GitNexus keeps the top-level tree-sitter dependency pinned to ^0.21.1 until the broader parser runtime upgrade is handled separately.

Unified with the Dart/Proto/Kotlin/C vendored grammars, this copy also vendors the grammar source — binding.gyp, bindings/node/binding.cc, src/parser.c (the ABI-14 default; ~18 MB, compresses heavily in git), src/scanner.c, and src/tree_sitter/ — so gitnexus/scripts/build-tree-sitter-grammars.cjs can source-build the native binding on any toolchain host when no committed prebuild matches (e.g. CI before the prebuilds land). Note: upstream deliberately omits the generated parser.c (see the FAQ below); GitNexus commits it on purpose so the source-build fallback is deterministic and never needs the tree-sitter CLI at install time. The native prebuilds/ are GitNexus-cross-built by .github/workflows/build-tree-sitter-prebuilds.yml (originally upstream-shipped).

When updating this vendor package, replace it from an official tree-sitter-swift npm release: refresh src/parser.c/src/scanner.c/ src/tree_sitter//binding.gyp/bindings/node/binding.cc (use the ABI-14 parser.c, not the legacy parser_abi13.c), bump version in package.json to retrigger the prebuild workflow, update the _vendoredBy provenance, and verify the packed GitNexus tarball can both load a committed prebuild and source-build tree-sitter-swift.

Parse rate badge Crates.io badge NPM badge Build

tree-sitter-swift

This contains a tree-sitter grammar for the Swift programming language.

Getting started

To use this parser to parse Swift code, you'll want to depend on either the Rust crate or the NPM package.

Rust

To use the Rust crate, you'll add this to your Cargo.toml:

tree-sitter = "0.23.0"
tree-sitter-swift = "=0.7.0"

Then you can use a tree-sitter parser with the language declared here:

let mut parser = tree_sitter::Parser::new();
parser.set_language(tree_sitter_swift::language())?;

// ...

let tree = parser.parse(&my_source_code, None)
    .ok_or_else(|| /* error handling code */)?;

Javascript

To use this from NPM, you'll add similar dependencies to package.json:

"dependencies: {
  "tree-sitter-swift": "0.7.0",
  "tree-sitter": "^0.22.1"
}

Your usage of the parser will look like:

const Parser = require("tree-sitter");
const Swift = require("tree-sitter-swift");

const parser = new Parser();
parser.setLanguage(Swift);

// ...

const tree = parser.parse(mySourceCode);

Editing the grammar

With this package checked out, a common workflow for editing the grammar will look something like:

  1. Make a change to grammar.ts.
  2. Run npm install && npm test to see whether the change has had impact on existing parsing behavior. The default npm test target requires valgrind to be installed; if you do not have it installed, and do not wish to, you can substitute tree-sitter test directly.
  3. Run tree-sitter parse on some real Swift codebase and see whether (or where) it fails.
  4. Use any failures to create new corpus test cases.

Contributions

All contributions to this repository are welcome.

If said contribution is to check generated files (e.g., parser.c) into the repository, be aware that your contribution will not be accepted. Make sure to read the FAQ entry and the prior discussions and compromises that have occurred already on this topic.

Using tree-sitter-swift in Web Assembly

To use tree-sitter-swift as a language for the web bindings version tree-sitter, which will likely be a more modern version than the published node module. see. Follow the instructions below

  1. Install the node modules npm install web-tree-sitter tree-sitter-swift
  2. Run the tree-sitter cli to create the wasm bundle
    $ npx tree-sitter build-asm ./node_modules/tree-sitter
    
  3. Boot tree-sitter wasm like this.
const Parser = require('web-tree-sitter');
async function run() {
  //needs to happen first
  await Parser.init();
  //wait for the load of swift
  const Swift = await Parser.Language.load('./tree-sitter-swift.wasm');

  const parser = new Parser();
  parser.setLanguage(Swift);

  //Parse your swift code here.
  const tree = parser.parse('print("Hello, World!")');
}
//if you want to run this
run().then(console.log, console.error);

Frequently asked questions

Where is your parser.c?

This repository currently omits most of the code that is autogenerated during a build. This means, for instance, that grammar.json and parser.c are both only available following a build. It also significantly reduces noise during diffs.

The side benefit of not checking in parser.c is that you can guarantee backwards compatibility. Parsers generated by the tree-sitter CLI aren't always backwards compatible. If you need a parser, generate it yourself using the CLI; all the information to do so is available in this package. By doing that, you'll also know for sure that your parser version and your library version are compatible.

If you need a parser.c, and you don't care about the tree-sitter version, but you don't have a local setup that would allow you to obtain the parser, you can just download one from a recent workflow run in this package. To do so:

  • Go to the GitHub actions page for this repository.
  • Click on the "Publish grammar.json and parser.c" action for the appropriate commit.
  • Go down to Artifacts and click on generated-parser-src. All the relevant parser files will be available in your download.